Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Difference From 6f42f3300ffaa219 To a81eb9b135e0fd97
2013-05-18
| ||
00:31 | Mark the previous commit as a 'Potentially Incompatible Change'. check-in: 3528e77627 user: mistachkin tags: trunk | |
00:28 | Disable use of the AllowPartiallyTrustedCallers attribute when compiled for the .NET Framework 4.0/4.5. check-in: 6f42f3300f user: mistachkin tags: trunk | |
2013-05-17
| ||
01:31 | Update Eagle in externals to the latest trunk code. check-in: 1b40ed593a user: mistachkin tags: trunk | |
2012-10-14
| ||
01:07 | Add workload to the stress test that allocates (large amounts of) native heap memory. check-in: 977ba2a5fb user: mistachkin tags: trunk | |
2012-10-13
| ||
22:38 | Revise handling of errors in the stress test. check-in: a81eb9b135 user: mistachkin tags: trunk | |
20:28 | Make the stress test failure handling more flexible, add more comments, and improve readability. check-in: 742684b09c user: mistachkin tags: trunk | |
Deleted .fossil-settings/crnl-glob.
|
| < |
Deleted .fossil-settings/ignore-glob.
|
| < < < < < < < |
Changes to Doc/Extra/dbfactorysupport.html.
︙ | ︙ | |||
81 82 83 84 85 86 87 | <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, | | | 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 | <configuration> <system.data> <DbProviderFactories> <remove invariant="System.Data.SQLite"/> <add name="SQLite Data Provider" invariant="System.Data.SQLite" description=".Net Framework Data Provider for SQLite" type="System.Data.SQLite.SQLiteFactory, System.Data.SQLite, Version=1.0.83.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139"/> </DbProviderFactories> </system.data> </configuration> </pre> </div> <p> |
︙ | ︙ |
Changes to Doc/Extra/environment.html.
︙ | ︙ | |||
70 71 72 73 74 75 76 | <td>If this environment variable is set [to anything], the native library pre-loading functionality will be disabled. By default, the native library pre-loading will attempt to load the native SQLite library from architecture-specific (e.g. "x86", "amd64", "x64") or platform-specific (e.g. "Win32") directories that reside underneath the application base directory.</td> </tr> | < < < < < < < < < | < < < < < < < < < < < | 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 | <td>If this environment variable is set [to anything], the native library pre-loading functionality will be disabled. By default, the native library pre-loading will attempt to load the native SQLite library from architecture-specific (e.g. "x86", "amd64", "x64") or platform-specific (e.g. "Win32") directories that reside underneath the application base directory.</td> </tr> <tr valign="top"> <td>PreLoadSQLite_BaseDirectory</td> <td>If this environment variable is set [to anything], it will be used instead of the application base directory by the native library pre-loader.</td> </tr> <tr valign="top"> <td>PreLoadSQLite_ProcessorArchitecture</td> <td>If this environment variable is set [to anything], it will be used instead of the processor architecture value contained in the PROCESSOR_ARCHITECTURE environment variable to help build the path of the native library to pre-load.</td> </tr> <tr valign="top"> <td>PROCESSOR_ARCHITECTURE</td> <td>This environment variable is normally set by the operating system itself and should reflect the native processor architecture of the current process (e.g. a 32-bit x86 application running on a 64-bit x64 operating system should have the value "x86"). </td> |
︙ | ︙ |
Changes to Doc/Extra/version.html.
︙ | ︙ | |||
39 40 41 42 43 44 45 | </td> </tr> </table> </div> <div id="mainSection"> <div id="mainBody"> <h1 class="heading">Version History</h1> | | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < < < | 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | </td> </tr> </table> </div> <div id="mainSection"> <div id="mainBody"> <h1 class="heading">Version History</h1> <p><b>1.0.83.0 - December XX, 2012 <font color="red">(release scheduled)</font></b></p> <ul> <li>Updated to <a href="http://www.sqlite.org/src/info/trunk">SQLite 3.7.15</a>.</li> <li>Add Visual Studio 2012 support to all the applicable solution/project files, their associated supporting files, and the test suite.</li> <li>Add Visual Studio 2012 support to the redesigned designer support installer.</li> <li>Allow opened connections to skip adding the extension functions included in the interop assembly via the new NoExtensionFunctions connection flag.</li> <li>Support loading of SQLite extensions via the new EnableExtensions and LoadExtension methods of the SQLiteConnection class. Pursuant to <a href="http://system.data.sqlite.org/index.html/info/17045010df">[17045010df]</a>.</li> <li>Add notifications before and after any connection is opened and closed, as well as other related notifications, via the new static Changed event.</li> <li>Add an overload of the SQLiteLog.LogMessage method that takes a single string parameter.</li> <li>Add an overload of the SQLiteConnection.LogMessage method that takes a SQLiteErrorCode parameter.</li> <li>All applicable calls into the SQLite core library now return a SQLiteErrorCode instead of an integer error code.</li> <li>Make sure the error code of the SQLiteException class gets serialized.</li> <li>Make the test project for the .NET Compact Framework more flexible.</li> <li>When available, the new sqlite3_errstr function from the core library is used to get the error message for a specific return code.</li> <li>The SetMemoryStatus, Shutdown, ResultCode, ExtendedResultCode, and SetAvRetry methods of the SQLiteConnection class now return a SQLiteErrorCode instead of an integer error code. <b>** Potentially Incompatible Change **</b></li> <li>The public constructor for the SQLiteException now takes a SQLiteErrorCode instead of an integer error code. <b>** Potentially Incompatible Change **</b></li> <li>The ErrorCode property of the SQLiteException is now an Int32, to allow the property inherited from the base class to be properly overridden. <b>** Potentially Incompatible Change **</b></li> <li>The ErrorCode field of the LogEventArgs is now an object instead of an integer. <b>** Potentially Incompatible Change **</b></li> <li>The names and messages associated with the SQLiteErrorCode enumeration values have been normalized to match those in the SQLite core library. <b>** Potentially Incompatible Change **</b></li> <li>Implement more robust locking semantics for the CriticalHandle derived classes when compiled for the .NET Compact Framework.</li> <li>Cache column indexes are they are looked up when using the SQLiteDataReader to improve performance.</li> <li>Prevent the SQLiteConnection.Close method from throwing non-fatal exceptions during its disposal.</li> <li>Rename the interop assembly functions sqlite3_cursor_rowid, sqlite3_context_collcompare, sqlite3_context_collseq, sqlite3_cursor_rowid, and sqlite3_table_cursor to include an "_interop" suffix. <b>** Potentially Incompatible Change **</b></li> <li>Prevent the LastInsertRowId, MemoryUsed, and MemoryHighwater connection properties from throwing NotSupportedException when running on the .NET Compact Framework. Fix for <a href="http://system.data.sqlite.org/index.html/info/dd45aba387">[dd45aba387]</a>.</li> <li>Add protection against ThreadAbortException asynchronously interrupting native resource initialization and finalization.</li> <li>Add test automation for the Windows CE binaries.</li> </ul> <p><b>1.0.82.0 - September 3, 2012</b></p> <ul> <li>Updated to <a href="http://www.sqlite.org/releaselog/3_7_14.html">SQLite 3.7.14</a>.</li> <li>Properly handle quoted data source values in the connection string. Fix for <a href="http://system.data.sqlite.org/index.html/info/8c3bee31c8">[8c3bee31c8]</a>.</li> <li>The <a href="http://nuget.org/packages/System.Data.SQLite">primary NuGet package</a> now supports x86 / x64 and the .NET Framework 2.0 / 4.0 (i.e. in a single package).</li> |
︙ | ︙ |
Changes to Doc/Extra/welcome.html.
︙ | ︙ | |||
156 157 158 159 160 161 162 | <font color="red"> Itanium processor support not currently included. </font> </p> <h1 class="heading">Distributing the Binaries (Compact Framework)</h1> <p>Both the <b>System.Data.SQLite.DLL </b>and <b>SQLite.Interop.XXX.DLL</b> files must be deployed on the Compact Framework. The XXX is the build number of | | | 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 | <font color="red"> Itanium processor support not currently included. </font> </p> <h1 class="heading">Distributing the Binaries (Compact Framework)</h1> <p>Both the <b>System.Data.SQLite.DLL </b>and <b>SQLite.Interop.XXX.DLL</b> files must be deployed on the Compact Framework. The XXX is the build number of the System.Data.SQLite library (e.g. "083"). The <b>SQLite.Interop.XXX.DLL</b> file is a fully native assembly compiled for the ARM processor, and System.Data.SQLite is the fully-managed Compact Framework assembly.</p> <hr /> <div id="footer"> <p> <a href="mailto:sqlite-users@sqlite.org?subject=SQLite.NET%20Class%20Library%20Documentation%20Feedback:%20Welcome"> |
︙ | ︙ |
Changes to Doc/SQLite.NET.chm.
cannot compute difference between binary files
Changes to Externals/Eagle/bin/Eagle.dll.
cannot compute difference between binary files
Changes to Externals/Eagle/bin/EagleShell.exe.
cannot compute difference between binary files
Changes to Externals/Eagle/bin/EagleShell.exe.mda.config.
︙ | ︙ | |||
9 10 11 12 13 14 15 | * this file, and for a DISCLAIMER OF ALL WARRANTIES. * * RCS: @(#) $Id: $ * --> <mdaConfig xmlns="http://schemas.microsoft.com/CLR/2004/10/mda"> <assistants> | | < | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | * this file, and for a DISCLAIMER OF ALL WARRANTIES. * * RCS: @(#) $Id: $ * --> <mdaConfig xmlns="http://schemas.microsoft.com/CLR/2004/10/mda"> <assistants> <!-- <bindingFailure /> <callbackOnCollectedDelegate listSize="50" /> <contextSwitchDeadlock enable="true" /> <dangerousThreadingAPI /> <dateTimeInvalidLocalFormat /> <dirtyCastAndCallOnInterface /> <disconnectedContext enable="true" /> |
︙ | ︙ | |||
61 62 63 64 65 66 67 | <overlappedFreeError /> <pInvokeLog> <filter> <match dllName="advapi32.dll" /> <match dllName="advpack.dll" /> <match dllName="kernel32.dll" /> <match dllName="mscoree.dll" /> | < | | 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 | <overlappedFreeError /> <pInvokeLog> <filter> <match dllName="advapi32.dll" /> <match dllName="advpack.dll" /> <match dllName="kernel32.dll" /> <match dllName="mscoree.dll" /> <match dllName="ntdll.dll" /> <match dllName="shell32.dll" /> <match dllName="user32.dll" /> <match dllName="wintrust.dll" /> </filter> </pInvokeLog> <pInvokeStackImbalance /> <raceOnRCWCleanup /> <reentrancy /> <releaseHandleFailed /> <reportAvOnComRelease allowAv="true" /> <streamWriterBufferedDataLost /> <virtualCERCall /> --> </assistants> </mdaConfig> |
Changes to Externals/Eagle/lib/Eagle1.0/init.eagle.
︙ | ︙ | |||
139 140 141 142 143 144 145 | set result ""; eval append result $args } proc lappendArgs { args } { # # NOTE: This should work properly in both Tcl and Eagle. # | | | 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 | set result ""; eval append result $args } proc lappendArgs { args } { # # NOTE: This should work properly in both Tcl and Eagle. # eval lappend result $args } proc getDictionaryValue { dictionary name {default ""} {wrap ""} } { # # NOTE: Locate the named value we are interested in. The dictionary must # be a list with an even number of elements in the following format: # |
︙ | ︙ | |||
635 636 637 638 639 640 641 | } if {[llength $args] > 0} then {eval lappend command $args} return [uplevel 1 $command] } | < < < < < < < < < < < < < < < < < < | 635 636 637 638 639 640 641 642 643 644 645 646 647 648 | } if {[llength $args] > 0} then {eval lappend command $args} return [uplevel 1 $command] } proc ldifference { list1 list2 } { set result [list] foreach element $list1 { if {[lsearch -exact $list2 $element] == -1} then { lappend result $element } |
︙ | ︙ | |||
994 995 996 997 998 999 1000 | # therefore, dispose it now. # unset errors; # dispose return $code } | < < < < < | 976 977 978 979 980 981 982 983 984 985 986 987 988 989 | # therefore, dispose it now. # unset errors; # dispose return $code } proc matchEngineName { name } { return [expr {[string length $name] == 0 || \ $name eq [info engine Name]}] } proc matchEngineCulture { culture } { return [expr {[string length $culture] == 0 || \ |
︙ | ︙ | |||
1061 1062 1063 1064 1065 1066 1067 | set components [list $baseUri releases $patchLevel] # # NOTE: Next, figure out what type of download is being # requested. # switch -exact -nocase -- $type { | | > > > > > > > > > > > | < | > | | | | > | < > > > | | > > > > > | | | 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 | set components [list $baseUri releases $patchLevel] # # NOTE: Next, figure out what type of download is being # requested. # switch -exact -nocase -- $type { source { # # NOTE: Source code download. This may be a RAR or an EXE # file. Append the appropriate file name and then # join all the URI components to form the final URI. # set fileName [appendArgs EagleSource $patchLevel $extension] lappend components $fileName set result [list [eval uri join $components] \ [file join $directory $fileName]] } setup { # # NOTE: Windows setup download. Always append an ".exe" # extension because we never distribute the setup as # a RAR file. Append the appropriate file name and # then join all the URI components to form the final # URI. # set fileName [appendArgs EagleSetup $patchLevel .exe] lappend components $fileName set result [list [eval uri join $components] \ [file join $directory $fileName]] } binary { # # NOTE: Binary file download. This may be a RAR or an EXE # file. Append the appropriate file name and then # join all the URI components to form the final URI. # set fileName [appendArgs EagleBinary $patchLevel $extension] lappend components $fileName set result [list [eval uri join $components] \ [file join $directory $fileName]] } } } } } } |
︙ | ︙ | |||
1252 1253 1254 1255 1256 1257 1258 | # make sure we get the same "flavor" of the engine. # The lines are organized so that the "latest stable # version" is on the first line (for a given public key # token), followed by development builds, experimental # builds, etc. # if {$protocolId eq "1" && \ | | | 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 | # make sure we get the same "flavor" of the engine. # The lines are organized so that the "latest stable # version" is on the first line (for a given public key # token), followed by development builds, experimental # builds, etc. # if {$protocolId eq "1" && \ $publicKeyToken eq [info engine PublicKeyToken] && \ [matchEngineName $name] && \ [matchEngineCulture $culture]} then { # # NOTE: Grab the patch level field. # set patchLevel [lindex $fields 4] |
︙ | ︙ | |||
1441 1442 1443 1444 1445 1446 1447 | # # 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 { | | | | | | 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 | # # HACK: Mono does not currently support calling the String.Format # overload that takes a variable number of arguments via # reflection (Mono bug #636939). # if {![isMono]} then { set line [string format -verbatim -- "{0,-$maxLength} = {1}" \ $nameString $valueString] } else { set line [object invoke String Format "{0,-$maxLength} = {1}" \ $nameString $valueString] } puts stdout $line } } proc pdict { d } { |
︙ | ︙ | |||
1552 1553 1554 1555 1556 1557 1558 | proc tclLog { string } { # # NOTE: This should work properly in both Tcl and Eagle. # catch {puts stderr $string} } | | < | < | > > > | | | | < < | < > | | < < < < | | < < < < < | | | < < < < < < < < < < < < < < < < < < < < | < < < < < < | | | | | | < < < < < < < | < < < < < < | | | | | | | 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 | proc tclLog { string } { # # NOTE: This should work properly in both Tcl and Eagle. # catch {puts stderr $string} } proc findDirectories { pattern } { # # NOTE: This should work properly in Eagle only. # set result [list] foreach dir [split [exec $::env(ComSpec) /c dir /ad /b \ [appendArgs \" [file nativename $pattern] \"]] \n] { set dir [string trim $dir] if {[string length $dir] > 0} then { set dir [getDirResultPath $pattern $dir] if {[lsearch -exact -nocase $result $dir] == -1} then { lappend result $dir } } } foreach dir [split [exec $::env(ComSpec) /c dir /ahd /b \ [appendArgs \" [file nativename $pattern] \"]] \n] { set dir [string trim $dir] if {[string length $dir] > 0} then { set dir [getDirResultPath $pattern $dir] if {[lsearch -exact -nocase $result $dir] == -1} then { lappend result $dir } } } return $result } proc findFiles { pattern } { # # NOTE: This should work properly in Eagle only. # set result [list] foreach fileName [split [exec $::env(ComSpec) /c dir /a-d /b \ [appendArgs \" [file nativename $pattern] \"]] \n] { set fileName [string trim $fileName] if {[string length $fileName] > 0} then { set fileName [getDirResultPath $pattern $fileName] if {[lsearch -exact -nocase $result $fileName] == -1} then { lappend result $fileName } } } foreach fileName [split [exec $::env(ComSpec) /c dir /ah-d /b \ [appendArgs \" [file nativename $pattern] \"]] \n] { set fileName [string trim $fileName] if {[string length $fileName] > 0} then { set fileName [getDirResultPath $pattern $fileName] if {[lsearch -exact -nocase $result $fileName] == -1} then { lappend result $fileName } } } return $result } proc findFilesRecursive { pattern } { # # NOTE: This should work properly in Eagle only. # set result [list] foreach fileName [split [exec $::env(ComSpec) /c dir /a-d /s /b \ [appendArgs \" [file nativename $pattern] \"]] \n] { set fileName [string trim $fileName] if {[string length $fileName] > 0} then { set fileName [getDirResultPath $pattern $fileName] if {[lsearch -exact -nocase $result $fileName] == -1} then { lappend result $fileName } } } foreach fileName [split [exec $::env(ComSpec) /c dir /ah-d /s /b \ [appendArgs \" [file nativename $pattern] \"]] \n] { set fileName [string trim $fileName] if {[string length $fileName] > 0} then { set fileName [getDirResultPath $pattern $fileName] if {[lsearch -exact -nocase $result $fileName] == -1} then { lappend result $fileName } } } return $result } |
︙ | ︙ | |||
1755 1756 1757 1758 1759 1760 1761 | eval lappend result [glob -nocomplain -types {f hidden} \ [file normalize $pattern]] return $result } proc findFilesRecursive { pattern } { | < < < < < < < | 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 | eval lappend result [glob -nocomplain -types {f hidden} \ [file normalize $pattern]] return $result } proc findFilesRecursive { pattern } { # # NOTE: This should work properly in Tcl only. # set result [list] catch { foreach fileName [split [exec $::env(ComSpec) /c dir /a-d /s /b \ |
︙ | ︙ | |||
1849 1850 1851 1852 1853 1854 1855 | } # # NOTE: Exports the necessary commands from this package and import them # into the global namespace. # exportAndImportPackageCommands [namespace current] [list \ | | < | < < < | < | | 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 | } # # NOTE: Exports the necessary commands from this package and import them # into the global namespace. # exportAndImportPackageCommands [namespace current] [list \ exportAndImportPackageCommands isEagle isMono getEnvironmentVariable \ getPluginPath getDictionaryValue getColumnValue getRowColumnValue \ appendArgs haveGaruda lappendArgs readFile filter map reduce \ getPlatformInfo execShell combineFlags tqputs tqlog] false false ########################################################################### ############################## END Tcl ONLY ############################### ########################################################################### } # # NOTE: Provide the Eagle library package to the interpreter. # package provide Eagle.Library \ [expr {[isEagle] ? [info engine PatchLevel] : "1.0"}] } |
Changes to Externals/Eagle/lib/Eagle1.0/safe.eagle.
︙ | ︙ | |||
71 72 73 74 75 76 77 | return } ########################################################################### ############################# END Eagle ONLY ############################## ########################################################################### } | | | 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 | return } ########################################################################### ############################# END Eagle ONLY ############################## ########################################################################### } # # NOTE: Provide the Eagle "safe" package to the interpreter. # package provide Eagle.Safe \ [expr {[isEagle] ? [info engine PatchLevel] : "1.0"}] } |
Changes to Externals/Eagle/lib/Eagle1.0/shell.eagle.
︙ | ︙ | |||
43 44 45 46 47 48 49 | # environment should be placed here. # ########################################################################### ############################## END Tcl ONLY ############################### ########################################################################### } | | | 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | # environment should be placed here. # ########################################################################### ############################## END Tcl ONLY ############################### ########################################################################### } # # NOTE: Provide the Eagle shell package to the interpreter. # package provide Eagle.Shell \ [expr {[isEagle] ? [info engine PatchLevel] : "1.0"}] } |
Changes to Externals/Eagle/lib/Eagle1.0/test.eagle.
︙ | ︙ | |||
295 296 297 298 299 300 301 | # # NOTE: Calculate how many whole seconds we need to spin for. # set seconds [expr {$milliseconds / 1000}] # | | | | | 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 | # # NOTE: Calculate how many whole seconds we need to spin for. # set seconds [expr {$milliseconds / 1000}] # # NOTE: Calculate the value of [clock seconds] now and at the stop time. # set start [clock seconds]; set stop [expr {$start + $seconds}] # # NOTE: Do nothing for X seconds (i.e. except call [clock seconds]). # while {$start <= [clock seconds] && [clock seconds] < $stop} {} # # NOTE: Record the final Tcl command count. # set after [info cmdcount] # |
︙ | ︙ | |||
384 385 386 387 388 389 390 | # upvar 1 $varName array # # TODO: Add more support for standard tcltest options here. # set options [list -configuration -constraints -exitOnComplete -file \ | | | | 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 | # upvar 1 $varName array # # TODO: Add more support for standard tcltest options here. # set options [list -configuration -constraints -exitOnComplete -file \ -logFile -match -no -notFile -postTest -preTest -skip -stopOnFailure \ -suffix -threshold] foreach {name value} $args { # # NOTE: Use the [tqputs] command here just in case the test log file # has not been setup yet (i.e. by default, this procedure is # almost always called by the test prologue file prior to the # test log file having been setup and we do not want to just |
︙ | ︙ | |||
414 415 416 417 418 419 420 | # # NOTE: Now, attempt to flush the test log queue, if available. # tlog "" } | < < < < < < < < < < < < < < < < < < < < < < < < < < < | 414 415 416 417 418 419 420 421 422 423 424 425 426 427 | # # NOTE: Now, attempt to flush the test log queue, if available. # tlog "" } proc getTemporaryPath {} { # # NOTE: Build the list of "temporary directory" override # environment variables to check. # set names [list] |
︙ | ︙ | |||
486 487 488 489 490 491 492 | # return [file normalize [file dirname [info nameofexecutable]]] } } proc getFiles { directory pattern } { if {[isEagle]} then { | < < | < < < < < < | | 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 | # return [file normalize [file dirname [info nameofexecutable]]] } } proc getFiles { directory pattern } { if {[isEagle]} then { return [lsort -dictionary [file list $directory $pattern]] } else { return [lsort -dictionary [glob -directory $directory -types \ {b c f p s} -nocomplain -- $pattern]] } } proc getTestFiles { directories matchFilePatterns skipFilePatterns } { set result [list] foreach directory $directories { |
︙ | ︙ | |||
602 603 604 605 606 607 608 | [append result . $::test_log_id] : ""}] } proc getTestLog {} { return [expr {[info exists ::test_log] ? $::test_log : ""}] } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 567 568 569 570 571 572 573 574 575 576 577 578 579 580 | [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 |
︙ | ︙ | |||
815 816 817 818 819 820 821 | "---- running nested shell: exec " \ [string trim [appendArgs $options " " -- " \"" \ [info nameofexecutable] "\" " $args]] \n] return [uplevel 1 execShell [list $options] $args] } | < < < < < < | 614 615 616 617 618 619 620 621 622 623 624 625 626 627 | "---- running nested shell: exec " \ [string trim [appendArgs $options " " -- " \"" \ [info nameofexecutable] "\" " $args]] \n] return [uplevel 1 execShell [list $options] $args] } proc isStopOnFailure {} { return [expr {[info exists ::test_stop_on_failure] && \ [string is boolean -strict $::test_stop_on_failure] && \ $::test_stop_on_failure}] } proc isExitOnComplete {} { |
︙ | ︙ | |||
882 883 884 885 886 887 888 | # proc [namespace current]::testPuts { args } { switch [llength $args] { 1 { # # NOTE: Only the string to be printed is specified (stdout). # | | | 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 | # proc [namespace current]::testPuts { args } { switch [llength $args] { 1 { # # NOTE: Only the string to be printed is specified (stdout). # return [tputs $::test_channel [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]] |
︙ | ︙ | |||
1120 1121 1122 1123 1124 1125 1126 | # # NOTE: Show what leaked, if anything. # set count 0; upvar 1 $statsVarName array foreach statistic $statistics { if {$array($statistic,after) > $array($statistic,before)} then { | | | | | 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 | # # 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. |
︙ | ︙ | |||
1286 1287 1288 1289 1290 1291 1292 | tputs $channel [appendArgs $status \n] if {[isEagle]} then { host title $status } } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | | 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 | 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 |
︙ | ︙ | |||
1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 | } # # NOTE: We evaluated another test file. # incr count # # NOTE: Record failed test count after this file. # if {[isEagle]} then { set after $::eagle_tests(failed) } else { set after $::tcltest::numTests(Failed) } # # NOTE: Did this file have any failing tests? # if {$after > $before} then { lappend failed [file tail $fileName] } | > > > > > > > > > > > > > < < < < < < < < < < < < < | 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 | } # # NOTE: We evaluated another test file. # incr count # # NOTE: In terms of files, not tests, what percent done are we now? # set percent [formatDecimal \ [expr {$total != 0 ? 100.0 * ($count / double($total)) : 100}]] if {$percent != $lastPercent} then { reportTestPercent $channel $percent \ [llength $failed] [llength $leaked] set lastPercent $percent } # # NOTE: Record failed test count after this file. # if {[isEagle]} then { set after $::eagle_tests(failed) } else { set after $::tcltest::numTests(Failed) } # # NOTE: Did this file have any failing tests? # if {$after > $before} then { lappend failed [file tail $fileName] } # # NOTE: Unset the current test file name, it is no longer # needed. # unset -nocomplain ::test_file # |
︙ | ︙ | |||
1536 1537 1538 1539 1540 1541 1542 | # # NOTE: Determine if any resource leaks have occurred and # output diagnostics as necessary if they have. # reportTestStatistics $channel $fileName leaks leaked } } else { | < < < < < < | 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 | # # NOTE: Determine if any resource leaks have occurred and # output diagnostics as necessary if they have. # reportTestStatistics $channel $fileName leaks leaked } } else { # # NOTE: This file does not actually count towards the total (i.e. # it contains no actual tests). # incr total -1 } |
︙ | ︙ | |||
1571 1572 1573 1574 1575 1576 1577 | # test failure with the stop-on-failure flag enabled), # break out of the test loop now. # if {$stop} then { break } } else { | < < < < < < | 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 | # test failure with the stop-on-failure flag enabled), # break out of the test loop now. # if {$stop} then { break } } else { # # NOTE: This file does not actually count towards the total (i.e. # it is part of the test suite infrastructure). # incr total -1 } |
︙ | ︙ | |||
1611 1612 1613 1614 1615 1616 1617 | 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 { | | < | < < < | 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 | 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 { constraints imports force } { if {[isEagle]} then { # # HACK: Flag the "test" and "runTest" script library procedures so # that they use the script location of their caller and not |
︙ | ︙ | |||
1976 1977 1978 1979 1980 1981 1982 | # type for the native Tcl shell. # catch {file delete $fileName} } } } | < < < < < < | > | | > > > | | > > > | | | > > > > | 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 | # type for the native Tcl shell. # catch {file delete $fileName} } } } proc getMachineForTclShell {} { return [testExecTclScript { puts -nonewline stdout $tcl_platform(machine) }] } proc getTkVersion {} { return [testExecTclScript { puts -nonewline stdout [package require Tk]; exit }] } 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 |
︙ | ︙ | |||
2218 2219 2220 2221 2222 2223 2224 | configureTcltest [list] [list test testConstraint] false } # # NOTE: We need several of our test related commands in the global # namespace as well. # | | < < | | | < < > | < < | < > | | | 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 | configureTcltest [list] [list test testConstraint] false } # # NOTE: We need several of our test related commands in the global # namespace as well. # exportAndImportPackageCommands [namespace current] [list addConstraint \ calculateRelativePerformance haveConstraint haveOrAddConstraint \ processTestArguments getTemporaryPath getTestLog getTestLogId getFiles \ getConstraints getTestFiles getTestRunId execTestShell runTestPrologue \ runTestEpilogue runTest runAllTests fixConstraints sourceIfValid \ isExitOnComplete getPassPercentage getSkipPercentage testExec tlog \ returnInfoScript tputs formatDecimal formatList configureTcltest \ calculateBogoCops removeConstraint machineToPlatform tsource testShim] \ false false ########################################################################### ############################## END Tcl ONLY ############################### ########################################################################### } # # NOTE: Provide the Eagle test package to the interpreter. # package provide Eagle.Test \ [expr {[isEagle] ? [info engine PatchLevel] : "1.0"}] } |
Changes to Externals/Eagle/lib/Eagle1.0/vendor.eagle.
︙ | ︙ | |||
40 41 42 43 44 45 46 | if {![uplevel 1 [list info exists $varName]]} then { continue } incr result if {!$quiet} then { | < | | < < | 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | if {![uplevel 1 [list info exists $varName]]} then { continue } incr result if {!$quiet} then { tqputs $channel [appendArgs \ "---- found vendor-specific test override \"" $varName "\".\n"] } } # # NOTE: Keep track of the list of test override variables, for later # use by the test suite. This needs to be done after the loop # above because the variable used to keep track is listed with |
︙ | ︙ | |||
108 109 110 111 112 113 114 | # if {![info exists ::env(EAGLELIBPATH)] || \ [lsearch -exact $::env(EAGLELIBPATH) $dir2] == -1} then { # # NOTE: If we have NOT been instructed to be quiet, report now. # if {!$quiet} then { | < | | | < | 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 | # if {![info exists ::env(EAGLELIBPATH)] || \ [lsearch -exact $::env(EAGLELIBPATH) $dir2] == -1} then { # # NOTE: If we have NOT been instructed to be quiet, report now. # if {!$quiet} then { tqputs $channel [appendArgs \ "---- found vendor-specific test package directory \"" \ $dir2 "\", adding...\n"] } # # NOTE: Append the directory to the necessary environment variable # so that it will get picked up when Eagle actually rebuilds # the auto-path list (below). # |
︙ | ︙ | |||
145 146 147 148 149 150 151 | set dir [file dirname $dir] } # # NOTE: If we have NOT been instructed to be quiet, report now. # if {!$quiet} then { | < | | < < | | < | < | < < < < < < < | 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 | set dir [file dirname $dir] } # # NOTE: If we have NOT been instructed to be quiet, report now. # if {!$quiet} then { tqputs $channel \ "---- could not find vendor-specific test package directory.\n" } # # NOTE: Directory not found, return failure. # return false } proc setupInterpreterTestPath { channel dir quiet } { set testPath [object invoke -flags +NonPublic Interpreter.GetActive \ TestPath] if {$dir ne $testPath} then { object invoke -flags +NonPublic Interpreter.GetActive TestPath $dir if {!$quiet} then { tqputs $channel [appendArgs \ "---- set interpreter test path to \"" $dir \".\n] } } } # # NOTE: Check for any overridden settings that may have been specified via # the command line, etc. # checkForTestOverrides stdout [expr {[info exists test_overrides] ? \ $test_overrides : [list binary_directory build_base_directory \ build_directory common_directory connection_flags database_directory \ datetime_format scratch_directory temporary_directory \ test_configuration test_overrides test_year test_year_clr_v2 \ test_year_clr_v4 vendor_directory]}] false # # NOTE: This variable will contain the name of the directory containing the # vendor-specific testing infrastructure. If the variable does not # already exist, create it; otherwise, it has been overridden and the # existing value should be left intact. # |
︙ | ︙ |
Changes to Externals/Eagle/lib/Test1.0/constraints.eagle.
︙ | ︙ | |||
16 17 18 19 20 21 22 | # # 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 { | < < < < < < < < < < < | < < | | | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 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 | # # NOTE: Use our own namespace here because even though we do not directly # support namespaces ourselves, we do not want to pollute the global # namespace if this script actually ends up being evaluated in Tcl. # namespace eval ::Eagle { proc checkForPlatform { channel } { tputs $channel "---- checking for platform... " if {[info exists ::tcl_platform(platform)]} then { addConstraint $::tcl_platform(platform) tputs $channel [appendArgs $::tcl_platform(platform) \n] } else { tputs $channel [appendArgs unknown \n] } ########################################################################### if {![isEagle]} then { # # BUGFIX: We do not normally want to skip any Mono bugs in native Tcl. # if {![info exists ::no(runtimeVersion)]} then { set constraints [list monoToDo monoBug monoCrash] # # NOTE: Add the necessary constraints for each version of Mono that # we know about. # foreach version [list 20 22 24 26 28 210 211 212 30] { addConstraint [appendArgs monoToDo $version] addConstraint [appendArgs monoBug $version] addConstraint [appendArgs monoCrash $version] } # # NOTE: Also add just the generic Mono constraints that do not have # a trailing version. # foreach constraint $constraints { addConstraint $constraint } } } } proc checkForVariable { channel name {notEmpty true} {constraint ""} } { tputs $channel [appendArgs "---- checking for variable \"" $name \ "\"... "] # # NOTE: First, normalize the variable name to be in the global scope. # |
︙ | ︙ | |||
650 651 652 653 654 655 656 | tputs $channel yes\n } else { tputs $channel no\n } } | < < < < < < < < < < < < < < < < < < < < < < < < < < | < < < < < < < < < < < | < < | 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 | tputs $channel yes\n } else { tputs $channel no\n } } proc checkForTestConfiguration { channel } { tputs $channel [appendArgs "---- checking for test configuration... "] if {[info exists ::test_configuration] && \ [string length $::test_configuration] > 0} then { addConstraint [appendArgs configuration. $::test_configuration] tputs $channel [appendArgs $::test_configuration \n] } else { tputs $channel [appendArgs unknown \n] } } proc checkForFile { channel name {constraint ""} } { tputs $channel [appendArgs "---- checking for file \"" $name \ "\"... "] |
︙ | ︙ | |||
914 915 916 917 918 919 920 | tputs $channel yes\n } else { tputs $channel no\n } } | < < < < < < < < < < < < < < < < < | 772 773 774 775 776 777 778 779 780 781 782 783 784 785 | tputs $channel yes\n } else { tputs $channel no\n } } proc checkForTiming { channel threshold {constraint ""} {tries 1} {delay 1000} {asynchronous false} } { tputs $channel [appendArgs \ "---- checking for precision timing (threshold of " $threshold \ " milliseconds, delay of " $delay " milliseconds)... "] |
︙ | ︙ | |||
1023 1024 1025 1026 1027 1028 1029 | tputs $channel yes\n } else { tputs $channel no\n } } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 | tputs $channel yes\n } else { tputs $channel no\n } } proc 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". |
︙ | ︙ | |||
1213 1214 1215 1216 1217 1218 1219 | tputs $channel trusted\n } else { tputs $channel untrusted\n } } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 | tputs $channel trusted\n } else { tputs $channel untrusted\n } } proc checkForStrongName { channel } { tputs $channel "---- checking for strong name... " if {[catch {object invoke Interpreter.GetActive GetStrongName} \ strongName] == 0 && \ [string length $strongName] > 0} then { # |
︙ | ︙ | |||
1480 1481 1482 1483 1484 1485 1486 | tputs $channel [appendArgs $::eagle_platform(imageRuntimeVersion) \ " " ( $dotVersion ) \n] } else { tputs $channel no\n } } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < > | > > > > | | > | | < | > > > | > | | | < | > | | | > | | > | > | > | | > > | > | < > > > > | > > > | > > | | | | > | | | > > > > > | | | < < > > > > > > > | > > | | > > > | | | | < < < < < | < < | | | | 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 | tputs $channel [appendArgs $::eagle_platform(imageRuntimeVersion) \ " " ( $dotVersion ) \n] } else { tputs $channel no\n } } proc checkForRuntimeVersion { channel } { tputs $channel "---- checking for runtime version... " if {[info exists ::eagle_platform(runtimeVersion)] && \ [string length $::eagle_platform(runtimeVersion)] > 0} then { # # NOTE: Get the major and minor portions of the version only. # set dotVersion [join [lrange [split \ $::eagle_platform(runtimeVersion) .] 0 1] .] # # NOTE: Now create a version string for use in the constraint name # (remove the periods). # set version [string map [list . ""] $dotVersion] if {[isMono]} then { if {[string length $version] > 0} then { # # NOTE: We are running on Mono. Keep track of the specific # version for usage in test constraints. # addConstraint [appendArgs mono $version] } if {[string length $dotVersion] > 0 && \ [regexp -- {^(\d+)\.(\d+)$} $dotVersion dummy \ majorVersion minorVersion]} then { set monoVersions [list] # # NOTE: Check for any Mono version 2.x or higher. # if {$majorVersion >= 2} then { # # NOTE: Check for any Mono version higher than 2.0. # if {$majorVersion > 2 || $minorVersion > 0} then { lappend monoVersions 20 } # # NOTE: Check for any Mono version higher than 2.2. # if {$majorVersion > 2 || $minorVersion > 2} then { lappend monoVersions 22 } # # NOTE: Check for any Mono version higher than 2.4. # if {$majorVersion > 2 || $minorVersion > 4} then { lappend monoVersions 24 } # # NOTE: Check for any Mono version higher than 2.6. # if {$majorVersion > 2 || $minorVersion > 6} then { lappend monoVersions 26 } # # NOTE: Check for any Mono version higher than 2.8. # if {$majorVersion > 2 || $minorVersion > 8} then { lappend monoVersions 28 } # # NOTE: Check for any Mono version higher than 2.10. # if {$majorVersion > 2 || $minorVersion > 10} then { lappend monoVersions 210 } # # NOTE: Check for any Mono version higher than 2.11. # if {$majorVersion > 2 || $minorVersion > 11} then { lappend monoVersions 211 } # # NOTE: Check for any Mono version higher than 2.12. # if {$majorVersion > 2 || $minorVersion > 12} then { lappend monoVersions 212 } } # # NOTE: Check for any Mono version 3.x or higher. # if {$majorVersion >= 3} then { # # NOTE: Check for any Mono version higher than 3.0. # if {$majorVersion > 3 || $minorVersion > 0} then { lappend monoVersions 30 } } # # NOTE: Add the necessary constraints for each version of Mono we # should NOT skip bugs for. # foreach monoVersion $monoVersions { addConstraint [appendArgs monoToDo $monoVersion] addConstraint [appendArgs monoBug $monoVersion] addConstraint [appendArgs monoCrash $monoVersion] } } } else { if {[string length $version] > 0} then { # # NOTE: We are running on the .NET Framework. Keep track of the # specific version for usage in test constraints. # addConstraint [appendArgs dotNet $version] } # # NOTE: We do not want to skip any Mono bugs on .NET. Add the # necessary constraints for each version of Mono we know # about. # foreach monoVersion [list 20 22 24 26 28 210 211 212 30] { addConstraint [appendArgs monoToDo $monoVersion] addConstraint [appendArgs monoBug $monoVersion] addConstraint [appendArgs monoCrash $monoVersion] } } tputs $channel [appendArgs $::eagle_platform(runtimeVersion) \ " " ( $dotVersion ) \n] } else { tputs $channel no\n |
︙ | ︙ | |||
1857 1858 1859 1860 1861 1862 1863 | tputs $channel yes\n } else { tputs $channel no\n } } | | | | < < < < < < < < | 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 | 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 |
︙ | ︙ | |||
2158 2159 2160 2161 2162 2163 2164 | # set key [appendArgs HKEY_LOCAL_MACHINE\\ \ [getSoftwareRegistryKey true] {\Microsoft\Windows Installer XML}] # # NOTE: The versions of WiX that we support. # | | | 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 | # set key [appendArgs HKEY_LOCAL_MACHINE\\ \ [getSoftwareRegistryKey true] {\Microsoft\Windows Installer XML}] # # NOTE: The versions of WiX that we support. # set versions [list 3.6 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 |
︙ | ︙ | |||
2223 2224 2225 2226 2227 2228 2229 | # addConstraint wix # # NOTE: Save the directory for later usage by # the test itself. # | < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 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 | # addConstraint wix # # NOTE: Save the directory for later usage by # the test itself. # set ::test_wix $directory # # NOTE: Show where we found it. # tputs $channel [appendArgs "yes (" $version ", via " $where ", \"" \ $directory "\")\n"] # # NOTE: We are done here, return now. # return } } tputs $channel no\n } proc checkForNetFx45 { channel } { tputs $channel "---- checking for .NET Framework 4.5... " # # NOTE: Platform must be Windows for this constraint to even be # checked (i.e. we require the registry). # |
︙ | ︙ | |||
2372 2373 2374 2375 2376 2377 2378 | # lappend visualStudioVersions [lindex $version 1] # # NOTE: Save the directory for later usage by # the test itself. # | < | < | 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 | # lappend visualStudioVersions [lindex $version 1] # # NOTE: Save the directory for later usage by # the test itself. # set ::test_visual_studio [file dirname $fileName] } } } if {[llength $visualStudioVersions] > 0} then { # # NOTE: Show where we found the latest version. |
︙ | ︙ | |||
2497 2498 2499 2500 2501 2502 2503 | ############################# BEGIN Tcl ONLY ############################## ########################################################################### # # NOTE: We need several of our test constraint related commands in the # global namespace. # | | < < < | | < < | < | > > | | 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 | ############################# 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 \ checkForWindowsCommandProcessor checkForUserInteraction \ checkForTclOptions checkForTestConfiguration checkForVariable \ checkForFossil] false false ########################################################################### ############################## END Tcl ONLY ############################### ########################################################################### } # # NOTE: Provide the Eagle test constraints package to the interpreter. # package provide Eagle.Test.Constraints \ [expr {[isEagle] ? [info engine PatchLevel] : "1.0"}] } |
Changes to Externals/Eagle/lib/Test1.0/epilogue.eagle.
︙ | ︙ | |||
156 157 158 159 160 161 162 | # set passedOrSkipped [expr {$eagle_tests(passed) + \ $eagle_tests(skipped)}] if {$passedOrSkipped == $eagle_tests(total)} then { set exitCode Success | < | < < < < | | < < < < | 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 | # set passedOrSkipped [expr {$eagle_tests(passed) + \ $eagle_tests(skipped)}] if {$passedOrSkipped == $eagle_tests(total)} then { set exitCode Success tresult Ok "OVERALL RESULT: SUCCESS\n" } else { set exitCode Failure tresult Error "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 tresult Ok [appendArgs \ "OVERALL RESULT: SUCCESS (" $percent "% >= " $test_threshold %)\n] } else { set exitCode Failure tresult Error [appendArgs \ "OVERALL RESULT: FAILURE (" $percent "% < " $test_threshold %)\n] } } |
︙ | ︙ | |||
256 257 258 259 260 261 262 | # set passedOrSkipped [expr {$::tcltest::numTests(Passed) + \ $::tcltest::numTests(Skipped)}] if {$passedOrSkipped == $::tcltest::numTests(Total)} then { set exitCode 0; # Success. | < | < < < < | | < < < < | 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 | # 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] } } |
︙ | ︙ |
Changes to Externals/Eagle/lib/Test1.0/prologue.eagle.
︙ | ︙ | |||
18 19 20 21 22 23 24 | if {[info level] > 0} then { error "cannot run, current level is not global" } # # NOTE: Make sure all the variables used by this prologue are unset. # | | | | | 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | if {[info level] > 0} then { error "cannot run, current level is not global" } # # NOTE: Make sure all the variables used by this prologue are unset. # unset -nocomplain pkg_dir pattern exec dummy directory name value \ expr publicKeyToken encoding memory stack drive server database \ timeout user password percent checkout timeStamp # # 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]]] } |
︙ | ︙ | |||
236 237 238 239 240 241 242 | } ############################################################################# # # NOTE: If command line arguments were supplied, process them now. # | < < < < < | < < < < < < < < < | 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 | } ############################################################################# # # 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) |
︙ | ︙ | |||
336 337 338 339 340 341 342 | # # NOTE: Set the pre-test script to the one provided by the command line. # set test_script(post) $test_flags(-postTest) } } | < < < < < < < < < < < < < < < < < < < < < | | < < < < < < < < < < < | < < < < < < | 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 | # # NOTE: Set the pre-test script to the one provided by the command line. # set test_script(post) $test_flags(-postTest) } } # # NOTE: Set the default test configuration (i.e. Debug or Release), if # necessary. # if {![info exists test_configuration]} then { set test_configuration [getPlatformInfo configuration Release] } # # 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? |
︙ | ︙ | |||
472 473 474 475 476 477 478 | # tputs $test_channel [appendArgs "---- testRunId: " \ [getTestRunId] \n] tputs $test_channel [appendArgs "---- processId: " \ [pid] \n] | < < < < < < < < < < < < < < < < | < | 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 | # 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. |
︙ | ︙ | |||
589 590 591 592 593 594 595 | [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] | < < < < < | 520 521 522 523 524 525 526 527 528 529 530 531 532 533 | [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] && \ |
︙ | ︙ | |||
733 734 735 736 737 738 739 | # checking [nearly] first as it may skip other constraints. # if {![info exists no(runtime)]} then { checkForRuntime $test_channel } # | | | < < < < < < < < | | | 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 | # 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? |
︙ | ︙ | |||
839 840 841 842 843 844 845 | # NOTE: Set the test password, if necessary. # if {![info exists password]} then { set password [getEnvironmentVariable password] } # | < < < < < < < < < < | | | | | < < < < < < < < < | | | 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 | # 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? # |
︙ | ︙ | |||
956 957 958 959 960 961 962 | # # NOTE: For tests "debug-1.1", "debug-2.1", "debug-3.1" and # "debug-4.1". # checkForCompileOption $test_channel DEBUGGER } | < < < < < < < < < < < | 855 856 857 858 859 860 861 862 863 864 865 866 867 868 | # # NOTE: For tests "debug-1.1", "debug-2.1", "debug-3.1" and # "debug-4.1". # checkForCompileOption $test_channel DEBUGGER } # # NOTE: Has isolated interpreter support been enabled (at compile-time)? # if {![info exists no(compileIsolatedInterpreters)]} then { # # NOTE: For test "xaml-1.2". # |
︙ | ︙ | |||
1074 1075 1076 1077 1078 1079 1080 | # "tclResetCancel-2.2", "tclResetCancel-3.1", # "tclResetCancel-4.1", "tclSet-1.1", and "tclSubst-1.1". # checkForCompileOption $test_channel TCL } # | | | 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 | # "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 } |
︙ | ︙ | |||
1137 1138 1139 1140 1141 1142 1143 | if {![info exists no(compileTclThreads)]} then { # # NOTE: For tests "tclLoad-1.5" and "tclLoad-1.6". # checkForCompileOption $test_channel TCL_THREADS } | < < < < < < < < < < < < < < | 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 | if {![info exists no(compileTclThreads)]} then { # # NOTE: For tests "tclLoad-1.5" and "tclLoad-1.6". # checkForCompileOption $test_channel TCL_THREADS } # # NOTE: Has runtime license checking support been disabled (at # compile-time). This only applies to third-party plugins # and applications. # if {![info exists no(compileLicensing)]} then { # |
︙ | ︙ | |||
1275 1276 1277 1278 1279 1280 1281 | checkForObjectMember $test_channel Eagle._Tests.Default \ *TestAddNamedFunction* checkForObjectMember $test_channel Eagle._Tests.Default \ *TestRemoveNamedFunction* # | | < < < < < < | 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 | checkForObjectMember $test_channel Eagle._Tests.Default \ *TestAddNamedFunction* checkForObjectMember $test_channel Eagle._Tests.Default \ *TestRemoveNamedFunction* # # NOTE: For test "interp-1.18". # checkForObjectMember $test_channel Eagle._Tests.Default \ *TestAddNamedFunction2* } # # NOTE: Has write-box testing support been disabled? # if {![info exists no(testWriteBox)]} then { # |
︙ | ︙ | |||
1460 1461 1462 1463 1464 1465 1466 | # # NOTE: For test "object-4.1". # checkForObjectMember $test_channel Eagle._Tests.Default \ *TestExpr* | < < < < < < < < < | 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 | # # 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 \ |
︙ | ︙ | |||
1623 1624 1625 1626 1627 1628 1629 | if {![info exists no(netFx45)]} then { # # NOTE: For test "object-12.1.*". # checkForNetFx45 $test_channel } | < < < < < < < | 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 | if {![info exists no(netFx45)]} then { # # NOTE: For test "object-12.1.*". # checkForNetFx45 $test_channel } # # NOTE: Has Visual Studio testing support been disabled? # if {![info exists no(visualStudio)]} then { checkForVisualStudio $test_channel } |
︙ | ︙ | |||
1654 1655 1656 1657 1658 1659 1660 | # # NOTE: Has managed debugger testing support been disabled? # if {![info exists no(managedDebugger)]} then { checkForManagedDebugger $test_channel } | < < < < < < < < | 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 | # # NOTE: Has managed debugger testing support been disabled? # if {![info exists no(managedDebugger)]} then { checkForManagedDebugger $test_channel } # # NOTE: Has 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". |
︙ | ︙ | |||
1771 1772 1773 1774 1775 1776 1777 | ############################################################################# ####################### BEGIN Tcl & Eagle Constraints ####################### ############################################################################# tputs $test_channel [appendArgs \ "---- start of common (Tcl & Eagle) test constraints...\n"] | < < < < < < < < < < < < < < < < < < < < < | 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 | ############################################################################# ####################### BEGIN Tcl & Eagle Constraints ####################### ############################################################################# tputs $test_channel [appendArgs \ "---- start of common (Tcl & Eagle) test constraints...\n"] # # NOTE: Has checking for the test configuration been disabled? # if {![info exists no(testConfiguration)]} then { checkForTestConfiguration $test_channel } # # NOTE: Has checking for the extra files needed by various tests been # disabled? # if {![info exists no(checkForFile)]} then { # # NOTE: For test "package-1.0". |
︙ | ︙ | |||
1917 1918 1919 1920 1921 1922 1923 | # # NOTE: For tests "excel-2.*". # if {![info exists no(test.xls)]} then { checkForFile $test_channel [file join $test_path test.xls] } | < < < < < < < | 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 | # # NOTE: For tests "excel-2.*". # if {![info exists no(test.xls)]} then { checkForFile $test_channel [file join $test_path test.xls] } # # NOTE: For test "interp-1.10". # if {![info exists no(settings.xml)]} then { checkForFile $test_channel [file join $test_path settings.xml] } |
︙ | ︙ | |||
1977 1978 1979 1980 1981 1982 1983 | if {![info exists no(sqlite3.dll)]} then { checkForFile $test_channel [file join $bin_path sqlite3.dll] # # NOTE: Did we manage to find the native SQLite library? If not, do we # at least know the machine type? # | | > | | | 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 | if {![info exists no(sqlite3.dll)]} then { checkForFile $test_channel [file join $bin_path sqlite3.dll] # # NOTE: Did we manage to find the native SQLite library? If not, do we # at least know the machine type? # if {![haveConstraint file_sqlite3.dll] && \ [info exists tcl_platform(machine)]} then { # # NOTE: Ok, now try to check for the machine specific native SQLite # library. # checkForFile $test_channel [file join $bin_path [machineToPlatform \ $tcl_platform(machine) true] sqlite3.dll] # # NOTE: Did we manage to find the native SQLite library yet? # if {![haveConstraint file_sqlite3.dll]} then { # # NOTE: Ok, now try to check for the platform specific native SQLite # library. # checkForFile $test_channel [file join $bin_path [machineToPlatform \ $tcl_platform(machine) false] sqlite3.dll] } } } if {![info exists no(System.Data.SQLite.dll)]} then { checkForFile $test_channel [file join $bin_path System.Data.SQLite.dll] } |
︙ | ︙ | |||
2016 2017 2018 2019 2020 2021 2022 | # NOTE: Check the core test constraints unless they have been # explicitly disabled. # if {![info exists no(platform)]} then { checkForPlatform $test_channel } | < < < < < < < < < < < < | 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 | # NOTE: Check the core test constraints unless they have been # explicitly disabled. # if {![info exists no(platform)]} then { checkForPlatform $test_channel } if {![info exists no(tclOptions)]} then { checkForTclOptions $test_channel } if {![info exists no(windowsCommandProcessor)]} then { checkForWindowsCommandProcessor $test_channel cmd.exe } if {![info exists no(fossil)]} then { checkForFossil $test_channel } |
︙ | ︙ | |||
2133 2134 2135 2136 2137 2138 2139 | checkForTip241 $test_channel } if {![info exists no(tip285)]} then { checkForTip285 $test_channel } | < < < < | 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 | checkForTip241 $test_channel } if {![info exists no(tip285)]} then { checkForTip285 $test_channel } # # NOTE: Has performance testing been disabled? # if {![info exists no(performance)]} then { checkForPerformance $test_channel } |
︙ | ︙ | |||
2165 2166 2167 2168 2169 2170 2171 | # # NOTE: Has interactive testing been disabled? # if {![info exists no(interactive)]} then { checkForInteractive $test_channel } | < < < < < < < < < < < < < < < < < < < < | 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 | # # NOTE: Has interactive testing been disabled? # if {![info exists no(interactive)]} then { checkForInteractive $test_channel } if {![info exists no(userInteraction)]} then { checkForUserInteraction $test_channel } # # NOTE: Check for network connectivity to our test host (i.e. # the Eagle distribution site). |
︙ | ︙ | |||
2351 2352 2353 2354 2355 2356 2357 | [formatList [getPlatformInfo compileOptions <none>]] \n] tputs $test_channel [appendArgs "---- strongName: " \ [getPlatformInfo strongName <none>] \n] tputs $test_channel [appendArgs "---- certificate: " \ [getPlatformInfo certificate <none>] \n] | < < < | 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 | [formatList [getPlatformInfo compileOptions <none>]] \n] tputs $test_channel [appendArgs "---- strongName: " \ [getPlatformInfo strongName <none>] \n] tputs $test_channel [appendArgs "---- certificate: " \ [getPlatformInfo certificate <none>] \n] } # # NOTE: Show the current test file name, if any. # tputs $test_channel [appendArgs "---- test file: " \ [expr {[info exists test_file] && [string length $test_file] > 0 ? \ |
︙ | ︙ |
Added Externals/MSVCPP/vcredist_x64_2005_SP1.exe.
cannot compute difference between binary files
Deleted Externals/MSVCPP/vcredist_x64_2005_SP1_MFC.exe.
cannot compute difference between binary files
Added Externals/MSVCPP/vcredist_x64_2008_SP1.exe.
cannot compute difference between binary files
Deleted Externals/MSVCPP/vcredist_x64_2008_SP1_MFC.exe.
cannot compute difference between binary files
Added Externals/MSVCPP/vcredist_x64_2010_SP1.exe.
cannot compute difference between binary files
Deleted Externals/MSVCPP/vcredist_x64_2010_SP1_MFC.exe.
cannot compute difference between binary files
Added Externals/MSVCPP/vcredist_x64_2012_RTM.exe.
cannot compute difference between binary files
Deleted Externals/MSVCPP/vcredist_x64_2012_VSU1.exe.
cannot compute difference between binary files
Added Externals/MSVCPP/vcredist_x86_2005_SP1.exe.
cannot compute difference between binary files
Deleted Externals/MSVCPP/vcredist_x86_2005_SP1_MFC.exe.
cannot compute difference between binary files
Added Externals/MSVCPP/vcredist_x86_2008_SP1.exe.
cannot compute difference between binary files
Deleted Externals/MSVCPP/vcredist_x86_2008_SP1_MFC.exe.
cannot compute difference between binary files
Added Externals/MSVCPP/vcredist_x86_2010_SP1.exe.
cannot compute difference between binary files
Deleted Externals/MSVCPP/vcredist_x86_2010_SP1_MFC.exe.
cannot compute difference between binary files
Added Externals/MSVCPP/vcredist_x86_2012_RTM.exe.
cannot compute difference between binary files
Deleted Externals/MSVCPP/vcredist_x86_2012_VSU1.exe.
cannot compute difference between binary files
Changes to Membership/Properties/AssemblyInfo.cs.
︙ | ︙ | |||
29 30 31 32 33 34 35 | // 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: | | | | 29 30 31 32 33 34 35 36 37 | // Major Version // Minor Version // Build Number // Revision // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: [assembly: AssemblyVersion("1.0.83.0")] [assembly: AssemblyFileVersion("1.0.83.0")] |
Deleted SQLite.Beta.nuspec.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Changes to SQLite.Designer/AssemblyInfo.cs.
︙ | ︙ | |||
39 40 41 42 43 44 45 | // 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: | | | | 39 40 41 42 43 44 45 46 47 | // Major Version // Minor Version // Build Number // Revision // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: [assembly: AssemblyVersion("1.0.83.0")] [assembly: AssemblyFileVersion("1.0.83.0")] |
Changes to SQLite.Designer/source.extension.vsixmanifest.
1 2 3 4 5 | <?xml version="1.0" encoding="utf-8"?> <Vsix Version="1.0.0" xmlns="http://schemas.microsoft.com/developer/vsx-schema/2010"> <Identifier Id="67b5f3a9-cde1-430f-a12b-af95bb064851"> <Name>System.Data.SQLite Designer</Name> <Author>http://system.data.sqlite.org/</Author> | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 | <?xml version="1.0" encoding="utf-8"?> <Vsix Version="1.0.0" xmlns="http://schemas.microsoft.com/developer/vsx-schema/2010"> <Identifier Id="67b5f3a9-cde1-430f-a12b-af95bb064851"> <Name>System.Data.SQLite Designer</Name> <Author>http://system.data.sqlite.org/</Author> <Version>1.0.83.0</Version> <Description>ADO.NET Data Designer for SQLite</Description> <Locale>1033</Locale> <InstalledByMsi>false</InstalledByMsi> <SupportedProducts> <VisualStudio Version="10.0"> <Edition>Pro</Edition> </VisualStudio> |
︙ | ︙ |
Changes to SQLite.Interop/SQLite.Interop.2010.vcxproj.
1 2 3 4 5 6 7 8 9 10 | <?xml version="1.0" encoding="utf-8"?> <!-- * * SQLite.Interop.2010.vcxproj - * * Written by Joe Mistachkin. * Released to the public domain, use at your own risk! * --> <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0"> | < < < < | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <?xml version="1.0" encoding="utf-8"?> <!-- * * SQLite.Interop.2010.vcxproj - * * Written by Joe Mistachkin. * Released to the public domain, use at your own risk! * --> <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0"> <ItemGroup Label="ProjectConfigurations"> <ProjectConfiguration Include="DebugNativeOnly|x64"> <Configuration>DebugNativeOnly</Configuration> <Platform>x64</Platform> </ProjectConfiguration> <ProjectConfiguration Include="Debug|Win32"> <Configuration>Debug</Configuration> |
︙ | ︙ |
Changes to SQLite.Interop/SQLite.Interop.2012.vcxproj.
1 2 3 4 5 6 7 8 9 10 | <?xml version="1.0" encoding="utf-8"?> <!-- * * SQLite.Interop.2012.vcxproj - * * Written by Joe Mistachkin. * Released to the public domain, use at your own risk! * --> <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0"> | < < < < | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <?xml version="1.0" encoding="utf-8"?> <!-- * * SQLite.Interop.2012.vcxproj - * * Written by Joe Mistachkin. * Released to the public domain, use at your own risk! * --> <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0"> <ItemGroup Label="ProjectConfigurations"> <ProjectConfiguration Include="DebugNativeOnly|x64"> <Configuration>DebugNativeOnly</Configuration> <Platform>x64</Platform> </ProjectConfiguration> <ProjectConfiguration Include="Debug|Win32"> <Configuration>Debug</Configuration> |
︙ | ︙ |
Changes to SQLite.Interop/SQLite.Interop.Static.2010.vcxproj.
1 2 3 4 5 6 7 8 9 10 | <?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"> | < < < < | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <?xml version="1.0" encoding="utf-8"?> <!-- * * SQLite.Interop.Static.2010.vcxproj - * * Written by Joe Mistachkin. * Released to the public domain, use at your own risk! * --> <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0"> <ItemGroup Label="ProjectConfigurations"> <ProjectConfiguration Include="DebugNativeOnly|x64"> <Configuration>DebugNativeOnly</Configuration> <Platform>x64</Platform> </ProjectConfiguration> <ProjectConfiguration Include="Debug|Win32"> <Configuration>Debug</Configuration> |
︙ | ︙ |
Changes to SQLite.Interop/SQLite.Interop.Static.2012.vcxproj.
1 2 3 4 5 6 7 8 9 10 | <?xml version="1.0" encoding="utf-8"?> <!-- * * SQLite.Interop.Static.2012.vcxproj - * * Written by Joe Mistachkin. * Released to the public domain, use at your own risk! * --> <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0"> | < < < < | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <?xml version="1.0" encoding="utf-8"?> <!-- * * SQLite.Interop.Static.2012.vcxproj - * * Written by Joe Mistachkin. * Released to the public domain, use at your own risk! * --> <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0"> <ItemGroup Label="ProjectConfigurations"> <ProjectConfiguration Include="DebugNativeOnly|x64"> <Configuration>DebugNativeOnly</Configuration> <Platform>x64</Platform> </ProjectConfiguration> <ProjectConfiguration Include="Debug|Win32"> <Configuration>Debug</Configuration> |
︙ | ︙ |
Changes to SQLite.Interop/props/SQLite.Interop.2005.vsprops.
︙ | ︙ | |||
15 16 17 18 19 20 21 | <UserMacro Name="ConfigurationYear" Value="2005" PerformEnvironmentSet="true" /> <UserMacro Name="INTEROP_BUILD_NUMBER" | | | | | | 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | <UserMacro Name="ConfigurationYear" Value="2005" PerformEnvironmentSet="true" /> <UserMacro Name="INTEROP_BUILD_NUMBER" Value="083" PerformEnvironmentSet="true" /> <UserMacro Name="INTEROP_LINKER_VERSION" Value="1.0" PerformEnvironmentSet="true" /> <UserMacro Name="INTEROP_MANIFEST_VERSION" Value="1.0.83.0" PerformEnvironmentSet="true" /> <UserMacro Name="INTEROP_RC_VERSION" Value="1,0,83,0" PerformEnvironmentSet="true" /> <UserMacro Name="INTEROP_DEBUG_DEFINES" Value="INTEROP_DEBUG=0x307;INTEROP_TEST_EXTENSION=1" PerformEnvironmentSet="true" /> <UserMacro Name="INTEROP_EXTRA_DEFINES" Value="INTEROP_EXTENSION_FUNCTIONS=1;INTEROP_CODEC=1" PerformEnvironmentSet="true" /> |
︙ | ︙ |
Changes to SQLite.Interop/props/SQLite.Interop.2008.vsprops.
︙ | ︙ | |||
15 16 17 18 19 20 21 | <UserMacro Name="ConfigurationYear" Value="2008" PerformEnvironmentSet="true" /> <UserMacro Name="INTEROP_BUILD_NUMBER" | | | | | | 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | <UserMacro Name="ConfigurationYear" Value="2008" PerformEnvironmentSet="true" /> <UserMacro Name="INTEROP_BUILD_NUMBER" Value="083" PerformEnvironmentSet="true" /> <UserMacro Name="INTEROP_LINKER_VERSION" Value="1.0" PerformEnvironmentSet="true" /> <UserMacro Name="INTEROP_MANIFEST_VERSION" Value="1.0.83.0" PerformEnvironmentSet="true" /> <UserMacro Name="INTEROP_RC_VERSION" Value="1,0,83,0" PerformEnvironmentSet="true" /> <UserMacro Name="INTEROP_DEBUG_DEFINES" Value="INTEROP_DEBUG=0x307;INTEROP_TEST_EXTENSION=1" PerformEnvironmentSet="true" /> <UserMacro Name="INTEROP_EXTRA_DEFINES" Value="INTEROP_EXTENSION_FUNCTIONS=1;INTEROP_CODEC=1" PerformEnvironmentSet="true" /> |
︙ | ︙ |
Changes to SQLite.Interop/props/SQLite.Interop.2010.props.
1 2 3 4 5 6 7 8 9 10 11 12 | <?xml version="1.0" encoding="utf-8"?> <!-- * * SQLite.Interop.2010.props - * * Written by Joe Mistachkin. * Released to the public domain, use at your own risk! * --> <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0"> <PropertyGroup Label="UserMacros"> <ConfigurationYear>2010</ConfigurationYear> | | | | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | <?xml version="1.0" encoding="utf-8"?> <!-- * * SQLite.Interop.2010.props - * * Written by Joe Mistachkin. * Released to the public domain, use at your own risk! * --> <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0"> <PropertyGroup Label="UserMacros"> <ConfigurationYear>2010</ConfigurationYear> <INTEROP_BUILD_NUMBER>083</INTEROP_BUILD_NUMBER> <INTEROP_LINKER_VERSION>1.0</INTEROP_LINKER_VERSION> <INTEROP_MANIFEST_VERSION>1.0.83.0</INTEROP_MANIFEST_VERSION> <INTEROP_RC_VERSION>1,0,83,0</INTEROP_RC_VERSION> <INTEROP_DEBUG_DEFINES>INTEROP_DEBUG=0x307;INTEROP_TEST_EXTENSION=1</INTEROP_DEBUG_DEFINES> <INTEROP_EXTRA_DEFINES>INTEROP_EXTENSION_FUNCTIONS=1;INTEROP_CODEC=1</INTEROP_EXTRA_DEFINES> <INTEROP_ASSEMBLY_RESOURCES>/ASSEMBLYRESOURCE:..\System.Data.SQLite\SQLiteCommand.bmp,System.Data.SQLite.SQLiteCommand.bmp /ASSEMBLYRESOURCE:..\System.Data.SQLite\SQLiteConnection.bmp,System.Data.SQLite.SQLiteConnection.bmp /ASSEMBLYRESOURCE:..\System.Data.SQLite\SQLiteDataAdapter.bmp,System.Data.SQLite.SQLiteDataAdapter.bmp</INTEROP_ASSEMBLY_RESOURCES> <INTEROP_KEY_FILE>$(ProjectDir)..\System.Data.SQLite\System.Data.SQLite.snk</INTEROP_KEY_FILE> <INTEROP_NATIVE_NAME>SQLite.Interop</INTEROP_NATIVE_NAME> <INTEROP_MIXED_NAME>System.Data.SQLite</INTEROP_MIXED_NAME> </PropertyGroup> <ItemGroup> |
︙ | ︙ |
Changes to SQLite.Interop/props/SQLite.Interop.2012.props.
1 2 3 4 5 6 7 8 9 10 11 12 | <?xml version="1.0" encoding="utf-8"?> <!-- * * SQLite.Interop.2012.props - * * Written by Joe Mistachkin. * Released to the public domain, use at your own risk! * --> <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0"> <PropertyGroup Label="UserMacros"> <ConfigurationYear>2012</ConfigurationYear> | | | | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | <?xml version="1.0" encoding="utf-8"?> <!-- * * SQLite.Interop.2012.props - * * Written by Joe Mistachkin. * Released to the public domain, use at your own risk! * --> <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0"> <PropertyGroup Label="UserMacros"> <ConfigurationYear>2012</ConfigurationYear> <INTEROP_BUILD_NUMBER>083</INTEROP_BUILD_NUMBER> <INTEROP_LINKER_VERSION>1.0</INTEROP_LINKER_VERSION> <INTEROP_MANIFEST_VERSION>1.0.83.0</INTEROP_MANIFEST_VERSION> <INTEROP_RC_VERSION>1,0,83,0</INTEROP_RC_VERSION> <INTEROP_DEBUG_DEFINES>INTEROP_DEBUG=0x307;INTEROP_TEST_EXTENSION=1</INTEROP_DEBUG_DEFINES> <INTEROP_EXTRA_DEFINES>INTEROP_EXTENSION_FUNCTIONS=1;INTEROP_CODEC=1</INTEROP_EXTRA_DEFINES> <INTEROP_ASSEMBLY_RESOURCES>/ASSEMBLYRESOURCE:..\System.Data.SQLite\SQLiteCommand.bmp,System.Data.SQLite.SQLiteCommand.bmp /ASSEMBLYRESOURCE:..\System.Data.SQLite\SQLiteConnection.bmp,System.Data.SQLite.SQLiteConnection.bmp /ASSEMBLYRESOURCE:..\System.Data.SQLite\SQLiteDataAdapter.bmp,System.Data.SQLite.SQLiteDataAdapter.bmp</INTEROP_ASSEMBLY_RESOURCES> <INTEROP_KEY_FILE>$(ProjectDir)..\System.Data.SQLite\System.Data.SQLite.snk</INTEROP_KEY_FILE> <INTEROP_NATIVE_NAME>SQLite.Interop</INTEROP_NATIVE_NAME> <INTEROP_MIXED_NAME>System.Data.SQLite</INTEROP_MIXED_NAME> </PropertyGroup> <ItemGroup> |
︙ | ︙ |
Changes to SQLite.Interop/props/sqlite3.props.
1 2 3 4 5 6 7 8 9 10 11 | <?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"> | | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | <?xml version="1.0" encoding="utf-8"?> <!-- * * sqlite3.props - * * Written by Joe Mistachkin. * Released to the public domain, use at your own risk! * --> <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0"> <PropertyGroup Label="UserMacros"> <SQLITE_MANIFEST_VERSION>3.7.15</SQLITE_MANIFEST_VERSION> <SQLITE_RC_VERSION>3,7,15</SQLITE_RC_VERSION> <SQLITE_COMMON_DEFINES>_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;SQLITE_THREADSAFE=1;SQLITE_USE_URI=1;SQLITE_ENABLE_COLUMN_METADATA=1;SQLITE_ENABLE_STAT3=1;SQLITE_ENABLE_FTS3=1;SQLITE_ENABLE_LOAD_EXTENSION=1;SQLITE_ENABLE_RTREE=1;SQLITE_SOUNDEX=1</SQLITE_COMMON_DEFINES> <SQLITE_EXTRA_DEFINES>SQLITE_HAS_CODEC=1</SQLITE_EXTRA_DEFINES> <SQLITE_WINCE_DEFINES>SQLITE_OMIT_WAL=1</SQLITE_WINCE_DEFINES> <SQLITE_DEBUG_DEFINES>SQLITE_DEBUG=1;SQLITE_MEMDEBUG=1;SQLITE_ENABLE_EXPENSIVE_ASSERT=1</SQLITE_DEBUG_DEFINES> <SQLITE_RELEASE_DEFINES>SQLITE_WIN32_MALLOC=1</SQLITE_RELEASE_DEFINES> <SQLITE_DISABLE_WARNINGS>4055;4100;4127;4146;4210;4232;4244;4245;4267;4306;4389;4701;4703;4706</SQLITE_DISABLE_WARNINGS> <SQLITE_DISABLE_X64_WARNINGS></SQLITE_DISABLE_X64_WARNINGS> |
︙ | ︙ |
Changes to SQLite.Interop/props/sqlite3.vsprops.
︙ | ︙ | |||
10 11 12 13 14 15 16 | <VisualStudioPropertySheet ProjectType="Visual C++" Version="8.00" Name="sqlite3" > <UserMacro Name="SQLITE_MANIFEST_VERSION" | | | | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | <VisualStudioPropertySheet ProjectType="Visual C++" Version="8.00" Name="sqlite3" > <UserMacro Name="SQLITE_MANIFEST_VERSION" Value="3.7.15" PerformEnvironmentSet="true" /> <UserMacro Name="SQLITE_RC_VERSION" Value="3,7,15" PerformEnvironmentSet="true" /> <UserMacro Name="SQLITE_COMMON_DEFINES" Value="_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;SQLITE_THREADSAFE=1;SQLITE_USE_URI=1;SQLITE_ENABLE_COLUMN_METADATA=1;SQLITE_ENABLE_STAT3=1;SQLITE_ENABLE_FTS3=1;SQLITE_ENABLE_LOAD_EXTENSION=1;SQLITE_ENABLE_RTREE=1;SQLITE_SOUNDEX=1" PerformEnvironmentSet="true" /> |
︙ | ︙ |
Changes to SQLite.Interop/src/contrib/extension-functions.c.
︙ | ︙ | |||
113 114 115 116 117 118 119 | #include <ctype.h> /* relicoder */ #include <math.h> #include <string.h> #include <stdio.h> | | | 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 | #include <ctype.h> /* relicoder */ #include <math.h> #include <string.h> #include <stdio.h> #ifndef _WIN32_WCE #include <errno.h> /* LMH 2007-03-25 */ #else int errno; #define strerror(x) "" #endif #include <stdlib.h> |
︙ | ︙ |
Changes to SQLite.Interop/src/core/sqlite3.c.
1 2 | /****************************************************************************** ** This file is an amalgamation of many separate C source files from SQLite | | | 1 2 3 4 5 6 7 8 9 10 | /****************************************************************************** ** This file is an amalgamation of many separate C source files from SQLite ** version 3.7.15. 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 |
︙ | ︙ | |||
302 303 304 305 306 307 308 | #endif /* Needed for various definitions... */ #ifndef _GNU_SOURCE # define _GNU_SOURCE #endif | < < < < | 302 303 304 305 306 307 308 309 310 311 312 313 314 315 | #endif /* Needed for various definitions... */ #ifndef _GNU_SOURCE # define _GNU_SOURCE #endif /* ** Include standard header files as necessary */ #ifdef HAVE_STDINT_H #include <stdint.h> #endif #ifdef HAVE_INTTYPES_H |
︙ | ︙ | |||
358 359 360 361 362 363 364 | ** threads can use SQLite as long as no two threads try to use the same ** database connection at the same time. ** ** Older versions of SQLite used an optional THREADSAFE macro. ** We support that for legacy. */ #if !defined(SQLITE_THREADSAFE) | | | | | | | 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 | ** threads can use SQLite as long as no two threads try to use the same ** database connection at the same time. ** ** Older versions of SQLite used an optional THREADSAFE macro. ** We support that for legacy. */ #if !defined(SQLITE_THREADSAFE) #if defined(THREADSAFE) # define SQLITE_THREADSAFE THREADSAFE #else # define SQLITE_THREADSAFE 1 /* IMP: R-07272-22309 */ #endif #endif /* ** Powersafe overwrite is on by default. But can be turned off using ** the -DSQLITE_POWERSAFE_OVERWRITE=0 command-line option. */ #ifndef SQLITE_POWERSAFE_OVERWRITE |
︙ | ︙ | |||
440 441 442 443 444 445 446 | ** Later we learn that _XOPEN_SOURCE is poorly or incorrectly ** implemented on some systems. So we avoid defining it at all ** if it is already defined or if it is unneeded because we are ** not doing a threadsafe build. Ticket #2681. ** ** See also ticket #2741. */ | | < | 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 | ** Later we learn that _XOPEN_SOURCE is poorly or incorrectly ** implemented on some systems. So we avoid defining it at all ** if it is already defined or if it is unneeded because we are ** not doing a threadsafe build. Ticket #2681. ** ** See also ticket #2741. */ #if !defined(_XOPEN_SOURCE) && !defined(__DARWIN__) && !defined(__APPLE__) && SQLITE_THREADSAFE # define _XOPEN_SOURCE 500 /* Needed to enable pthread recursive mutexes */ #endif /* ** The TCL headers are only needed when compiling the TCL bindings. */ #if defined(SQLITE_TCL) || defined(TCLSH) |
︙ | ︙ | |||
674 675 676 677 678 679 680 | ** 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()]. */ | | | | | 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 | ** string contains the date and time of the check-in (UTC) and an SHA1 ** hash of the entire source tree. ** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ #define SQLITE_VERSION "3.7.15" #define SQLITE_VERSION_NUMBER 3007015 #define SQLITE_SOURCE_ID "2012-10-12 18:06:07 de784399ed1f0e27fc875e32719643d19819c8fb" /* ** CAPI3REF: Run-Time Library Version Numbers ** KEYWORDS: sqlite3_version, sqlite3_sourceid ** ** These interfaces provide the same information as the [SQLITE_VERSION], ** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros |
︙ | ︙ | |||
855 856 857 858 859 860 861 | ** host languages that are garbage collected, and where the order in which ** destructors are called is arbitrary. ** ** Applications should [sqlite3_finalize | finalize] all [prepared statements], ** [sqlite3_blob_close | close] all [BLOB handles], and ** [sqlite3_backup_finish | finish] all [sqlite3_backup] objects associated ** with the [sqlite3] object prior to attempting to close the object. ^If | | | 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 | ** host languages that are garbage collected, and where the order in which ** destructors are called is arbitrary. ** ** Applications should [sqlite3_finalize | finalize] all [prepared statements], ** [sqlite3_blob_close | close] all [BLOB handles], and ** [sqlite3_backup_finish | finish] all [sqlite3_backup] objects associated ** with the [sqlite3] object prior to attempting to close the object. ^If ** sqlite3_close() is called on a [database connection] that still has ** outstanding [prepared statements], [BLOB handles], and/or ** [sqlite3_backup] objects then it returns SQLITE_OK but the deallocation ** of resources is deferred until all [prepared statements], [BLOB handles], ** and [sqlite3_backup] objects are also destroyed. ** ** ^If an [sqlite3] object is destroyed while a transaction is open, ** the transaction is automatically rolled back. |
︙ | ︙ | |||
992 993 994 995 996 997 998 | #define SQLITE_MISMATCH 20 /* Data type mismatch */ #define SQLITE_MISUSE 21 /* Library used incorrectly */ #define SQLITE_NOLFS 22 /* Uses OS features not supported on host */ #define SQLITE_AUTH 23 /* Authorization denied */ #define SQLITE_FORMAT 24 /* Auxiliary database format error */ #define SQLITE_RANGE 25 /* 2nd parameter to sqlite3_bind out of range */ #define SQLITE_NOTADB 26 /* File opened that is not a database file */ | < < | 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 | #define SQLITE_MISMATCH 20 /* Data type mismatch */ #define SQLITE_MISUSE 21 /* Library used incorrectly */ #define SQLITE_NOLFS 22 /* Uses OS features not supported on host */ #define SQLITE_AUTH 23 /* Authorization denied */ #define SQLITE_FORMAT 24 /* Auxiliary database format error */ #define SQLITE_RANGE 25 /* 2nd parameter to sqlite3_bind out of range */ #define SQLITE_NOTADB 26 /* File opened that is not a database file */ #define SQLITE_ROW 100 /* sqlite3_step() has another row ready */ #define SQLITE_DONE 101 /* sqlite3_step() has finished executing */ /* end-of-error-codes */ /* ** CAPI3REF: Extended Result Codes ** KEYWORDS: {extended error code} {extended error codes} |
︙ | ︙ | |||
1043 1044 1045 1046 1047 1048 1049 | #define SQLITE_IOERR_CLOSE (SQLITE_IOERR | (16<<8)) #define SQLITE_IOERR_DIR_CLOSE (SQLITE_IOERR | (17<<8)) #define SQLITE_IOERR_SHMOPEN (SQLITE_IOERR | (18<<8)) #define SQLITE_IOERR_SHMSIZE (SQLITE_IOERR | (19<<8)) #define SQLITE_IOERR_SHMLOCK (SQLITE_IOERR | (20<<8)) #define SQLITE_IOERR_SHMMAP (SQLITE_IOERR | (21<<8)) #define SQLITE_IOERR_SEEK (SQLITE_IOERR | (22<<8)) | < < < < < < < < < < < < < < | 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 | #define SQLITE_IOERR_CLOSE (SQLITE_IOERR | (16<<8)) #define SQLITE_IOERR_DIR_CLOSE (SQLITE_IOERR | (17<<8)) #define SQLITE_IOERR_SHMOPEN (SQLITE_IOERR | (18<<8)) #define SQLITE_IOERR_SHMSIZE (SQLITE_IOERR | (19<<8)) #define SQLITE_IOERR_SHMLOCK (SQLITE_IOERR | (20<<8)) #define SQLITE_IOERR_SHMMAP (SQLITE_IOERR | (21<<8)) #define SQLITE_IOERR_SEEK (SQLITE_IOERR | (22<<8)) #define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8)) #define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8)) #define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8)) #define SQLITE_CANTOPEN_ISDIR (SQLITE_CANTOPEN | (2<<8)) #define SQLITE_CANTOPEN_FULLPATH (SQLITE_CANTOPEN | (3<<8)) #define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8)) #define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8)) #define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8)) #define SQLITE_ABORT_ROLLBACK (SQLITE_ABORT | (2<<8)) /* ** CAPI3REF: Flags For File Open Operations ** ** These bit values are intended for use in the ** 3rd parameter to the [sqlite3_open_v2()] interface and ** in the 4th parameter to the [sqlite3_vfs.xOpen] method. |
︙ | ︙ | |||
1305 1306 1307 1308 1309 1310 1311 | int (*xDeviceCharacteristics)(sqlite3_file*); /* Methods above are valid for version 1 */ int (*xShmMap)(sqlite3_file*, int iPg, int pgsz, int, void volatile**); int (*xShmLock)(sqlite3_file*, int offset, int n, int flags); void (*xShmBarrier)(sqlite3_file*); int (*xShmUnmap)(sqlite3_file*, int deleteFlag); /* Methods above are valid for version 2 */ | < < < | 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 | int (*xDeviceCharacteristics)(sqlite3_file*); /* Methods above are valid for version 1 */ int (*xShmMap)(sqlite3_file*, int iPg, int pgsz, int, void volatile**); int (*xShmLock)(sqlite3_file*, int offset, int n, int flags); void (*xShmBarrier)(sqlite3_file*); int (*xShmUnmap)(sqlite3_file*, int deleteFlag); /* Methods above are valid for version 2 */ /* Additional methods may be added in future releases */ }; /* ** CAPI3REF: Standard File Control Opcodes ** ** These integer constants are opcodes for the xFileControl method |
︙ | ︙ | |||
1442 1443 1444 1445 1446 1447 1448 1449 1450 | ** VFS has handled the PRAGMA itself and the parser generates a no-op ** prepared statement. ^If the [SQLITE_FCNTL_PRAGMA] file control returns ** any result code other than [SQLITE_OK] or [SQLITE_NOTFOUND], that means ** that the VFS encountered an error while handling the [PRAGMA] and the ** compilation of the PRAGMA fails with an error. ^The [SQLITE_FCNTL_PRAGMA] ** file control occurs at the beginning of pragma statement analysis and so ** it is able to override built-in [PRAGMA] statements. ** ** <li>[[SQLITE_FCNTL_BUSYHANDLER]] | > < | < < < < < < < < < < < < < < < < < < < < < < < | 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 | ** VFS has handled the PRAGMA itself and the parser generates a no-op ** prepared statement. ^If the [SQLITE_FCNTL_PRAGMA] file control returns ** any result code other than [SQLITE_OK] or [SQLITE_NOTFOUND], that means ** that the VFS encountered an error while handling the [PRAGMA] and the ** compilation of the PRAGMA fails with an error. ^The [SQLITE_FCNTL_PRAGMA] ** file control occurs at the beginning of pragma statement analysis and so ** it is able to override built-in [PRAGMA] statements. ** </ul> ** ** <li>[[SQLITE_FCNTL_BUSYHANDLER]] ** ^This file-control may be invoked by SQLite on the database file handle ** shortly after it is opened in order to provide a custom VFS with access ** to the connections busy-handler callback. The argument is of type (void **) ** - an array of two (void *) values. The first (void *) actually points ** to a function of type (int (*)(void *)). In order to invoke the connections ** busy-handler, this function should be invoked with the second (void *) in ** the array as the only argument. If it returns non-zero, then the operation ** should be retried. If it returns zero, the custom VFS should abandon the ** current operation. */ #define SQLITE_FCNTL_LOCKSTATE 1 #define SQLITE_GET_LOCKPROXYFILE 2 #define SQLITE_SET_LOCKPROXYFILE 3 #define SQLITE_LAST_ERRNO 4 #define SQLITE_FCNTL_SIZE_HINT 5 #define SQLITE_FCNTL_CHUNK_SIZE 6 #define SQLITE_FCNTL_FILE_POINTER 7 #define SQLITE_FCNTL_SYNC_OMITTED 8 #define SQLITE_FCNTL_WIN32_AV_RETRY 9 #define SQLITE_FCNTL_PERSIST_WAL 10 #define SQLITE_FCNTL_OVERWRITE 11 #define SQLITE_FCNTL_VFSNAME 12 #define SQLITE_FCNTL_POWERSAFE_OVERWRITE 13 #define SQLITE_FCNTL_PRAGMA 14 #define SQLITE_FCNTL_BUSYHANDLER 15 /* ** 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 |
︙ | ︙ | |||
2159 2160 2161 2162 2163 2164 2165 | ** ** [[SQLITE_CONFIG_GETPCACHE2]] <dt>SQLITE_CONFIG_GETPCACHE2</dt> ** <dd> ^(This option takes a single argument which is a pointer to an ** [sqlite3_pcache_methods2] object. SQLite copies of the current ** page cache implementation into that object.)^ </dd> ** ** [[SQLITE_CONFIG_LOG]] <dt>SQLITE_CONFIG_LOG</dt> | < < | | 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 | ** ** [[SQLITE_CONFIG_GETPCACHE2]] <dt>SQLITE_CONFIG_GETPCACHE2</dt> ** <dd> ^(This option takes a single argument which is a pointer to an ** [sqlite3_pcache_methods2] object. SQLite copies of the current ** page cache implementation into that object.)^ </dd> ** ** [[SQLITE_CONFIG_LOG]] <dt>SQLITE_CONFIG_LOG</dt> ** <dd> ^The SQLITE_CONFIG_LOG option takes two arguments: a pointer to a ** function with a call signature of void(*)(void*,int,const char*), ** and a pointer to void. ^If the function pointer is not NULL, it is ** invoked by [sqlite3_log()] to process each logging event. ^If the ** function pointer is NULL, the [sqlite3_log()] interface becomes a no-op. ** ^The void pointer that is the second argument to SQLITE_CONFIG_LOG is ** passed through as the first parameter to the application-defined logger ** function whenever that function is invoked. ^The second parameter to |
︙ | ︙ | |||
2192 2193 2194 2195 2196 2197 2198 | ** connection is opened. If it is globally disabled, filenames are ** only interpreted as URIs if the SQLITE_OPEN_URI flag is set when the ** database connection is opened. By default, URI handling is globally ** disabled. The default value may be changed by compiling with the ** [SQLITE_USE_URI] symbol defined. ** ** [[SQLITE_CONFIG_COVERING_INDEX_SCAN]] <dt>SQLITE_CONFIG_COVERING_INDEX_SCAN | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 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 | ** connection is opened. If it is globally disabled, filenames are ** only interpreted as URIs if the SQLITE_OPEN_URI flag is set when the ** database connection is opened. By default, URI handling is globally ** disabled. The default value may be changed by compiling with the ** [SQLITE_USE_URI] symbol defined. ** ** [[SQLITE_CONFIG_COVERING_INDEX_SCAN]] <dt>SQLITE_CONFIG_COVERING_INDEX_SCAN ** <dd> This option taks a single integer argument which is interpreted as ** a boolean in order to enable or disable the use of covering indices for ** full table scans in the query optimizer. The default setting is determined ** by the [SQLITE_ALLOW_COVERING_INDEX_SCAN] compile-time option, or is "on" ** if that compile-time option is omitted. ** The ability to disable the use of covering indices for full table scans ** is because some incorrectly coded legacy applications might malfunction ** malfunction when the optimization is enabled. Providing the ability to ** disable the optimization allows the older, buggy application code to work ** without change even with newer versions of SQLite. ** ** [[SQLITE_CONFIG_PCACHE]] [[SQLITE_CONFIG_GETPCACHE]] ** <dt>SQLITE_CONFIG_PCACHE and SQLITE_CONFIG_GETPCACHE ** <dd> These options are obsolete and should not be used by new code. ** They are retained for backwards compatibility but are now no-ops. ** </dl> */ #define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */ #define SQLITE_CONFIG_MULTITHREAD 2 /* nil */ #define SQLITE_CONFIG_SERIALIZED 3 /* nil */ #define SQLITE_CONFIG_MALLOC 4 /* sqlite3_mem_methods* */ #define SQLITE_CONFIG_GETMALLOC 5 /* sqlite3_mem_methods* */ |
︙ | ︙ | |||
2261 2262 2263 2264 2265 2266 2267 | #define SQLITE_CONFIG_PCACHE 14 /* no-op */ #define SQLITE_CONFIG_GETPCACHE 15 /* no-op */ #define SQLITE_CONFIG_LOG 16 /* xFunc, void* */ #define SQLITE_CONFIG_URI 17 /* int */ #define SQLITE_CONFIG_PCACHE2 18 /* sqlite3_pcache_methods2* */ #define SQLITE_CONFIG_GETPCACHE2 19 /* sqlite3_pcache_methods2* */ #define SQLITE_CONFIG_COVERING_INDEX_SCAN 20 /* int */ | < < | 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 | #define SQLITE_CONFIG_PCACHE 14 /* no-op */ #define SQLITE_CONFIG_GETPCACHE 15 /* no-op */ #define SQLITE_CONFIG_LOG 16 /* xFunc, void* */ #define SQLITE_CONFIG_URI 17 /* int */ #define SQLITE_CONFIG_PCACHE2 18 /* sqlite3_pcache_methods2* */ #define SQLITE_CONFIG_GETPCACHE2 19 /* sqlite3_pcache_methods2* */ #define SQLITE_CONFIG_COVERING_INDEX_SCAN 20 /* int */ /* ** CAPI3REF: Database Connection Configuration Options ** ** These constants are the available integer configuration options that ** can be passed as the second argument to the [sqlite3_db_config()] interface. ** |
︙ | ︙ | |||
3096 3097 3098 3099 3100 3101 3102 | ** various times when an SQL statement is being run by [sqlite3_step()]. ** ^The sqlite3_trace() callback is invoked with a UTF-8 rendering of the ** SQL statement text as the statement first begins executing. ** ^(Additional sqlite3_trace() callbacks might occur ** as each triggered subprogram is entered. The callbacks for triggers ** contain a UTF-8 SQL comment that identifies the trigger.)^ ** | < < < | 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 | ** various times when an SQL statement is being run by [sqlite3_step()]. ** ^The sqlite3_trace() callback is invoked with a UTF-8 rendering of the ** SQL statement text as the statement first begins executing. ** ^(Additional sqlite3_trace() callbacks might occur ** as each triggered subprogram is entered. The callbacks for triggers ** contain a UTF-8 SQL comment that identifies the trigger.)^ ** ** ^The callback function registered by sqlite3_profile() is invoked ** as each SQL statement finishes. ^The profile callback contains ** the original statement text and an estimate of wall-clock time ** of how long that statement took to run. ^The profile callback ** time is in units of nanoseconds, however the current implementation ** is only capable of millisecond resolution so the six least significant ** digits in the time are meaningless. Future versions of SQLite |
︙ | ︙ | |||
3290 3291 3292 3293 3294 3295 3296 | ** ** <li> <b>cache</b>: ^The cache parameter may be set to either "shared" or ** "private". ^Setting it to "shared" is equivalent to setting the ** SQLITE_OPEN_SHAREDCACHE bit in the flags argument passed to ** sqlite3_open_v2(). ^Setting the cache parameter to "private" is ** equivalent to setting the SQLITE_OPEN_PRIVATECACHE bit. ** ^If sqlite3_open_v2() is used and the "cache" parameter is present in | | | 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 | ** ** <li> <b>cache</b>: ^The cache parameter may be set to either "shared" or ** "private". ^Setting it to "shared" is equivalent to setting the ** SQLITE_OPEN_SHAREDCACHE bit in the flags argument passed to ** sqlite3_open_v2(). ^Setting the cache parameter to "private" is ** equivalent to setting the SQLITE_OPEN_PRIVATECACHE bit. ** ^If sqlite3_open_v2() is used and the "cache" parameter is present in ** a URI filename, its value overrides any behaviour requested by setting ** SQLITE_OPEN_PRIVATECACHE or SQLITE_OPEN_SHAREDCACHE flag. ** </ul> ** ** ^Specifying an unknown parameter in the query component of a URI is not an ** error. Future versions of SQLite might understand additional query ** parameters. See "[query parameters with special meaning to SQLite]" for ** additional information. |
︙ | ︙ | |||
3637 3638 3639 3640 3641 3642 3643 | ** original SQL text. This causes the [sqlite3_step()] interface to ** behave differently in three ways: ** ** <ol> ** <li> ** ^If the database schema changes, instead of returning [SQLITE_SCHEMA] as it ** always used to do, [sqlite3_step()] will automatically recompile the SQL | | < | 3551 3552 3553 3554 3555 3556 3557 3558 3559 3560 3561 3562 3563 3564 3565 | ** original SQL text. This causes the [sqlite3_step()] interface to ** behave differently in three ways: ** ** <ol> ** <li> ** ^If the database schema changes, instead of returning [SQLITE_SCHEMA] as it ** always used to do, [sqlite3_step()] will automatically recompile the SQL ** statement and try to run it again. ** </li> ** ** <li> ** ^When an error occurs, [sqlite3_step()] will return one of the detailed ** [error codes] or [extended error codes]. ^The legacy behavior was that ** [sqlite3_step()] would only return a generic [SQLITE_ERROR] result code ** and the application would have to make a second call to [sqlite3_reset()] |
︙ | ︙ | |||
3842 3843 3844 3845 3846 3847 3848 | ** ^The index for named parameters can be looked up using the ** [sqlite3_bind_parameter_index()] API if desired. ^The index ** for "?NNN" parameters is the value of NNN. ** ^The NNN value must be between 1 and the [sqlite3_limit()] ** parameter [SQLITE_LIMIT_VARIABLE_NUMBER] (default value: 999). ** ** ^The third argument is the value to bind to the parameter. | < < < | 3755 3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 | ** ^The index for named parameters can be looked up using the ** [sqlite3_bind_parameter_index()] API if desired. ^The index ** for "?NNN" parameters is the value of NNN. ** ^The NNN value must be between 1 and the [sqlite3_limit()] ** parameter [SQLITE_LIMIT_VARIABLE_NUMBER] (default value: 999). ** ** ^The third argument is the value to bind to the parameter. ** ** ^(In those routines that have a fourth argument, its value is the ** number of bytes in the parameter. To be clear: the value is the ** number of <u>bytes</u> in the value, not the number of characters.)^ ** ^If the fourth parameter to sqlite3_bind_text() or sqlite3_bind_text16() ** is negative, then the length of the string is ** the number of bytes up to the first zero terminator. |
︙ | ︙ | |||
4612 4613 4614 4615 4616 4617 4618 | */ #ifndef SQLITE_OMIT_DEPRECATED SQLITE_API SQLITE_DEPRECATED int sqlite3_aggregate_count(sqlite3_context*); SQLITE_API SQLITE_DEPRECATED int sqlite3_expired(sqlite3_stmt*); SQLITE_API SQLITE_DEPRECATED int sqlite3_transfer_bindings(sqlite3_stmt*, sqlite3_stmt*); SQLITE_API SQLITE_DEPRECATED int sqlite3_global_recover(void); SQLITE_API SQLITE_DEPRECATED void sqlite3_thread_cleanup(void); | | < | 4522 4523 4524 4525 4526 4527 4528 4529 4530 4531 4532 4533 4534 4535 4536 | */ #ifndef SQLITE_OMIT_DEPRECATED SQLITE_API SQLITE_DEPRECATED int sqlite3_aggregate_count(sqlite3_context*); SQLITE_API SQLITE_DEPRECATED int sqlite3_expired(sqlite3_stmt*); SQLITE_API SQLITE_DEPRECATED int sqlite3_transfer_bindings(sqlite3_stmt*, sqlite3_stmt*); SQLITE_API SQLITE_DEPRECATED int sqlite3_global_recover(void); SQLITE_API SQLITE_DEPRECATED void sqlite3_thread_cleanup(void); SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int),void*,sqlite3_int64); #endif /* ** CAPI3REF: Obtaining SQL Function Parameter Values ** ** The C-language implementation of SQL functions and aggregates uses ** this set of interface routines to access the parameter values on |
︙ | ︙ | |||
4693 4694 4695 4696 4697 4698 4699 | ** called once for each invocation of the xStep callback and then one ** last time when the xFinal callback is invoked. ^(When no rows match ** an aggregate query, the xStep() callback of the aggregate function ** implementation is never called and xFinal() is called exactly once. ** In those cases, sqlite3_aggregate_context() might be called for the ** first time from within xFinal().)^ ** | | | < | < < | 4602 4603 4604 4605 4606 4607 4608 4609 4610 4611 4612 4613 4614 4615 4616 4617 4618 4619 4620 4621 4622 4623 | ** called once for each invocation of the xStep callback and then one ** last time when the xFinal callback is invoked. ^(When no rows match ** an aggregate query, the xStep() callback of the aggregate function ** implementation is never called and xFinal() is called exactly once. ** In those cases, sqlite3_aggregate_context() might be called for the ** first time from within xFinal().)^ ** ** ^The sqlite3_aggregate_context(C,N) routine returns a NULL pointer if N is ** less than or equal to zero or if a memory allocate error occurs. ** ** ^(The amount of space allocated by sqlite3_aggregate_context(C,N) is ** determined by the N parameter on first successful call. Changing the ** value of N in subsequent call to sqlite3_aggregate_context() within ** the same aggregate function instance will not resize the memory ** allocation.)^ ** ** ^SQLite automatically frees the memory allocated by ** sqlite3_aggregate_context() when the aggregate query concludes. ** ** The first parameter must be a copy of the ** [sqlite3_context | SQL function context] that is the first parameter ** to the xStep or xFinal callback routine that implements the aggregate |
︙ | ︙ | |||
4801 4802 4803 4804 4805 4806 4807 | ** argument is SQLITE_STATIC, it means that the content pointer is constant ** and will never change. It does not need to be destroyed. ^The ** SQLITE_TRANSIENT value means that the content will likely change in ** the near future and that SQLite should make its own private copy of ** the content before returning. ** ** The typedef is necessary to work around problems in certain | | | 4707 4708 4709 4710 4711 4712 4713 4714 4715 4716 4717 4718 4719 4720 4721 | ** argument is SQLITE_STATIC, it means that the content pointer is constant ** and will never change. It does not need to be destroyed. ^The ** SQLITE_TRANSIENT value means that the content will likely change in ** the near future and that SQLite should make its own private copy of ** the content before returning. ** ** The typedef is necessary to work around problems in certain ** C++ compilers. See ticket #2191. */ typedef void (*sqlite3_destructor_type)(void*); #define SQLITE_STATIC ((sqlite3_destructor_type)0) #define SQLITE_TRANSIENT ((sqlite3_destructor_type)-1) /* ** CAPI3REF: Setting The Result Of An SQL Function |
︙ | ︙ | |||
5600 5601 5602 5603 5604 5605 5606 | /* ** CAPI3REF: Load An Extension ** ** ^This interface loads an SQLite extension library from the named file. ** ** ^The sqlite3_load_extension() interface attempts to load an | | < < < < < | | < < < < | 5506 5507 5508 5509 5510 5511 5512 5513 5514 5515 5516 5517 5518 5519 5520 5521 5522 5523 5524 | /* ** CAPI3REF: Load An Extension ** ** ^This interface loads an SQLite extension library from the named file. ** ** ^The sqlite3_load_extension() interface attempts to load an ** SQLite extension library contained in the file zFile. ** ** ^The entry point is zProc. ** ^zProc may be 0, in which case the name of the entry point ** defaults to "sqlite3_extension_init". ** ^The sqlite3_load_extension() interface returns ** [SQLITE_OK] on success and [SQLITE_ERROR] if something goes wrong. ** ^If an error occurs and pzErrMsg is not 0, then the ** [sqlite3_load_extension()] interface shall attempt to ** fill *pzErrMsg with error message text stored in memory ** obtained from [sqlite3_malloc()]. The calling function ** should free this memory by calling [sqlite3_free()]. |
︙ | ︙ | |||
5639 5640 5641 5642 5643 5644 5645 | char **pzErrMsg /* Put error message here if not 0 */ ); /* ** CAPI3REF: Enable Or Disable Extension Loading ** ** ^So as not to open security holes in older applications that are | | | | | | 5536 5537 5538 5539 5540 5541 5542 5543 5544 5545 5546 5547 5548 5549 5550 5551 5552 5553 5554 5555 5556 5557 5558 5559 5560 5561 5562 5563 5564 5565 5566 | char **pzErrMsg /* Put error message here if not 0 */ ); /* ** CAPI3REF: Enable Or Disable Extension Loading ** ** ^So as not to open security holes in older applications that are ** unprepared to deal with extension loading, and as a means of disabling ** extension loading while evaluating user-entered SQL, the following API ** is provided to turn the [sqlite3_load_extension()] mechanism on and off. ** ** ^Extension loading is off by default. See ticket #1863. ** ^Call the sqlite3_enable_load_extension() routine with onoff==1 ** to turn extension loading on and call it with onoff==0 to turn ** it back off again. */ SQLITE_API int sqlite3_enable_load_extension(sqlite3 *db, int onoff); /* ** CAPI3REF: Automatically Load Statically Linked Extensions ** ** ^This interface causes the xEntryPoint() function to be invoked for ** each new [database connection] that is created. The idea here is that ** xEntryPoint() is the entry point for a statically linked SQLite extension ** that is to be automatically loaded into all new database connections. ** ** ^(Even though the function prototype shows that xEntryPoint() takes ** no arguments and returns void, SQLite invokes xEntryPoint() with three ** arguments and expects and integer result as if the signature of the ** entry point where as follows: ** |
︙ | ︙ | |||
7006 7007 7008 7009 7010 7011 7012 | ** If the requested page is already in the page cache, then the page cache ** implementation must return a pointer to the page buffer with its content ** intact. If the requested page is not already in the cache, then the ** cache implementation should use the value of the createFlag ** parameter to help it determined what action to take: ** ** <table border=1 width=85% align=center> | | | 6903 6904 6905 6906 6907 6908 6909 6910 6911 6912 6913 6914 6915 6916 6917 | ** If the requested page is already in the page cache, then the page cache ** implementation must return a pointer to the page buffer with its content ** intact. If the requested page is not already in the cache, then the ** cache implementation should use the value of the createFlag ** parameter to help it determined what action to take: ** ** <table border=1 width=85% align=center> ** <tr><th> createFlag <th> Behaviour when page is not already in cache ** <tr><td> 0 <td> Do not allocate a new page. Return NULL. ** <tr><td> 1 <td> Allocate a new page if it easy and convenient to do so. ** Otherwise return NULL. ** <tr><td> 2 <td> Make every effort to allocate a new page. Only return ** NULL if allocating a new page is effectively impossible. ** </table> ** |
︙ | ︙ | |||
7435 7436 7437 7438 7439 7440 7441 | ** and extensions to compare the contents of two buffers containing UTF-8 ** strings in a case-independent fashion, using the same definition of "case ** independence" that SQLite uses internally when comparing identifiers. */ SQLITE_API int sqlite3_stricmp(const char *, const char *); SQLITE_API int sqlite3_strnicmp(const char *, const char *, int); | < < < < < < < < < < < < < < < | | 7332 7333 7334 7335 7336 7337 7338 7339 7340 7341 7342 7343 7344 7345 7346 7347 7348 7349 | ** and extensions to compare the contents of two buffers containing UTF-8 ** strings in a case-independent fashion, using the same definition of "case ** independence" that SQLite uses internally when comparing identifiers. */ SQLITE_API int sqlite3_stricmp(const char *, const char *); SQLITE_API int sqlite3_strnicmp(const char *, const char *, int); /* ** CAPI3REF: Error Logging Interface ** ** ^The [sqlite3_log()] interface writes a message into the error log ** established by the [SQLITE_CONFIG_LOG] option to [sqlite3_config()]. ** ^If logging is enabled, the zFormat string and subsequent arguments are ** used with [sqlite3_snprintf()] to generate the final output string. ** ** The sqlite3_log() interface is intended for use by extensions such as ** virtual tables, collating functions, and SQL functions. While there is ** nothing to prevent an application from calling sqlite3_log(), doing so |
︙ | ︙ | |||
7826 7827 7828 7829 7830 7831 7832 | ** 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. ** ************************************************************************* | | | 7708 7709 7710 7711 7712 7713 7714 7715 7716 7717 7718 7719 7720 7721 7722 | ** 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 is the header file for the generic hash-table implemenation ** used in SQLite. */ #ifndef _SQLITE_HASH_H_ #define _SQLITE_HASH_H_ /* Forward declarations of structures. */ typedef struct Hash Hash; |
︙ | ︙ | |||
8138 8139 8140 8141 8142 8143 8144 | /* ** Provide a default value for SQLITE_TEMP_STORE in case it is not specified ** on the command-line */ #ifndef SQLITE_TEMP_STORE # define SQLITE_TEMP_STORE 1 | < | 8020 8021 8022 8023 8024 8025 8026 8027 8028 8029 8030 8031 8032 8033 | /* ** Provide a default value for SQLITE_TEMP_STORE in case it is not specified ** on the command-line */ #ifndef SQLITE_TEMP_STORE # define SQLITE_TEMP_STORE 1 #endif /* ** GCC does not define the offsetof() macro so we'll have to do it ** ourselves. */ #ifndef offsetof |
︙ | ︙ | |||
8286 8287 8288 8289 8290 8291 8292 | */ #ifdef SQLITE_4_BYTE_ALIGNED_MALLOC # define EIGHT_BYTE_ALIGNMENT(X) ((((char*)(X) - (char*)0)&3)==0) #else # define EIGHT_BYTE_ALIGNMENT(X) ((((char*)(X) - (char*)0)&7)==0) #endif | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 8167 8168 8169 8170 8171 8172 8173 8174 8175 8176 8177 8178 8179 8180 | */ #ifdef SQLITE_4_BYTE_ALIGNED_MALLOC # define EIGHT_BYTE_ALIGNMENT(X) ((((char*)(X) - (char*)0)&3)==0) #else # define EIGHT_BYTE_ALIGNMENT(X) ((((char*)(X) - (char*)0)&7)==0) #endif /* ** An instance of the following structure is used to store the busy-handler ** callback for a given sqlite handle. ** ** The sqlite.busyHandler member of the sqlite struct contains the busy ** callback for the database handle. Each pager opened via the sqlite |
︙ | ︙ | |||
8370 8371 8372 8373 8374 8375 8376 | /* ** A convenience macro that returns the number of elements in ** an array. */ #define ArraySize(X) ((int)(sizeof(X)/sizeof(X[0]))) | < < < < < | 8208 8209 8210 8211 8212 8213 8214 8215 8216 8217 8218 8219 8220 8221 | /* ** A convenience macro that returns the number of elements in ** an array. */ #define ArraySize(X) ((int)(sizeof(X)/sizeof(X[0]))) /* ** The following value as a destructor means to use sqlite3DbFree(). ** The sqlite3DbFree() routine requires two parameters instead of the ** one parameter that destructors normally want. So we have to introduce ** this magic value that the code knows to handle differently. Any ** pointer will work here as long as it is distinct from SQLITE_STATIC ** and SQLITE_TRANSIENT. |
︙ | ︙ | |||
8550 8551 8552 8553 8554 8555 8556 | #define BTREE_OMIT_JOURNAL 1 /* Do not create or use a rollback journal */ #define BTREE_MEMORY 2 /* This is an in-memory DB */ #define BTREE_SINGLE 4 /* The file contains at most 1 b-tree */ #define BTREE_UNORDERED 8 /* Use of a hash implementation is OK */ SQLITE_PRIVATE int sqlite3BtreeClose(Btree*); SQLITE_PRIVATE int sqlite3BtreeSetCacheSize(Btree*,int); | < | 8383 8384 8385 8386 8387 8388 8389 8390 8391 8392 8393 8394 8395 8396 | #define BTREE_OMIT_JOURNAL 1 /* Do not create or use a rollback journal */ #define BTREE_MEMORY 2 /* This is an in-memory DB */ #define BTREE_SINGLE 4 /* The file contains at most 1 b-tree */ #define BTREE_UNORDERED 8 /* Use of a hash implementation is OK */ SQLITE_PRIVATE int sqlite3BtreeClose(Btree*); SQLITE_PRIVATE int sqlite3BtreeSetCacheSize(Btree*,int); SQLITE_PRIVATE int sqlite3BtreeSetSafetyLevel(Btree*,int,int,int); SQLITE_PRIVATE int sqlite3BtreeSyncDisabled(Btree*); SQLITE_PRIVATE int sqlite3BtreeSetPageSize(Btree *p, int nPagesize, int nReserve, int eFix); SQLITE_PRIVATE int sqlite3BtreeGetPageSize(Btree*); SQLITE_PRIVATE int sqlite3BtreeMaxPageCount(Btree*,int); SQLITE_PRIVATE u32 sqlite3BtreeLastPage(Btree*); SQLITE_PRIVATE int sqlite3BtreeSecureDelete(Btree*,int); |
︙ | ︙ | |||
8605 8606 8607 8608 8609 8610 8611 | SQLITE_PRIVATE int sqlite3BtreeDropTable(Btree*, int, int*); SQLITE_PRIVATE int sqlite3BtreeClearTable(Btree*, int, int*); SQLITE_PRIVATE void sqlite3BtreeTripAllCursors(Btree*, int); SQLITE_PRIVATE void sqlite3BtreeGetMeta(Btree *pBtree, int idx, u32 *pValue); SQLITE_PRIVATE int sqlite3BtreeUpdateMeta(Btree*, int idx, u32 value); | < < < | 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 | SQLITE_PRIVATE int sqlite3BtreeDropTable(Btree*, int, int*); SQLITE_PRIVATE int sqlite3BtreeClearTable(Btree*, int, int*); SQLITE_PRIVATE void sqlite3BtreeTripAllCursors(Btree*, int); SQLITE_PRIVATE void sqlite3BtreeGetMeta(Btree *pBtree, int idx, u32 *pValue); SQLITE_PRIVATE int sqlite3BtreeUpdateMeta(Btree*, int idx, u32 value); /* ** The second parameter to sqlite3BtreeGetMeta or sqlite3BtreeUpdateMeta ** should be one of the following values. The integer values are assigned ** to constants so that the offset of the corresponding field in an ** SQLite database header may be found using the following formula: ** ** offset = 36 + (idx * 4) ** ** For example, the free-page-count field is located at byte offset 36 of ** the database file header. The incr-vacuum-flag field is located at ** byte offset 64 (== 36+4*7). */ #define BTREE_FREE_PAGE_COUNT 0 #define BTREE_SCHEMA_VERSION 1 #define BTREE_FILE_FORMAT 2 #define BTREE_DEFAULT_CACHE_SIZE 3 #define BTREE_LARGEST_ROOT_PAGE 4 #define BTREE_TEXT_ENCODING 5 #define BTREE_USER_VERSION 6 #define BTREE_INCR_VACUUM 7 /* ** Values that may be OR'd together to form the second argument of an ** sqlite3BtreeCursorHints() call. */ #define BTREE_BULKLOAD 0x00000001 |
︙ | ︙ | |||
9122 9123 9124 9125 9126 9127 9128 | 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*); | | | 8951 8952 8953 8954 8955 8956 8957 8958 8959 8960 8961 8962 8963 8964 8965 | SQLITE_PRIVATE void sqlite3VdbeChangeToNoop(Vdbe*, int addr); SQLITE_PRIVATE void sqlite3VdbeChangeP4(Vdbe*, int addr, const char *zP4, int N); SQLITE_PRIVATE void sqlite3VdbeUsesBtree(Vdbe*, int); SQLITE_PRIVATE VdbeOp *sqlite3VdbeGetOp(Vdbe*, int); SQLITE_PRIVATE int sqlite3VdbeMakeLabel(Vdbe*); SQLITE_PRIVATE void sqlite3VdbeRunOnlyOnce(Vdbe*); SQLITE_PRIVATE void sqlite3VdbeDelete(Vdbe*); SQLITE_PRIVATE void sqlite3VdbeDeleteObject(sqlite3*,Vdbe*); SQLITE_PRIVATE void sqlite3VdbeMakeReady(Vdbe*,Parse*); SQLITE_PRIVATE int sqlite3VdbeFinalize(Vdbe*); SQLITE_PRIVATE void sqlite3VdbeResolveLabel(Vdbe*, int); SQLITE_PRIVATE int sqlite3VdbeCurrentAddr(Vdbe*); #ifdef SQLITE_DEBUG SQLITE_PRIVATE int sqlite3VdbeAssertMayAbort(Vdbe *, int); SQLITE_PRIVATE void sqlite3VdbeTrace(Vdbe*,FILE*); |
︙ | ︙ | |||
9252 9253 9254 9255 9256 9257 9258 | #define PAGER_JOURNALMODE_DELETE 0 /* Commit by deleting journal file */ #define PAGER_JOURNALMODE_PERSIST 1 /* Commit by zeroing journal header */ #define PAGER_JOURNALMODE_OFF 2 /* Journal omitted. */ #define PAGER_JOURNALMODE_TRUNCATE 3 /* Commit by truncating journal */ #define PAGER_JOURNALMODE_MEMORY 4 /* In-memory journal file */ #define PAGER_JOURNALMODE_WAL 5 /* Use write-ahead logging */ | < < < < < < | 9081 9082 9083 9084 9085 9086 9087 9088 9089 9090 9091 9092 9093 9094 | #define PAGER_JOURNALMODE_DELETE 0 /* Commit by deleting journal file */ #define PAGER_JOURNALMODE_PERSIST 1 /* Commit by zeroing journal header */ #define PAGER_JOURNALMODE_OFF 2 /* Journal omitted. */ #define PAGER_JOURNALMODE_TRUNCATE 3 /* Commit by truncating journal */ #define PAGER_JOURNALMODE_MEMORY 4 /* In-memory journal file */ #define PAGER_JOURNALMODE_WAL 5 /* Use write-ahead logging */ /* ** The remainder of this file contains the declarations of the functions ** that make up the Pager sub-system API. See source code comments for ** a detailed description of each routine. */ /* Open and close a Pager connection. */ |
︙ | ︙ | |||
9282 9283 9284 9285 9286 9287 9288 | SQLITE_PRIVATE int sqlite3PagerReadFileheader(Pager*, int, unsigned char*); /* Functions used to configure a Pager object. */ SQLITE_PRIVATE void sqlite3PagerSetBusyhandler(Pager*, int(*)(void *), void *); SQLITE_PRIVATE int sqlite3PagerSetPagesize(Pager*, u32*, int); SQLITE_PRIVATE int sqlite3PagerMaxPageCount(Pager*, int); SQLITE_PRIVATE void sqlite3PagerSetCachesize(Pager*, int); | < | 9105 9106 9107 9108 9109 9110 9111 9112 9113 9114 9115 9116 9117 9118 | SQLITE_PRIVATE int sqlite3PagerReadFileheader(Pager*, int, unsigned char*); /* Functions used to configure a Pager object. */ SQLITE_PRIVATE void sqlite3PagerSetBusyhandler(Pager*, int(*)(void *), void *); SQLITE_PRIVATE int sqlite3PagerSetPagesize(Pager*, u32*, int); SQLITE_PRIVATE int sqlite3PagerMaxPageCount(Pager*, int); SQLITE_PRIVATE void sqlite3PagerSetCachesize(Pager*, int); SQLITE_PRIVATE void sqlite3PagerShrink(Pager*); SQLITE_PRIVATE void sqlite3PagerSetSafetyLevel(Pager*,int,int,int); SQLITE_PRIVATE int sqlite3PagerLockingMode(Pager *, int); SQLITE_PRIVATE int sqlite3PagerSetJournalMode(Pager *, int); SQLITE_PRIVATE int sqlite3PagerGetJournalMode(Pager*); SQLITE_PRIVATE int sqlite3PagerOkToChangeJournalMode(Pager*); SQLITE_PRIVATE i64 sqlite3PagerJournalSizeLimit(Pager *, i64); |
︙ | ︙ | |||
9429 9430 9431 9432 9433 9434 9435 | #define PGHDR_DIRTY 0x002 /* Page has changed */ #define PGHDR_NEED_SYNC 0x004 /* Fsync the rollback journal before ** writing this page to the database */ #define PGHDR_NEED_READ 0x008 /* Content is unread */ #define PGHDR_REUSE_UNLIKELY 0x010 /* A hint that reuse is unlikely */ #define PGHDR_DONT_WRITE 0x020 /* Do not write content to disk */ | < < | 9251 9252 9253 9254 9255 9256 9257 9258 9259 9260 9261 9262 9263 9264 | #define PGHDR_DIRTY 0x002 /* Page has changed */ #define PGHDR_NEED_SYNC 0x004 /* Fsync the rollback journal before ** writing this page to the database */ #define PGHDR_NEED_READ 0x008 /* Content is unread */ #define PGHDR_REUSE_UNLIKELY 0x010 /* A hint that reuse is unlikely */ #define PGHDR_DONT_WRITE 0x020 /* Do not write content to disk */ /* Initialize and shutdown the page cache subsystem */ SQLITE_PRIVATE int sqlite3PcacheInitialize(void); SQLITE_PRIVATE void sqlite3PcacheShutdown(void); /* Page cache buffer management: ** These routines implement SQLITE_CONFIG_PAGECACHE. */ |
︙ | ︙ | |||
9642 9643 9644 9645 9646 9647 9648 9649 9650 9651 9652 9653 9654 9655 | ** Determine if we are dealing with WinRT, which provides only a subset of ** the full Win32 API. */ #if !defined(SQLITE_OS_WINRT) # define SQLITE_OS_WINRT 0 #endif /* If the SET_FULLSYNC macro is not defined above, then make it ** a no-op */ #ifndef SET_FULLSYNC # define SET_FULLSYNC(x,y) #endif | > > > > > > > > | 9462 9463 9464 9465 9466 9467 9468 9469 9470 9471 9472 9473 9474 9475 9476 9477 9478 9479 9480 9481 9482 9483 | ** Determine if we are dealing with WinRT, which provides only a subset of ** the full Win32 API. */ #if !defined(SQLITE_OS_WINRT) # define SQLITE_OS_WINRT 0 #endif /* ** When compiled for WinCE or WinRT, there is no concept of the current ** directory. */ #if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT # define SQLITE_CURDIR 1 #endif /* If the SET_FULLSYNC macro is not defined above, then make it ** a no-op */ #ifndef SET_FULLSYNC # define SET_FULLSYNC(x,y) #endif |
︙ | ︙ | |||
9794 9795 9796 9797 9798 9799 9800 | #define SQLITE_FCNTL_DB_UNCHANGED 0xca093fa0 SQLITE_PRIVATE int sqlite3OsSectorSize(sqlite3_file *id); SQLITE_PRIVATE int sqlite3OsDeviceCharacteristics(sqlite3_file *id); SQLITE_PRIVATE int sqlite3OsShmMap(sqlite3_file *,int,int,int,void volatile **); SQLITE_PRIVATE int sqlite3OsShmLock(sqlite3_file *id, int, int, int); SQLITE_PRIVATE void sqlite3OsShmBarrier(sqlite3_file *id); SQLITE_PRIVATE int sqlite3OsShmUnmap(sqlite3_file *id, int); | < < | 9622 9623 9624 9625 9626 9627 9628 9629 9630 9631 9632 9633 9634 9635 | #define SQLITE_FCNTL_DB_UNCHANGED 0xca093fa0 SQLITE_PRIVATE int sqlite3OsSectorSize(sqlite3_file *id); SQLITE_PRIVATE int sqlite3OsDeviceCharacteristics(sqlite3_file *id); SQLITE_PRIVATE int sqlite3OsShmMap(sqlite3_file *,int,int,int,void volatile **); SQLITE_PRIVATE int sqlite3OsShmLock(sqlite3_file *id, int, int, int); SQLITE_PRIVATE void sqlite3OsShmBarrier(sqlite3_file *id); SQLITE_PRIVATE int sqlite3OsShmUnmap(sqlite3_file *id, int); /* ** Functions for accessing sqlite3_vfs methods */ SQLITE_PRIVATE int sqlite3OsOpen(sqlite3_vfs *, const char *, sqlite3_file*, int, int *); SQLITE_PRIVATE int sqlite3OsDelete(sqlite3_vfs *, const char *, int); |
︙ | ︙ | |||
10035 10036 10037 10038 10039 10040 10041 | struct Vdbe *pVdbe; /* List of active virtual machines */ CollSeq *pDfltColl; /* The default collating sequence (BINARY) */ sqlite3_mutex *mutex; /* Connection mutex */ Db *aDb; /* All backends */ int nDb; /* Number of backends currently in use */ int flags; /* Miscellaneous flags. See below */ i64 lastRowid; /* ROWID of most recent insert (see above) */ | < | | 9861 9862 9863 9864 9865 9866 9867 9868 9869 9870 9871 9872 9873 9874 9875 9876 9877 9878 | struct Vdbe *pVdbe; /* List of active virtual machines */ CollSeq *pDfltColl; /* The default collating sequence (BINARY) */ sqlite3_mutex *mutex; /* Connection mutex */ Db *aDb; /* All backends */ int nDb; /* Number of backends currently in use */ int flags; /* Miscellaneous flags. See below */ i64 lastRowid; /* ROWID of most recent insert (see above) */ unsigned int openFlags; /* Flags passed to sqlite3_vfs.xOpen() */ int errCode; /* Most recent error code (SQLITE_*) */ int errMask; /* & result codes with this before returning */ u8 dbOptFlags; /* Flags to enable/disable optimizations */ u8 autoCommit; /* The auto-commit flag. */ u8 temp_store; /* 1: file 2: memory 0: default */ u8 mallocFailed; /* True if we have seen a malloc failure */ u8 dfltLockMode; /* Default locking-mode for attached dbs */ signed char nextAutovac; /* Autovac setting after VACUUM if >=0 */ u8 suppressErr; /* Do not issue error messages if true */ u8 vtabOnConflict; /* Value to return for s3_vtab_on_conflict() */ |
︙ | ︙ | |||
10156 10157 10158 10159 10160 10161 10162 | /* DELETE, or UPDATE and return */ /* the count using a callback. */ #define SQLITE_NullCallback 0x00000020 /* Invoke the callback once if the */ /* result set is empty */ #define SQLITE_SqlTrace 0x00000040 /* Debug print SQL as it executes */ #define SQLITE_VdbeListing 0x00000080 /* Debug listings of VDBE programs */ #define SQLITE_WriteSchema 0x00000100 /* OK to update SQLITE_MASTER */ | | | 9981 9982 9983 9984 9985 9986 9987 9988 9989 9990 9991 9992 9993 9994 9995 | /* DELETE, or UPDATE and return */ /* the count using a callback. */ #define SQLITE_NullCallback 0x00000020 /* Invoke the callback once if the */ /* result set is empty */ #define SQLITE_SqlTrace 0x00000040 /* Debug print SQL as it executes */ #define SQLITE_VdbeListing 0x00000080 /* Debug listings of VDBE programs */ #define SQLITE_WriteSchema 0x00000100 /* OK to update SQLITE_MASTER */ /* 0x00000200 Unused */ #define SQLITE_IgnoreChecks 0x00000400 /* Do not enforce check constraints */ #define SQLITE_ReadUncommitted 0x0000800 /* For shared-cache mode */ #define SQLITE_LegacyFileFmt 0x00001000 /* Create new databases in format 1 */ #define SQLITE_FullFSync 0x00002000 /* Use full fsync on the backend */ #define SQLITE_CkptFullFSync 0x00004000 /* Use full fsync for checkpoint */ #define SQLITE_RecoveryMode 0x00008000 /* Ignore schema errors */ #define SQLITE_ReverseOrder 0x00010000 /* Reverse unordered SELECTs */ |
︙ | ︙ | |||
10184 10185 10186 10187 10188 10189 10190 | #define SQLITE_ColumnCache 0x0002 /* Column cache */ #define SQLITE_GroupByOrder 0x0004 /* GROUPBY cover of ORDERBY */ #define SQLITE_FactorOutConst 0x0008 /* Constant factoring */ #define SQLITE_IdxRealAsInt 0x0010 /* Store REAL as INT in indices */ #define SQLITE_DistinctOpt 0x0020 /* DISTINCT using indexes */ #define SQLITE_CoverIdxScan 0x0040 /* Covering index scans */ #define SQLITE_OrderByIdxJoin 0x0080 /* ORDER BY of joins via index */ | < < | | 10009 10010 10011 10012 10013 10014 10015 10016 10017 10018 10019 10020 10021 10022 10023 | #define SQLITE_ColumnCache 0x0002 /* Column cache */ #define SQLITE_GroupByOrder 0x0004 /* GROUPBY cover of ORDERBY */ #define SQLITE_FactorOutConst 0x0008 /* Constant factoring */ #define SQLITE_IdxRealAsInt 0x0010 /* Store REAL as INT in indices */ #define SQLITE_DistinctOpt 0x0020 /* DISTINCT using indexes */ #define SQLITE_CoverIdxScan 0x0040 /* Covering index scans */ #define SQLITE_OrderByIdxJoin 0x0080 /* ORDER BY of joins via index */ #define SQLITE_AllOpts 0x00ff /* All optimizations */ /* ** Macros for testing whether or not optimizations are enabled or disabled. */ #ifndef SQLITE_OMIT_BUILTIN_TEST #define OptimizationDisabled(db, mask) (((db)->dbOptFlags&(mask))!=0) #define OptimizationEnabled(db, mask) (((db)->dbOptFlags&(mask))==0) |
︙ | ︙ | |||
10363 10364 10365 10366 10367 10368 10369 | #define COLFLAG_HIDDEN 0x0002 /* A hidden column in a virtual table */ /* ** A "Collating Sequence" is defined by an instance of the following ** structure. Conceptually, a collating sequence consists of a name and ** a comparison routine that defines the order of that sequence. ** | > > > > > > > > > > > > | | 10186 10187 10188 10189 10190 10191 10192 10193 10194 10195 10196 10197 10198 10199 10200 10201 10202 10203 10204 10205 10206 10207 10208 10209 10210 10211 10212 | #define COLFLAG_HIDDEN 0x0002 /* A hidden column in a virtual table */ /* ** A "Collating Sequence" is defined by an instance of the following ** structure. Conceptually, a collating sequence consists of a name and ** a comparison routine that defines the order of that sequence. ** ** There may two separate implementations of the collation function, one ** that processes text in UTF-8 encoding (CollSeq.xCmp) and another that ** processes text encoded in UTF-16 (CollSeq.xCmp16), using the machine ** native byte order. When a collation sequence is invoked, SQLite selects ** the version that will require the least expensive encoding ** translations, if any. ** ** The CollSeq.pUser member variable is an extra parameter that passed in ** as the first argument to the UTF-8 comparison function, xCmp. ** CollSeq.pUser16 is the equivalent for the UTF-16 comparison function, ** xCmp16. ** ** If both CollSeq.xCmp and CollSeq.xCmp16 are NULL, it means that the ** collating sequence is undefined. Indices built on an undefined ** collating sequence may not be read or written. */ struct CollSeq { char *zName; /* Name of the collating sequence, UTF-8 encoded */ u8 enc; /* Text encoding handled by xCmp() */ void *pUser; /* First argument to xCmp() */ |
︙ | ︙ | |||
10697 10698 10699 10700 10701 10702 10703 | ** must be unique and what to do if they are not. When Index.onError=OE_None, ** it means this is not a unique index. Otherwise it is a unique index ** and the value of Index.onError indicate the which conflict resolution ** algorithm to employ whenever an attempt is made to insert a non-unique ** element. */ struct Index { | | | | | | | | | | > | < | | | | 10532 10533 10534 10535 10536 10537 10538 10539 10540 10541 10542 10543 10544 10545 10546 10547 10548 10549 10550 10551 10552 10553 10554 10555 10556 10557 10558 10559 | ** must be unique and what to do if they are not. When Index.onError=OE_None, ** it means this is not a unique index. Otherwise it is a unique index ** and the value of Index.onError indicate the which conflict resolution ** algorithm to employ whenever an attempt is made to insert a non-unique ** element. */ struct Index { char *zName; /* Name of this index */ int *aiColumn; /* Which columns are used by this index. 1st is 0 */ tRowcnt *aiRowEst; /* Result of ANALYZE: Est. rows selected by each column */ Table *pTable; /* The SQL table being indexed */ char *zColAff; /* String defining the affinity of each column */ Index *pNext; /* The next index associated with the same table */ Schema *pSchema; /* Schema containing this index */ u8 *aSortOrder; /* Array of size Index.nColumn. True==DESC, False==ASC */ char **azColl; /* Array of collation sequence names for index */ int nColumn; /* Number of columns in the table used by this index */ int tnum; /* Page containing root of this index in database file */ u8 onError; /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */ u8 autoIndex; /* True if is automatically created (ex: by UNIQUE) */ u8 bUnordered; /* Use this index for == or IN queries only */ #ifdef SQLITE_ENABLE_STAT3 int nSample; /* Number of elements in aSample[] */ tRowcnt avgEq; /* Average nEq value for key values not in aSample */ IndexSample *aSample; /* Samples of the left-most key */ #endif }; |
︙ | ︙ | |||
10891 10892 10893 10894 10895 10896 10897 10898 10899 10900 10901 10902 10903 10904 | Expr *pLeft; /* Left subnode */ Expr *pRight; /* Right subnode */ union { ExprList *pList; /* Function arguments or in "<expr> IN (<expr-list)" */ Select *pSelect; /* Used for sub-selects and "<expr> IN (<select>)" */ } x; /* If the EP_Reduced flag is set in the Expr.flags mask, then no ** space is allocated for the fields below this point. An attempt to ** access them will result in a segfault or malfunction. *********************************************************************/ #if SQLITE_MAX_EXPR_DEPTH>0 | > | 10726 10727 10728 10729 10730 10731 10732 10733 10734 10735 10736 10737 10738 10739 10740 | Expr *pLeft; /* Left subnode */ Expr *pRight; /* Right subnode */ union { ExprList *pList; /* Function arguments or in "<expr> IN (<expr-list)" */ Select *pSelect; /* Used for sub-selects and "<expr> IN (<select>)" */ } x; CollSeq *pColl; /* The collation type of the column or 0 */ /* If the EP_Reduced flag is set in the Expr.flags mask, then no ** space is allocated for the fields below this point. An attempt to ** access them will result in a segfault or malfunction. *********************************************************************/ #if SQLITE_MAX_EXPR_DEPTH>0 |
︙ | ︙ | |||
10926 10927 10928 10929 10930 10931 10932 | #define EP_Agg 0x0002 /* Contains one or more aggregate functions */ #define EP_Resolved 0x0004 /* IDs have been resolved to COLUMNs */ #define EP_Error 0x0008 /* Expression contains one or more errors */ #define EP_Distinct 0x0010 /* Aggregate function with DISTINCT keyword */ #define EP_VarSelect 0x0020 /* pSelect is correlated, not constant */ #define EP_DblQuoted 0x0040 /* token.z was originally in "..." */ #define EP_InfixFunc 0x0080 /* True for an infix function: LIKE, GLOB, etc */ | | | 10762 10763 10764 10765 10766 10767 10768 10769 10770 10771 10772 10773 10774 10775 10776 | #define EP_Agg 0x0002 /* Contains one or more aggregate functions */ #define EP_Resolved 0x0004 /* IDs have been resolved to COLUMNs */ #define EP_Error 0x0008 /* Expression contains one or more errors */ #define EP_Distinct 0x0010 /* Aggregate function with DISTINCT keyword */ #define EP_VarSelect 0x0020 /* pSelect is correlated, not constant */ #define EP_DblQuoted 0x0040 /* token.z was originally in "..." */ #define EP_InfixFunc 0x0080 /* True for an infix function: LIKE, GLOB, etc */ #define EP_ExpCollate 0x0100 /* Collating sequence specified explicitly */ #define EP_FixedDest 0x0200 /* Result needed in a specific register */ #define EP_IntValue 0x0400 /* Integer value contained in u.iValue */ #define EP_xIsSelect 0x0800 /* x.pSelect is valid (otherwise x.pList is) */ #define EP_Hint 0x1000 /* Not used */ #define EP_Reduced 0x2000 /* Expr struct is EXPR_REDUCEDSIZE bytes only */ #define EP_TokenOnly 0x4000 /* Expr struct is EXPR_TOKENONLYSIZE bytes only */ #define EP_Static 0x8000 /* Held in memory not obtained from malloc() */ |
︙ | ︙ | |||
10984 10985 10986 10987 10988 10989 10990 | /* ** A list of expressions. Each expression may optionally have a ** name. An expr/name combination can be used in several ways, such ** as the list of "expr AS ID" fields following a "SELECT" or in the ** list of "ID = expr" items in an UPDATE. A list of expressions can ** also be used as the argument to a function, in which case the a.zName ** field is not used. | < < < < < < < < | | | | | < | | | 10820 10821 10822 10823 10824 10825 10826 10827 10828 10829 10830 10831 10832 10833 10834 10835 10836 10837 10838 10839 10840 10841 10842 10843 10844 10845 | /* ** A list of expressions. Each expression may optionally have a ** name. An expr/name combination can be used in several ways, such ** as the list of "expr AS ID" fields following a "SELECT" or in the ** list of "ID = expr" items in an UPDATE. A list of expressions can ** also be used as the argument to a function, in which case the a.zName ** field is not used. */ struct ExprList { int nExpr; /* Number of expressions on the list */ int iECursor; /* VDBE Cursor associated with this ExprList */ struct ExprList_item { /* For each expression in the list */ Expr *pExpr; /* The list of expressions */ char *zName; /* Token associated with this expression */ char *zSpan; /* Original text of the expression */ u8 sortOrder; /* 1 for DESC or 0 for ASC */ u8 done; /* A flag to indicate when processing is finished */ u16 iOrderByCol; /* For ORDER BY, column number in result set */ u16 iAlias; /* Index into Parse.aAlias[] for zName */ } *a; /* Alloc a power of two greater or equal to nExpr */ }; /* ** An instance of this structure is used by the parser to record both ** the parse tree for an expression and the span of input text for an ** expression. |
︙ | ︙ | |||
11088 11089 11090 11091 11092 11093 11094 | 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 */ | | | < | 10915 10916 10917 10918 10919 10920 10921 10922 10923 10924 10925 10926 10927 10928 10929 10930 | char *zName; /* Name of the table */ char *zAlias; /* The "B" part of a "A AS B" phrase. zName is the "A" */ Table *pTab; /* An SQL table corresponding to zName */ Select *pSelect; /* A SELECT statement used in place of a table name */ int addrFillSub; /* Address of subroutine to manifest a subquery */ int regReturn; /* Register holding return address of addrFillSub */ u8 jointype; /* Type of join between this able and the previous */ 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 */ |
︙ | ︙ | |||
11172 11173 11174 11175 11176 11177 11178 | int p1, p2; /* Operands of the opcode used to ends the loop */ union { /* Information that depends on plan.wsFlags */ struct { int nIn; /* Number of entries in aInLoop[] */ struct InLoop { int iCur; /* The VDBE cursor used by this IN operator */ int addrInTop; /* Top of the IN loop */ | < < | 10998 10999 11000 11001 11002 11003 11004 11005 11006 11007 11008 11009 11010 11011 11012 11013 11014 11015 | int p1, p2; /* Operands of the opcode used to ends the loop */ union { /* Information that depends on plan.wsFlags */ struct { int nIn; /* Number of entries in aInLoop[] */ struct InLoop { int iCur; /* The VDBE cursor used by this IN operator */ int addrInTop; /* Top of the IN loop */ } *aInLoop; /* Information about each nested IN operator */ } in; /* Used when plan.wsFlags&WHERE_IN_ABLE */ Index *pCovidx; /* Possible covering index for WHERE_MULTI_OR */ } u; /* The following field is really not part of the current level. But ** we need a place to cache virtual table index information for each ** virtual table in the FROM clause and the WhereLevel structure is ** a convenient place since there is one WhereLevel for each FROM clause ** element. */ |
︙ | ︙ | |||
11272 11273 11274 11275 11276 11277 11278 | /* ** Allowed values for the NameContext, ncFlags field. */ #define NC_AllowAgg 0x01 /* Aggregate functions are allowed here */ #define NC_HasAgg 0x02 /* One or more aggregate functions seen */ #define NC_IsCheck 0x04 /* True if resolving names in a CHECK constraint */ #define NC_InAggFunc 0x08 /* True if analyzing arguments to an agg func */ | < < | 11096 11097 11098 11099 11100 11101 11102 11103 11104 11105 11106 11107 11108 11109 | /* ** Allowed values for the NameContext, ncFlags field. */ #define NC_AllowAgg 0x01 /* Aggregate functions are allowed here */ #define NC_HasAgg 0x02 /* One or more aggregate functions seen */ #define NC_IsCheck 0x04 /* True if resolving names in a CHECK constraint */ #define NC_InAggFunc 0x08 /* True if analyzing arguments to an agg func */ /* ** An instance of the following structure contains all information ** needed to generate code for a single SELECT statement. ** ** nLimit is set to -1 if there is no LIMIT clause. nOffset is set to 0. ** If there is a LIMIT clause, the parser sets nLimit to the value of the |
︙ | ︙ | |||
11318 11319 11320 11321 11322 11323 11324 | Expr *pOffset; /* OFFSET expression. NULL means not used. */ }; /* ** Allowed values for Select.selFlags. The "SF" prefix stands for ** "Select Flag". */ | | | | | | | | | < < | 11140 11141 11142 11143 11144 11145 11146 11147 11148 11149 11150 11151 11152 11153 11154 11155 11156 11157 11158 11159 11160 11161 | Expr *pOffset; /* OFFSET expression. NULL means not used. */ }; /* ** Allowed values for Select.selFlags. The "SF" prefix stands for ** "Select Flag". */ #define SF_Distinct 0x01 /* Output should be DISTINCT */ #define SF_Resolved 0x02 /* Identifiers have been resolved */ #define SF_Aggregate 0x04 /* Contains aggregate functions */ #define SF_UsesEphemeral 0x08 /* Uses the OpenEphemeral opcode */ #define SF_Expanded 0x10 /* sqlite3SelectExpand() called on this */ #define SF_HasTypeInfo 0x20 /* FROM subqueries have Table metadata */ #define SF_UseSorter 0x40 /* Sort using a sorter */ #define SF_Values 0x80 /* Synthesized from VALUES clause */ /* ** 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 */ |
︙ | ︙ | |||
11556 11557 11558 11559 11560 11561 11562 | #define OPFLAG_APPEND 0x08 /* This is likely to be an append */ #define OPFLAG_USESEEKRESULT 0x10 /* Try to avoid a seek in BtreeInsert() */ #define OPFLAG_CLEARCACHE 0x20 /* Clear pseudo-table cache in OP_Column */ #define OPFLAG_LENGTHARG 0x40 /* OP_Column only used for length() */ #define OPFLAG_TYPEOFARG 0x80 /* OP_Column only used for typeof() */ #define OPFLAG_BULKCSR 0x01 /* OP_Open** used to open bulk cursor */ #define OPFLAG_P2ISREG 0x02 /* P2 to OP_Open** is a register number */ | < | 11376 11377 11378 11379 11380 11381 11382 11383 11384 11385 11386 11387 11388 11389 | #define OPFLAG_APPEND 0x08 /* This is likely to be an append */ #define OPFLAG_USESEEKRESULT 0x10 /* Try to avoid a seek in BtreeInsert() */ #define OPFLAG_CLEARCACHE 0x20 /* Clear pseudo-table cache in OP_Column */ #define OPFLAG_LENGTHARG 0x40 /* OP_Column only used for length() */ #define OPFLAG_TYPEOFARG 0x80 /* OP_Column only used for typeof() */ #define OPFLAG_BULKCSR 0x01 /* OP_Open** used to open bulk cursor */ #define OPFLAG_P2ISREG 0x02 /* P2 to OP_Open** is a register number */ /* * Each trigger present in the database schema is stored as an instance of * struct Trigger. * * Pointers to instances of struct Trigger are stored in two ways. * 1. In the "trigHash" hash table (part of the sqlite3* that represents the |
︙ | ︙ | |||
11709 11710 11711 11712 11713 11714 11715 | int nLookaside; /* Default lookaside buffer count */ sqlite3_mem_methods m; /* Low-level memory allocation interface */ sqlite3_mutex_methods mutex; /* Low-level mutex interface */ sqlite3_pcache_methods2 pcache2; /* Low-level page-cache interface */ void *pHeap; /* Heap storage space */ int nHeap; /* Size of pHeap[] */ int mnReq, mxReq; /* Min and max heap requests sizes */ | < < < < < < < | 11528 11529 11530 11531 11532 11533 11534 11535 11536 11537 11538 11539 11540 11541 11542 11543 11544 11545 11546 11547 11548 11549 11550 11551 11552 11553 11554 11555 11556 11557 11558 11559 11560 11561 11562 11563 11564 11565 11566 11567 11568 11569 11570 11571 | int nLookaside; /* Default lookaside buffer count */ sqlite3_mem_methods m; /* Low-level memory allocation interface */ sqlite3_mutex_methods mutex; /* Low-level mutex interface */ sqlite3_pcache_methods2 pcache2; /* Low-level page-cache interface */ void *pHeap; /* Heap storage space */ int nHeap; /* Size of pHeap[] */ int mnReq, mxReq; /* Min and max heap requests sizes */ void *pScratch; /* Scratch memory */ int szScratch; /* Size of each scratch buffer */ int nScratch; /* Number of scratch buffers */ void *pPage; /* Page cache memory */ int szPage; /* Size of each page in pPage[] */ int nPage; /* Number of pages in pPage[] */ int mxParserStack; /* maximum depth of the parser stack */ int sharedCacheEnabled; /* true if shared-cache mode enabled */ /* The above might be initialized to non-zero. The following need to always ** initially be zero, however. */ int isInit; /* True after initialization has finished */ int inProgress; /* True while initialization in progress */ int isMutexInit; /* True after mutexes are initialized */ int isMallocInit; /* True after malloc is initialized */ int isPCacheInit; /* True after malloc is initialized */ sqlite3_mutex *pInitMutex; /* Mutex used by sqlite3_initialize() */ int nRefInitMutex; /* Number of users of pInitMutex */ void (*xLog)(void*,int,const char*); /* Function for logging */ void *pLogArg; /* First argument to xLog() */ int bLocaltimeFault; /* True to fail localtime() calls */ }; /* ** Context pointer passed down through the tree-walk. */ struct Walker { int (*xExprCallback)(Walker*, Expr*); /* Callback for expressions */ int (*xSelectCallback)(Walker*,Select*); /* Callback for SELECTs */ Parse *pParse; /* Parser context. */ int walkerDepth; /* Number of subqueries */ union { /* Extra data for callback */ NameContext *pNC; /* Naming context */ int i; /* Integer value */ SrcList *pSrcList; /* FROM clause */ struct SrcCount *pSrcCount; /* Counting column references */ } u; }; |
︙ | ︙ | |||
12043 12044 12045 12046 12047 12048 12049 | SQLITE_PRIVATE void sqlite3IdListDelete(sqlite3*, IdList*); SQLITE_PRIVATE void sqlite3SrcListDelete(sqlite3*, SrcList*); SQLITE_PRIVATE Index *sqlite3CreateIndex(Parse*,Token*,Token*,SrcList*,ExprList*,int,Token*, Token*, int, int); SQLITE_PRIVATE void sqlite3DropIndex(Parse*, SrcList*, int); SQLITE_PRIVATE int sqlite3Select(Parse*, Select*, SelectDest*); SQLITE_PRIVATE Select *sqlite3SelectNew(Parse*,ExprList*,SrcList*,Expr*,ExprList*, | | | | 11855 11856 11857 11858 11859 11860 11861 11862 11863 11864 11865 11866 11867 11868 11869 11870 11871 11872 11873 11874 11875 | SQLITE_PRIVATE void sqlite3IdListDelete(sqlite3*, IdList*); SQLITE_PRIVATE void sqlite3SrcListDelete(sqlite3*, SrcList*); SQLITE_PRIVATE Index *sqlite3CreateIndex(Parse*,Token*,Token*,SrcList*,ExprList*,int,Token*, Token*, int, int); SQLITE_PRIVATE void sqlite3DropIndex(Parse*, SrcList*, int); SQLITE_PRIVATE int sqlite3Select(Parse*, Select*, SelectDest*); SQLITE_PRIVATE Select *sqlite3SelectNew(Parse*,ExprList*,SrcList*,Expr*,ExprList*, Expr*,ExprList*,int,Expr*,Expr*); SQLITE_PRIVATE void sqlite3SelectDelete(sqlite3*, Select*); SQLITE_PRIVATE Table *sqlite3SrcListLookup(Parse*, SrcList*); SQLITE_PRIVATE int sqlite3IsReadOnly(Parse*, Table*, int); SQLITE_PRIVATE void sqlite3OpenTable(Parse*, int iCur, int iDb, Table*, int); #if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY) SQLITE_PRIVATE Expr *sqlite3LimitWhere(Parse *, SrcList *, Expr *, ExprList *, Expr *, Expr *, char *); #endif 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,int); SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo*); SQLITE_PRIVATE int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int, u8); SQLITE_PRIVATE void sqlite3ExprCodeGetColumnOfTable(Vdbe*, Table*, int, int, int); |
︙ | ︙ | |||
12117 12118 12119 12120 12121 12122 12123 | SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(Parse*,Table*,int,int, int*,int,int,int,int,int*); SQLITE_PRIVATE void sqlite3CompleteInsertion(Parse*, Table*, int, int, int*, int, int, int); SQLITE_PRIVATE int sqlite3OpenTableAndIndices(Parse*, Table*, int, int); SQLITE_PRIVATE void sqlite3BeginWriteOperation(Parse*, int, int); SQLITE_PRIVATE void sqlite3MultiWrite(Parse*); SQLITE_PRIVATE void sqlite3MayAbort(Parse*); | | | 11929 11930 11931 11932 11933 11934 11935 11936 11937 11938 11939 11940 11941 11942 11943 | SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(Parse*,Table*,int,int, int*,int,int,int,int,int*); SQLITE_PRIVATE void sqlite3CompleteInsertion(Parse*, Table*, int, int, int*, int, int, int); SQLITE_PRIVATE int sqlite3OpenTableAndIndices(Parse*, Table*, int, int); SQLITE_PRIVATE void sqlite3BeginWriteOperation(Parse*, int, int); SQLITE_PRIVATE void sqlite3MultiWrite(Parse*); SQLITE_PRIVATE void sqlite3MayAbort(Parse*); SQLITE_PRIVATE void sqlite3HaltConstraint(Parse*, int, char*, int); SQLITE_PRIVATE Expr *sqlite3ExprDup(sqlite3*,Expr*,int); SQLITE_PRIVATE ExprList *sqlite3ExprListDup(sqlite3*,ExprList*,int); SQLITE_PRIVATE SrcList *sqlite3SrcListDup(sqlite3*,SrcList*,int); SQLITE_PRIVATE IdList *sqlite3IdListDup(sqlite3*,IdList*); SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3*,Select*,int); SQLITE_PRIVATE void sqlite3FuncDefInsert(FuncDefHash*, FuncDef*); SQLITE_PRIVATE FuncDef *sqlite3FindFunction(sqlite3*,const char*,int,int,u8,u8); |
︙ | ︙ | |||
12230 12231 12232 12233 12234 12235 12236 | ** x = sqlite3GetVarint32( A, &B ); ** x = sqlite3PutVarint32( A, B ); ** ** x = getVarint32( A, B ); ** x = putVarint32( A, B ); ** */ | | < | < < < < < < < < < | | | 12042 12043 12044 12045 12046 12047 12048 12049 12050 12051 12052 12053 12054 12055 12056 12057 12058 12059 12060 12061 12062 12063 12064 12065 12066 12067 12068 12069 12070 12071 12072 12073 12074 12075 12076 12077 12078 | ** x = sqlite3GetVarint32( A, &B ); ** x = sqlite3PutVarint32( A, B ); ** ** x = getVarint32( A, B ); ** x = putVarint32( A, B ); ** */ #define getVarint32(A,B) (u8)((*(A)<(u8)0x80) ? ((B) = (u32)*(A)),1 : sqlite3GetVarint32((A), (u32 *)&(B))) #define putVarint32(A,B) (u8)(((u32)(B)<(u32)0x80) ? (*(A) = (unsigned char)(B)),1 : sqlite3PutVarint32((A), (B))) #define getVarint sqlite3GetVarint #define putVarint sqlite3PutVarint SQLITE_PRIVATE const char *sqlite3IndexAffinityStr(Vdbe *, Index *); SQLITE_PRIVATE void sqlite3TableAffinityStr(Vdbe *, Table *); SQLITE_PRIVATE char sqlite3CompareAffinity(Expr *pExpr, char aff2); SQLITE_PRIVATE int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity); SQLITE_PRIVATE char sqlite3ExprAffinity(Expr *pExpr); SQLITE_PRIVATE int sqlite3Atoi64(const char*, i64*, int, u8); SQLITE_PRIVATE void sqlite3Error(sqlite3*, int, const char*,...); SQLITE_PRIVATE void *sqlite3HexToBlob(sqlite3*, const char *z, int n); SQLITE_PRIVATE u8 sqlite3HexToInt(int h); SQLITE_PRIVATE int sqlite3TwoPartName(Parse *, Token *, Token *, Token **); SQLITE_PRIVATE const char *sqlite3ErrStr(int); SQLITE_PRIVATE int sqlite3ReadSchema(Parse *pParse); SQLITE_PRIVATE CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char*,int); SQLITE_PRIVATE CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char*zName); SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr); SQLITE_PRIVATE Expr *sqlite3ExprSetColl(Expr*, CollSeq*); SQLITE_PRIVATE Expr *sqlite3ExprSetCollByToken(Parse *pParse, Expr*, Token*); SQLITE_PRIVATE int sqlite3CheckCollSeq(Parse *, CollSeq *); SQLITE_PRIVATE int sqlite3CheckObjectName(Parse *, const char *); SQLITE_PRIVATE void sqlite3VdbeSetChanges(sqlite3 *, int); SQLITE_PRIVATE int sqlite3AddInt64(i64*,i64); SQLITE_PRIVATE int sqlite3SubInt64(i64*,i64); SQLITE_PRIVATE int sqlite3MulInt64(i64*,i64); SQLITE_PRIVATE int sqlite3AbsInt32(int); |
︙ | ︙ | |||
12309 12310 12311 12312 12313 12314 12315 | SQLITE_PRIVATE void sqlite3AlterFunctions(void); SQLITE_PRIVATE void sqlite3AlterRenameTable(Parse*, SrcList*, Token*); SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *, int *); SQLITE_PRIVATE void sqlite3NestedParse(Parse*, const char*, ...); SQLITE_PRIVATE void sqlite3ExpirePreparedStatements(sqlite3*); SQLITE_PRIVATE int sqlite3CodeSubselect(Parse *, Expr *, int, int); SQLITE_PRIVATE void sqlite3SelectPrep(Parse*, Select*, NameContext*); | < | 12111 12112 12113 12114 12115 12116 12117 12118 12119 12120 12121 12122 12123 12124 | SQLITE_PRIVATE void sqlite3AlterFunctions(void); SQLITE_PRIVATE void sqlite3AlterRenameTable(Parse*, SrcList*, Token*); SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *, int *); SQLITE_PRIVATE void sqlite3NestedParse(Parse*, const char*, ...); SQLITE_PRIVATE void sqlite3ExpirePreparedStatements(sqlite3*); SQLITE_PRIVATE int sqlite3CodeSubselect(Parse *, Expr *, int, int); SQLITE_PRIVATE void sqlite3SelectPrep(Parse*, Select*, NameContext*); SQLITE_PRIVATE int sqlite3ResolveExprNames(NameContext*, Expr*); SQLITE_PRIVATE void sqlite3ResolveSelectNames(Parse*, Select*, NameContext*); SQLITE_PRIVATE int sqlite3ResolveOrderGroupBy(Parse*, Select*, ExprList*, const char*); SQLITE_PRIVATE void sqlite3ColumnDefault(Vdbe *, Table *, int, int); SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *, Token *); SQLITE_PRIVATE void sqlite3AlterBeginAddColumn(Parse *, SrcList *); SQLITE_PRIVATE CollSeq *sqlite3GetCollSeq(Parse*, u8, CollSeq *, const char*); |
︙ | ︙ | |||
12448 12449 12450 12451 12452 12453 12454 | #define sqlite3FkCheck(a,b,c,d) #define sqlite3FkDropTable(a,b,c) #define sqlite3FkOldmask(a,b) 0 #define sqlite3FkRequired(a,b,c,d) 0 #endif #ifndef SQLITE_OMIT_FOREIGN_KEY SQLITE_PRIVATE void sqlite3FkDelete(sqlite3 *, Table*); | < < | 12249 12250 12251 12252 12253 12254 12255 12256 12257 12258 12259 12260 12261 12262 12263 12264 | #define sqlite3FkCheck(a,b,c,d) #define sqlite3FkDropTable(a,b,c) #define sqlite3FkOldmask(a,b) 0 #define sqlite3FkRequired(a,b,c,d) 0 #endif #ifndef SQLITE_OMIT_FOREIGN_KEY SQLITE_PRIVATE void sqlite3FkDelete(sqlite3 *, Table*); #else #define sqlite3FkDelete(a,b) #endif /* ** Available fault injectors. Should be numbered beginning with 0. */ #define SQLITE_FAULTINJECTOR_MALLOC 0 |
︙ | ︙ | |||
12476 12477 12478 12479 12480 12481 12482 | #else #define sqlite3BeginBenignMalloc() #define sqlite3EndBenignMalloc() #endif #define IN_INDEX_ROWID 1 #define IN_INDEX_EPH 2 | | < < < | 12275 12276 12277 12278 12279 12280 12281 12282 12283 12284 12285 12286 12287 12288 12289 12290 12291 12292 12293 12294 12295 12296 12297 | #else #define sqlite3BeginBenignMalloc() #define sqlite3EndBenignMalloc() #endif #define IN_INDEX_ROWID 1 #define IN_INDEX_EPH 2 #define IN_INDEX_INDEX 3 SQLITE_PRIVATE int sqlite3FindInIndex(Parse *, Expr *, int*); #ifdef SQLITE_ENABLE_ATOMIC_WRITE SQLITE_PRIVATE int sqlite3JournalOpen(sqlite3_vfs *, const char *, sqlite3_file *, int, int); SQLITE_PRIVATE int sqlite3JournalSize(sqlite3_vfs *); SQLITE_PRIVATE int sqlite3JournalCreate(sqlite3_file *); #else #define sqlite3JournalSize(pVfs) ((pVfs)->szOsFile) #endif SQLITE_PRIVATE void sqlite3MemJournalOpen(sqlite3_file *); SQLITE_PRIVATE int sqlite3MemJournalSize(void); SQLITE_PRIVATE int sqlite3IsMemJournal(sqlite3_file *); #if SQLITE_MAX_EXPR_DEPTH>0 |
︙ | ︙ | |||
12739 12740 12741 12742 12743 12744 12745 | 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,0,0},/* pcache2 */ (void*)0, /* pHeap */ 0, /* nHeap */ 0, 0, /* mnHeap, mxHeap */ | < < < < < < | 12535 12536 12537 12538 12539 12540 12541 12542 12543 12544 12545 12546 12547 12548 12549 12550 12551 12552 12553 12554 12555 12556 12557 12558 12559 12560 12561 12562 12563 12564 12565 12566 12567 | 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,0,0},/* pcache2 */ (void*)0, /* pHeap */ 0, /* nHeap */ 0, 0, /* mnHeap, mxHeap */ (void*)0, /* pScratch */ 0, /* szScratch */ 0, /* nScratch */ (void*)0, /* pPage */ 0, /* szPage */ 0, /* nPage */ 0, /* mxParserStack */ 0, /* sharedCacheEnabled */ /* All the rest should always be initialized to zero */ 0, /* isInit */ 0, /* inProgress */ 0, /* isMutexInit */ 0, /* isMallocInit */ 0, /* isPCacheInit */ 0, /* pInitMutex */ 0, /* nRefInitMutex */ 0, /* xLog */ 0, /* pLogArg */ 0, /* bLocaltimeFault */ }; /* ** Hash table for global functions - functions common to all ** database connections. After initialization, this table is ** read-only. |
︙ | ︙ | |||
12863 12864 12865 12866 12867 12868 12869 12870 12871 12872 12873 12874 12875 12876 | "CASE_SENSITIVE_LIKE", #endif #ifdef SQLITE_CHECK_PAGES "CHECK_PAGES", #endif #ifdef SQLITE_COVERAGE_TEST "COVERAGE_TEST", #endif #ifdef SQLITE_DEBUG "DEBUG", #endif #ifdef SQLITE_DEFAULT_LOCKING_MODE "DEFAULT_LOCKING_MODE=" CTIMEOPT_VAL(SQLITE_DEFAULT_LOCKING_MODE), #endif | > > > < < < | 12653 12654 12655 12656 12657 12658 12659 12660 12661 12662 12663 12664 12665 12666 12667 12668 12669 12670 12671 12672 12673 12674 12675 12676 | "CASE_SENSITIVE_LIKE", #endif #ifdef SQLITE_CHECK_PAGES "CHECK_PAGES", #endif #ifdef SQLITE_COVERAGE_TEST "COVERAGE_TEST", #endif #ifdef SQLITE_CURDIR "CURDIR", #endif #ifdef SQLITE_DEBUG "DEBUG", #endif #ifdef SQLITE_DEFAULT_LOCKING_MODE "DEFAULT_LOCKING_MODE=" CTIMEOPT_VAL(SQLITE_DEFAULT_LOCKING_MODE), #endif #ifdef SQLITE_DISABLE_DIRSYNC "DISABLE_DIRSYNC", #endif #ifdef SQLITE_DISABLE_LFS "DISABLE_LFS", #endif #ifdef SQLITE_ENABLE_ATOMIC_WRITE |
︙ | ︙ | |||
12963 12964 12965 12966 12967 12968 12969 | #endif #ifdef SQLITE_INT64_TYPE "INT64_TYPE", #endif #ifdef SQLITE_LOCK_TRACE "LOCK_TRACE", #endif | < < < | 12753 12754 12755 12756 12757 12758 12759 12760 12761 12762 12763 12764 12765 12766 | #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 |
︙ | ︙ | |||
13023 13024 13025 13026 13027 13028 13029 13030 13031 13032 13033 13034 13035 13036 | #endif #ifdef SQLITE_OMIT_CAST "OMIT_CAST", #endif #ifdef SQLITE_OMIT_CHECK "OMIT_CHECK", #endif #ifdef SQLITE_OMIT_COMPLETE "OMIT_COMPLETE", #endif #ifdef SQLITE_OMIT_COMPOUND_SELECT "OMIT_COMPOUND_SELECT", #endif #ifdef SQLITE_OMIT_DATETIME_FUNCS | > > > > > | 12810 12811 12812 12813 12814 12815 12816 12817 12818 12819 12820 12821 12822 12823 12824 12825 12826 12827 12828 | #endif #ifdef SQLITE_OMIT_CAST "OMIT_CAST", #endif #ifdef SQLITE_OMIT_CHECK "OMIT_CHECK", #endif /* // redundant ** #ifdef SQLITE_OMIT_COMPILEOPTION_DIAGS ** "OMIT_COMPILEOPTION_DIAGS", ** #endif */ #ifdef SQLITE_OMIT_COMPLETE "OMIT_COMPLETE", #endif #ifdef SQLITE_OMIT_COMPOUND_SELECT "OMIT_COMPOUND_SELECT", #endif #ifdef SQLITE_OMIT_DATETIME_FUNCS |
︙ | ︙ | |||
13076 13077 13078 13079 13080 13081 13082 13083 13084 13085 13086 13087 13088 13089 | "OMIT_LOCALTIME", #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 | > > > | 12868 12869 12870 12871 12872 12873 12874 12875 12876 12877 12878 12879 12880 12881 12882 12883 12884 | "OMIT_LOCALTIME", #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 |
︙ | ︙ | |||
13164 13165 13166 13167 13168 13169 13170 | #endif #ifdef SQLITE_SOUNDEX "SOUNDEX", #endif #ifdef SQLITE_TCL "TCL", #endif | | | | 12959 12960 12961 12962 12963 12964 12965 12966 12967 12968 12969 12970 12971 12972 12973 12974 12975 12976 12977 12978 12979 | #endif #ifdef SQLITE_SOUNDEX "SOUNDEX", #endif #ifdef SQLITE_TCL "TCL", #endif #ifdef SQLITE_TEMP_STORE "TEMP_STORE=" CTIMEOPT_VAL(SQLITE_TEMP_STORE), #endif #ifdef SQLITE_TEST "TEST", #endif #ifdef SQLITE_THREADSAFE "THREADSAFE=" CTIMEOPT_VAL(SQLITE_THREADSAFE), #endif #ifdef SQLITE_USE_ALLOCA "USE_ALLOCA", #endif #ifdef SQLITE_ZERO_MALLOC "ZERO_MALLOC" |
︙ | ︙ | |||
13196 13197 13198 13199 13200 13201 13202 | int i, n; if( sqlite3StrNICmp(zOptName, "SQLITE_", 7)==0 ) zOptName += 7; n = sqlite3Strlen30(zOptName); /* Since ArraySize(azCompileOpt) is normally in single digits, a ** linear search is adequate. No need for a binary search. */ for(i=0; i<ArraySize(azCompileOpt); i++){ | | | < < < | 12991 12992 12993 12994 12995 12996 12997 12998 12999 13000 13001 13002 13003 13004 13005 13006 | int i, n; if( sqlite3StrNICmp(zOptName, "SQLITE_", 7)==0 ) zOptName += 7; n = sqlite3Strlen30(zOptName); /* Since ArraySize(azCompileOpt) is normally in single digits, a ** linear search is adequate. No need for a binary search. */ for(i=0; i<ArraySize(azCompileOpt); i++){ if( (sqlite3StrNICmp(zOptName, azCompileOpt[i], n)==0) && ( (azCompileOpt[i][n]==0) || (azCompileOpt[i][n]=='=') ) ) return 1; } return 0; } /* ** Return the N-th compile-time option string. If N is out of range, ** return a NULL pointer. |
︙ | ︙ | |||
13257 13258 13259 13260 13261 13262 13263 | ** source code file "vdbe.c". When that file became too big (over ** 6000 lines long) it was split up into several smaller files and ** this header information was factored out. */ #ifndef _VDBEINT_H_ #define _VDBEINT_H_ | < < < < < < < < | 13049 13050 13051 13052 13053 13054 13055 13056 13057 13058 13059 13060 13061 13062 | ** source code file "vdbe.c". When that file became too big (over ** 6000 lines long) it was split up into several smaller files and ** this header information was factored out. */ #ifndef _VDBEINT_H_ #define _VDBEINT_H_ /* ** SQL is translated into a sequence of instructions to be ** executed by a virtual machine. Each instruction is an instance ** of the following structure. */ typedef struct VdbeOp Op; |
︙ | ︙ | |||
13310 13311 13312 13313 13314 13315 13316 | 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 */ | < | 13094 13095 13096 13097 13098 13099 13100 13101 13102 13103 13104 13105 13106 13107 | Bool useRandomRowid; /* Generate new record numbers semi-randomly */ Bool nullRow; /* True if pointing to a row with no data */ Bool deferredMoveto; /* A call to sqlite3BtreeMoveto() is needed */ Bool isTable; /* True if a table requiring integer keys */ Bool isIndex; /* True if an index containing keys only - no data */ Bool isOrdered; /* True if the underlying table is BTREE_UNORDERED */ Bool isSorter; /* True if a new-style sorter */ 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 */ |
︙ | ︙ | |||
13370 13371 13372 13373 13374 13375 13376 | VdbeFrame *pParent; /* Parent of this frame, or NULL if parent is main */ Op *aOp; /* Program instructions for parent frame */ Mem *aMem; /* Array of memory cells for parent frame */ u8 *aOnceFlag; /* Array of OP_Once flags for parent frame */ VdbeCursor **apCsr; /* Array of Vdbe cursors for parent frame */ void *token; /* Copy of SubProgram.token */ i64 lastRowid; /* Last insert rowid (sqlite3.lastRowid) */ | | | 13153 13154 13155 13156 13157 13158 13159 13160 13161 13162 13163 13164 13165 13166 13167 | VdbeFrame *pParent; /* Parent of this frame, or NULL if parent is main */ Op *aOp; /* Program instructions for parent frame */ Mem *aMem; /* Array of memory cells for parent frame */ u8 *aOnceFlag; /* Array of OP_Once flags for parent frame */ VdbeCursor **apCsr; /* Array of Vdbe cursors for parent frame */ void *token; /* Copy of SubProgram.token */ i64 lastRowid; /* Last insert rowid (sqlite3.lastRowid) */ u16 nCursor; /* Number of entries in apCsr */ int pc; /* Program Counter in parent (calling) frame */ int nOp; /* Size of aOp array */ int nMem; /* Number of entries in aMem */ int nOnceFlag; /* Number of entries in aOnceFlag */ int nChildMem; /* Number of memory cells for child frame */ int nChildCsr; /* Number of cursors for child frame */ int nChange; /* Statement changes (Vdbe.nChanges) */ |
︙ | ︙ | |||
13556 13557 13558 13559 13560 13561 13562 | Mem *pResultSet; /* Pointer to an array of results */ int nMem; /* Number of memory locations currently allocated */ int nOp; /* Number of instructions in the program */ int nOpAlloc; /* Number of slots allocated for aOp[] */ int nLabel; /* Number of labels used */ int *aLabel; /* Space to hold the labels */ u16 nResColumn; /* Number of columns in one row of the result set */ | | | 13339 13340 13341 13342 13343 13344 13345 13346 13347 13348 13349 13350 13351 13352 13353 | Mem *pResultSet; /* Pointer to an array of results */ int nMem; /* Number of memory locations currently allocated */ int nOp; /* Number of instructions in the program */ int nOpAlloc; /* Number of slots allocated for aOp[] */ int nLabel; /* Number of labels used */ int *aLabel; /* Space to hold the labels */ u16 nResColumn; /* Number of columns in one row of the result set */ u16 nCursor; /* Number of slots in apCsr[] */ u32 magic; /* Magic number for sanity checking */ char *zErrMsg; /* Error message written here */ Vdbe *pPrev,*pNext; /* Linked list of VDBEs with the same Vdbe.db */ VdbeCursor **apCsr; /* One element of this array for each open cursor */ Mem *aVar; /* Values for the OP_Variable opcode. */ char **azVar; /* Name of variables */ ynVar nVar; /* Number of entries in aVar[] */ |
︙ | ︙ | |||
13676 13677 13678 13679 13680 13681 13682 13683 13684 13685 13686 13687 13688 13689 13690 13691 13692 13693 13694 13695 13696 | 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); SQLITE_PRIVATE int sqlite3VdbeTransferError(Vdbe *p); SQLITE_PRIVATE int sqlite3VdbeSorterInit(sqlite3 *, VdbeCursor *); SQLITE_PRIVATE void sqlite3VdbeSorterClose(sqlite3 *, VdbeCursor *); SQLITE_PRIVATE int sqlite3VdbeSorterRowkey(const VdbeCursor *, Mem *); SQLITE_PRIVATE int sqlite3VdbeSorterNext(sqlite3 *, const VdbeCursor *, int *); SQLITE_PRIVATE int sqlite3VdbeSorterRewind(sqlite3 *, const VdbeCursor *, int *); SQLITE_PRIVATE int sqlite3VdbeSorterWrite(sqlite3 *, const VdbeCursor *, Mem *); SQLITE_PRIVATE int sqlite3VdbeSorterCompare(const VdbeCursor *, Mem *, int *); #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) | > > > > > > > > > > | 13459 13460 13461 13462 13463 13464 13465 13466 13467 13468 13469 13470 13471 13472 13473 13474 13475 13476 13477 13478 13479 13480 13481 13482 13483 13484 13485 13486 13487 13488 13489 | 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); SQLITE_PRIVATE int sqlite3VdbeTransferError(Vdbe *p); #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(const VdbeCursor *, Mem *); SQLITE_PRIVATE int sqlite3VdbeSorterNext(sqlite3 *, const VdbeCursor *, int *); SQLITE_PRIVATE int sqlite3VdbeSorterRewind(sqlite3 *, const VdbeCursor *, int *); SQLITE_PRIVATE int sqlite3VdbeSorterWrite(sqlite3 *, const VdbeCursor *, Mem *); SQLITE_PRIVATE int sqlite3VdbeSorterCompare(const 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) |
︙ | ︙ | |||
13914 13915 13916 13917 13918 13919 13920 | */ case SQLITE_DBSTATUS_STMT_USED: { struct Vdbe *pVdbe; /* Used to iterate through VMs */ int nByte = 0; /* Used to accumulate return value */ db->pnBytesFreed = &nByte; for(pVdbe=db->pVdbe; pVdbe; pVdbe=pVdbe->pNext){ | | < | 13707 13708 13709 13710 13711 13712 13713 13714 13715 13716 13717 13718 13719 13720 13721 | */ case SQLITE_DBSTATUS_STMT_USED: { struct Vdbe *pVdbe; /* Used to iterate through VMs */ int nByte = 0; /* Used to accumulate return value */ db->pnBytesFreed = &nByte; for(pVdbe=db->pVdbe; pVdbe; pVdbe=pVdbe->pNext){ sqlite3VdbeDeleteObject(db, pVdbe); } db->pnBytesFreed = 0; *pHighwater = 0; *pCurrent = nByte; break; |
︙ | ︙ | |||
15231 15232 15233 15234 15235 15236 15237 | int bExtend, /* True to extend file if necessary */ void volatile **pp /* OUT: Pointer to mapping */ ){ DO_OS_MALLOC_TEST(id); return id->pMethods->xShmMap(id, iPage, pgsz, bExtend, pp); } | < < < < < < < < < < < < < < < < < < < < | 15023 15024 15025 15026 15027 15028 15029 15030 15031 15032 15033 15034 15035 15036 | int bExtend, /* True to extend file if necessary */ void volatile **pp /* OUT: Pointer to mapping */ ){ DO_OS_MALLOC_TEST(id); return id->pMethods->xShmMap(id, iPage, pgsz, bExtend, pp); } /* ** The next group of routines are convenience wrappers around the ** VFS methods. */ SQLITE_PRIVATE int sqlite3OsOpen( sqlite3_vfs *pVfs, const char *zPath, |
︙ | ︙ | |||
21486 21487 21488 21489 21490 21491 21492 | ** ** If some prefix of the input string is a valid number, this routine ** returns FALSE but it still converts the prefix and writes the result ** into *pResult. */ SQLITE_PRIVATE int sqlite3AtoF(const char *z, double *pResult, int length, u8 enc){ #ifndef SQLITE_OMIT_FLOATING_POINT | | < < | < < < < < < < < < < | 21258 21259 21260 21261 21262 21263 21264 21265 21266 21267 21268 21269 21270 21271 21272 21273 21274 21275 21276 21277 21278 21279 21280 21281 21282 21283 21284 21285 21286 | ** ** If some prefix of the input string is a valid number, this routine ** returns FALSE but it still converts the prefix and writes the result ** into *pResult. */ SQLITE_PRIVATE int sqlite3AtoF(const char *z, double *pResult, int length, u8 enc){ #ifndef SQLITE_OMIT_FLOATING_POINT int incr = (enc==SQLITE_UTF8?1:2); const char *zEnd = z + length; /* sign * significand * (10 ^ (esign * exponent)) */ int sign = 1; /* sign of significand */ i64 s = 0; /* significand */ int d = 0; /* adjust exponent for shifting decimal point */ int esign = 1; /* sign of exponent */ int e = 0; /* exponent */ int eValid = 1; /* True exponent is either not used or is well-formed */ double result; int nDigits = 0; *pResult = 0.0; /* Default return value, in case of an error */ if( enc==SQLITE_UTF16BE ) z++; /* skip leading spaces */ while( z<zEnd && sqlite3Isspace(*z) ) z+=incr; if( z>=zEnd ) return 0; /* get sign of significand */ if( *z=='-' ){ |
︙ | ︙ | |||
21645 21646 21647 21648 21649 21650 21651 | } } /* store the result */ *pResult = result; /* return true if number and no extra non-whitespace chracters after */ | | | 21405 21406 21407 21408 21409 21410 21411 21412 21413 21414 21415 21416 21417 21418 21419 | } } /* store the result */ *pResult = result; /* return true if number and no extra non-whitespace chracters after */ return z>=zEnd && nDigits>0 && eValid; #else return !sqlite3Atoi64(z, pResult, length, enc); #endif /* SQLITE_OMIT_FLOATING_POINT */ } /* ** Compare the 19-character string zNum against the text representation |
︙ | ︙ | |||
21694 21695 21696 21697 21698 21699 21700 | ** integer, then write that value into *pNum and return 0. ** ** If zNum is exactly 9223372036854665808, return 2. This special ** case is broken out because while 9223372036854665808 cannot be a ** signed 64-bit integer, its negative -9223372036854665808 can be. ** ** If zNum is too big for a 64-bit integer and is not | | < | < < | < < < < < < < < < | 21454 21455 21456 21457 21458 21459 21460 21461 21462 21463 21464 21465 21466 21467 21468 21469 21470 21471 21472 21473 21474 21475 21476 21477 21478 21479 21480 21481 21482 | ** integer, then write that value into *pNum and return 0. ** ** If zNum is exactly 9223372036854665808, return 2. This special ** case is broken out because while 9223372036854665808 cannot be a ** signed 64-bit integer, its negative -9223372036854665808 can be. ** ** If zNum is too big for a 64-bit integer and is not ** 9223372036854665808 then return 1. ** ** length is the number of bytes in the string (bytes, not characters). ** The string is not necessarily zero-terminated. The encoding is ** given by enc. */ SQLITE_PRIVATE int sqlite3Atoi64(const char *zNum, i64 *pNum, int length, u8 enc){ int incr = (enc==SQLITE_UTF8?1:2); u64 u = 0; int neg = 0; /* assume positive */ int i; int c = 0; const char *zStart; const char *zEnd = zNum + length; if( enc==SQLITE_UTF16BE ) zNum++; while( zNum<zEnd && sqlite3Isspace(*zNum) ) zNum+=incr; if( zNum<zEnd ){ if( *zNum=='-' ){ neg = 1; zNum+=incr; }else if( *zNum=='+' ){ zNum+=incr; |
︙ | ︙ | |||
21745 21746 21747 21748 21749 21750 21751 | *pNum = -(i64)u; }else{ *pNum = (i64)u; } testcase( i==18 ); testcase( i==19 ); testcase( i==20 ); | | | 21493 21494 21495 21496 21497 21498 21499 21500 21501 21502 21503 21504 21505 21506 21507 | *pNum = -(i64)u; }else{ *pNum = (i64)u; } testcase( i==18 ); testcase( i==19 ); testcase( i==20 ); if( (c!=0 && &zNum[i]<zEnd) || (i==0 && zStart==zNum) || i>19*incr ){ /* zNum is empty or contains non-numeric text or is longer ** than 19 digits (thus guaranteeing that it is too large) */ return 1; }else if( i<19*incr ){ /* Less than 19 digits, so we know that it fits in 64 bits */ assert( u<=LARGEST_INT64 ); return 0; |
︙ | ︙ | |||
22629 22630 22631 22632 22633 22634 22635 | pEntry->chain = elem->next; } pEntry->count--; assert( pEntry->count>=0 ); } sqlite3_free( elem ); pH->count--; | | | 22377 22378 22379 22380 22381 22382 22383 22384 22385 22386 22387 22388 22389 22390 22391 | pEntry->chain = elem->next; } pEntry->count--; assert( pEntry->count>=0 ); } sqlite3_free( elem ); pH->count--; if( pH->count<=0 ){ assert( pH->first==0 ); assert( pH->count==0 ); sqlite3HashClear(pH); } } /* Attempt to locate an element of the hash table pH with a key |
︙ | ︙ | |||
22927 22928 22929 22930 22931 22932 22933 | ** * sqlite3_vfs method implementations. ** * Locking primitives for the proxy uber-locking-method. (MacOSX only) ** * Definitions of sqlite3_vfs objects for all locking methods ** plus implementations of sqlite3_os_init() and sqlite3_os_end(). */ #if SQLITE_OS_UNIX /* This file is used on unix only */ | < < < < < < < | 22675 22676 22677 22678 22679 22680 22681 22682 22683 22684 22685 22686 22687 22688 | ** * sqlite3_vfs method implementations. ** * Locking primitives for the proxy uber-locking-method. (MacOSX only) ** * Definitions of sqlite3_vfs objects for all locking methods ** plus implementations of sqlite3_os_init() and sqlite3_os_end(). */ #if SQLITE_OS_UNIX /* This file is used on unix only */ /* ** There are various methods for file locking used for concurrency ** control: ** ** 1. POSIX locking (the default), ** 2. No locking, ** 3. Dot-file locking, |
︙ | ︙ | |||
23007 23008 23009 23010 23011 23012 23013 | #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> /* #include <time.h> */ #include <sys/time.h> #include <errno.h> | | | 22748 22749 22750 22751 22752 22753 22754 22755 22756 22757 22758 22759 22760 22761 22762 | #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 # include <sys/ioctl.h> # if OS_VXWORKS |
︙ | ︙ | |||
23106 23107 23108 23109 23110 23111 23112 | unsigned short int ctrlFlags; /* Behavioral bits. UNIXFILE_* flags */ int lastErrno; /* The unix errno from last I/O error */ void *lockingContext; /* Locking style specific state */ UnixUnusedFd *pUnused; /* Pre-allocated UnixUnusedFd */ const char *zPath; /* Name of the file */ unixShm *pShm; /* Shared memory segment information */ int szChunk; /* Configured by FCNTL_CHUNK_SIZE */ | < < < < < < < < < < < | 22847 22848 22849 22850 22851 22852 22853 22854 22855 22856 22857 22858 22859 22860 22861 22862 22863 22864 22865 22866 22867 22868 22869 22870 22871 22872 22873 22874 22875 22876 22877 22878 22879 22880 22881 | unsigned short int ctrlFlags; /* Behavioral bits. UNIXFILE_* flags */ int lastErrno; /* The unix errno from last I/O error */ void *lockingContext; /* Locking style specific state */ UnixUnusedFd *pUnused; /* Pre-allocated UnixUnusedFd */ const char *zPath; /* Name of the file */ unixShm *pShm; /* Shared memory segment information */ int szChunk; /* Configured by FCNTL_CHUNK_SIZE */ #if SQLITE_ENABLE_LOCKING_STYLE int openFlags; /* The flags specified at open() */ #endif #if SQLITE_ENABLE_LOCKING_STYLE || defined(__APPLE__) unsigned fsFlags; /* cached details from statfs() */ #endif #if OS_VXWORKS struct vxworksFileId *pId; /* Unique file ID */ #endif #ifdef SQLITE_DEBUG /* The next group of variables are used to track whether or not the ** transaction counter in bytes 24-27 of database files are updated ** whenever any part of the database changes. An assertion fault will ** occur if a file is updated without also updating the transaction ** counter. This test is made to avoid new problems similar to the ** one described by ticket #3584. */ unsigned char transCntrChng; /* True if the transaction counter changed */ unsigned char dbUpdate; /* True if any part of database file changed */ unsigned char inNormalWrite; /* True if in a normal write operation */ #endif #ifdef SQLITE_TEST /* In test mode, increase the size of this structure a bit so that ** it is larger than the struct CrashFile defined in test6.c. */ char aPadding[32]; #endif }; |
︙ | ︙ | |||
23161 23162 23163 23164 23165 23166 23167 | #else # define UNIXFILE_DIRSYNC 0x00 #endif #define UNIXFILE_PSOW 0x10 /* SQLITE_IOCAP_POWERSAFE_OVERWRITE */ #define UNIXFILE_DELETE 0x20 /* Delete on close */ #define UNIXFILE_URI 0x40 /* Filename might have query parameters */ #define UNIXFILE_NOLOCK 0x80 /* Do no file locking */ | < | 22891 22892 22893 22894 22895 22896 22897 22898 22899 22900 22901 22902 22903 22904 | #else # define UNIXFILE_DIRSYNC 0x00 #endif #define UNIXFILE_PSOW 0x10 /* SQLITE_IOCAP_POWERSAFE_OVERWRITE */ #define UNIXFILE_DELETE 0x20 /* Delete on close */ #define UNIXFILE_URI 0x40 /* Filename might have query parameters */ #define UNIXFILE_NOLOCK 0x80 /* Do no file locking */ /* ** 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 ***************************************/ /* |
︙ | ︙ | |||
23403 23404 23405 23406 23407 23408 23409 | */ #if SQLITE_THREADSAFE #define threadid pthread_self() #else #define threadid 0 #endif | < < < < < < < < < < < | 23132 23133 23134 23135 23136 23137 23138 23139 23140 23141 23142 23143 23144 23145 | */ #if SQLITE_THREADSAFE #define threadid pthread_self() #else #define threadid 0 #endif /* ** Different Unix systems declare open() in different ways. Same use ** open(const char*,int,mode_t). Others use open(const char*,int,...). ** The difference is important when using a pointer to the function. ** ** The safest way to deal with the problem is to always use this wrapper ** which always has the same well-defined interface. |
︙ | ︙ | |||
23445 23446 23447 23448 23449 23450 23451 | /* ** 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 { | | | 23163 23164 23165 23166 23167 23168 23169 23170 23171 23172 23173 23174 23175 23176 23177 | /* ** 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 { const char *zName; /* Name of the sytem call */ sqlite3_syscall_ptr pCurrent; /* Current value of the system call */ sqlite3_syscall_ptr pDefault; /* Default value */ } aSyscall[] = { { "open", (sqlite3_syscall_ptr)posixOpen, 0 }, #define osOpen ((int(*)(const char*,int,int))aSyscall[0].pCurrent) { "close", (sqlite3_syscall_ptr)close, 0 }, |
︙ | ︙ | |||
23520 23521 23522 23523 23524 23525 23526 23527 23528 23529 23530 23531 23532 23533 23534 | { "pwrite64", (sqlite3_syscall_ptr)pwrite64, 0 }, #else { "pwrite64", (sqlite3_syscall_ptr)0, 0 }, #endif #define osPwrite64 ((ssize_t(*)(int,const void*,size_t,off_t))\ aSyscall[13].pCurrent) { "fchmod", (sqlite3_syscall_ptr)fchmod, 0 }, #define osFchmod ((int(*)(int,mode_t))aSyscall[14].pCurrent) #if defined(HAVE_POSIX_FALLOCATE) && HAVE_POSIX_FALLOCATE { "fallocate", (sqlite3_syscall_ptr)posix_fallocate, 0 }, #else { "fallocate", (sqlite3_syscall_ptr)0, 0 }, #endif | > > > > | 23238 23239 23240 23241 23242 23243 23244 23245 23246 23247 23248 23249 23250 23251 23252 23253 23254 23255 23256 | { "pwrite64", (sqlite3_syscall_ptr)pwrite64, 0 }, #else { "pwrite64", (sqlite3_syscall_ptr)0, 0 }, #endif #define osPwrite64 ((ssize_t(*)(int,const void*,size_t,off_t))\ aSyscall[13].pCurrent) #if SQLITE_ENABLE_LOCKING_STYLE { "fchmod", (sqlite3_syscall_ptr)fchmod, 0 }, #else { "fchmod", (sqlite3_syscall_ptr)0, 0 }, #endif #define osFchmod ((int(*)(int,mode_t))aSyscall[14].pCurrent) #if defined(HAVE_POSIX_FALLOCATE) && HAVE_POSIX_FALLOCATE { "fallocate", (sqlite3_syscall_ptr)posix_fallocate, 0 }, #else { "fallocate", (sqlite3_syscall_ptr)0, 0 }, #endif |
︙ | ︙ | |||
23545 23546 23547 23548 23549 23550 23551 | { "rmdir", (sqlite3_syscall_ptr)rmdir, 0 }, #define osRmdir ((int(*)(const char*))aSyscall[19].pCurrent) { "fchown", (sqlite3_syscall_ptr)posixFchown, 0 }, #define osFchown ((int(*)(int,uid_t,gid_t))aSyscall[20].pCurrent) | | < | < < < < < < < < < | 23267 23268 23269 23270 23271 23272 23273 23274 23275 23276 23277 23278 23279 23280 23281 23282 | { "rmdir", (sqlite3_syscall_ptr)rmdir, 0 }, #define osRmdir ((int(*)(const char*))aSyscall[19].pCurrent) { "fchown", (sqlite3_syscall_ptr)posixFchown, 0 }, #define osFchown ((int(*)(int,uid_t,gid_t))aSyscall[20].pCurrent) { "umask", (sqlite3_syscall_ptr)umask, 0 }, #define osUmask ((mode_t(*)(mode_t))aSyscall[21].pCurrent) }; /* End of the overrideable system calls */ /* ** This is the xSetSystemCall() method of sqlite3_vfs for all of the ** "unix" VFSes. Return SQLITE_OK opon successfully updating the ** system call pointer, or SQLITE_NOTFOUND if there is no configurable |
︙ | ︙ | |||
23662 23663 23664 23665 23666 23667 23668 | ** In that way, if a database file is -rw-rw-rw or -rw-rw-r-, and a ** transaction crashes and leaves behind hot journals, then any ** process that is able to write to the database will also be able to ** recover the hot journals. */ static int robust_open(const char *z, int f, mode_t m){ int fd; | > > > | > > > > < | < < < < < | | < | < | 23374 23375 23376 23377 23378 23379 23380 23381 23382 23383 23384 23385 23386 23387 23388 23389 23390 23391 23392 23393 23394 23395 23396 23397 23398 23399 23400 23401 23402 23403 23404 23405 23406 23407 23408 | ** In that way, if a database file is -rw-rw-rw or -rw-rw-r-, and a ** transaction crashes and leaves behind hot journals, then any ** process that is able to write to the database will also be able to ** recover the hot journals. */ static int robust_open(const char *z, int f, mode_t m){ int fd; mode_t m2; mode_t origM = 0; if( m==0 ){ m2 = SQLITE_DEFAULT_FILE_PERMISSIONS; }else{ m2 = m; origM = osUmask(0); } do{ #if defined(O_CLOEXEC) fd = osOpen(z,f|O_CLOEXEC,m2); #else fd = osOpen(z,f,m2); #endif }while( fd<0 && errno==EINTR ); if( m ){ osUmask(origM); } #if defined(FD_CLOEXEC) && (!defined(O_CLOEXEC) || O_CLOEXEC==0) if( fd>=0 ) osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC); #endif return fd; } /* ** Helper functions to obtain and relinquish the global mutex. The ** global mutex is used to protect the unixInodeInfo and ** vxworksFileId objects used by this file, all of which may be |
︙ | ︙ | |||
23887 23888 23889 23890 23891 23892 23893 23894 23895 23896 23897 23898 23899 23900 | case ENOSYS: /* these should force the client to close the file and reconnect */ default: return sqliteIOErr; } } /****************************************************************************** ****************** Begin Unique File ID Utility Used By VxWorks *************** ** ** On most versions of unix, we can get a unique ID for a file by concatenating ** the device number and the inode number. But this does not work on VxWorks. | > | 23598 23599 23600 23601 23602 23603 23604 23605 23606 23607 23608 23609 23610 23611 23612 | case ENOSYS: /* these should force the client to close the file and reconnect */ default: return sqliteIOErr; } } /****************************************************************************** ****************** Begin Unique File ID Utility Used By VxWorks *************** ** ** On most versions of unix, we can get a unique ID for a file by concatenating ** the device number and the inode number. But this does not work on VxWorks. |
︙ | ︙ | |||
24224 24225 24226 24227 24228 24229 24230 24231 24232 24233 24234 24235 24236 24237 | /* This is a threadsafe build, but strerror_r() is not available. */ zErr = ""; #else /* Non-threadsafe build, use strerror(). */ zErr = strerror(iErrno); #endif if( zPath==0 ) zPath = ""; sqlite3_log(errcode, "os_unix.c:%d: (%d) %s(%s) - %s", iLine, iErrno, zFunc, zPath, zErr ); return errcode; | > | 23936 23937 23938 23939 23940 23941 23942 23943 23944 23945 23946 23947 23948 23949 23950 | /* This is a threadsafe build, but strerror_r() is not available. */ zErr = ""; #else /* Non-threadsafe build, use strerror(). */ zErr = strerror(iErrno); #endif assert( errcode!=SQLITE_OK ); if( zPath==0 ) zPath = ""; sqlite3_log(errcode, "os_unix.c:%d: (%d) %s(%s) - %s", iLine, iErrno, zFunc, zPath, zErr ); return errcode; |
︙ | ︙ | |||
24388 24389 24390 24391 24392 24393 24394 | }else{ pInode->nRef++; } *ppInode = pInode; return SQLITE_OK; } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 24101 24102 24103 24104 24105 24106 24107 24108 24109 24110 24111 24112 24113 24114 | }else{ pInode->nRef++; } *ppInode = pInode; return SQLITE_OK; } /* ** This routine checks if there is a RESERVED lock held on the specified ** file by this or any other process. If such a lock is held, set *pResOut ** 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. */ |
︙ | ︙ | |||
24963 24964 24965 24966 24967 24968 24969 | ** Lower the locking level on file descriptor pFile to eFileLock. eFileLock ** must be either NO_LOCK or SHARED_LOCK. ** ** If the locking level of the file descriptor is already at or below ** the requested locking level, this routine is a no-op. */ static int unixUnlock(sqlite3_file *id, int eFileLock){ | < < < < < | 24632 24633 24634 24635 24636 24637 24638 24639 24640 24641 24642 24643 24644 24645 24646 24647 24648 24649 24650 24651 24652 24653 24654 24655 24656 24657 24658 24659 24660 | ** Lower the locking level on file descriptor pFile to eFileLock. eFileLock ** must be either NO_LOCK or SHARED_LOCK. ** ** If the locking level of the file descriptor is already at or below ** the requested locking level, this routine is a no-op. */ static int unixUnlock(sqlite3_file *id, int eFileLock){ return posixUnlock(id, eFileLock, 0); } /* ** This function performs the parts of the "close file" operation ** common to all locking schemes. It closes the directory and file ** handles, if they are valid, and sets all fields of the unixFile ** structure to 0. ** ** 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->ctrlFlags & UNIXFILE_DELETE ){ |
︙ | ︙ | |||
25009 25010 25011 25012 25013 25014 25015 | /* ** Close a file. */ static int unixClose(sqlite3_file *id){ int rc = SQLITE_OK; unixFile *pFile = (unixFile *)id; | < | 24673 24674 24675 24676 24677 24678 24679 24680 24681 24682 24683 24684 24685 24686 | /* ** Close a file. */ static int unixClose(sqlite3_file *id){ int rc = SQLITE_OK; unixFile *pFile = (unixFile *)id; unixUnlock(id, NO_LOCK); unixEnterMutex(); /* unixFile.pInode is always valid here. Otherwise, a different close ** routine (e.g. nolockClose()) would be called instead. */ assert( pFile->pInode->nLock>0 || pFile->pInode->bProcessLock==0 ); |
︙ | ︙ | |||
25078 25079 25080 25081 25082 25083 25084 | /******************* End of the no-op lock implementation ********************* ******************************************************************************/ /****************************************************************************** ************************* Begin dot-file Locking ****************************** ** | | | | 24741 24742 24743 24744 24745 24746 24747 24748 24749 24750 24751 24752 24753 24754 24755 24756 24757 24758 24759 24760 24761 24762 24763 24764 24765 24766 24767 24768 24769 24770 | /******************* End of the no-op lock implementation ********************* ******************************************************************************/ /****************************************************************************** ************************* Begin dot-file Locking ****************************** ** ** The dotfile locking implementation uses the existance of separate lock ** files (really a directory) to control access to the database. This works ** on just about every filesystem imaginable. But there are serious downsides: ** ** (1) There is zero concurrency. A single reader blocks all other ** connections from reading or writing the database. ** ** (2) An application crash or power loss can leave stale lock files ** sitting around that need to be cleared manually. ** ** Nevertheless, a dotlock is an appropriate locking mode for use if no ** other locking strategy is available. ** ** Dotfile locking works by creating a subdirectory in the same directory as ** the database and with the same name but with a ".lock" extension added. ** The existance of a lock directory implies an EXCLUSIVE lock. All other ** lock types (SHARED, RESERVED, PENDING) are mapped into EXCLUSIVE. */ /* ** The file suffix added to the data base filename in order to create the ** lock directory. */ |
︙ | ︙ | |||
26241 26242 26243 26244 26245 26246 26247 | void *pBuf, int amt, sqlite3_int64 offset ){ unixFile *pFile = (unixFile *)id; int got; assert( id ); | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > | 25904 25905 25906 25907 25908 25909 25910 25911 25912 25913 25914 25915 25916 25917 25918 25919 25920 25921 25922 25923 25924 25925 25926 25927 25928 25929 25930 25931 25932 25933 25934 25935 25936 25937 25938 25939 25940 25941 25942 25943 25944 25945 25946 25947 25948 25949 25950 25951 25952 25953 25954 25955 25956 25957 25958 25959 25960 25961 25962 25963 25964 25965 25966 25967 25968 25969 25970 25971 25972 25973 25974 25975 25976 25977 25978 25979 25980 25981 25982 | void *pBuf, int amt, sqlite3_int64 offset ){ unixFile *pFile = (unixFile *)id; int got; assert( id ); /* If this is a database file (not a journal, master-journal or temp ** file), the bytes in the locking range should never be read or written. */ #if 0 assert( pFile->pUnused==0 || offset>=PENDING_BYTE+512 || offset+amt<=PENDING_BYTE ); #endif got = seekAndRead(pFile, offset, pBuf, amt); if( got==amt ){ return SQLITE_OK; }else if( got<0 ){ /* lastErrno set by seekAndRead */ return SQLITE_IOERR_READ; }else{ pFile->lastErrno = 0; /* not a system error */ /* Unread parts of the buffer must be zero-filled */ memset(&((char*)pBuf)[got], 0, amt-got); return SQLITE_IOERR_SHORT_READ; } } /* ** Seek to the offset in id->offset then read cnt bytes into pBuf. ** Return the number of bytes actually read. Update the offset. ** ** To avoid stomping the errno value on a failed write the lastErrno value ** is set before returning. */ static int seekAndWrite(unixFile *id, i64 offset, const void *pBuf, int cnt){ int got; #if (!defined(USE_PREAD) && !defined(USE_PREAD64)) i64 newOffset; #endif assert( cnt==(cnt&0x1ffff) ); cnt &= 0x1ffff; 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)); return got; } /* ** Write data from a buffer into a file. Return SQLITE_OK on success ** or some other error code on failure. */ |
︙ | ︙ | |||
26385 26386 26387 26388 26389 26390 26391 | rc = seekAndRead(pFile, 24, oldCntr, 4); SimulateIOErrorBenign(0); if( rc!=4 || memcmp(oldCntr, &((char*)pBuf)[24-offset], 4)!=0 ){ pFile->transCntrChng = 1; /* The transaction counter has changed */ } } } | < < < < < < < < < < < < < < < < < | 26016 26017 26018 26019 26020 26021 26022 26023 26024 26025 26026 26027 26028 26029 | rc = seekAndRead(pFile, 24, oldCntr, 4); SimulateIOErrorBenign(0); if( rc!=4 || memcmp(oldCntr, &((char*)pBuf)[24-offset], 4)!=0 ){ pFile->transCntrChng = 1; /* The transaction counter has changed */ } } } #endif while( amt>0 && (wrote = seekAndWrite(pFile, offset, pBuf, amt))>0 ){ amt -= wrote; offset += wrote; pBuf = &((char*)pBuf)[wrote]; } |
︙ | ︙ | |||
26631 26632 26633 26634 26635 26636 26637 | 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 | | | 26245 26246 26247 26248 26249 26250 26251 26252 26253 26254 26255 26256 26257 26258 26259 | 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); |
︙ | ︙ | |||
26686 26687 26688 26689 26690 26691 26692 | ** source. */ if( pFile->inNormalWrite && nByte==0 ){ pFile->transCntrChng = 1; } #endif | < < < < < < < < | 26300 26301 26302 26303 26304 26305 26306 26307 26308 26309 26310 26311 26312 26313 | ** source. */ if( pFile->inNormalWrite && nByte==0 ){ pFile->transCntrChng = 1; } #endif return SQLITE_OK; } } /* ** Determine the current size of a file in bytes */ |
︙ | ︙ | |||
26782 26783 26784 26785 26786 26787 26788 | if( nWrite!=1 ) return SQLITE_IOERR_WRITE; iWrite += nBlk; } #endif } } | < < < < < < < < < < < < < < < < | 26388 26389 26390 26391 26392 26393 26394 26395 26396 26397 26398 26399 26400 26401 26402 26403 26404 26405 26406 26407 26408 26409 26410 26411 26412 26413 26414 26415 26416 26417 26418 26419 26420 | if( nWrite!=1 ) return SQLITE_IOERR_WRITE; iWrite += nBlk; } #endif } } return SQLITE_OK; } /* ** If *pArg is inititially negative then this is a query. Set *pArg to ** 1 or 0 depending on whether or not bit mask of pFile->ctrlFlags is set. ** ** If *pArg is 0 or 1, then clear or set the mask bit of pFile->ctrlFlags. */ static void unixModeBit(unixFile *pFile, unsigned char mask, int *pArg){ if( *pArg<0 ){ *pArg = (pFile->ctrlFlags & mask)!=0; }else if( (*pArg)==0 ){ pFile->ctrlFlags &= ~mask; }else{ pFile->ctrlFlags |= mask; } } /* ** 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: { |
︙ | ︙ | |||
26854 26855 26856 26857 26858 26859 26860 | unixModeBit(pFile, UNIXFILE_PSOW, (int*)pArg); return SQLITE_OK; } case SQLITE_FCNTL_VFSNAME: { *(char**)pArg = sqlite3_mprintf("%s", pFile->pVfs->zName); return SQLITE_OK; } | < < < < < < < < < < < < < < < < < < < < | 26444 26445 26446 26447 26448 26449 26450 26451 26452 26453 26454 26455 26456 26457 | unixModeBit(pFile, UNIXFILE_PSOW, (int*)pArg); return SQLITE_OK; } case SQLITE_FCNTL_VFSNAME: { *(char**)pArg = sqlite3_mprintf("%s", pFile->pVfs->zName); return SQLITE_OK; } #ifdef SQLITE_DEBUG /* The pager calls this method to signal that it has done ** a rollback and that the database is therefore unchanged and ** it hence it is OK for the transaction change counter to be ** unchanged. */ case SQLITE_FCNTL_DB_UNCHANGED: { |
︙ | ︙ | |||
26905 26906 26907 26908 26909 26910 26911 | ** larger for some devices. ** ** SQLite code assumes this function cannot fail. It also assumes that ** if two files are created in the same file-system directory (i.e. ** a database and its journal file) that the sector size will be the ** same for both. */ | < | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | | > | 26475 26476 26477 26478 26479 26480 26481 26482 26483 26484 26485 26486 26487 26488 26489 26490 26491 26492 26493 26494 26495 26496 26497 26498 26499 26500 26501 26502 26503 26504 26505 26506 26507 26508 26509 26510 26511 26512 26513 | ** larger for some devices. ** ** SQLite code assumes this function cannot fail. It also assumes that ** if two files are created in the same file-system directory (i.e. ** a database and its journal file) that the sector size will be the ** same for both. */ static int unixSectorSize(sqlite3_file *pFile){ (void)pFile; return SQLITE_DEFAULT_SECTOR_SIZE; } /* ** Return the device characteristics for the file. ** ** This VFS is set up to return SQLITE_IOCAP_POWERSAFE_OVERWRITE by default. ** However, that choice is contraversial since technically the underlying ** file system does not always provide powersafe overwrites. (In other ** words, after a power-loss event, parts of the file that were never ** written might end up being altered.) However, non-PSOW behavior is very, ** very rare. And asserting PSOW makes a large reduction in the amount ** of required I/O for journaling, since a lot of padding is eliminated. ** Hence, while POWERSAFE_OVERWRITE is on by default, there is a file-control ** available to turn it off and URI query parameter available to turn it off. */ static int unixDeviceCharacteristics(sqlite3_file *id){ unixFile *p = (unixFile*)id; if( p->ctrlFlags & UNIXFILE_PSOW ){ return SQLITE_IOCAP_POWERSAFE_OVERWRITE; }else{ return 0; } } #ifndef SQLITE_OMIT_WAL /* ** Object used to represent an shared memory buffer. |
︙ | ︙ | |||
27186 27187 27188 27189 27190 27191 27192 | 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 ){ | | | 26670 26671 26672 26673 26674 26675 26676 26677 26678 26679 26680 26681 26682 26683 26684 | 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]); } } sqlite3_free(p->apRegion); if( p->h>=0 ){ robust_close(pFd, p->h, __LINE__); |
︙ | ︙ | |||
27426 27427 27428 27429 27430 27431 27432 | rc = SQLITE_IOERR_SHMSIZE; goto shmpage_out; } if( sStat.st_size<nByte ){ /* The requested memory region does not exist. If bExtend is set to ** false, exit early. *pp will be set to NULL and SQLITE_OK returned. | | < < < < | < < < < | < < < | < < < < | | > | < < | | 26910 26911 26912 26913 26914 26915 26916 26917 26918 26919 26920 26921 26922 26923 26924 26925 26926 26927 26928 26929 26930 26931 26932 26933 26934 26935 26936 26937 26938 26939 26940 26941 26942 26943 26944 26945 26946 26947 26948 26949 | rc = SQLITE_IOERR_SHMSIZE; goto shmpage_out; } if( sStat.st_size<nByte ){ /* The requested memory region does not exist. If bExtend is set to ** false, exit early. *pp will be set to NULL and SQLITE_OK returned. ** ** Alternatively, if bExtend is true, use ftruncate() to allocate ** the requested memory region. */ if( !bExtend ) goto shmpage_out; if( robust_ftruncate(pShmNode->h, nByte) ){ rc = unixLogError(SQLITE_IOERR_SHMSIZE, "ftruncate", pShmNode->zFilename); goto shmpage_out; } } } /* Map the requested memory region into this processes address space. */ apNew = (char **)sqlite3_realloc( pShmNode->apRegion, (iRegion+1)*sizeof(char *) ); if( !apNew ){ rc = SQLITE_IOERR_NOMEM; goto shmpage_out; } pShmNode->apRegion = apNew; while(pShmNode->nRegion<=iRegion){ void *pMem; if( pShmNode->h>=0 ){ pMem = mmap(0, szRegion, pShmNode->isReadonly ? PROT_READ : PROT_READ|PROT_WRITE, MAP_SHARED, pShmNode->h, szRegion*(i64)pShmNode->nRegion ); if( pMem==MAP_FAILED ){ rc = unixLogError(SQLITE_IOERR_SHMMAP, "mmap", pShmNode->zFilename); goto shmpage_out; } |
︙ | ︙ | |||
27684 27685 27686 27687 27688 27689 27690 | #else # define unixShmMap 0 # define unixShmLock 0 # define unixShmBarrier 0 # define unixShmUnmap 0 #endif /* #ifndef SQLITE_OMIT_WAL */ | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 27152 27153 27154 27155 27156 27157 27158 27159 27160 27161 27162 27163 27164 27165 | #else # define unixShmMap 0 # define unixShmLock 0 # define unixShmBarrier 0 # define unixShmUnmap 0 #endif /* #ifndef SQLITE_OMIT_WAL */ /* ** Here ends the implementation of all sqlite3_file methods. ** ********************** End sqlite3_file Methods ******************************* ******************************************************************************/ /* |
︙ | ︙ | |||
27972 27973 27974 27975 27976 27977 27978 | CKLOCK, /* xCheckReservedLock */ \ unixFileControl, /* xFileControl */ \ unixSectorSize, /* xSectorSize */ \ unixDeviceCharacteristics, /* xDeviceCapabilities */ \ unixShmMap, /* xShmMap */ \ unixShmLock, /* xShmLock */ \ unixShmBarrier, /* xShmBarrier */ \ | | < < | | 27210 27211 27212 27213 27214 27215 27216 27217 27218 27219 27220 27221 27222 27223 27224 27225 27226 27227 27228 27229 27230 27231 27232 27233 27234 27235 27236 27237 27238 27239 27240 27241 | CKLOCK, /* xCheckReservedLock */ \ unixFileControl, /* xFileControl */ \ unixSectorSize, /* xSectorSize */ \ unixDeviceCharacteristics, /* xDeviceCapabilities */ \ unixShmMap, /* xShmMap */ \ unixShmLock, /* xShmLock */ \ unixShmBarrier, /* xShmBarrier */ \ unixShmUnmap /* xShmUnmap */ \ }; \ static const sqlite3_io_methods *FINDER##Impl(const char *z, unixFile *p){ \ UNUSED_PARAMETER(z); UNUSED_PARAMETER(p); \ return &METHOD; \ } \ static const sqlite3_io_methods *(*const FINDER)(const char*,unixFile *p) \ = FINDER##Impl; /* ** Here are all of the sqlite3_io_methods objects for each of the ** locking strategies. Functions that return pointers to these methods ** are also created. */ IOMETHODS( posixIoFinder, /* Finder function name */ posixIoMethods, /* sqlite3_io_methods object name */ 2, /* shared memory is enabled */ unixClose, /* xClose method */ unixLock, /* xLock method */ unixUnlock, /* xUnlock method */ unixCheckReservedLock /* xCheckReservedLock method */ ) IOMETHODS( nolockIoFinder, /* Finder function name */ |
︙ | ︙ | |||
28242 28243 28244 28245 28246 28247 28248 | assert( zFilename!=0 || (ctrlFlags & UNIXFILE_NOLOCK)!=0 ); OSTRACE(("OPEN %-3d %s\n", h, zFilename)); pNew->h = h; pNew->pVfs = pVfs; pNew->zPath = zFilename; pNew->ctrlFlags = (u8)ctrlFlags; | < | | 27478 27479 27480 27481 27482 27483 27484 27485 27486 27487 27488 27489 27490 27491 27492 27493 27494 27495 27496 | assert( zFilename!=0 || (ctrlFlags & UNIXFILE_NOLOCK)!=0 ); OSTRACE(("OPEN %-3d %s\n", h, zFilename)); pNew->h = h; pNew->pVfs = pVfs; pNew->zPath = zFilename; pNew->ctrlFlags = (u8)ctrlFlags; if( sqlite3_uri_boolean(((ctrlFlags & UNIXFILE_URI) ? zFilename : 0), "psow", SQLITE_POWERSAFE_OVERWRITE) ){ pNew->ctrlFlags |= UNIXFILE_PSOW; } if( memcmp(pVfs->zName,"unix-excl",10)==0 ){ pNew->ctrlFlags |= UNIXFILE_EXCL; } #if OS_VXWORKS pNew->pId = vxworksFindFileId(zFilename); if( pNew->pId==0 ){ ctrlFlags |= UNIXFILE_NOLOCK; |
︙ | ︙ | |||
28279 28280 28281 28282 28283 28284 28285 | #if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE || pLockingStyle == &nfsIoMethods #endif ){ unixEnterMutex(); rc = findInodeInfo(pNew, &pNew->pInode); if( rc!=SQLITE_OK ){ | | | 27514 27515 27516 27517 27518 27519 27520 27521 27522 27523 27524 27525 27526 27527 27528 | #if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE || pLockingStyle == &nfsIoMethods #endif ){ unixEnterMutex(); rc = findInodeInfo(pNew, &pNew->pInode); if( rc!=SQLITE_OK ){ /* If an error occured in findInodeInfo(), close the file descriptor ** immediately, before releasing the mutex. findInodeInfo() may fail ** in two scenarios: ** ** (a) A call to fstat() failed. ** (b) A malloc failed. ** ** Scenario (b) may only occur if the process is holding no other |
︙ | ︙ | |||
28378 28379 28380 28381 28382 28383 28384 | pNew->lastErrno = 0; #if OS_VXWORKS if( rc!=SQLITE_OK ){ if( h>=0 ) robust_close(pNew, h, __LINE__); h = -1; osUnlink(zFilename); | | > < | 27613 27614 27615 27616 27617 27618 27619 27620 27621 27622 27623 27624 27625 27626 27627 27628 27629 27630 27631 27632 27633 27634 27635 | pNew->lastErrno = 0; #if OS_VXWORKS if( rc!=SQLITE_OK ){ if( h>=0 ) robust_close(pNew, h, __LINE__); h = -1; osUnlink(zFilename); isDelete = 0; } if( isDelete ) pNew->ctrlFlags |= UNIXFILE_DELETE; #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. |
︙ | ︙ | |||
28886 28887 28888 28889 28890 28891 28892 | 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); | | < < < | < < | 28121 28122 28123 28124 28125 28126 28127 28128 28129 28130 28131 28132 28133 28134 28135 28136 | sqlite3_vfs *NotUsed, /* VFS containing this as the xDelete method */ const char *zPath, /* Name of file to be deleted */ int dirSync /* If true, fsync() directory after deleting file */ ){ int rc = SQLITE_OK; UNUSED_PARAMETER(NotUsed); SimulateIOError(return SQLITE_IOERR_DELETE); if( osUnlink(zPath)==(-1) && errno!=ENOENT ){ return unixLogError(SQLITE_IOERR_DELETE, "unlink", zPath); } #ifndef SQLITE_DISABLE_DIRSYNC if( (dirSync & 1)!=0 ){ int fd; rc = osOpenDirectory(zPath, &fd); if( rc==SQLITE_OK ){ #if OS_VXWORKS |
︙ | ︙ | |||
28917 28918 28919 28920 28921 28922 28923 | } } #endif return rc; } /* | | | 28147 28148 28149 28150 28151 28152 28153 28154 28155 28156 28157 28158 28159 28160 28161 | } } #endif return rc; } /* ** Test the existance of or access permissions of file zPath. The ** test performed depends on the value of flags: ** ** SQLITE_ACCESS_EXISTS: Return 1 if the file exists ** SQLITE_ACCESS_READWRITE: Return 1 if the file is read and writable. ** SQLITE_ACCESS_READONLY: Return 1 if the file is readable. ** ** Otherwise return 0. |
︙ | ︙ | |||
30480 30481 30482 30483 30484 30485 30486 | UNIXVFS("unix-proxy", proxyIoFinder ), #endif }; unsigned int i; /* Loop counter */ /* Double-check that the aSyscall[] array has been constructed ** correctly. See ticket [bb3a86e890c8e96ab] */ | | | 29710 29711 29712 29713 29714 29715 29716 29717 29718 29719 29720 29721 29722 29723 29724 | UNIXVFS("unix-proxy", proxyIoFinder ), #endif }; unsigned int i; /* Loop counter */ /* Double-check that the aSyscall[] array has been constructed ** correctly. See ticket [bb3a86e890c8e96ab] */ assert( ArraySize(aSyscall)==22 ); /* Register all VFSes defined in the aVfs[] array */ for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){ sqlite3_vfs_register(&aVfs[i], i==0); } return SQLITE_OK; } |
︙ | ︙ | |||
30863 30864 30865 30866 30867 30868 30869 | #if SQLITE_OS_WINCE LPWSTR 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 | < < < < < < < < < | 30093 30094 30095 30096 30097 30098 30099 30100 30101 30102 30103 30104 30105 30106 30107 30108 30109 30110 30111 | #if SQLITE_OS_WINCE LPWSTR 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 }; /* ** Allowed values for winFile.ctrlFlags */ #define WINFILE_PERSIST_WAL 0x04 /* Persistent WAL mode */ #define WINFILE_PSOW 0x10 /* SQLITE_IOCAP_POWERSAFE_OVERWRITE */ /* * The size of the buffer used by sqlite3_win32_write_debug(). */ #ifndef SQLITE_WIN32_DBG_BUF_SIZE |
︙ | ︙ | |||
31030 31031 31032 31033 31034 31035 31036 | /* ** 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 win_syscall { | | | 30251 30252 30253 30254 30255 30256 30257 30258 30259 30260 30261 30262 30263 30264 30265 | /* ** 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 win_syscall { const char *zName; /* Name of the sytem call */ sqlite3_syscall_ptr pCurrent; /* Current value of the system call */ sqlite3_syscall_ptr pDefault; /* Default value */ } aSyscall[] = { #if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT { "AreFileApisANSI", (SYSCALL)AreFileApisANSI, 0 }, #else { "AreFileApisANSI", (SYSCALL)0, 0 }, |
︙ | ︙ | |||
31710 31711 31712 31713 31714 31715 31716 | } /* ** This function outputs the specified (ANSI) string to the Win32 debugger ** (if available). */ | | | 30931 30932 30933 30934 30935 30936 30937 30938 30939 30940 30941 30942 30943 30944 30945 | } /* ** This function outputs the specified (ANSI) string to the Win32 debugger ** (if available). */ SQLITE_API void sqlite3_win32_write_debug(char *zBuf, int nBuf){ char zDbgBuf[SQLITE_WIN32_DBG_BUF_SIZE]; int nMin = MIN(nBuf, (SQLITE_WIN32_DBG_BUF_SIZE - 1)); /* may be negative. */ if( nMin<-1 ) nMin = -1; /* all negative values become -1. */ assert( nMin==-1 || nMin==0 || nMin<SQLITE_WIN32_DBG_BUF_SIZE ); #if defined(SQLITE_WIN32_HAS_ANSI) if( nMin>0 ){ memset(zDbgBuf, 0, SQLITE_WIN32_DBG_BUF_SIZE); |
︙ | ︙ | |||
32236 32237 32238 32239 32240 32241 32242 | sqlite3EndBenignMalloc(); /* free the system buffer allocated by FormatMessage */ osLocalFree(zTemp); } } #endif if( 0 == dwLen ){ | | | 31457 31458 31459 31460 31461 31462 31463 31464 31465 31466 31467 31468 31469 31470 31471 | sqlite3EndBenignMalloc(); /* free the system buffer allocated by FormatMessage */ osLocalFree(zTemp); } } #endif if( 0 == dwLen ){ sqlite3_snprintf(nBuf, zBuf, "OsError 0x%x (%u)", lastErrno, lastErrno); }else{ /* copy a maximum of nBuf chars to output buffer */ sqlite3_snprintf(nBuf, zBuf, "%s", zOut); /* free the UTF8 buffer */ sqlite3_free(zOut); } return 0; |
︙ | ︙ | |||
32279 32280 32281 32282 32283 32284 32285 | zMsg[0] = 0; getLastErrorMsg(lastErrno, sizeof(zMsg), zMsg); assert( errcode!=SQLITE_OK ); if( zPath==0 ) zPath = ""; for(i=0; zMsg[i] && zMsg[i]!='\r' && zMsg[i]!='\n'; i++){} zMsg[i] = 0; sqlite3_log(errcode, | | | 31500 31501 31502 31503 31504 31505 31506 31507 31508 31509 31510 31511 31512 31513 31514 | zMsg[0] = 0; getLastErrorMsg(lastErrno, sizeof(zMsg), zMsg); assert( errcode!=SQLITE_OK ); if( zPath==0 ) zPath = ""; for(i=0; zMsg[i] && zMsg[i]!='\r' && zMsg[i]!='\n'; i++){} zMsg[i] = 0; sqlite3_log(errcode, "os_win.c:%d: (%d) %s(%s) - %s", iLine, lastErrno, zFunc, zPath, zMsg ); return errcode; } /* |
︙ | ︙ | |||
32343 32344 32345 32346 32347 32348 32349 | } } #if SQLITE_OS_WINCE /************************************************************************* ** This section contains code for WinCE only. */ | < | | | 31564 31565 31566 31567 31568 31569 31570 31571 31572 31573 31574 31575 31576 31577 31578 31579 31580 | } } #if SQLITE_OS_WINCE /************************************************************************* ** This section contains code for WinCE only. */ /* ** Windows CE does not have a localtime() function. So create a ** substitute. */ /* #include <time.h> */ struct tm *__cdecl localtime(const time_t *t) { static struct tm y; FILETIME uTm, lTm; SYSTEMTIME pTm; |
︙ | ︙ | |||
32370 32371 32372 32373 32374 32375 32376 | y.tm_wday = pTm.wDayOfWeek; y.tm_mday = pTm.wDay; y.tm_hour = pTm.wHour; y.tm_min = pTm.wMinute; y.tm_sec = pTm.wSecond; return &y; } | < | 31590 31591 31592 31593 31594 31595 31596 31597 31598 31599 31600 31601 31602 31603 | y.tm_wday = pTm.wDayOfWeek; y.tm_mday = pTm.wDay; y.tm_hour = pTm.wHour; y.tm_min = pTm.wMinute; y.tm_sec = pTm.wSecond; return &y; } #define HANDLE_TO_WINFILE(a) (winFile*)&((char*)a)[-(int)offsetof(winFile,h)] /* ** Acquire a lock on the handle h */ static void winceMutexAcquire(HANDLE h){ |
︙ | ︙ | |||
32392 32393 32394 32395 32396 32397 32398 | */ #define winceMutexRelease(h) ReleaseMutex(h) /* ** Create the mutex and shared memory used for locking in the file ** descriptor pFile */ | | < < | < | | < | | | | | < | < < < < < < | | | | 31611 31612 31613 31614 31615 31616 31617 31618 31619 31620 31621 31622 31623 31624 31625 31626 31627 31628 31629 31630 31631 31632 31633 31634 31635 31636 31637 31638 31639 31640 31641 31642 31643 31644 31645 31646 31647 31648 31649 31650 31651 31652 31653 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 | */ #define winceMutexRelease(h) ReleaseMutex(h) /* ** Create the mutex and shared memory used for locking in the file ** descriptor pFile */ static BOOL winceCreateLock(const char *zFilename, winFile *pFile){ LPWSTR zTok; LPWSTR zName; BOOL bInit = TRUE; zName = utf8ToUnicode(zFilename); if( zName==0 ){ /* out of memory */ return FALSE; } /* Initialize the local lockdata */ memset(&pFile->local, 0, sizeof(pFile->local)); /* Replace the backslashes from the filename and lowercase it ** to derive a mutex name. */ zTok = osCharLowerW(zName); for (;*zTok;zTok++){ if (*zTok == '\\') *zTok = '_'; } /* Create/open the named mutex */ pFile->hMutex = osCreateMutexW(NULL, FALSE, zName); if (!pFile->hMutex){ pFile->lastErrno = osGetLastError(); winLogError(SQLITE_ERROR, pFile->lastErrno, "winceCreateLock1", zFilename); sqlite3_free(zName); return FALSE; } /* Acquire the mutex before continuing */ winceMutexAcquire(pFile->hMutex); /* Since the names of named mutexes, semaphores, file mappings etc are ** case-sensitive, take advantage of that by uppercasing the mutex name ** and using that as the shared filemapping name. */ osCharUpperW(zName); pFile->hShared = osCreateFileMappingW(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof(winceLock), zName); /* Set a flag that indicates we're the first to create the memory so it ** must be zero-initialized */ if (osGetLastError() == ERROR_ALREADY_EXISTS){ bInit = FALSE; } sqlite3_free(zName); /* If we succeeded in making the shared memory handle, map it. */ if (pFile->hShared){ pFile->shared = (winceLock*)osMapViewOfFile(pFile->hShared, FILE_MAP_READ|FILE_MAP_WRITE, 0, 0, sizeof(winceLock)); /* If mapping failed, close the shared memory handle and erase it */ if (!pFile->shared){ pFile->lastErrno = osGetLastError(); winLogError(SQLITE_ERROR, pFile->lastErrno, "winceCreateLock2", zFilename); osCloseHandle(pFile->hShared); pFile->hShared = NULL; } } /* If shared memory could not be created, then close the mutex and fail */ if (pFile->hShared == NULL){ winceMutexRelease(pFile->hMutex); osCloseHandle(pFile->hMutex); pFile->hMutex = NULL; return FALSE; } /* Initialize the shared memory if we're supposed to */ if (bInit) { memset(pFile->shared, 0, sizeof(winceLock)); } winceMutexRelease(pFile->hMutex); return TRUE; } /* ** Destroy the part of winFile that deals with wince locks */ static void winceDestroyLock(winFile *pFile){ if (pFile->hMutex){ |
︙ | ︙ | |||
32560 32561 32562 32563 32564 32565 32566 | pFile->shared->nReaders ++; } bReturn = TRUE; } } /* Want a pending lock? */ | | < | < | 31768 31769 31770 31771 31772 31773 31774 31775 31776 31777 31778 31779 31780 31781 31782 31783 31784 31785 31786 31787 31788 31789 31790 31791 31792 | pFile->shared->nReaders ++; } bReturn = TRUE; } } /* Want a pending lock? */ else if (dwFileOffsetLow == (DWORD)PENDING_BYTE && nNumberOfBytesToLockLow == 1){ /* If no pending lock has been acquired, then acquire it */ if (pFile->shared->bPending == 0) { pFile->shared->bPending = TRUE; pFile->local.bPending = TRUE; bReturn = TRUE; } } /* Want a reserved lock? */ else if (dwFileOffsetLow == (DWORD)RESERVED_BYTE && nNumberOfBytesToLockLow == 1){ if (pFile->shared->bReserved == 0) { pFile->shared->bReserved = TRUE; pFile->local.bReserved = TRUE; bReturn = TRUE; } } |
︙ | ︙ | |||
32615 32616 32617 32618 32619 32620 32621 | pFile->local.bExclusive = FALSE; pFile->shared->bExclusive = FALSE; bReturn = TRUE; } /* Did we just have a reader lock? */ else if (pFile->local.nReaders){ | | < | < | < | 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 | pFile->local.bExclusive = FALSE; pFile->shared->bExclusive = FALSE; bReturn = TRUE; } /* Did we just have a reader lock? */ else if (pFile->local.nReaders){ assert(nNumberOfBytesToUnlockLow == (DWORD)SHARED_SIZE || nNumberOfBytesToUnlockLow == 1); pFile->local.nReaders --; if (pFile->local.nReaders == 0) { pFile->shared->nReaders --; } bReturn = TRUE; } } /* Releasing a pending lock */ else if (dwFileOffsetLow == (DWORD)PENDING_BYTE && nNumberOfBytesToUnlockLow == 1){ if (pFile->local.bPending){ pFile->local.bPending = FALSE; pFile->shared->bPending = FALSE; bReturn = TRUE; } } /* Releasing a reserved lock */ else if (dwFileOffsetLow == (DWORD)RESERVED_BYTE && nNumberOfBytesToUnlockLow == 1){ if (pFile->local.bReserved) { pFile->local.bReserved = FALSE; pFile->shared->bReserved = FALSE; bReturn = TRUE; } } |
︙ | ︙ | |||
32740 32741 32742 32743 32744 32745 32746 | static int seekWinFile(winFile *pFile, sqlite3_int64 iOffset){ #if !SQLITE_OS_WINRT LONG upperBits; /* Most sig. 32 bits of new offset */ LONG lowerBits; /* Least sig. 32 bits of new offset */ DWORD dwRet; /* Value returned by SetFilePointer() */ DWORD lastErrno; /* Value returned by GetLastError() */ | < < | < < < < < < < < < < | < < < < < < > < | 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 31989 31990 31991 31992 31993 31994 31995 31996 31997 31998 31999 32000 32001 32002 32003 32004 32005 32006 32007 32008 32009 32010 32011 32012 32013 32014 32015 32016 32017 32018 32019 32020 32021 32022 32023 32024 32025 32026 32027 32028 32029 32030 32031 32032 32033 32034 32035 32036 32037 32038 32039 32040 32041 32042 32043 | static int seekWinFile(winFile *pFile, sqlite3_int64 iOffset){ #if !SQLITE_OS_WINRT LONG upperBits; /* Most sig. 32 bits of new offset */ LONG lowerBits; /* Least sig. 32 bits of new offset */ DWORD dwRet; /* Value returned by SetFilePointer() */ DWORD lastErrno; /* Value returned by GetLastError() */ upperBits = (LONG)((iOffset>>32) & 0x7fffffff); lowerBits = (LONG)(iOffset & 0xffffffff); /* API oddity: If successful, SetFilePointer() returns a dword ** containing the lower 32-bits of the new file-offset. Or, if it fails, ** it returns INVALID_SET_FILE_POINTER. However according to MSDN, ** INVALID_SET_FILE_POINTER may also be a valid new offset. So to determine ** whether an error has actually occured, it is also necessary to call ** GetLastError(). */ dwRet = osSetFilePointer(pFile->h, lowerBits, &upperBits, FILE_BEGIN); if( (dwRet==INVALID_SET_FILE_POINTER && ((lastErrno = osGetLastError())!=NO_ERROR)) ){ pFile->lastErrno = lastErrno; winLogError(SQLITE_IOERR_SEEK, pFile->lastErrno, "seekWinFile", pFile->zPath); return 1; } return 0; #else /* ** Same as above, except that this implementation works for WinRT. */ LARGE_INTEGER x; /* The new offset */ BOOL bRet; /* Value returned by SetFilePointerEx() */ x.QuadPart = iOffset; bRet = osSetFilePointerEx(pFile->h, x, 0, FILE_BEGIN); if(!bRet){ pFile->lastErrno = osGetLastError(); winLogError(SQLITE_IOERR_SEEK, pFile->lastErrno, "seekWinFile", pFile->zPath); return 1; } return 0; #endif } /* ** Close a file. ** ** It is reported that an attempt to close a handle might sometimes ** fail. This is a very unreasonable result, but Windows is notorious ** for being unreasonable so I do not doubt that it might happen. If ** the close fails, we pause for 100 milliseconds and try again. As ** many as MX_CLOSE_ATTEMPT attempts to close the handle are made before ** giving up and returning an error. */ #define MX_CLOSE_ATTEMPT 3 static int winClose(sqlite3_file *id){ int rc, cnt = 0; winFile *pFile = (winFile*)id; assert( id!=0 ); #ifndef SQLITE_OMIT_WAL assert( pFile->pShm==0 ); #endif OSTRACE(("CLOSE %d\n", pFile->h)); do{ rc = osCloseHandle(pFile->h); /* SimulateIOError( rc=0; cnt=MX_CLOSE_ATTEMPT; ); */ }while( rc==0 && ++cnt < MX_CLOSE_ATTEMPT && (sqlite3_win32_sleep(100), 1) ); #if SQLITE_OS_WINCE #define WINCE_DELETION_ATTEMPTS 3 winceDestroyLock(pFile); if( pFile->zDeleteOnClose ){ int cnt = 0; while( osDeleteFileW(pFile->zDeleteOnClose)==0 && osGetFileAttributesW(pFile->zDeleteOnClose)!=0xffffffff && cnt++ < WINCE_DELETION_ATTEMPTS ){ sqlite3_win32_sleep(100); /* Wait a little before trying again */ } sqlite3_free(pFile->zDeleteOnClose); } #endif OSTRACE(("CLOSE %d %s\n", pFile->h, rc ? "ok" : "failed")); if( rc ){ pFile->h = NULL; } OpenCounter(-1); return rc ? SQLITE_OK : winLogError(SQLITE_IOERR_CLOSE, osGetLastError(), "winClose", pFile->zPath); } /* ** Read data from a file into a buffer. Return SQLITE_OK if all |
︙ | ︙ | |||
32869 32870 32871 32872 32873 32874 32875 | OVERLAPPED overlapped; /* The offset for ReadFile. */ #endif winFile *pFile = (winFile*)id; /* file handle */ DWORD nRead; /* Number of bytes actually read from file */ int nRetry = 0; /* Number of retrys */ assert( id!=0 ); | < < < < | < < < < < < < < < < < < < < < < < < < < < | < < | < < < < < < < < < < < < < < < < < | 32054 32055 32056 32057 32058 32059 32060 32061 32062 32063 32064 32065 32066 32067 32068 32069 32070 32071 32072 32073 32074 32075 32076 32077 32078 32079 32080 32081 32082 32083 32084 32085 32086 32087 32088 32089 32090 32091 32092 32093 32094 32095 32096 32097 32098 32099 32100 32101 32102 32103 32104 32105 32106 32107 32108 32109 32110 32111 32112 32113 32114 32115 32116 32117 32118 | OVERLAPPED overlapped; /* The offset for ReadFile. */ #endif 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 SQLITE_OS_WINCE if( seekWinFile(pFile, offset) ){ return SQLITE_FULL; } while( !osReadFile(pFile->h, pBuf, amt, &nRead, 0) ){ #else memset(&overlapped, 0, sizeof(OVERLAPPED)); overlapped.Offset = (LONG)(offset & 0xffffffff); overlapped.OffsetHigh = (LONG)((offset>>32) & 0x7fffffff); while( !osReadFile(pFile->h, pBuf, amt, &nRead, &overlapped) && osGetLastError()!=ERROR_HANDLE_EOF ){ #endif DWORD lastErrno; if( retryIoerr(&nRetry, &lastErrno) ) continue; pFile->lastErrno = lastErrno; return winLogError(SQLITE_IOERR_READ, pFile->lastErrno, "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; } /* ** Write data from a buffer into a file. Return SQLITE_OK on success ** or some other error code on failure. */ static int winWrite( 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 = 0; /* 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)); #if SQLITE_OS_WINCE rc = seekWinFile(pFile, offset); if( rc==0 ){ #else { #endif |
︙ | ︙ | |||
32994 32995 32996 32997 32998 32999 33000 | if( !osWriteFile(pFile->h, aRem, nRem, &nWrite, 0) ){ #else if( !osWriteFile(pFile->h, aRem, nRem, &nWrite, &overlapped) ){ #endif if( retryIoerr(&nRetry, &lastErrno) ) continue; break; } | < | < < < < > > < < | | < | | < < < < < < < < < | < | 32135 32136 32137 32138 32139 32140 32141 32142 32143 32144 32145 32146 32147 32148 32149 32150 32151 32152 32153 32154 32155 32156 32157 32158 32159 32160 32161 32162 32163 32164 32165 32166 32167 32168 32169 32170 32171 32172 32173 32174 32175 32176 32177 32178 32179 32180 32181 32182 32183 32184 32185 32186 32187 32188 32189 32190 32191 32192 32193 32194 32195 32196 32197 32198 32199 32200 32201 32202 32203 32204 32205 32206 32207 32208 32209 32210 32211 | if( !osWriteFile(pFile->h, aRem, nRem, &nWrite, 0) ){ #else if( !osWriteFile(pFile->h, aRem, nRem, &nWrite, &overlapped) ){ #endif if( retryIoerr(&nRetry, &lastErrno) ) continue; break; } if( nWrite<=0 ){ lastErrno = osGetLastError(); break; } #if !SQLITE_OS_WINCE offset += nWrite; overlapped.Offset = (LONG)(offset & 0xffffffff); overlapped.OffsetHigh = (LONG)((offset>>32) & 0x7fffffff); #endif aRem += nWrite; nRem -= nWrite; } if( nRem>0 ){ pFile->lastErrno = lastErrno; rc = 1; } } if( rc ){ if( ( pFile->lastErrno==ERROR_HANDLE_DISK_FULL ) || ( pFile->lastErrno==ERROR_DISK_FULL )){ return SQLITE_FULL; } return winLogError(SQLITE_IOERR_WRITE, pFile->lastErrno, "winWrite", pFile->zPath); }else{ logIoerr(nRetry); } return SQLITE_OK; } /* ** Truncate an open file to a specified size */ static int winTruncate(sqlite3_file *id, sqlite3_int64 nByte){ winFile *pFile = (winFile*)id; /* File handle object */ int rc = SQLITE_OK; /* Return code for this function */ assert( pFile ); OSTRACE(("TRUNCATE %d %lld\n", pFile->h, nByte)); 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, pFile->lastErrno, "winTruncate1", pFile->zPath); }else if( 0==osSetEndOfFile(pFile->h) ){ pFile->lastErrno = osGetLastError(); rc = winLogError(SQLITE_IOERR_TRUNCATE, pFile->lastErrno, "winTruncate2", pFile->zPath); } OSTRACE(("TRUNCATE %d %lld %s\n", pFile->h, nByte, rc ? "failed" : "ok")); return rc; } #ifdef SQLITE_TEST /* ** Count the number of fullsyncs and normal syncs. This is used to test ** that syncs and fullsyncs are occuring at the right times. |
︙ | ︙ | |||
33111 33112 33113 33114 33115 33116 33117 33118 33119 33120 33121 33122 33123 | #endif assert( pFile ); /* Check that one of SQLITE_SYNC_NORMAL or FULL was passed */ assert((flags&0x0F)==SQLITE_SYNC_NORMAL || (flags&0x0F)==SQLITE_SYNC_FULL ); /* Unix cannot, but some systems may return SQLITE_FULL from here. This ** line is to test that doing so does not cause any problems. */ SimulateDiskfullError( return SQLITE_FULL ); | > > < < < < < < < < | 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 32278 32279 32280 32281 32282 32283 32284 32285 32286 32287 32288 32289 32290 32291 32292 32293 | #endif assert( pFile ); /* Check that one of SQLITE_SYNC_NORMAL or FULL was passed */ assert((flags&0x0F)==SQLITE_SYNC_NORMAL || (flags&0x0F)==SQLITE_SYNC_FULL ); OSTRACE(("SYNC %d lock=%d\n", pFile->h, pFile->locktype)); /* Unix cannot, but some systems may return SQLITE_FULL from here. This ** line is to test that doing so does not cause any problems. */ SimulateDiskfullError( return SQLITE_FULL ); #ifndef SQLITE_TEST UNUSED_PARAMETER(flags); #else if( (flags&0x0F)==SQLITE_SYNC_FULL ){ sqlite3_fullsync_count++; } sqlite3_sync_count++; #endif /* If we compiled with the SQLITE_NO_SYNC flag, then syncing is a ** no-op */ #ifdef SQLITE_NO_SYNC return SQLITE_OK; #else rc = osFlushFileBuffers(pFile->h); SimulateIOError( rc=FALSE ); if( rc ){ return SQLITE_OK; }else{ pFile->lastErrno = osGetLastError(); return winLogError(SQLITE_IOERR_FSYNC, pFile->lastErrno, "winSync", pFile->zPath); } #endif } /* ** Determine the current size of a file in bytes */ static int winFileSize(sqlite3_file *id, sqlite3_int64 *pSize){ winFile *pFile = (winFile*)id; int rc = SQLITE_OK; assert( id!=0 ); SimulateIOError(return SQLITE_IOERR_FSTAT); #if SQLITE_OS_WINRT { FILE_STANDARD_INFO info; if( osGetFileInformationByHandleEx(pFile->h, FileStandardInfo, &info, sizeof(info)) ){ *pSize = info.EndOfFile.QuadPart; }else{ |
︙ | ︙ | |||
33189 33190 33191 33192 33193 33194 33195 | && ((lastErrno = osGetLastError())!=NO_ERROR) ){ pFile->lastErrno = lastErrno; rc = winLogError(SQLITE_IOERR_FSTAT, pFile->lastErrno, "winFileSize", pFile->zPath); } } #endif | < < | 32308 32309 32310 32311 32312 32313 32314 32315 32316 32317 32318 32319 32320 32321 | && ((lastErrno = osGetLastError())!=NO_ERROR) ){ pFile->lastErrno = lastErrno; rc = winLogError(SQLITE_IOERR_FSTAT, pFile->lastErrno, "winFileSize", pFile->zPath); } } #endif return rc; } /* ** LOCKFILE_FAIL_IMMEDIATELY is undefined on some Windows systems. */ #ifndef LOCKFILE_FAIL_IMMEDIATELY |
︙ | ︙ | |||
33232 33233 33234 33235 33236 33237 33238 | /* ** Acquire a reader lock. ** Different API routines are called depending on whether or not this ** is Win9x or WinNT. */ static int getReadLock(winFile *pFile){ int res; | < | 32349 32350 32351 32352 32353 32354 32355 32356 32357 32358 32359 32360 32361 32362 | /* ** Acquire a reader lock. ** Different API routines are called depending on whether or not this ** is Win9x or WinNT. */ static int getReadLock(winFile *pFile){ int res; if( isNT() ){ #if SQLITE_OS_WINCE /* ** NOTE: Windows CE is handled differently here due its lack of the Win32 ** API LockFileEx. */ res = winceLockFile(&pFile->h, SHARED_FIRST, 0, 1, 0); |
︙ | ︙ | |||
33258 33259 33260 33261 33262 33263 33264 | SHARED_FIRST+pFile->sharedLockByte, 0, 1, 0); } #endif if( res == 0 ){ pFile->lastErrno = osGetLastError(); /* No need to log a failure to lock */ } | < < < | 32374 32375 32376 32377 32378 32379 32380 32381 32382 32383 32384 32385 32386 32387 32388 32389 32390 32391 32392 32393 32394 32395 32396 32397 32398 32399 32400 32401 32402 32403 32404 32405 32406 32407 32408 32409 | SHARED_FIRST+pFile->sharedLockByte, 0, 1, 0); } #endif if( res == 0 ){ pFile->lastErrno = osGetLastError(); /* No need to log a failure to lock */ } return res; } /* ** Undo a readlock */ static int unlockReadLock(winFile *pFile){ int res; DWORD lastErrno; if( isNT() ){ res = winUnlockFile(&pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0); } #ifdef SQLITE_WIN32_HAS_ANSI else{ res = winUnlockFile(&pFile->h, SHARED_FIRST+pFile->sharedLockByte, 0, 1, 0); } #endif if( res==0 && ((lastErrno = osGetLastError())!=ERROR_NOT_LOCKED) ){ pFile->lastErrno = lastErrno; winLogError(SQLITE_IOERR_UNLOCK, pFile->lastErrno, "unlockReadLock", pFile->zPath); } return res; } /* ** Lock the file with the lock specified by parameter locktype - one ** of the following: ** |
︙ | ︙ | |||
33321 33322 33323 33324 33325 33326 33327 | int res = 1; /* Result of a Windows lock call */ int newLocktype; /* Set pFile->locktype to this value before exiting */ int gotPendingLock = 0;/* True if we acquired a PENDING lock this time */ winFile *pFile = (winFile*)id; DWORD lastErrno = NO_ERROR; assert( id!=0 ); | | | < | 32434 32435 32436 32437 32438 32439 32440 32441 32442 32443 32444 32445 32446 32447 32448 32449 32450 32451 32452 32453 32454 32455 | int res = 1; /* Result of a Windows lock call */ int newLocktype; /* Set pFile->locktype to this value before exiting */ int gotPendingLock = 0;/* True if we acquired a PENDING lock this time */ winFile *pFile = (winFile*)id; DWORD lastErrno = NO_ERROR; assert( id!=0 ); OSTRACE(("LOCK %d %d was %d(%d)\n", pFile->h, locktype, pFile->locktype, pFile->sharedLockByte)); /* If there is already a lock of this type or more restrictive on the ** OsFile, do nothing. Don't use the end_lock: exit path, as ** sqlite3OsEnterMutex() hasn't been called yet. */ if( pFile->locktype>=locktype ){ return SQLITE_OK; } /* Make sure the locking sequence is correct */ assert( pFile->locktype!=NO_LOCK || locktype==SHARED_LOCK ); assert( locktype!=PENDING_LOCK ); |
︙ | ︙ | |||
33357 33358 33359 33360 33361 33362 33363 | PENDING_BYTE, 0, 1, 0))==0 ){ /* Try 3 times to get the pending lock. This is needed to work ** around problems caused by indexing and/or anti-virus software on ** Windows systems. ** If you are using this code as a model for alternative VFSes, do not ** copy this retry logic. It is a hack intended for Windows only. */ | | < | 32469 32470 32471 32472 32473 32474 32475 32476 32477 32478 32479 32480 32481 32482 32483 | PENDING_BYTE, 0, 1, 0))==0 ){ /* Try 3 times to get the pending lock. This is needed to work ** around problems caused by indexing and/or anti-virus software on ** Windows systems. ** If you are using this code as a model for alternative VFSes, do not ** copy this retry logic. It is a hack intended for Windows only. */ OSTRACE(("could not get a PENDING lock. cnt=%d\n", cnt)); if( cnt ) sqlite3_win32_sleep(1); } gotPendingLock = res; if( !res ){ lastErrno = osGetLastError(); } } |
︙ | ︙ | |||
33403 33404 33405 33406 33407 33408 33409 33410 33411 33412 33413 33414 33415 33416 33417 33418 33419 33420 33421 33422 33423 33424 33425 33426 33427 33428 33429 33430 33431 33432 | } /* Acquire an EXCLUSIVE lock */ if( locktype==EXCLUSIVE_LOCK && res ){ assert( pFile->locktype>=SHARED_LOCK ); res = unlockReadLock(pFile); res = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS, SHARED_FIRST, 0, SHARED_SIZE, 0); if( res ){ newLocktype = EXCLUSIVE_LOCK; }else{ lastErrno = osGetLastError(); getReadLock(pFile); } } /* If we are holding a PENDING lock that ought to be released, then ** release it now. */ if( gotPendingLock && locktype==SHARED_LOCK ){ winUnlockFile(&pFile->h, PENDING_BYTE, 0, 1, 0); } /* Update the state of the lock has held in the file descriptor then ** return the appropriate result code. */ if( res ){ rc = SQLITE_OK; }else{ | > > | | < < < | | | < < | | < < < < < < < < < < < < < < < < < < < < | < < < < < < < < < < < < < < < < < | 32514 32515 32516 32517 32518 32519 32520 32521 32522 32523 32524 32525 32526 32527 32528 32529 32530 32531 32532 32533 32534 32535 32536 32537 32538 32539 32540 32541 32542 32543 32544 32545 32546 32547 32548 32549 32550 32551 32552 32553 32554 32555 32556 32557 32558 32559 32560 32561 32562 32563 32564 32565 32566 32567 32568 32569 32570 32571 32572 32573 32574 32575 32576 32577 32578 32579 32580 32581 32582 32583 32584 32585 32586 32587 32588 32589 32590 32591 32592 32593 32594 32595 32596 32597 32598 32599 32600 32601 32602 32603 32604 32605 32606 32607 32608 32609 32610 32611 32612 32613 32614 32615 32616 32617 32618 32619 32620 32621 32622 32623 32624 32625 32626 32627 32628 32629 32630 32631 32632 32633 32634 32635 32636 32637 32638 32639 32640 32641 32642 32643 32644 32645 32646 32647 32648 32649 32650 32651 32652 32653 32654 32655 32656 32657 32658 32659 32660 32661 32662 32663 32664 32665 32666 32667 32668 32669 32670 32671 32672 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 32702 32703 32704 32705 32706 32707 | } /* Acquire an EXCLUSIVE lock */ if( locktype==EXCLUSIVE_LOCK && res ){ assert( pFile->locktype>=SHARED_LOCK ); res = unlockReadLock(pFile); OSTRACE(("unreadlock = %d\n", res)); res = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS, SHARED_FIRST, 0, SHARED_SIZE, 0); if( res ){ newLocktype = EXCLUSIVE_LOCK; }else{ lastErrno = osGetLastError(); OSTRACE(("error-code = %d\n", lastErrno)); getReadLock(pFile); } } /* If we are holding a PENDING lock that ought to be released, then ** release it now. */ if( gotPendingLock && locktype==SHARED_LOCK ){ winUnlockFile(&pFile->h, PENDING_BYTE, 0, 1, 0); } /* Update the state of the lock has held in the file descriptor then ** return the appropriate result code. */ if( res ){ rc = SQLITE_OK; }else{ OSTRACE(("LOCK FAILED %d trying for %d but got %d\n", pFile->h, locktype, newLocktype)); pFile->lastErrno = lastErrno; rc = SQLITE_BUSY; } pFile->locktype = (u8)newLocktype; return rc; } /* ** This routine checks if there is a RESERVED lock held on the specified ** file by this or any other process. If such a lock is held, return ** non-zero, otherwise zero. */ static int winCheckReservedLock(sqlite3_file *id, int *pResOut){ int rc; winFile *pFile = (winFile*)id; SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; ); assert( id!=0 ); if( pFile->locktype>=RESERVED_LOCK ){ rc = 1; OSTRACE(("TEST WR-LOCK %d %d (local)\n", pFile->h, rc)); }else{ rc = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS, RESERVED_BYTE, 0, 1, 0); if( rc ){ winUnlockFile(&pFile->h, RESERVED_BYTE, 0, 1, 0); } rc = !rc; OSTRACE(("TEST WR-LOCK %d %d (remote)\n", pFile->h, rc)); } *pResOut = rc; return SQLITE_OK; } /* ** Lower the locking level on file descriptor id to locktype. locktype ** must be either NO_LOCK or SHARED_LOCK. ** ** If the locking level of the file descriptor is already at or below ** the requested locking level, this routine is a no-op. ** ** It is not possible for this routine to fail if the second argument ** is NO_LOCK. If the second argument is SHARED_LOCK then this routine ** might return SQLITE_IOERR; */ static int winUnlock(sqlite3_file *id, int locktype){ int type; winFile *pFile = (winFile*)id; int rc = SQLITE_OK; assert( pFile!=0 ); assert( locktype<=SHARED_LOCK ); OSTRACE(("UNLOCK %d to %d was %d(%d)\n", pFile->h, locktype, pFile->locktype, pFile->sharedLockByte)); type = pFile->locktype; if( type>=EXCLUSIVE_LOCK ){ winUnlockFile(&pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0); if( locktype==SHARED_LOCK && !getReadLock(pFile) ){ /* This should never happen. We should always be able to ** reacquire the read lock */ rc = winLogError(SQLITE_IOERR_UNLOCK, osGetLastError(), "winUnlock", pFile->zPath); } } if( type>=RESERVED_LOCK ){ winUnlockFile(&pFile->h, RESERVED_BYTE, 0, 1, 0); } if( locktype==NO_LOCK && type>=SHARED_LOCK ){ unlockReadLock(pFile); } if( type>=PENDING_LOCK ){ winUnlockFile(&pFile->h, PENDING_BYTE, 0, 1, 0); } pFile->locktype = (u8)locktype; return rc; } /* ** If *pArg is inititially negative then this is a query. Set *pArg to ** 1 or 0 depending on whether or not bit mask of pFile->ctrlFlags is set. ** ** If *pArg is 0 or 1, then clear or set the mask bit of pFile->ctrlFlags. */ static void winModeBit(winFile *pFile, unsigned char mask, int *pArg){ if( *pArg<0 ){ *pArg = (pFile->ctrlFlags & mask)!=0; }else if( (*pArg)==0 ){ pFile->ctrlFlags &= ~mask; }else{ pFile->ctrlFlags |= mask; } } /* ** 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: { winModeBit(pFile, WINFILE_PERSIST_WAL, (int*)pArg); return SQLITE_OK; } case SQLITE_FCNTL_POWERSAFE_OVERWRITE: { winModeBit(pFile, WINFILE_PSOW, (int*)pArg); return SQLITE_OK; } case SQLITE_FCNTL_VFSNAME: { *(char**)pArg = sqlite3_mprintf("win32"); 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; } /* ** Return the sector size in bytes of the underlying block device for ** the specified file. This is almost always 512 bytes, but may be ** larger for some devices. |
︙ | ︙ | |||
33650 33651 33652 33653 33654 33655 33656 33657 33658 33659 33660 33661 33662 33663 33664 | */ static int winDeviceCharacteristics(sqlite3_file *id){ winFile *p = (winFile*)id; return SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN | ((p->ctrlFlags & WINFILE_PSOW)?SQLITE_IOCAP_POWERSAFE_OVERWRITE:0); } /* ** Windows will only let you create file view mappings ** on allocation size granularity boundaries. ** During sqlite3_os_init() we do a GetSystemInfo() ** to get the granularity size. */ SYSTEM_INFO winSysInfo; | > > < < | 32721 32722 32723 32724 32725 32726 32727 32728 32729 32730 32731 32732 32733 32734 32735 32736 32737 32738 32739 32740 32741 32742 32743 32744 | */ static int winDeviceCharacteristics(sqlite3_file *id){ winFile *p = (winFile*)id; return SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN | ((p->ctrlFlags & WINFILE_PSOW)?SQLITE_IOCAP_POWERSAFE_OVERWRITE:0); } #ifndef SQLITE_OMIT_WAL /* ** Windows will only let you create file view mappings ** on allocation size granularity boundaries. ** During sqlite3_os_init() we do a GetSystemInfo() ** to get the granularity size. */ SYSTEM_INFO winSysInfo; /* ** Helper functions to obtain and relinquish the global mutex. The ** global mutex is used to protect the winLockInfo objects used by ** this file, all of which may be shared by multiple threads. ** ** Function winShmMutexHeld() is used to assert() that the global mutex ** is held when required. This function is only used as part of assert() |
︙ | ︙ | |||
33783 33784 33785 33786 33787 33788 33789 | int nByte /* Number of bytes to lock or unlock */ ){ int rc = 0; /* Result code form Lock/UnlockFileEx() */ /* Access to the winShmNode object is serialized by the caller */ assert( sqlite3_mutex_held(pFile->mutex) || pFile->nRef==0 ); | < < < | | > > | < < | | > | | > | | 32854 32855 32856 32857 32858 32859 32860 32861 32862 32863 32864 32865 32866 32867 32868 32869 32870 32871 32872 32873 32874 32875 32876 32877 32878 32879 32880 32881 32882 32883 32884 32885 32886 32887 32888 32889 32890 32891 32892 32893 32894 32895 32896 32897 32898 32899 32900 32901 32902 32903 32904 32905 32906 32907 32908 32909 32910 32911 32912 32913 32914 32915 32916 32917 32918 32919 32920 32921 32922 32923 32924 | int nByte /* Number of bytes to lock or unlock */ ){ int rc = 0; /* Result code form Lock/UnlockFileEx() */ /* Access to the winShmNode object is serialized by the caller */ assert( sqlite3_mutex_held(pFile->mutex) || pFile->nRef==0 ); /* Release/Acquire the system-level lock */ if( lockType==_SHM_UNLCK ){ rc = winUnlockFile(&pFile->hFile.h, ofst, 0, nByte, 0); }else{ /* Initialize the locking parameters */ DWORD dwFlags = LOCKFILE_FAIL_IMMEDIATELY; if( lockType == _SHM_WRLCK ) dwFlags |= LOCKFILE_EXCLUSIVE_LOCK; rc = winLockFile(&pFile->hFile.h, dwFlags, ofst, 0, nByte, 0); } if( rc!= 0 ){ rc = SQLITE_OK; }else{ pFile->lastErrno = osGetLastError(); rc = SQLITE_BUSY; } OSTRACE(("SHM-LOCK %d %s %s 0x%08lx\n", pFile->hFile.h, rc==SQLITE_OK ? "ok" : "failed", lockType==_SHM_UNLCK ? "UnlockFileEx" : "LockFileEx", pFile->lastErrno)); return rc; } /* Forward references to VFS methods */ static int winOpen(sqlite3_vfs*,const char*,sqlite3_file*,int,int*); static int winDelete(sqlite3_vfs *,const char*,int); /* ** Purge the winShmNodeList list of all entries with winShmNode.nRef==0. ** ** This is not a VFS shared-memory method; it is a utility function called ** by VFS shared-memory methods. */ static void winShmPurge(sqlite3_vfs *pVfs, int deleteFlag){ winShmNode **pp; winShmNode *p; BOOL bRc; assert( winShmMutexHeld() ); pp = &winShmNodeList; while( (p = *pp)!=0 ){ if( p->nRef==0 ){ int i; if( p->mutex ) sqlite3_mutex_free(p->mutex); for(i=0; i<p->nRegion; i++){ bRc = osUnmapViewOfFile(p->aRegion[i].pMap); OSTRACE(("SHM-PURGE pid-%d unmap region=%d %s\n", (int)osGetCurrentProcessId(), i, bRc ? "ok" : "failed")); bRc = osCloseHandle(p->aRegion[i].hMap); OSTRACE(("SHM-PURGE pid-%d close region=%d %s\n", (int)osGetCurrentProcessId(), i, bRc ? "ok" : "failed")); } if( p->hFile.h != INVALID_HANDLE_VALUE ){ SimulateIOErrorBenign(1); winClose((sqlite3_file *)&p->hFile); SimulateIOErrorBenign(0); } if( deleteFlag ){ SimulateIOErrorBenign(1); sqlite3BeginBenignMalloc(); |
︙ | ︙ | |||
33920 33921 33922 33923 33924 33925 33926 | rc = SQLITE_IOERR_NOMEM; goto shm_open_err; } rc = winOpen(pDbFd->pVfs, pShmNode->zFilename, /* Name of the file (UTF-8) */ (sqlite3_file*)&pShmNode->hFile, /* File handle here */ | | | 32990 32991 32992 32993 32994 32995 32996 32997 32998 32999 33000 33001 33002 33003 33004 | rc = SQLITE_IOERR_NOMEM; goto shm_open_err; } rc = winOpen(pDbFd->pVfs, pShmNode->zFilename, /* Name of the file (UTF-8) */ (sqlite3_file*)&pShmNode->hFile, /* File handle here */ SQLITE_OPEN_WAL | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, /* Mode flags */ 0); if( SQLITE_OK!=rc ){ goto shm_open_err; } /* Check to see if another process is holding the dead-man switch. ** If not, truncate the file to zero length. |
︙ | ︙ | |||
34117 34118 34119 34120 34121 34122 34123 | if( rc==SQLITE_OK ){ assert( (p->sharedMask & mask)==0 ); p->exclMask |= mask; } } } sqlite3_mutex_leave(pShmNode->mutex); | | | | | 33187 33188 33189 33190 33191 33192 33193 33194 33195 33196 33197 33198 33199 33200 33201 33202 33203 | if( rc==SQLITE_OK ){ assert( (p->sharedMask & mask)==0 ); p->exclMask |= mask; } } } sqlite3_mutex_leave(pShmNode->mutex); OSTRACE(("SHM-LOCK shmid-%d, pid-%d got %03x,%03x %s\n", p->id, (int)osGetCurrentProcessId(), p->sharedMask, p->exclMask, rc ? "failed" : "ok")); return rc; } /* ** Implement a memory barrier or memory fence on shared memory. ** ** All loads and stores begun before the barrier must complete before |
︙ | ︙ | |||
34240 34241 34242 34243 34244 34245 34246 | NULL, PAGE_READWRITE, 0, nByte, NULL ); #elif defined(SQLITE_WIN32_HAS_ANSI) hMap = osCreateFileMappingA(pShmNode->hFile.h, NULL, PAGE_READWRITE, 0, nByte, NULL ); #endif | | | | | | 33310 33311 33312 33313 33314 33315 33316 33317 33318 33319 33320 33321 33322 33323 33324 33325 33326 33327 33328 33329 33330 33331 33332 33333 33334 33335 33336 33337 33338 33339 33340 | NULL, PAGE_READWRITE, 0, nByte, NULL ); #elif defined(SQLITE_WIN32_HAS_ANSI) hMap = osCreateFileMappingA(pShmNode->hFile.h, NULL, PAGE_READWRITE, 0, nByte, NULL ); #endif OSTRACE(("SHM-MAP pid-%d create region=%d nbyte=%d %s\n", (int)osGetCurrentProcessId(), pShmNode->nRegion, nByte, hMap ? "ok" : "failed")); if( hMap ){ int iOffset = pShmNode->nRegion*szRegion; int iOffsetShift = iOffset % winSysInfo.dwAllocationGranularity; #if SQLITE_OS_WINRT pMap = osMapViewOfFileFromApp(hMap, FILE_MAP_WRITE | FILE_MAP_READ, iOffset - iOffsetShift, szRegion + iOffsetShift ); #else pMap = osMapViewOfFile(hMap, FILE_MAP_WRITE | FILE_MAP_READ, 0, iOffset - iOffsetShift, szRegion + iOffsetShift ); #endif OSTRACE(("SHM-MAP pid-%d map region=%d offset=%d size=%d %s\n", (int)osGetCurrentProcessId(), pShmNode->nRegion, iOffset, szRegion, pMap ? "ok" : "failed")); } if( !pMap ){ pShmNode->lastErrno = osGetLastError(); rc = winLogError(SQLITE_IOERR_SHMMAP, pShmNode->lastErrno, "winShmMap3", pDbFd->zPath); if( hMap ) osCloseHandle(hMap); |
︙ | ︙ | |||
34293 34294 34295 34296 34297 34298 34299 | #else # define winShmMap 0 # define winShmLock 0 # define winShmBarrier 0 # define winShmUnmap 0 #endif /* #ifndef SQLITE_OMIT_WAL */ | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | < < | 33363 33364 33365 33366 33367 33368 33369 33370 33371 33372 33373 33374 33375 33376 33377 33378 33379 33380 33381 33382 33383 33384 33385 33386 33387 33388 33389 33390 33391 33392 33393 33394 33395 33396 33397 33398 33399 33400 33401 33402 33403 33404 | #else # define winShmMap 0 # define winShmLock 0 # define winShmBarrier 0 # define winShmUnmap 0 #endif /* #ifndef SQLITE_OMIT_WAL */ /* ** Here ends the implementation of all sqlite3_file methods. ** ********************** End sqlite3_file Methods ******************************* ******************************************************************************/ /* ** This vector defines all the methods that can operate on an ** sqlite3_file for win32. */ static const sqlite3_io_methods winIoMethod = { 2, /* iVersion */ winClose, /* xClose */ winRead, /* xRead */ winWrite, /* xWrite */ winTruncate, /* xTruncate */ winSync, /* xSync */ winFileSize, /* xFileSize */ winLock, /* xLock */ winUnlock, /* xUnlock */ winCheckReservedLock, /* xCheckReservedLock */ winFileControl, /* xFileControl */ winSectorSize, /* xSectorSize */ winDeviceCharacteristics, /* xDeviceCharacteristics */ winShmMap, /* xShmMap */ winShmLock, /* xShmLock */ winShmBarrier, /* xShmBarrier */ winShmUnmap /* xShmUnmap */ }; /**************************************************************************** **************************** sqlite3_vfs methods **************************** ** ** This division contains the implementation of methods on the ** sqlite3_vfs object. |
︙ | ︙ | |||
34610 34611 34612 34613 34614 34615 34616 | WCHAR zWidePath[MAX_PATH]; osGetTempPathW(MAX_PATH-30, zWidePath); zMulti = unicodeToUtf8(zWidePath); if( zMulti ){ sqlite3_snprintf(MAX_PATH-30, zTempPath, "%s", zMulti); sqlite3_free(zMulti); }else{ | < < < | | | 33454 33455 33456 33457 33458 33459 33460 33461 33462 33463 33464 33465 33466 33467 33468 33469 33470 33471 33472 33473 33474 33475 33476 33477 33478 33479 33480 33481 33482 33483 33484 33485 33486 33487 33488 33489 33490 33491 33492 33493 33494 33495 33496 33497 33498 33499 33500 33501 33502 33503 33504 33505 33506 33507 33508 33509 33510 33511 | WCHAR zWidePath[MAX_PATH]; osGetTempPathW(MAX_PATH-30, zWidePath); zMulti = unicodeToUtf8(zWidePath); if( zMulti ){ sqlite3_snprintf(MAX_PATH-30, zTempPath, "%s", zMulti); sqlite3_free(zMulti); }else{ return SQLITE_IOERR_NOMEM; } } #ifdef SQLITE_WIN32_HAS_ANSI else{ char *zUtf8; char zMbcsPath[MAX_PATH]; osGetTempPathA(MAX_PATH-30, zMbcsPath); zUtf8 = sqlite3_win32_mbcs_to_utf8(zMbcsPath); if( zUtf8 ){ sqlite3_snprintf(MAX_PATH-30, zTempPath, "%s", zUtf8); sqlite3_free(zUtf8); }else{ return SQLITE_IOERR_NOMEM; } } #endif #endif /* Check that the output buffer is large enough for the temporary file ** name. If it is not, return SQLITE_ERROR. */ nTempPath = sqlite3Strlen30(zTempPath); if( (nTempPath + sqlite3Strlen30(SQLITE_TEMP_FILE_PREFIX) + 18) >= nBuf ){ return SQLITE_ERROR; } for(i=nTempPath; i>0 && zTempPath[i-1]=='\\'; i--){} zTempPath[i] = 0; sqlite3_snprintf(nBuf-18, zBuf, (nTempPath > 0) ? "%s\\"SQLITE_TEMP_FILE_PREFIX : SQLITE_TEMP_FILE_PREFIX, zTempPath); j = sqlite3Strlen30(zBuf); sqlite3_randomness(15, &zBuf[j]); for(i=0; i<15; i++, j++){ zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ]; } zBuf[j] = 0; zBuf[j+1] = 0; OSTRACE(("TEMP FILENAME: %s\n", zBuf)); return SQLITE_OK; } /* ** Return TRUE if the named file is really a directory. Return false if ** it is something other than a directory, or if there is any kind of memory ** allocation failure. */ |
︙ | ︙ | |||
34725 34726 34727 34728 34729 34730 34731 34732 34733 34734 34735 34736 34737 34738 34739 34740 34741 34742 | #if !defined(NDEBUG) || SQLITE_OS_WINCE int eType = flags&0xFFFFFF00; /* Type of file to open */ #endif 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); #ifndef NDEBUG int isOpenJournal = (isCreate && ( eType==SQLITE_OPEN_MASTER_JOURNAL || eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_WAL )); #endif | > > < < < | 33566 33567 33568 33569 33570 33571 33572 33573 33574 33575 33576 33577 33578 33579 33580 33581 33582 33583 33584 33585 33586 33587 33588 33589 33590 33591 33592 | #if !defined(NDEBUG) || SQLITE_OS_WINCE int eType = flags&0xFFFFFF00; /* Type of file to open */ #endif int isExclusive = (flags & SQLITE_OPEN_EXCLUSIVE); int isDelete = (flags & SQLITE_OPEN_DELETEONCLOSE); int isCreate = (flags & SQLITE_OPEN_CREATE); #ifndef NDEBUG int isReadonly = (flags & SQLITE_OPEN_READONLY); #endif int isReadWrite = (flags & SQLITE_OPEN_READWRITE); #ifndef NDEBUG int isOpenJournal = (isCreate && ( eType==SQLITE_OPEN_MASTER_JOURNAL || eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_WAL )); #endif /* Check the following statements are true: ** ** (a) Exactly one of the READWRITE and READONLY flags must be set, and ** (b) if CREATE is set, then READWRITE must also be set, and ** (c) if EXCLUSIVE is set, then CREATE must also be set. ** (d) if DELETEONCLOSE is set, then CREATE must also be set. */ |
︙ | ︙ | |||
34765 34766 34767 34768 34769 34770 34771 | /* Assert that the upper layer has set one of the "file-type" flags. */ assert( eType==SQLITE_OPEN_MAIN_DB || eType==SQLITE_OPEN_TEMP_DB || eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_TEMP_JOURNAL || eType==SQLITE_OPEN_SUBJOURNAL || eType==SQLITE_OPEN_MASTER_JOURNAL || eType==SQLITE_OPEN_TRANSIENT_DB || eType==SQLITE_OPEN_WAL ); | | | < > > < < < < | 33605 33606 33607 33608 33609 33610 33611 33612 33613 33614 33615 33616 33617 33618 33619 33620 33621 33622 33623 33624 33625 33626 33627 33628 33629 33630 33631 33632 33633 33634 33635 33636 33637 33638 33639 33640 33641 33642 33643 33644 33645 33646 33647 33648 33649 33650 33651 33652 33653 33654 33655 33656 33657 | /* Assert that the upper layer has set one of the "file-type" flags. */ assert( eType==SQLITE_OPEN_MAIN_DB || eType==SQLITE_OPEN_TEMP_DB || eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_TEMP_JOURNAL || eType==SQLITE_OPEN_SUBJOURNAL || eType==SQLITE_OPEN_MASTER_JOURNAL || eType==SQLITE_OPEN_TRANSIENT_DB || eType==SQLITE_OPEN_WAL ); assert( id!=0 ); UNUSED_PARAMETER(pVfs); #if SQLITE_OS_WINRT if( !sqlite3_temp_directory ){ sqlite3_log(SQLITE_ERROR, "sqlite3_temp_directory variable should be set for WinRT"); } #endif pFile->h = INVALID_HANDLE_VALUE; /* If the second argument to this function is NULL, generate a ** temporary file name to use */ if( !zUtf8Name ){ assert(isDelete && !isOpenJournal); rc = getTempname(MAX_PATH+2, zTmpname); if( rc!=SQLITE_OK ){ return rc; } zUtf8Name = zTmpname; } /* Database filenames are double-zero terminated if they are not ** URIs with parameters. Hence, they can always be passed into ** sqlite3_uri_parameter(). */ assert( (eType!=SQLITE_OPEN_MAIN_DB) || (flags & SQLITE_OPEN_URI) || zUtf8Name[strlen(zUtf8Name)+1]==0 ); /* Convert the filename to the system encoding. */ zConverted = convertUtf8Filename(zUtf8Name); if( zConverted==0 ){ return SQLITE_IOERR_NOMEM; } if( winIsDir(zConverted) ){ sqlite3_free(zConverted); return SQLITE_CANTOPEN_ISDIR; } if( isReadWrite ){ dwDesiredAccess = GENERIC_READ | GENERIC_WRITE; }else{ dwDesiredAccess = GENERIC_READ; |
︙ | ︙ | |||
34897 34898 34899 34900 34901 34902 34903 | retryIoerr(&cnt, &lastErrno) ){ /* Noop */ } } #endif logIoerr(cnt); | | > | | < < | > > > > > > > | > | > | < | < < < < < < < < < < < < < < < < < < < | 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 33791 33792 33793 33794 33795 33796 33797 33798 33799 33800 | retryIoerr(&cnt, &lastErrno) ){ /* Noop */ } } #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 = lastErrno; winLogError(SQLITE_CANTOPEN, pFile->lastErrno, "winOpen", zUtf8Name); sqlite3_free(zConverted); if( isReadWrite && !isExclusive ){ return winOpen(pVfs, zName, id, ((flags|SQLITE_OPEN_READONLY)&~(SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE)), pOutFlags); }else{ return SQLITE_CANTOPEN_BKPT; } } if( pOutFlags ){ if( isReadWrite ){ *pOutFlags = SQLITE_OPEN_READWRITE; }else{ *pOutFlags = SQLITE_OPEN_READONLY; } } memset(pFile, 0, sizeof(*pFile)); pFile->pMethod = &winIoMethod; pFile->h = h; pFile->lastErrno = NO_ERROR; pFile->pVfs = pVfs; #ifndef SQLITE_OMIT_WAL pFile->pShm = 0; #endif pFile->zPath = zName; if( sqlite3_uri_boolean(zName, "psow", SQLITE_POWERSAFE_OVERWRITE) ){ pFile->ctrlFlags |= WINFILE_PSOW; } #if SQLITE_OS_WINCE if( isReadWrite && eType==SQLITE_OPEN_MAIN_DB && !winceCreateLock(zName, pFile) ){ osCloseHandle(h); sqlite3_free(zConverted); return SQLITE_CANTOPEN_BKPT; } if( isTemp ){ pFile->zDeleteOnClose = zConverted; }else #endif { sqlite3_free(zConverted); } OpenCounter(+1); return rc; } /* ** Delete the named file. ** |
︙ | ︙ | |||
34992 34993 34994 34995 34996 34997 34998 | DWORD attr; DWORD lastErrno; void *zConverted; UNUSED_PARAMETER(pVfs); UNUSED_PARAMETER(syncDir); SimulateIOError(return SQLITE_IOERR_DELETE); | < < < < < < < | < < < < < < | < | 33817 33818 33819 33820 33821 33822 33823 33824 33825 33826 33827 33828 33829 33830 33831 33832 33833 33834 33835 33836 33837 33838 33839 33840 33841 33842 33843 33844 33845 33846 33847 33848 33849 33850 33851 | DWORD attr; DWORD lastErrno; void *zConverted; UNUSED_PARAMETER(pVfs); UNUSED_PARAMETER(syncDir); SimulateIOError(return SQLITE_IOERR_DELETE); zConverted = convertUtf8Filename(zFilename); if( zConverted==0 ){ return SQLITE_IOERR_NOMEM; } if( isNT() ){ do { #if SQLITE_OS_WINRT WIN32_FILE_ATTRIBUTE_DATA sAttrData; memset(&sAttrData, 0, sizeof(sAttrData)); if ( osGetFileAttributesExW(zConverted, GetFileExInfoStandard, &sAttrData) ){ attr = sAttrData.dwFileAttributes; }else{ rc = SQLITE_OK; /* Already gone? */ break; } #else attr = osGetFileAttributesW(zConverted); #endif if ( attr==INVALID_FILE_ATTRIBUTES ){ rc = SQLITE_OK; /* Already gone? */ break; } if ( attr&FILE_ATTRIBUTE_DIRECTORY ){ rc = SQLITE_ERROR; /* Files only. */ break; } if ( osDeleteFileW(zConverted) ){ |
︙ | ︙ | |||
35048 35049 35050 35051 35052 35053 35054 | } while(1); } #ifdef SQLITE_WIN32_HAS_ANSI else{ do { attr = osGetFileAttributesA(zConverted); if ( attr==INVALID_FILE_ATTRIBUTES ){ | < < < < < | < | | | < < < < | 33859 33860 33861 33862 33863 33864 33865 33866 33867 33868 33869 33870 33871 33872 33873 33874 33875 33876 33877 33878 33879 33880 33881 33882 33883 33884 33885 33886 33887 33888 33889 33890 33891 33892 33893 33894 33895 33896 33897 33898 33899 33900 33901 33902 33903 33904 33905 33906 33907 33908 33909 33910 33911 33912 33913 33914 33915 33916 33917 33918 33919 | } while(1); } #ifdef SQLITE_WIN32_HAS_ANSI else{ do { attr = osGetFileAttributesA(zConverted); if ( attr==INVALID_FILE_ATTRIBUTES ){ rc = SQLITE_OK; /* Already gone? */ break; } if ( attr&FILE_ATTRIBUTE_DIRECTORY ){ rc = SQLITE_ERROR; /* Files only. */ break; } if ( osDeleteFileA(zConverted) ){ rc = SQLITE_OK; /* Deleted OK. */ break; } if ( !retryIoerr(&cnt, &lastErrno) ){ rc = SQLITE_ERROR; /* No more retries. */ break; } } while(1); } #endif if( rc ){ rc = winLogError(SQLITE_IOERR_DELETE, lastErrno, "winDelete", zFilename); }else{ logIoerr(cnt); } sqlite3_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 */ const char *zFilename, /* Name of file to check */ int flags, /* Type of test to make on this file */ int *pResOut /* OUT: Result */ ){ DWORD attr; int rc = 0; DWORD lastErrno; void *zConverted; UNUSED_PARAMETER(pVfs); SimulateIOError( return SQLITE_IOERR_ACCESS; ); zConverted = convertUtf8Filename(zFilename); if( zConverted==0 ){ return SQLITE_IOERR_NOMEM; } if( isNT() ){ int cnt = 0; WIN32_FILE_ATTRIBUTE_DATA sAttrData; memset(&sAttrData, 0, sizeof(sAttrData)); while( !(rc = osGetFileAttributesExW((LPCWSTR)zConverted, |
︙ | ︙ | |||
35155 35156 35157 35158 35159 35160 35161 | rc = attr!=INVALID_FILE_ATTRIBUTES && (attr & FILE_ATTRIBUTE_READONLY)==0; break; default: assert(!"Invalid flags argument"); } *pResOut = rc; | < < | 33956 33957 33958 33959 33960 33961 33962 33963 33964 33965 33966 33967 33968 33969 | rc = attr!=INVALID_FILE_ATTRIBUTES && (attr & FILE_ATTRIBUTE_READONLY)==0; break; default: assert(!"Invalid flags argument"); } *pResOut = rc; return SQLITE_OK; } /* ** Returns non-zero if the specified path name should be used verbatim. If ** non-zero is returned from this function, the calling function must simply |
︙ | ︙ | |||
35224 35225 35226 35227 35228 35229 35230 | ** NOTE: We are dealing with a relative path name and the data ** directory has been set. Therefore, use it as the basis ** for converting the relative path name to an absolute ** one by prepending the data directory and a slash. */ char zOut[MAX_PATH+1]; memset(zOut, 0, MAX_PATH+1); | | < > > > > > | | 34023 34024 34025 34026 34027 34028 34029 34030 34031 34032 34033 34034 34035 34036 34037 34038 34039 34040 34041 34042 34043 34044 34045 34046 | ** NOTE: We are dealing with a relative path name and the data ** directory has been set. Therefore, use it as the basis ** for converting the relative path name to an absolute ** one by prepending the data directory and a slash. */ char zOut[MAX_PATH+1]; memset(zOut, 0, MAX_PATH+1); cygwin_conv_to_win32_path(zRelative, zOut); /* POSIX to Win32 */ sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s\\%s", sqlite3_data_directory, zOut); }else{ /* ** NOTE: The Cygwin docs state that the maximum length needed ** for the buffer passed to cygwin_conv_to_full_win32_path ** is MAX_PATH. */ cygwin_conv_to_full_win32_path(zRelative, zFull); } return SQLITE_OK; #endif #if (SQLITE_OS_WINCE || SQLITE_OS_WINRT) && !defined(__CYGWIN__) SimulateIOError( return SQLITE_ERROR ); /* WinCE has no concept of a relative pathname, or so I am told. */ |
︙ | ︙ | |||
35387 35388 35389 35390 35391 35392 35393 | sqlite3_free(zConverted); return (void*)h; } static void winDlError(sqlite3_vfs *pVfs, int nBuf, char *zBufOut){ UNUSED_PARAMETER(pVfs); getLastErrorMsg(osGetLastError(), nBuf, zBufOut); } | | | | 34190 34191 34192 34193 34194 34195 34196 34197 34198 34199 34200 34201 34202 34203 34204 34205 34206 | sqlite3_free(zConverted); return (void*)h; } static void winDlError(sqlite3_vfs *pVfs, int nBuf, char *zBufOut){ UNUSED_PARAMETER(pVfs); getLastErrorMsg(osGetLastError(), nBuf, zBufOut); } static void (*winDlSym(sqlite3_vfs *pVfs, void *pHandle, const char *zSymbol))(void){ UNUSED_PARAMETER(pVfs); return (void(*)(void))osGetProcAddressA((HANDLE)pHandle, zSymbol); } static void winDlClose(sqlite3_vfs *pVfs, void *pHandle){ UNUSED_PARAMETER(pVfs); osFreeLibrary((HANDLE)pHandle); } #else /* if SQLITE_OMIT_LOAD_EXTENSION is defined: */ #define winDlOpen 0 |
︙ | ︙ | |||
35487 35488 35489 35490 35491 35492 35493 | FILETIME ft; static const sqlite3_int64 winFiletimeEpoch = 23058135*(sqlite3_int64)8640000; #ifdef SQLITE_TEST static const sqlite3_int64 unixEpoch = 24405875*(sqlite3_int64)8640000; #endif /* 2^32 - to avoid use of LL and warnings in gcc */ static const sqlite3_int64 max32BitValue = | | < | 34290 34291 34292 34293 34294 34295 34296 34297 34298 34299 34300 34301 34302 34303 34304 | FILETIME ft; static const sqlite3_int64 winFiletimeEpoch = 23058135*(sqlite3_int64)8640000; #ifdef SQLITE_TEST static const sqlite3_int64 unixEpoch = 24405875*(sqlite3_int64)8640000; #endif /* 2^32 - to avoid use of LL and warnings in gcc */ static const sqlite3_int64 max32BitValue = (sqlite3_int64)2000000000 + (sqlite3_int64)2000000000 + (sqlite3_int64)294967296; #if SQLITE_OS_WINCE SYSTEMTIME time; osGetSystemTime(&time); /* if SystemTimeToFileTime() fails, it returns zero. */ if (!osSystemTimeToFileTime(&time,&ft)){ return SQLITE_ERROR; |
︙ | ︙ | |||
35597 35598 35599 35600 35601 35602 35603 35604 35605 35606 35607 35608 35609 35610 | winNextSystemCall, /* xNextSystemCall */ }; /* Double-check that the aSyscall[] array has been constructed ** correctly. See ticket [bb3a86e890c8e96ab] */ assert( ArraySize(aSyscall)==74 ); /* get memory map allocation granularity */ memset(&winSysInfo, 0, sizeof(SYSTEM_INFO)); #if SQLITE_OS_WINRT osGetNativeSystemInfo(&winSysInfo); #else osGetSystemInfo(&winSysInfo); #endif | > | | | 34399 34400 34401 34402 34403 34404 34405 34406 34407 34408 34409 34410 34411 34412 34413 34414 34415 34416 34417 34418 34419 34420 34421 34422 | winNextSystemCall, /* xNextSystemCall */ }; /* Double-check that the aSyscall[] array has been constructed ** correctly. See ticket [bb3a86e890c8e96ab] */ assert( ArraySize(aSyscall)==74 ); #ifndef SQLITE_OMIT_WAL /* get memory map allocation granularity */ memset(&winSysInfo, 0, sizeof(SYSTEM_INFO)); #if SQLITE_OS_WINRT osGetNativeSystemInfo(&winSysInfo); #else osGetSystemInfo(&winSysInfo); #endif assert(winSysInfo.dwAllocationGranularity > 0); #endif sqlite3_vfs_register(&winVfs, 1); return SQLITE_OK; } SQLITE_API int sqlite3_os_end(void){ #if SQLITE_OS_WINRT |
︙ | ︙ | |||
35698 35699 35700 35701 35702 35703 35704 | #define BITVEC_NPTR (BITVEC_USIZE/sizeof(Bitvec *)) /* ** A bitmap is an instance of the following structure. ** | | | 34501 34502 34503 34504 34505 34506 34507 34508 34509 34510 34511 34512 34513 34514 34515 | #define BITVEC_NPTR (BITVEC_USIZE/sizeof(Bitvec *)) /* ** A bitmap is an instance of the following structure. ** ** This bitmap records the existance of zero or more bits ** with values between 1 and iSize, inclusive. ** ** There are three possible representations of the bitmap. ** If iSize<=BITVEC_NBIT, then Bitvec.u.aBitmap[] is a straight ** bitmap. The least significant bit is bit 1. ** ** If iSize>BITVEC_NBIT and iDivisor==0 then Bitvec.u.aHash[] is |
︙ | ︙ | |||
38242 38243 38244 38245 38246 38247 38248 38249 38250 38251 38252 38253 38254 38255 38256 38257 38258 38259 38260 | #ifdef SQLITE_OMIT_WAL # define sqlite3WalOpen(x,y,z) 0 # define sqlite3WalLimit(x,y) # define sqlite3WalClose(w,x,y,z) 0 # define sqlite3WalBeginReadTransaction(y,z) 0 # define sqlite3WalEndReadTransaction(z) # define sqlite3WalDbsize(y) 0 # define sqlite3WalBeginWriteTransaction(y) 0 # define sqlite3WalEndWriteTransaction(x) 0 # define sqlite3WalUndo(x,y,z) 0 # define sqlite3WalSavepoint(y,z) # define sqlite3WalSavepointUndo(y,z) 0 # define sqlite3WalFrames(u,v,w,x,y,z) 0 # define sqlite3WalCheckpoint(r,s,t,u,v,w,x,y,z) 0 # define sqlite3WalCallback(z) 0 # define sqlite3WalExclusiveMode(y,z) 0 # define sqlite3WalHeapMemory(z) 0 # define sqlite3WalFramesize(z) 0 | > < | 37045 37046 37047 37048 37049 37050 37051 37052 37053 37054 37055 37056 37057 37058 37059 37060 37061 37062 37063 37064 37065 37066 37067 37068 37069 37070 37071 | #ifdef SQLITE_OMIT_WAL # define sqlite3WalOpen(x,y,z) 0 # define sqlite3WalLimit(x,y) # define sqlite3WalClose(w,x,y,z) 0 # define sqlite3WalBeginReadTransaction(y,z) 0 # define sqlite3WalEndReadTransaction(z) # define sqlite3WalRead(v,w,x,y,z) 0 # define sqlite3WalDbsize(y) 0 # define sqlite3WalBeginWriteTransaction(y) 0 # define sqlite3WalEndWriteTransaction(x) 0 # define sqlite3WalUndo(x,y,z) 0 # define sqlite3WalSavepoint(y,z) # define sqlite3WalSavepointUndo(y,z) 0 # define sqlite3WalFrames(u,v,w,x,y,z) 0 # define sqlite3WalCheckpoint(r,s,t,u,v,w,x,y,z) 0 # define sqlite3WalCallback(z) 0 # define sqlite3WalExclusiveMode(y,z) 0 # define sqlite3WalHeapMemory(z) 0 # define sqlite3WalFramesize(z) 0 #else #define WAL_SAVEPOINT_NDATA 4 /* Connection to a write-ahead log (WAL) file. ** There is one object of this type for each pager. */ |
︙ | ︙ | |||
38282 38283 38284 38285 38286 38287 38288 | ** write to or checkpoint the WAL. sqlite3WalCloseSnapshot() closes the ** transaction and releases the lock. */ SQLITE_PRIVATE int sqlite3WalBeginReadTransaction(Wal *pWal, int *); SQLITE_PRIVATE void sqlite3WalEndReadTransaction(Wal *pWal); /* Read a page from the write-ahead log, if it is present. */ | < | | 37085 37086 37087 37088 37089 37090 37091 37092 37093 37094 37095 37096 37097 37098 37099 | ** write to or checkpoint the WAL. sqlite3WalCloseSnapshot() closes the ** transaction and releases the lock. */ SQLITE_PRIVATE int sqlite3WalBeginReadTransaction(Wal *pWal, int *); SQLITE_PRIVATE void sqlite3WalEndReadTransaction(Wal *pWal); /* Read a page from the write-ahead log, if it is present. */ SQLITE_PRIVATE int sqlite3WalRead(Wal *pWal, Pgno pgno, int *pInWal, int nOut, u8 *pOut); /* If the WAL is not empty, return the size of the database. */ SQLITE_PRIVATE Pgno sqlite3WalDbsize(Wal *pWal); /* Obtain or release the WRITER lock. */ SQLITE_PRIVATE int sqlite3WalBeginWriteTransaction(Wal *pWal); SQLITE_PRIVATE int sqlite3WalEndWriteTransaction(Wal *pWal); |
︙ | ︙ | |||
38601 38602 38603 38604 38605 38606 38607 | ** by finalizing the journal file. Once in WRITER_FINISHED state, it is ** not possible to modify the database further. At this point, the upper ** layer must either commit or rollback the transaction. ** ** * A write transaction is active. ** * An EXCLUSIVE or greater lock is held on the database file. ** * All writing and syncing of journal and database data has finished. | | | 37403 37404 37405 37406 37407 37408 37409 37410 37411 37412 37413 37414 37415 37416 37417 | ** by finalizing the journal file. Once in WRITER_FINISHED state, it is ** not possible to modify the database further. At this point, the upper ** layer must either commit or rollback the transaction. ** ** * A write transaction is active. ** * An EXCLUSIVE or greater lock is held on the database file. ** * All writing and syncing of journal and database data has finished. ** If no error occured, all that remains is to finalize the journal to ** commit the transaction. If an error did occur, the caller will need ** to rollback the transaction. ** ** ERROR: ** ** The ERROR state is entered when an IO or disk-full error (including ** SQLITE_IOERR_NOMEM) occurs at a point in the code that makes it |
︙ | ︙ | |||
38849 38850 38851 38852 38853 38854 38855 | ** The flag is cleared as soon as the journal file is finalized (either ** by PagerCommitPhaseTwo or PagerRollback). If an IO error prevents the ** journal file from being successfully finalized, the setMaster flag ** is cleared anyway (and the pager will move to ERROR state). ** ** doNotSpill, doNotSyncSpill ** | | | 37651 37652 37653 37654 37655 37656 37657 37658 37659 37660 37661 37662 37663 37664 37665 | ** The flag is cleared as soon as the journal file is finalized (either ** by PagerCommitPhaseTwo or PagerRollback). If an IO error prevents the ** journal file from being successfully finalized, the setMaster flag ** is cleared anyway (and the pager will move to ERROR state). ** ** doNotSpill, doNotSyncSpill ** ** These two boolean variables control the behaviour of cache-spills ** (calls made by the pcache module to the pagerStress() routine to ** write cached data to the file-system in order to free up memory). ** ** When doNotSpill is non-zero, writing to the database from pagerStress() ** is disabled altogether. This is done in a very obscure case that ** comes up during savepoint rollback that requires the pcache module ** to allocate a new page to prevent the journal file from being written |
︙ | ︙ | |||
38983 38984 38985 38986 38987 38988 38989 | sqlite3_file *sjfd; /* File descriptor for sub-journal */ i64 journalOff; /* Current write offset in the journal file */ i64 journalHdr; /* Byte offset to previous journal header */ sqlite3_backup *pBackup; /* Pointer to list of ongoing backup processes */ PagerSavepoint *aSavepoint; /* Array of active savepoints */ int nSavepoint; /* Number of elements in aSavepoint[] */ char dbFileVers[16]; /* Changes whenever database file changes */ | < < < < < | 37785 37786 37787 37788 37789 37790 37791 37792 37793 37794 37795 37796 37797 37798 | sqlite3_file *sjfd; /* File descriptor for sub-journal */ i64 journalOff; /* Current write offset in the journal file */ i64 journalHdr; /* Byte offset to previous journal header */ sqlite3_backup *pBackup; /* Pointer to list of ongoing backup processes */ PagerSavepoint *aSavepoint; /* Array of active savepoints */ int nSavepoint; /* Number of elements in aSavepoint[] */ char dbFileVers[16]; /* Changes whenever database file changes */ /* ** End of the routinely-changing class members ***************************************************************************/ u16 nExtra; /* Add this many bytes to each in-memory page */ i16 nReserve; /* Number of unused bytes at end of each page */ u32 vfsFlags; /* Flags for sqlite3_vfs.xOpen() */ |
︙ | ︙ | |||
39098 39099 39100 39101 39102 39103 39104 | */ #ifdef SQLITE_OMIT_MEMORYDB # define MEMDB 0 #else # define MEMDB pPager->memDb #endif | < < < < < < < < < < | 37895 37896 37897 37898 37899 37900 37901 37902 37903 37904 37905 37906 37907 37908 | */ #ifdef SQLITE_OMIT_MEMORYDB # define MEMDB 0 #else # define MEMDB pPager->memDb #endif /* ** The maximum legal page number is (2^31 - 1). */ #define PAGER_MAX_PGNO 2147483647 /* ** The argument to this macro is a file descriptor (type sqlite3_file*). |
︙ | ︙ | |||
39742 39743 39744 39745 39746 39747 39748 | ){ memcpy(zHeader, aJournalMagic, sizeof(aJournalMagic)); put32bits(&zHeader[sizeof(aJournalMagic)], 0xffffffff); }else{ memset(zHeader, 0, sizeof(aJournalMagic)+4); } | | | 38529 38530 38531 38532 38533 38534 38535 38536 38537 38538 38539 38540 38541 38542 38543 | ){ memcpy(zHeader, aJournalMagic, sizeof(aJournalMagic)); put32bits(&zHeader[sizeof(aJournalMagic)], 0xffffffff); }else{ memset(zHeader, 0, sizeof(aJournalMagic)+4); } /* The random check-hash initialiser */ sqlite3_randomness(sizeof(pPager->cksumInit), &pPager->cksumInit); put32bits(&zHeader[sizeof(aJournalMagic)+4], pPager->cksumInit); /* The initial database size */ put32bits(&zHeader[sizeof(aJournalMagic)+8], pPager->dbOrigSize); /* The assumed sector size for this process */ put32bits(&zHeader[sizeof(aJournalMagic)+12], pPager->sectorSize); |
︙ | ︙ | |||
40181 40182 40183 40184 40185 40186 40187 | if( rc2==SQLITE_FULL || rc2==SQLITE_IOERR ){ pPager->errCode = rc; pPager->eState = PAGER_ERROR; } return rc; } | < < | 38968 38969 38970 38971 38972 38973 38974 38975 38976 38977 38978 38979 38980 38981 | if( rc2==SQLITE_FULL || rc2==SQLITE_IOERR ){ pPager->errCode = rc; pPager->eState = PAGER_ERROR; } return rc; } /* ** This routine ends a transaction. A transaction is usually ended by ** either a COMMIT or a ROLLBACK operation. This routine may be called ** after rollback of a hot-journal, or if an error occurs while opening ** the journal file or writing the very first journal-header of a ** database transaction. ** |
︙ | ︙ | |||
40236 40237 40238 40239 40240 40241 40242 | ** database then the IO error code is returned to the user. If the ** operation to finalize the journal file fails, then the code still ** tries to unlock the database file if not in exclusive mode. If the ** unlock operation fails as well, then the first error code related ** to the first error encountered (the journal finalization one) is ** returned. */ | | | 39021 39022 39023 39024 39025 39026 39027 39028 39029 39030 39031 39032 39033 39034 39035 | ** database then the IO error code is returned to the user. If the ** operation to finalize the journal file fails, then the code still ** tries to unlock the database file if not in exclusive mode. If the ** unlock operation fails as well, then the first error code related ** to the first error encountered (the journal finalization one) is ** returned. */ static int pager_end_transaction(Pager *pPager, int hasMaster){ int rc = SQLITE_OK; /* Error code from journal finalization operation */ int rc2 = SQLITE_OK; /* Error code from db file unlock operation */ /* Do nothing if the pager does not have an open write transaction ** or at least a RESERVED lock. This function may be called when there ** is no write-transaction active but a RESERVED or greater lock is ** held under two circumstances: |
︙ | ︙ | |||
40286 40287 40288 40289 40290 40291 40292 | pPager->journalOff = 0; }else{ /* This branch may be executed with Pager.journalMode==MEMORY if ** a hot-journal was just rolled back. In this case the journal ** file should be closed and deleted. If this connection writes to ** the database file, it will do so using an in-memory journal. */ | < | | 39071 39072 39073 39074 39075 39076 39077 39078 39079 39080 39081 39082 39083 39084 39085 39086 39087 39088 39089 39090 | pPager->journalOff = 0; }else{ /* This branch may be executed with Pager.journalMode==MEMORY if ** a hot-journal was just rolled back. In this case the journal ** file should be closed and deleted. If this connection writes to ** the database file, it will do so using an in-memory journal. */ assert( pPager->journalMode==PAGER_JOURNALMODE_DELETE || pPager->journalMode==PAGER_JOURNALMODE_MEMORY || pPager->journalMode==PAGER_JOURNALMODE_WAL ); sqlite3OsClose(pPager->jfd); if( !pPager->tempFile ){ rc = sqlite3OsDelete(pPager->pVfs, pPager->zJournal, 0); } } } #ifdef SQLITE_CHECK_PAGES sqlite3PcacheIterateDirty(pPager->pPCache, pager_set_pagehash); |
︙ | ︙ | |||
40322 40323 40324 40325 40326 40327 40328 | if( pagerUseWal(pPager) ){ /* Drop the WAL write-lock, if any. Also, if the connection was in ** locking_mode=exclusive mode but is no longer, drop the EXCLUSIVE ** lock held on the database file. */ rc2 = sqlite3WalEndWriteTransaction(pPager->pWal); assert( rc2==SQLITE_OK ); | < < < < < < < < < < | 39106 39107 39108 39109 39110 39111 39112 39113 39114 39115 39116 39117 39118 39119 39120 | if( pagerUseWal(pPager) ){ /* Drop the WAL write-lock, if any. Also, if the connection was in ** locking_mode=exclusive mode but is no longer, drop the EXCLUSIVE ** lock held on the database file. */ rc2 = sqlite3WalEndWriteTransaction(pPager->pWal); assert( rc2==SQLITE_OK ); } if( !pPager->exclusiveMode && (!pagerUseWal(pPager) || sqlite3WalExclusiveMode(pPager->pWal, 0)) ){ rc2 = pagerUnlockDb(pPager, SHARED_LOCK); pPager->changeCountDone = 0; } pPager->eState = PAGER_READER; |
︙ | ︙ | |||
40371 40372 40373 40374 40375 40376 40377 | assert( assert_pager_state(pPager) ); if( pPager->eState>=PAGER_WRITER_LOCKED ){ sqlite3BeginBenignMalloc(); sqlite3PagerRollback(pPager); sqlite3EndBenignMalloc(); }else if( !pPager->exclusiveMode ){ assert( pPager->eState==PAGER_READER ); | | | 39145 39146 39147 39148 39149 39150 39151 39152 39153 39154 39155 39156 39157 39158 39159 | assert( assert_pager_state(pPager) ); if( pPager->eState>=PAGER_WRITER_LOCKED ){ sqlite3BeginBenignMalloc(); sqlite3PagerRollback(pPager); sqlite3EndBenignMalloc(); }else if( !pPager->exclusiveMode ){ assert( pPager->eState==PAGER_READER ); pager_end_transaction(pPager, 0); } } pager_unlock(pPager); } /* ** Parameter aData must point to a buffer of pPager->pageSize bytes |
︙ | ︙ | |||
40595 40596 40597 40598 40599 40600 40601 | if( isOpen(pPager->fd) && (pPager->eState>=PAGER_WRITER_DBMOD || pPager->eState==PAGER_OPEN) && isSynced ){ i64 ofst = (pgno-1)*(i64)pPager->pageSize; testcase( !isSavepnt && pPg!=0 && (pPg->flags&PGHDR_NEED_SYNC)!=0 ); assert( !pagerUseWal(pPager) ); | | | 39369 39370 39371 39372 39373 39374 39375 39376 39377 39378 39379 39380 39381 39382 39383 | if( isOpen(pPager->fd) && (pPager->eState>=PAGER_WRITER_DBMOD || pPager->eState==PAGER_OPEN) && isSynced ){ i64 ofst = (pgno-1)*(i64)pPager->pageSize; testcase( !isSavepnt && pPg!=0 && (pPg->flags&PGHDR_NEED_SYNC)!=0 ); assert( !pagerUseWal(pPager) ); rc = sqlite3OsWrite(pPager->fd, (u8*)aData, pPager->pageSize, ofst); if( pgno>pPager->dbFileSize ){ pPager->dbFileSize = pgno; } if( pPager->pBackup ){ CODEC1(pPager, aData, pgno, 3, rc=SQLITE_NOMEM); sqlite3BackupUpdate(pPager->pBackup, pgno, (u8*)aData); CODEC2(pPager, aData, pgno, 7, rc=SQLITE_NOMEM, aData); |
︙ | ︙ | |||
40986 40987 40988 40989 40990 40991 40992 | u32 nRec; /* Number of Records in the journal */ u32 u; /* Unsigned loop counter */ Pgno mxPg = 0; /* Size of the original file in pages */ int rc; /* Result code of a subroutine */ int res = 1; /* Value returned by sqlite3OsAccess() */ char *zMaster = 0; /* Name of master journal file if any */ int needPagerReset; /* True to reset page prior to first page rollback */ | < | 39760 39761 39762 39763 39764 39765 39766 39767 39768 39769 39770 39771 39772 39773 | u32 nRec; /* Number of Records in the journal */ u32 u; /* Unsigned loop counter */ Pgno mxPg = 0; /* Size of the original file in pages */ int rc; /* Result code of a subroutine */ int res = 1; /* Value returned by sqlite3OsAccess() */ char *zMaster = 0; /* Name of master journal file if any */ int needPagerReset; /* True to reset page prior to first page rollback */ /* Figure out how many records are in the journal. Abort early if ** the journal is empty. */ assert( isOpen(pPager->jfd) ); rc = sqlite3OsFileSize(pPager->jfd, &szJ); if( rc!=SQLITE_OK ){ |
︙ | ︙ | |||
41087 41088 41089 41090 41091 41092 41093 | */ for(u=0; u<nRec; u++){ if( needPagerReset ){ pager_reset(pPager); needPagerReset = 0; } rc = pager_playback_one_page(pPager,&pPager->journalOff,0,1,0); | | < < | 39860 39861 39862 39863 39864 39865 39866 39867 39868 39869 39870 39871 39872 39873 39874 | */ for(u=0; u<nRec; u++){ if( needPagerReset ){ pager_reset(pPager); needPagerReset = 0; } rc = pager_playback_one_page(pPager,&pPager->journalOff,0,1,0); if( rc!=SQLITE_OK ){ if( rc==SQLITE_DONE ){ pPager->journalOff = szJ; break; }else if( rc==SQLITE_IOERR_SHORT_READ ){ /* If the journal has been truncated, simply stop reading and ** processing the journal. This might happen if the journal was ** not completely written and synced prior to a crash. In that |
︙ | ︙ | |||
41149 41150 41151 41152 41153 41154 41155 | } if( rc==SQLITE_OK && (pPager->eState>=PAGER_WRITER_DBMOD || pPager->eState==PAGER_OPEN) ){ rc = sqlite3PagerSync(pPager); } if( rc==SQLITE_OK ){ | | < < < < | 39920 39921 39922 39923 39924 39925 39926 39927 39928 39929 39930 39931 39932 39933 39934 39935 39936 39937 39938 39939 39940 39941 39942 39943 | } if( rc==SQLITE_OK && (pPager->eState>=PAGER_WRITER_DBMOD || pPager->eState==PAGER_OPEN) ){ rc = sqlite3PagerSync(pPager); } if( rc==SQLITE_OK ){ rc = pager_end_transaction(pPager, zMaster[0]!='\0'); testcase( rc!=SQLITE_OK ); } if( rc==SQLITE_OK && zMaster[0] && res ){ /* If there was a master journal and this routine will return success, ** see if it is possible to delete the master journal. */ rc = pager_delmaster(pPager, zMaster); testcase( rc!=SQLITE_OK ); } /* The Pager.sectorSize variable may have been updated while rolling ** back a journal created by a process with a different sector size ** value. Reset it to the correct value for this process. */ setSectorSize(pPager); return rc; |
︙ | ︙ | |||
41184 41185 41186 41187 41188 41189 41190 | ** ** If page 1 is read, then the value of Pager.dbFileVers[] is set to ** the value read from the database file. ** ** If an IO error occurs, then the IO error is returned to the caller. ** Otherwise, SQLITE_OK is returned. */ | | > < | | < > | < | 39951 39952 39953 39954 39955 39956 39957 39958 39959 39960 39961 39962 39963 39964 39965 39966 39967 39968 39969 39970 39971 39972 39973 39974 39975 39976 39977 39978 39979 39980 39981 39982 39983 39984 39985 | ** ** If page 1 is read, then the value of Pager.dbFileVers[] is set to ** the value read from the database file. ** ** If an IO error occurs, then the IO error is returned to the caller. ** Otherwise, SQLITE_OK is returned. */ static int readDbPage(PgHdr *pPg){ Pager *pPager = pPg->pPager; /* Pager object associated with page pPg */ Pgno pgno = pPg->pgno; /* Page number to read */ int rc = SQLITE_OK; /* Return code */ int isInWal = 0; /* True if page is in log file */ int pgsz = pPager->pageSize; /* Number of bytes to read */ assert( pPager->eState>=PAGER_READER && !MEMDB ); assert( isOpen(pPager->fd) ); if( NEVER(!isOpen(pPager->fd)) ){ assert( pPager->tempFile ); memset(pPg->pData, 0, pPager->pageSize); return SQLITE_OK; } if( pagerUseWal(pPager) ){ /* Try to pull the page from the write-ahead log. */ rc = sqlite3WalRead(pPager->pWal, pgno, &isInWal, pgsz, pPg->pData); } if( rc==SQLITE_OK && !isInWal ){ i64 iOffset = (pgno-1)*(i64)pPager->pageSize; rc = sqlite3OsRead(pPager->fd, pPg->pData, pgsz, iOffset); if( rc==SQLITE_IOERR_SHORT_READ ){ rc = SQLITE_OK; } } |
︙ | ︙ | |||
41284 41285 41286 41287 41288 41289 41290 | ** return an SQLite error code. Otherwise, SQLITE_OK. */ static int pagerUndoCallback(void *pCtx, Pgno iPg){ int rc = SQLITE_OK; Pager *pPager = (Pager *)pCtx; PgHdr *pPg; | < < < < | < | 40050 40051 40052 40053 40054 40055 40056 40057 40058 40059 40060 40061 40062 40063 40064 40065 40066 40067 40068 40069 | ** return an SQLite error code. Otherwise, SQLITE_OK. */ static int pagerUndoCallback(void *pCtx, Pgno iPg){ int rc = SQLITE_OK; Pager *pPager = (Pager *)pCtx; PgHdr *pPg; pPg = sqlite3PagerLookup(pPager, iPg); if( pPg ){ if( sqlite3PcachePageRefcount(pPg)==1 ){ sqlite3PcacheDrop(pPg); }else{ rc = readDbPage(pPg); if( rc==SQLITE_OK ){ pPager->xReiniter(pPg); } sqlite3PagerUnref(pPg); } } |
︙ | ︙ | |||
41438 41439 41440 41441 41442 41443 41444 | ** the duplicate call is harmless. */ sqlite3WalEndReadTransaction(pPager->pWal); rc = sqlite3WalBeginReadTransaction(pPager->pWal, &changed); if( rc!=SQLITE_OK || changed ){ pager_reset(pPager); | < | 40199 40200 40201 40202 40203 40204 40205 40206 40207 40208 40209 40210 40211 40212 | ** the duplicate call is harmless. */ sqlite3WalEndReadTransaction(pPager->pWal); rc = sqlite3WalBeginReadTransaction(pPager->pWal, &changed); if( rc!=SQLITE_OK || changed ){ pager_reset(pPager); } return rc; } #endif /* |
︙ | ︙ | |||
41529 41530 41531 41532 41533 41534 41535 | int isWal; /* True if WAL file exists */ Pgno nPage; /* Size of the database file */ rc = pagerPagecount(pPager, &nPage); if( rc ) return rc; if( nPage==0 ){ rc = sqlite3OsDelete(pPager->pVfs, pPager->zWal, 0); | < | 40289 40290 40291 40292 40293 40294 40295 40296 40297 40298 40299 40300 40301 40302 | int isWal; /* True if WAL file exists */ Pgno nPage; /* Size of the database file */ rc = pagerPagecount(pPager, &nPage); if( rc ) return rc; if( nPage==0 ){ rc = sqlite3OsDelete(pPager->pVfs, pPager->zWal, 0); isWal = 0; }else{ rc = sqlite3OsAccess( pPager->pVfs, pPager->zWal, SQLITE_ACCESS_EXISTS, &isWal ); } if( rc==SQLITE_OK ){ |
︙ | ︙ | |||
41700 41701 41702 41703 41704 41705 41706 | /* ** Change the maximum number of in-memory pages that are allowed. */ SQLITE_PRIVATE void sqlite3PagerSetCachesize(Pager *pPager, int mxPage){ sqlite3PcacheSetCachesize(pPager->pPCache, mxPage); } | < < < < < < < < < < < < < < < < < < < < < < < | 40459 40460 40461 40462 40463 40464 40465 40466 40467 40468 40469 40470 40471 40472 | /* ** Change the maximum number of in-memory pages that are allowed. */ SQLITE_PRIVATE void sqlite3PagerSetCachesize(Pager *pPager, int mxPage){ sqlite3PcacheSetCachesize(pPager->pPCache, mxPage); } /* ** Free as much memory as possible from the pager. */ SQLITE_PRIVATE void sqlite3PagerShrink(Pager *pPager){ sqlite3PcacheShrink(pPager->pPCache); } |
︙ | ︙ | |||
41878 41879 41880 41881 41882 41883 41884 | pPager->xBusyHandler = xBusyHandler; pPager->pBusyHandlerArg = pBusyHandlerArg; if( isOpen(pPager->fd) ){ void **ap = (void **)&pPager->xBusyHandler; assert( ((int(*)(void *))(ap[0]))==xBusyHandler ); assert( ap[1]==pBusyHandlerArg ); | | | 40614 40615 40616 40617 40618 40619 40620 40621 40622 40623 40624 40625 40626 40627 40628 | pPager->xBusyHandler = xBusyHandler; pPager->pBusyHandlerArg = pBusyHandlerArg; if( isOpen(pPager->fd) ){ void **ap = (void **)&pPager->xBusyHandler; assert( ((int(*)(void *))(ap[0]))==xBusyHandler ); assert( ap[1]==pBusyHandlerArg ); sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_BUSYHANDLER, (void *)ap); } } /* ** Change the page size used by the Pager object. The new page size ** is passed in *pPageSize. ** |
︙ | ︙ | |||
41958 41959 41960 41961 41962 41963 41964 | *pPageSize = pPager->pageSize; if( rc==SQLITE_OK ){ if( nReserve<0 ) nReserve = pPager->nReserve; assert( nReserve>=0 && nReserve<1000 ); pPager->nReserve = (i16)nReserve; pagerReportSize(pPager); | < | 40694 40695 40696 40697 40698 40699 40700 40701 40702 40703 40704 40705 40706 40707 | *pPageSize = pPager->pageSize; if( rc==SQLITE_OK ){ if( nReserve<0 ) nReserve = pPager->nReserve; assert( nReserve>=0 && nReserve<1000 ); pPager->nReserve = (i16)nReserve; pagerReportSize(pPager); } return rc; } /* ** Return a pointer to the "temporary page" buffer held internally ** by the pager. This is a buffer that is big enough to hold the |
︙ | ︙ | |||
42112 42113 42114 42115 42116 42117 42118 | ** be necessary to write the current content out to the sub-journal ** (as determined by function subjRequiresPage()). ** ** If the condition asserted by this function were not true, and the ** dirty page were to be discarded from the cache via the pagerStress() ** routine, pagerStress() would not write the current page content to ** the database file. If a savepoint transaction were rolled back after | | | 40847 40848 40849 40850 40851 40852 40853 40854 40855 40856 40857 40858 40859 40860 40861 | ** be necessary to write the current content out to the sub-journal ** (as determined by function subjRequiresPage()). ** ** If the condition asserted by this function were not true, and the ** dirty page were to be discarded from the cache via the pagerStress() ** routine, pagerStress() would not write the current page content to ** the database file. If a savepoint transaction were rolled back after ** this happened, the correct behaviour would be to restore the current ** content of the page. However, since this content is not present in either ** the database file or the portion of the rollback journal and ** sub-journal rolled back the content could not be restored and the ** database image would become corrupt. It is therefore fortunate that ** this circumstance cannot arise. */ #if defined(SQLITE_DEBUG) |
︙ | ︙ | |||
42136 42137 42138 42139 42140 42141 42142 | #endif /* ** Truncate the in-memory database file image to nPage pages. This ** function does not actually modify the database file on disk. It ** just sets the internal state of the pager object so that the ** truncation will be done when the current transaction is committed. | < < < < < < | < < < < < < < < | 40871 40872 40873 40874 40875 40876 40877 40878 40879 40880 40881 40882 40883 40884 40885 40886 40887 40888 40889 40890 | #endif /* ** Truncate the in-memory database file image to nPage pages. This ** function does not actually modify the database file on disk. It ** just sets the internal state of the pager object so that the ** truncation will be done when the current transaction is committed. */ SQLITE_PRIVATE void sqlite3PagerTruncateImage(Pager *pPager, Pgno nPage){ assert( pPager->dbSize>=nPage ); assert( pPager->eState>=PAGER_WRITER_CACHEMOD ); pPager->dbSize = nPage; assertTruncateConstraint(pPager); } /* ** This function is called before attempting a hot-journal rollback. It ** syncs the journal file to disk, then sets pPager->journalHdr to the ** size of the journal file so that the pager_playback() routine knows |
︙ | ︙ | |||
42183 42184 42185 42186 42187 42188 42189 | rc = sqlite3OsSync(pPager->jfd, SQLITE_SYNC_NORMAL); } if( rc==SQLITE_OK ){ rc = sqlite3OsFileSize(pPager->jfd, &pPager->journalHdr); } return rc; } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 40904 40905 40906 40907 40908 40909 40910 40911 40912 40913 40914 40915 40916 40917 | rc = sqlite3OsSync(pPager->jfd, SQLITE_SYNC_NORMAL); } if( rc==SQLITE_OK ){ rc = sqlite3OsFileSize(pPager->jfd, &pPager->journalHdr); } return rc; } /* ** Shutdown the page cache. Free all memory and close all files. ** ** If a transaction was in progress when this routine is called, that ** transaction is rolled back. All outstanding pages are invalidated ** and their memory is freed. Any attempt to use a page associated |
︙ | ︙ | |||
42279 42280 42281 42282 42283 42284 42285 | */ SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager){ u8 *pTmp = (u8 *)pPager->pTmpSpace; assert( assert_pager_state(pPager) ); disable_simulated_io_errors(); sqlite3BeginBenignMalloc(); | < | 40925 40926 40927 40928 40929 40930 40931 40932 40933 40934 40935 40936 40937 40938 | */ 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; #endif pager_reset(pPager); |
︙ | ︙ | |||
42541 42542 42543 42544 42545 42546 42547 | rc = pagerOpentemp(pPager, pPager->fd, pPager->vfsFlags); } /* Before the first write, give the VFS a hint of what the final ** file size will be. */ assert( rc!=SQLITE_OK || isOpen(pPager->fd) ); | | < < | 41186 41187 41188 41189 41190 41191 41192 41193 41194 41195 41196 41197 41198 41199 41200 | rc = pagerOpentemp(pPager, pPager->fd, pPager->vfsFlags); } /* Before the first write, give the VFS a hint of what the final ** file size will be. */ assert( rc!=SQLITE_OK || isOpen(pPager->fd) ); if( rc==SQLITE_OK && pPager->dbSize>pPager->dbHintSize ){ sqlite3_int64 szFile = pPager->pageSize * (sqlite3_int64)pPager->dbSize; sqlite3OsFileControlHint(pPager->fd, SQLITE_FCNTL_SIZE_HINT, &szFile); pPager->dbHintSize = pPager->dbSize; } while( rc==SQLITE_OK && pList ){ Pgno pgno = pList->pgno; |
︙ | ︙ | |||
43097 43098 43099 43100 43101 43102 43103 | }else if( memDb ){ pPager->journalMode = PAGER_JOURNALMODE_MEMORY; } /* pPager->xBusyHandler = 0; */ /* pPager->pBusyHandlerArg = 0; */ pPager->xReiniter = xReinit; /* memset(pPager->aHash, 0, sizeof(pPager->aHash)); */ | < | 41740 41741 41742 41743 41744 41745 41746 41747 41748 41749 41750 41751 41752 41753 | }else if( memDb ){ pPager->journalMode = PAGER_JOURNALMODE_MEMORY; } /* pPager->xBusyHandler = 0; */ /* pPager->pBusyHandlerArg = 0; */ pPager->xReiniter = xReinit; /* memset(pPager->aHash, 0, sizeof(pPager->aHash)); */ *ppPager = pPager; return SQLITE_OK; } |
︙ | ︙ | |||
43287 43288 43289 43290 43291 43292 43293 | if( pPager->eLock<=SHARED_LOCK ){ rc = hasHotJournal(pPager, &bHotJournal); } if( rc!=SQLITE_OK ){ goto failed; } if( bHotJournal ){ | < < < < < | 41929 41930 41931 41932 41933 41934 41935 41936 41937 41938 41939 41940 41941 41942 | if( pPager->eLock<=SHARED_LOCK ){ rc = hasHotJournal(pPager, &bHotJournal); } if( rc!=SQLITE_OK ){ goto failed; } if( bHotJournal ){ /* Get an EXCLUSIVE lock on the database file. At this point it is ** important that a RESERVED lock is not obtained on the way to the ** EXCLUSIVE lock. If it were, another process might open the ** database file, detect the RESERVED lock, and conclude that the ** database is safe to read while this process is still rolling the ** hot-journal back. ** |
︙ | ︙ | |||
43389 43390 43391 43392 43393 43394 43395 | assert( pPager->eState==PAGER_OPEN ); assert( (pPager->eLock==SHARED_LOCK) || (pPager->exclusiveMode && pPager->eLock>SHARED_LOCK) ); } | | < | < | | 42026 42027 42028 42029 42030 42031 42032 42033 42034 42035 42036 42037 42038 42039 42040 42041 42042 | assert( pPager->eState==PAGER_OPEN ); assert( (pPager->eLock==SHARED_LOCK) || (pPager->exclusiveMode && pPager->eLock>SHARED_LOCK) ); } if( !pPager->tempFile && (pPager->pBackup || sqlite3PcachePagecount(pPager->pPCache)>0) ){ /* The shared-lock has just been acquired on the database file ** and there are already pages in the cache (from a previous ** read or write transaction). Check to see if the database ** has been modified. If the database has changed, flush the ** cache. ** ** Database changes is detected by looking at 15 bytes beginning |
︙ | ︙ | |||
43419 43420 43421 43422 43423 43424 43425 | rc = pagerPagecount(pPager, &nPage); if( rc ) goto failed; if( nPage>0 ){ IOTRACE(("CKVERS %p %d\n", pPager, sizeof(dbFileVers))); rc = sqlite3OsRead(pPager->fd, &dbFileVers, sizeof(dbFileVers), 24); | | < < < < < < < < < < | 42054 42055 42056 42057 42058 42059 42060 42061 42062 42063 42064 42065 42066 42067 42068 42069 42070 42071 42072 42073 42074 42075 42076 | rc = pagerPagecount(pPager, &nPage); if( rc ) goto failed; if( nPage>0 ){ IOTRACE(("CKVERS %p %d\n", pPager, sizeof(dbFileVers))); rc = sqlite3OsRead(pPager->fd, &dbFileVers, sizeof(dbFileVers), 24); if( rc!=SQLITE_OK ){ goto failed; } }else{ memset(dbFileVers, 0, sizeof(dbFileVers)); } if( memcmp(pPager->dbFileVers, dbFileVers, sizeof(dbFileVers))!=0 ){ pager_reset(pPager); } } /* If there is a WAL file in the file-system, open this database in WAL ** mode. Otherwise, the following function call is a no-op. */ rc = pagerOpenWalIfPresent(pPager); |
︙ | ︙ | |||
43479 43480 43481 43482 43483 43484 43485 | ** transaction and unlock the pager. ** ** Except, in locking_mode=EXCLUSIVE when there is nothing to in ** the rollback journal, the unlock is not performed and there is ** nothing to rollback, so this routine is a no-op. */ static void pagerUnlockIfUnused(Pager *pPager){ | | | 42104 42105 42106 42107 42108 42109 42110 42111 42112 42113 42114 42115 42116 42117 42118 | ** transaction and unlock the pager. ** ** Except, in locking_mode=EXCLUSIVE when there is nothing to in ** the rollback journal, the unlock is not performed and there is ** nothing to rollback, so this routine is a no-op. */ static void pagerUnlockIfUnused(Pager *pPager){ if( (sqlite3PcacheRefCount(pPager->pPCache)==0) ){ pagerUnlockAndRollback(pPager); } } /* ** Acquire a reference to page number pgno in pager pPager (a page ** reference has type DbPage*). If the requested reference is |
︙ | ︙ | |||
43538 43539 43540 43541 43542 43543 43544 | ** Since Lookup() never goes to disk, it never has to deal with locks ** or journal files. */ SQLITE_PRIVATE int sqlite3PagerAcquire( Pager *pPager, /* The pager open on the database file */ Pgno pgno, /* Page number to fetch */ DbPage **ppPage, /* Write a pointer to the page here */ | | | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 42163 42164 42165 42166 42167 42168 42169 42170 42171 42172 42173 42174 42175 42176 42177 42178 42179 42180 42181 42182 42183 42184 42185 42186 42187 42188 42189 42190 42191 42192 42193 | ** Since Lookup() never goes to disk, it never has to deal with locks ** or journal files. */ SQLITE_PRIVATE int sqlite3PagerAcquire( Pager *pPager, /* The pager open on the database file */ Pgno pgno, /* Page number to fetch */ DbPage **ppPage, /* Write a pointer to the page here */ int noContent /* Do not bother reading content from disk if true */ ){ int rc; PgHdr *pPg; assert( pPager->eState>=PAGER_READER ); assert( assert_pager_state(pPager) ); if( pgno==0 ){ return SQLITE_CORRUPT_BKPT; } /* If the pager is in the error state, return an error immediately. ** Otherwise, request the page from the PCache layer. */ if( pPager->errCode!=SQLITE_OK ){ rc = pPager->errCode; }else{ rc = sqlite3PcacheFetch(pPager->pPCache, pgno, 1, ppPage); } if( rc!=SQLITE_OK ){ /* Either the call to sqlite3PcacheFetch() returned an error or the ** pager was already in the error-state when this function was called. ** Set pPg to 0 and jump to the exception handler. */ |
︙ | ︙ | |||
43660 43661 43662 43663 43664 43665 43666 | TESTONLY( rc = ) addToSavepointBitvecs(pPager, pgno); testcase( rc==SQLITE_NOMEM ); sqlite3EndBenignMalloc(); } memset(pPg->pData, 0, pPager->pageSize); IOTRACE(("ZERO %p %d\n", pPager, pgno)); }else{ | < < < < | | 42238 42239 42240 42241 42242 42243 42244 42245 42246 42247 42248 42249 42250 42251 42252 42253 42254 | TESTONLY( rc = ) addToSavepointBitvecs(pPager, pgno); testcase( rc==SQLITE_NOMEM ); sqlite3EndBenignMalloc(); } memset(pPg->pData, 0, pPager->pageSize); IOTRACE(("ZERO %p %d\n", pPager, pgno)); }else{ assert( pPg->pPager==pPager ); pPager->aStat[PAGER_STAT_MISS]++; rc = readDbPage(pPg); if( rc!=SQLITE_OK ){ goto pager_acquire_err; } } pager_set_pagehash(pPg); } |
︙ | ︙ | |||
43719 43720 43721 43722 43723 43724 43725 | ** page is added to the LRU list. When all references to all pages ** are released, a rollback occurs and the lock on the database is ** removed. */ SQLITE_PRIVATE void sqlite3PagerUnref(DbPage *pPg){ if( pPg ){ Pager *pPager = pPg->pPager; | < < < | < | 42293 42294 42295 42296 42297 42298 42299 42300 42301 42302 42303 42304 42305 42306 42307 | ** page is added to the LRU list. When all references to all pages ** are released, a rollback occurs and the lock on the database is ** removed. */ SQLITE_PRIVATE void sqlite3PagerUnref(DbPage *pPg){ if( pPg ){ Pager *pPager = pPg->pPager; sqlite3PcacheRelease(pPg); pagerUnlockIfUnused(pPager); } } /* ** This function is called at the start of every write transaction. ** There must already be a RESERVED or EXCLUSIVE lock on the database |
︙ | ︙ | |||
44058 44059 44060 44061 44062 44063 44064 | SQLITE_PRIVATE int sqlite3PagerWrite(DbPage *pDbPage){ int rc = SQLITE_OK; PgHdr *pPg = pDbPage; Pager *pPager = pPg->pPager; Pgno nPagePerSector = (pPager->sectorSize/pPager->pageSize); | < | 42628 42629 42630 42631 42632 42633 42634 42635 42636 42637 42638 42639 42640 42641 | SQLITE_PRIVATE int sqlite3PagerWrite(DbPage *pDbPage){ int rc = SQLITE_OK; PgHdr *pPg = pDbPage; Pager *pPager = pPg->pPager; Pgno nPagePerSector = (pPager->sectorSize/pPager->pageSize); assert( pPager->eState>=PAGER_WRITER_LOCKED ); assert( pPager->eState!=PAGER_ERROR ); assert( assert_pager_state(pPager) ); if( nPagePerSector>1 ){ Pgno nPageCount; /* Total number of pages in database file */ Pgno pg1; /* First page of the sector pPg is located on. */ |
︙ | ︙ | |||
44226 44227 44228 44229 44230 44231 44232 | # define DIRECT_MODE 0 assert( isDirectMode==0 ); UNUSED_PARAMETER(isDirectMode); #else # define DIRECT_MODE isDirectMode #endif | | | 42795 42796 42797 42798 42799 42800 42801 42802 42803 42804 42805 42806 42807 42808 42809 | # define DIRECT_MODE 0 assert( isDirectMode==0 ); UNUSED_PARAMETER(isDirectMode); #else # define DIRECT_MODE isDirectMode #endif if( !pPager->changeCountDone && pPager->dbSize>0 ){ PgHdr *pPgHdr; /* Reference to page 1 */ assert( !pPager->tempFile && isOpen(pPager->fd) ); /* Open page 1 of the file for writing. */ rc = sqlite3PagerGet(pPager, 1, &pPgHdr); assert( pPgHdr==0 || rc==SQLITE_OK ); |
︙ | ︙ | |||
44258 44259 44260 44261 44262 44263 44264 | assert( pPager->dbFileSize>0 ); CODEC2(pPager, pPgHdr->pData, 1, 6, rc=SQLITE_NOMEM, zBuf); if( rc==SQLITE_OK ){ rc = sqlite3OsWrite(pPager->fd, zBuf, pPager->pageSize, 0); pPager->aStat[PAGER_STAT_WRITE]++; } if( rc==SQLITE_OK ){ | < < < < < | 42827 42828 42829 42830 42831 42832 42833 42834 42835 42836 42837 42838 42839 42840 | assert( pPager->dbFileSize>0 ); CODEC2(pPager, pPgHdr->pData, 1, 6, rc=SQLITE_NOMEM, zBuf); if( rc==SQLITE_OK ){ rc = sqlite3OsWrite(pPager->fd, zBuf, pPager->pageSize, 0); pPager->aStat[PAGER_STAT_WRITE]++; } if( rc==SQLITE_OK ){ pPager->changeCountDone = 1; } }else{ pPager->changeCountDone = 1; } } |
︙ | ︙ | |||
44448 44449 44450 44451 44452 44453 44454 44455 44456 44457 44458 44459 44460 44461 | rc = pager_incr_changecounter(pPager, 0); } } #else rc = pager_incr_changecounter(pPager, 0); #endif if( rc!=SQLITE_OK ) goto commit_phase_one_exit; /* Write the master journal name into the journal file. If a master ** journal file name has already been written to the journal file, ** or if zMaster is NULL (no master journal), then this call is a no-op. */ rc = writeMasterJournal(pPager, zMaster); if( rc!=SQLITE_OK ) goto commit_phase_one_exit; | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 43012 43013 43014 43015 43016 43017 43018 43019 43020 43021 43022 43023 43024 43025 43026 43027 43028 43029 43030 43031 43032 43033 43034 43035 43036 43037 43038 43039 43040 43041 43042 43043 43044 43045 43046 43047 43048 43049 43050 43051 43052 43053 43054 43055 43056 43057 | rc = pager_incr_changecounter(pPager, 0); } } #else rc = pager_incr_changecounter(pPager, 0); #endif if( rc!=SQLITE_OK ) goto commit_phase_one_exit; /* If this transaction has made the database smaller, then all pages ** being discarded by the truncation must be written to the journal ** file. This can only happen in auto-vacuum mode. ** ** Before reading the pages with page numbers larger than the ** current value of Pager.dbSize, set dbSize back to the value ** that it took at the start of the transaction. Otherwise, the ** calls to sqlite3PagerGet() return zeroed pages instead of ** reading data from the database file. */ #ifndef SQLITE_OMIT_AUTOVACUUM if( pPager->dbSize<pPager->dbOrigSize && pPager->journalMode!=PAGER_JOURNALMODE_OFF ){ Pgno i; /* Iterator variable */ const Pgno iSkip = PAGER_MJ_PGNO(pPager); /* Pending lock page */ const Pgno dbSize = pPager->dbSize; /* Database image size */ pPager->dbSize = pPager->dbOrigSize; for( i=dbSize+1; i<=pPager->dbOrigSize; i++ ){ if( !sqlite3BitvecTest(pPager->pInJournal, i) && i!=iSkip ){ PgHdr *pPage; /* Page to journal */ rc = sqlite3PagerGet(pPager, i, &pPage); if( rc!=SQLITE_OK ) goto commit_phase_one_exit; rc = sqlite3PagerWrite(pPage); sqlite3PagerUnref(pPage); if( rc!=SQLITE_OK ) goto commit_phase_one_exit; } } pPager->dbSize = dbSize; } #endif /* Write the master journal name into the journal file. If a master ** journal file name has already been written to the journal file, ** or if zMaster is NULL (no master journal), then this call is a no-op. */ rc = writeMasterJournal(pPager, zMaster); if( rc!=SQLITE_OK ) goto commit_phase_one_exit; |
︙ | ︙ | |||
44476 44477 44478 44479 44480 44481 44482 | rc = pager_write_pagelist(pPager,sqlite3PcacheDirtyList(pPager->pPCache)); if( rc!=SQLITE_OK ){ assert( rc!=SQLITE_IOERR_BLOCKED ); goto commit_phase_one_exit; } sqlite3PcacheCleanAll(pPager->pPCache); | | | | | < < < | | 43072 43073 43074 43075 43076 43077 43078 43079 43080 43081 43082 43083 43084 43085 43086 43087 43088 43089 43090 | rc = pager_write_pagelist(pPager,sqlite3PcacheDirtyList(pPager->pPCache)); if( rc!=SQLITE_OK ){ assert( rc!=SQLITE_IOERR_BLOCKED ); goto commit_phase_one_exit; } sqlite3PcacheCleanAll(pPager->pPCache); /* If the file on disk is not the same size as the database image, ** then use pager_truncate to grow or shrink the file here. */ if( pPager->dbSize!=pPager->dbFileSize ){ Pgno nNew = pPager->dbSize - (pPager->dbSize==PAGER_MJ_PGNO(pPager)); assert( pPager->eState==PAGER_WRITER_DBMOD ); rc = pager_truncate(pPager, nNew); if( rc!=SQLITE_OK ) goto commit_phase_one_exit; } /* Finally, sync the database file. */ |
︙ | ︙ | |||
44556 44557 44558 44559 44560 44561 44562 | ){ assert( pPager->journalOff==JOURNAL_HDR_SZ(pPager) || !pPager->journalOff ); pPager->eState = PAGER_READER; return SQLITE_OK; } PAGERTRACE(("COMMIT %d\n", PAGERID(pPager))); | | | 43149 43150 43151 43152 43153 43154 43155 43156 43157 43158 43159 43160 43161 43162 43163 | ){ assert( pPager->journalOff==JOURNAL_HDR_SZ(pPager) || !pPager->journalOff ); pPager->eState = PAGER_READER; return SQLITE_OK; } PAGERTRACE(("COMMIT %d\n", PAGERID(pPager))); rc = pager_end_transaction(pPager, pPager->setMaster); return pager_error(pPager, rc); } /* ** If a write transaction is open, then all changes made within the ** transaction are reverted and the current write-transaction is closed. ** The pager falls back to PAGER_READER state if successful, or PAGER_ERROR |
︙ | ︙ | |||
44601 44602 44603 44604 44605 44606 44607 | assert( assert_pager_state(pPager) ); if( pPager->eState==PAGER_ERROR ) return pPager->errCode; if( pPager->eState<=PAGER_READER ) return SQLITE_OK; if( pagerUseWal(pPager) ){ int rc2; rc = sqlite3PagerSavepoint(pPager, SAVEPOINT_ROLLBACK, -1); | | | | | 43194 43195 43196 43197 43198 43199 43200 43201 43202 43203 43204 43205 43206 43207 43208 43209 43210 43211 43212 43213 43214 43215 43216 43217 43218 43219 43220 43221 43222 43223 43224 43225 43226 43227 | assert( assert_pager_state(pPager) ); if( pPager->eState==PAGER_ERROR ) return pPager->errCode; if( pPager->eState<=PAGER_READER ) return SQLITE_OK; if( pagerUseWal(pPager) ){ int rc2; rc = sqlite3PagerSavepoint(pPager, SAVEPOINT_ROLLBACK, -1); rc2 = pager_end_transaction(pPager, pPager->setMaster); if( rc==SQLITE_OK ) rc = rc2; }else if( !isOpen(pPager->jfd) || pPager->eState==PAGER_WRITER_LOCKED ){ int eState = pPager->eState; rc = pager_end_transaction(pPager, 0); if( !MEMDB && eState>PAGER_WRITER_LOCKED ){ /* This can happen using journal_mode=off. Move the pager to the error ** state to indicate that the contents of the cache may not be trusted. ** Any active readers will get SQLITE_ABORT. */ pPager->errCode = SQLITE_ABORT; pPager->eState = PAGER_ERROR; return rc; } }else{ rc = pager_playback(pPager, 0); } assert( pPager->eState==PAGER_READER || rc!=SQLITE_OK ); assert( rc==SQLITE_OK || rc==SQLITE_FULL || rc==SQLITE_NOMEM || (rc&0xFF)==SQLITE_IOERR ); /* If an error occurs during a ROLLBACK, we can no longer trust the pager ** cache. So call pager_error() on the way out to make any error persistent. */ return pager_error(pPager, rc); } |
︙ | ︙ | |||
45003 45004 45005 45006 45007 45008 45009 | ** ** If the isCommit flag is set, there is no need to remember that ** the journal needs to be sync()ed before database page pPg->pgno ** can be written to. The caller has already promised not to write to it. */ if( (pPg->flags&PGHDR_NEED_SYNC) && !isCommit ){ needSyncPgno = pPg->pgno; | < | | 43596 43597 43598 43599 43600 43601 43602 43603 43604 43605 43606 43607 43608 43609 43610 | ** ** If the isCommit flag is set, there is no need to remember that ** the journal needs to be sync()ed before database page pPg->pgno ** can be written to. The caller has already promised not to write to it. */ if( (pPg->flags&PGHDR_NEED_SYNC) && !isCommit ){ needSyncPgno = pPg->pgno; assert( pageInJournal(pPg) || pPg->pgno>pPager->dbOrigSize ); assert( pPg->flags&PGHDR_DIRTY ); } /* If the cache contains a page with page-number pgno, remove it ** from its hash chain. Also, if the PGHDR_NEED_SYNC flag was set for ** page pgno before the 'move' operation, it needs to be retained ** for the page moved there. |
︙ | ︙ | |||
45354 45355 45356 45357 45358 45359 45360 | rc = pagerExclusiveLock(pPager); } /* Open the connection to the log file. If this operation fails, ** (e.g. due to malloc() failure), return an error code. */ if( rc==SQLITE_OK ){ | | < | 43946 43947 43948 43949 43950 43951 43952 43953 43954 43955 43956 43957 43958 43959 43960 43961 43962 43963 43964 | rc = pagerExclusiveLock(pPager); } /* Open the connection to the log file. If this operation fails, ** (e.g. due to malloc() failure), return an error code. */ if( rc==SQLITE_OK ){ rc = sqlite3WalOpen(pPager->pVfs, pPager->fd, pPager->zWal, pPager->exclusiveMode, pPager->journalSizeLimit, &pPager->pWal ); } return rc; } /* ** The caller must be holding a SHARED lock on the database file to call |
︙ | ︙ | |||
45450 45451 45452 45453 45454 45455 45456 | */ if( rc==SQLITE_OK && pPager->pWal ){ rc = pagerExclusiveLock(pPager); if( rc==SQLITE_OK ){ rc = sqlite3WalClose(pPager->pWal, pPager->ckptSyncFlags, pPager->pageSize, (u8*)pPager->pTmpSpace); pPager->pWal = 0; | < | 44041 44042 44043 44044 44045 44046 44047 44048 44049 44050 44051 44052 44053 44054 | */ if( rc==SQLITE_OK && pPager->pWal ){ rc = pagerExclusiveLock(pPager); if( rc==SQLITE_OK ){ rc = sqlite3WalClose(pPager->pWal, pPager->ckptSyncFlags, pPager->pageSize, (u8*)pPager->pTmpSpace); pPager->pWal = 0; } } return rc; } #endif /* !SQLITE_OMIT_WAL */ |
︙ | ︙ | |||
46699 46700 46701 46702 46703 46704 46705 | /* If more than one frame was recovered from the log file, report an ** event via sqlite3_log(). This is to help with identifying performance ** problems caused by applications routinely shutting down without ** checkpointing the log file. */ if( pWal->hdr.nPage ){ | < | | | 45289 45290 45291 45292 45293 45294 45295 45296 45297 45298 45299 45300 45301 45302 45303 45304 | /* If more than one frame was recovered from the log file, report an ** event via sqlite3_log(). This is to help with identifying performance ** problems caused by applications routinely shutting down without ** checkpointing the log file. */ if( pWal->hdr.nPage ){ sqlite3_log(SQLITE_OK, "Recovered %d frames from WAL file %s", pWal->hdr.nPage, pWal->zWalName ); } } recovery_error: WALTRACE(("WAL%p: recovery %s\n", pWal, rc ? "failed" : "ok")); walUnlockExclusive(pWal, iLock, nLock); |
︙ | ︙ | |||
47215 47216 47217 47218 47219 47220 47221 | u32 nBackfill = pInfo->nBackfill; /* Sync the WAL to disk */ if( sync_flags ){ rc = sqlite3OsSync(pWal->pWalFd, sync_flags); } | | | < | 45804 45805 45806 45807 45808 45809 45810 45811 45812 45813 45814 45815 45816 45817 45818 45819 45820 45821 45822 45823 45824 45825 45826 45827 | u32 nBackfill = pInfo->nBackfill; /* Sync the WAL to disk */ if( sync_flags ){ rc = sqlite3OsSync(pWal->pWalFd, sync_flags); } /* If the database file may grow as a result of this checkpoint, hint ** about the eventual size of the db file to the VFS layer. */ if( rc==SQLITE_OK ){ i64 nReq = ((i64)mxPage * szPage); rc = sqlite3OsFileSize(pWal->pDbFd, &nSize); if( rc==SQLITE_OK && nSize<nReq ){ sqlite3OsFileControlHint(pWal->pDbFd, SQLITE_FCNTL_SIZE_HINT, &nReq); } } /* Iterate through the contents of the WAL, copying data to the db file. */ while( rc==SQLITE_OK && 0==walIteratorNext(pIter, &iDbpage, &iFrame) ){ i64 iOffset; assert( walFramePgno(pWal, iFrame)==iDbpage ); if( iFrame<=nBackfill || iFrame>mxSafeFrame || iDbpage>mxPage ) continue; iOffset = walFrameOffset(iFrame, szPage) + WAL_FRAME_HDRSIZE; |
︙ | ︙ | |||
47781 47782 47783 47784 47785 47786 47787 | if( pWal->readLock>=0 ){ walUnlockShared(pWal, WAL_READ_LOCK(pWal->readLock)); pWal->readLock = -1; } } /* | | | < > | | | | > > | | 46369 46370 46371 46372 46373 46374 46375 46376 46377 46378 46379 46380 46381 46382 46383 46384 46385 46386 46387 46388 46389 46390 46391 46392 46393 46394 46395 46396 46397 46398 46399 46400 46401 46402 46403 46404 46405 46406 46407 46408 46409 46410 46411 | if( pWal->readLock>=0 ){ walUnlockShared(pWal, WAL_READ_LOCK(pWal->readLock)); pWal->readLock = -1; } } /* ** Read a page from the WAL, if it is present in the WAL and if the ** current read transaction is configured to use the WAL. ** ** The *pInWal is set to 1 if the requested page is in the WAL and ** has been loaded. Or *pInWal is set to 0 if the page was not in ** the WAL and needs to be read out of the database. */ SQLITE_PRIVATE int sqlite3WalRead( Wal *pWal, /* WAL handle */ Pgno pgno, /* Database page number to read data for */ int *pInWal, /* OUT: True if data is read from WAL */ int nOut, /* Size of buffer pOut in bytes */ u8 *pOut /* Buffer to write page data to */ ){ u32 iRead = 0; /* If !=0, WAL frame to return data from */ u32 iLast = pWal->hdr.mxFrame; /* Last page in WAL for this reader */ int iHash; /* Used to loop through N hash tables */ /* This routine is only be called from within a read transaction. */ assert( pWal->readLock>=0 || pWal->lockError ); /* If the "last page" field of the wal-index header snapshot is 0, then ** no data will be read from the wal under any circumstances. Return early ** in this case as an optimization. Likewise, if pWal->readLock==0, ** then the WAL is ignored by the reader so return early, as if the ** WAL were empty. */ if( iLast==0 || pWal->readLock==0 ){ *pInWal = 0; return SQLITE_OK; } /* Search the hash table or tables for an entry matching page number ** pgno. Each iteration of the following for() loop searches one ** hash table (each hash table indexes up to HASHTABLE_NPAGE frames). ** |
︙ | ︙ | |||
47878 47879 47880 47881 47882 47883 47884 | break; } } assert( iRead==iRead2 ); } #endif | < < < | < | < < | < < < < < | | | | | | | | > | | | > > > > > | 46468 46469 46470 46471 46472 46473 46474 46475 46476 46477 46478 46479 46480 46481 46482 46483 46484 46485 46486 46487 46488 46489 46490 46491 46492 46493 46494 46495 46496 46497 46498 46499 46500 46501 | break; } } assert( iRead==iRead2 ); } #endif /* If iRead is non-zero, then it is the log frame number that contains the ** required page. Read and return data from the log file. */ if( iRead ){ int sz; i64 iOffset; sz = pWal->hdr.szPage; sz = (sz&0xfe00) + ((sz&0x0001)<<16); testcase( sz<=32768 ); testcase( sz>=65536 ); iOffset = walFrameOffset(iRead, sz) + WAL_FRAME_HDRSIZE; *pInWal = 1; /* testcase( IS_BIG_INT(iOffset) ); // requires a 4GiB WAL */ return sqlite3OsRead(pWal->pWalFd, pOut, (nOut>sz ? sz : nOut), iOffset); } *pInWal = 0; return SQLITE_OK; } /* ** Return the size of the database in pages (or zero, if unknown). */ SQLITE_PRIVATE Pgno sqlite3WalDbsize(Wal *pWal){ if( pWal && ALWAYS(pWal->readLock>=0) ){ return pWal->hdr.nPage; |
︙ | ︙ | |||
48015 48016 48017 48018 48019 48020 48021 | ** are no outstanding references to any page other than page 1. And ** page 1 is never written to the log until the transaction is ** committed. As a result, the call to xUndo may not fail. */ assert( walFramePgno(pWal, iFrame)!=1 ); rc = xUndo(pUndoCtx, walFramePgno(pWal, iFrame)); } | | | 46600 46601 46602 46603 46604 46605 46606 46607 46608 46609 46610 46611 46612 46613 46614 | ** are no outstanding references to any page other than page 1. And ** page 1 is never written to the log until the transaction is ** committed. As a result, the call to xUndo may not fail. */ assert( walFramePgno(pWal, iFrame)!=1 ); rc = xUndo(pUndoCtx, walFramePgno(pWal, iFrame)); } walCleanupHash(pWal); } assert( rc==SQLITE_OK ); return rc; } /* ** Argument aWalData must point to an array of WAL_SAVEPOINT_NDATA u32 |
︙ | ︙ | |||
48449 48450 48451 48452 48453 48454 48455 | rc = SQLITE_OK; } } /* Read the wal-index header. */ if( rc==SQLITE_OK ){ rc = walIndexReadHdr(pWal, &isChanged); | < < < | 47034 47035 47036 47037 47038 47039 47040 47041 47042 47043 47044 47045 47046 47047 | rc = SQLITE_OK; } } /* Read the wal-index header. */ if( rc==SQLITE_OK ){ rc = walIndexReadHdr(pWal, &isChanged); } /* Copy data from the log to the database file. */ if( rc==SQLITE_OK ){ if( pWal->hdr.mxFrame && walPagesize(pWal)!=nBuf ){ rc = SQLITE_CORRUPT_BKPT; }else{ |
︙ | ︙ | |||
49018 49019 49020 49021 49022 49023 49024 | sqlite3 *db; /* Database connection currently using this Btree */ BtCursor *pCursor; /* A list of all open cursors */ MemPage *pPage1; /* First page of the database */ u8 openFlags; /* Flags to sqlite3BtreeOpen() */ #ifndef SQLITE_OMIT_AUTOVACUUM u8 autoVacuum; /* True if auto-vacuum is enabled */ u8 incrVacuum; /* True if incr-vacuum is enabled */ | < | 47600 47601 47602 47603 47604 47605 47606 47607 47608 47609 47610 47611 47612 47613 | sqlite3 *db; /* Database connection currently using this Btree */ BtCursor *pCursor; /* A list of all open cursors */ MemPage *pPage1; /* First page of the database */ u8 openFlags; /* Flags to sqlite3BtreeOpen() */ #ifndef SQLITE_OMIT_AUTOVACUUM u8 autoVacuum; /* True if auto-vacuum is enabled */ u8 incrVacuum; /* True if incr-vacuum is enabled */ #endif u8 inTransaction; /* Transaction state */ u8 max1bytePayload; /* Maximum first byte of cell for a 1-byte payload */ u16 btsFlags; /* Boolean parameters. See BTS_* macros below */ u16 maxLocal; /* Maximum local payload in non-LEAFDATA tables */ u16 minLocal; /* Minimum local payload in non-LEAFDATA tables */ u16 maxLeaf; /* Maximum local payload in a LEAFDATA table */ |
︙ | ︙ | |||
49585 49586 49587 49588 49589 49590 49591 | ** This routine is used to extract the "offset to cell content area" value ** from the header of a btree page. If the page size is 65536 and the page ** is empty, the offset should be 65536, but the 2-byte value stores zero. ** This routine makes the necessary adjustment to 65536. */ #define get2byteNotZero(X) (((((int)get2byte(X))-1)&0xffff)+1) | < < < < < < < < < < < < < < < < < < < | 48166 48167 48168 48169 48170 48171 48172 48173 48174 48175 48176 48177 48178 48179 | ** This routine is used to extract the "offset to cell content area" value ** from the header of a btree page. If the page size is 65536 and the page ** is empty, the offset should be 65536, but the 2-byte value stores zero. ** This routine makes the necessary adjustment to 65536. */ #define get2byteNotZero(X) (((((int)get2byte(X))-1)&0xffff)+1) #ifndef SQLITE_OMIT_SHARED_CACHE /* ** A list of BtShared objects that are eligible for participation ** in shared cache. This variable has file scope during normal builds, ** but the test harness needs to access it so we make it global for ** test builds. ** |
︙ | ︙ | |||
50116 50117 50118 50119 50120 50121 50122 | ** Clear (destroy) the BtShared.pHasContent bitvec. This should be ** invoked at the conclusion of each write-transaction. */ static void btreeClearHasContent(BtShared *pBt){ sqlite3BitvecDestroy(pBt->pHasContent); pBt->pHasContent = 0; } | < < < < < < < < < < < < < | 48678 48679 48680 48681 48682 48683 48684 48685 48686 48687 48688 48689 48690 48691 | ** Clear (destroy) the BtShared.pHasContent bitvec. This should be ** invoked at the conclusion of each write-transaction. */ static void btreeClearHasContent(BtShared *pBt){ sqlite3BitvecDestroy(pBt->pHasContent); pBt->pHasContent = 0; } /* ** Save the current cursor position in the variables BtCursor.nKey ** and BtCursor.pKey. The cursor's state is set to CURSOR_REQUIRESEEK. ** ** The caller must ensure that the cursor is valid (has eState==CURSOR_VALID) ** prior to calling this routine. |
︙ | ︙ | |||
50169 50170 50171 50172 50173 50174 50175 | }else{ rc = SQLITE_NOMEM; } } assert( !pCur->apPage[0]->intKey || !pCur->pKey ); if( rc==SQLITE_OK ){ | > > | > > > | | | | | < < < < | 48718 48719 48720 48721 48722 48723 48724 48725 48726 48727 48728 48729 48730 48731 48732 48733 48734 48735 48736 48737 48738 48739 48740 48741 48742 48743 48744 48745 48746 48747 48748 48749 48750 48751 48752 48753 48754 48755 48756 48757 48758 48759 | }else{ rc = SQLITE_NOMEM; } } assert( !pCur->apPage[0]->intKey || !pCur->pKey ); if( rc==SQLITE_OK ){ int i; for(i=0; i<=pCur->iPage; i++){ releasePage(pCur->apPage[i]); pCur->apPage[i] = 0; } pCur->iPage = -1; pCur->eState = CURSOR_REQUIRESEEK; } invalidateOverflowCache(pCur); return rc; } /* ** Save the positions of all cursors (except pExcept) that are open on ** the table with root-page iRoot. Usually, this is called just before cursor ** pExcept is used to modify the table (BtreeDelete() or BtreeInsert()). */ static int saveAllCursors(BtShared *pBt, Pgno iRoot, BtCursor *pExcept){ BtCursor *p; assert( sqlite3_mutex_held(pBt->mutex) ); assert( pExcept==0 || pExcept->pBt==pBt ); for(p=pBt->pCursor; p; p=p->pNext){ if( p!=pExcept && (0==iRoot || p->pgnoRoot==iRoot) && p->eState==CURSOR_VALID ){ int rc = saveCursorPosition(p); if( SQLITE_OK!=rc ){ return rc; } } } return SQLITE_OK; } /* |
︙ | ︙ | |||
51123 51124 51125 51126 51127 51128 51129 | ** means we have started to be concerned about content and the disk ** read should occur at that point. */ static int btreeGetPage( BtShared *pBt, /* The btree */ Pgno pgno, /* Number of the page to fetch */ MemPage **ppPage, /* Return the page in this parameter */ | | < < < < | | 49673 49674 49675 49676 49677 49678 49679 49680 49681 49682 49683 49684 49685 49686 49687 49688 49689 49690 49691 49692 49693 | ** means we have started to be concerned about content and the disk ** read should occur at that point. */ static int btreeGetPage( BtShared *pBt, /* The btree */ Pgno pgno, /* Number of the page to fetch */ MemPage **ppPage, /* Return the page in this parameter */ int noContent /* Do not load page content if true */ ){ int rc; DbPage *pDbPage; assert( sqlite3_mutex_held(pBt->mutex) ); rc = sqlite3PagerAcquire(pBt->pPager, pgno, (DbPage**)&pDbPage, noContent); if( rc ) return rc; *ppPage = btreePageFromDbPage(pDbPage, pgno, pBt); return SQLITE_OK; } /* ** Retrieve a page from the pager cache. If the requested page is not |
︙ | ︙ | |||
51176 51177 51178 51179 51180 51181 51182 | ** convenience wrapper around separate calls to btreeGetPage() and ** btreeInitPage(). ** ** If an error occurs, then the value *ppPage is set to is undefined. It ** may remain unchanged, or it may be set to an invalid value. */ static int getAndInitPage( | | | | < | | 49722 49723 49724 49725 49726 49727 49728 49729 49730 49731 49732 49733 49734 49735 49736 49737 49738 49739 49740 49741 49742 49743 49744 49745 49746 | ** convenience wrapper around separate calls to btreeGetPage() and ** btreeInitPage(). ** ** If an error occurs, then the value *ppPage is set to is undefined. It ** may remain unchanged, or it may be set to an invalid value. */ static int getAndInitPage( BtShared *pBt, /* The database file */ Pgno pgno, /* Number of the page to get */ MemPage **ppPage /* Write the page pointer here */ ){ int rc; assert( sqlite3_mutex_held(pBt->mutex) ); if( pgno>btreePagecount(pBt) ){ rc = SQLITE_CORRUPT_BKPT; }else{ rc = btreeGetPage(pBt, pgno, ppPage, 0); if( rc==SQLITE_OK ){ rc = btreeInitPage(*ppPage); if( rc!=SQLITE_OK ){ releasePage(*ppPage); } } } |
︙ | ︙ | |||
51418 51419 51420 51421 51422 51423 51424 | if( pBt==0 ){ rc = SQLITE_NOMEM; goto btree_open_out; } rc = sqlite3PagerOpen(pVfs, &pBt->pPager, zFilename, EXTRA_SIZE, flags, vfsFlags, pageReinit); if( rc==SQLITE_OK ){ | < | 49963 49964 49965 49966 49967 49968 49969 49970 49971 49972 49973 49974 49975 49976 | if( pBt==0 ){ rc = SQLITE_NOMEM; goto btree_open_out; } rc = sqlite3PagerOpen(pVfs, &pBt->pPager, zFilename, EXTRA_SIZE, flags, vfsFlags, pageReinit); if( rc==SQLITE_OK ){ rc = sqlite3PagerReadFileheader(pBt->pPager,sizeof(zDbHeader),zDbHeader); } if( rc!=SQLITE_OK ){ goto btree_open_out; } pBt->openFlags = (u8)flags; pBt->db = db; |
︙ | ︙ | |||
51685 51686 51687 51688 51689 51690 51691 | assert( sqlite3_mutex_held(p->db->mutex) ); sqlite3BtreeEnter(p); sqlite3PagerSetCachesize(pBt->pPager, mxPage); sqlite3BtreeLeave(p); return SQLITE_OK; } | < < < < < < < < < < < < < | 50229 50230 50231 50232 50233 50234 50235 50236 50237 50238 50239 50240 50241 50242 | assert( sqlite3_mutex_held(p->db->mutex) ); sqlite3BtreeEnter(p); sqlite3PagerSetCachesize(pBt->pPager, mxPage); sqlite3BtreeLeave(p); return SQLITE_OK; } /* ** Change the way data is synced to disk in order to increase or decrease ** how well the database resists damage due to OS crashes and power ** failures. Level 1 is the same as asynchronous (no syncs() occur and ** there is a high probability of damage) Level 2 is the default. There ** is a very low but non-zero probability of damage. Level 3 reduces the ** probability of damage to near zero but with a write performance reduction. |
︙ | ︙ | |||
51802 51803 51804 51805 51806 51807 51808 | ** may only be called if it is guaranteed that the b-tree mutex is already ** held. ** ** This is useful in one special case in the backup API code where it is ** known that the shared b-tree mutex is held, but the mutex on the ** database handle that owns *p is not. In this case if sqlite3BtreeEnter() ** were to be called, it might collide with some other operation on the | | | 50333 50334 50335 50336 50337 50338 50339 50340 50341 50342 50343 50344 50345 50346 50347 | ** may only be called if it is guaranteed that the b-tree mutex is already ** held. ** ** This is useful in one special case in the backup API code where it is ** known that the shared b-tree mutex is held, but the mutex on the ** database handle that owns *p is not. In this case if sqlite3BtreeEnter() ** were to be called, it might collide with some other operation on the ** database handle that owns *p, causing undefined behaviour. */ SQLITE_PRIVATE int sqlite3BtreeGetReserveNoMutex(Btree *p){ assert( sqlite3_mutex_held(p->pBt->mutex) ); return p->pBt->pageSize - p->pBt->usableSize; } #endif /* SQLITE_HAS_CODEC || SQLITE_DEBUG */ |
︙ | ︙ | |||
51923 51924 51925 51926 51927 51928 51929 | int nPageFile = 0; /* Number of pages in the database file */ int nPageHeader; /* Number of pages in the database according to hdr */ assert( sqlite3_mutex_held(pBt->mutex) ); assert( pBt->pPage1==0 ); rc = sqlite3PagerSharedLock(pBt->pPager); if( rc!=SQLITE_OK ) return rc; | | | 50454 50455 50456 50457 50458 50459 50460 50461 50462 50463 50464 50465 50466 50467 50468 | int nPageFile = 0; /* Number of pages in the database file */ int nPageHeader; /* Number of pages in the database according to hdr */ assert( sqlite3_mutex_held(pBt->mutex) ); assert( pBt->pPage1==0 ); rc = sqlite3PagerSharedLock(pBt->pPager); if( rc!=SQLITE_OK ) return rc; rc = btreeGetPage(pBt, 1, &pPage1, 0); if( rc!=SQLITE_OK ) return rc; /* Do some checking to help insure the file we opened really is ** a valid database file. */ nPage = nPageHeader = get4byte(28+(u8*)pPage1->aData); sqlite3PagerPagecount(pBt->pPager, &nPageFile); |
︙ | ︙ | |||
52059 52060 52061 52062 52063 52064 52065 | page1_init_failed: releasePage(pPage1); pBt->pPage1 = 0; return rc; } | < < < < < < < < < < < < < < < < < < < < < < < | | 50590 50591 50592 50593 50594 50595 50596 50597 50598 50599 50600 50601 50602 50603 50604 50605 50606 50607 50608 50609 50610 50611 50612 50613 50614 | page1_init_failed: releasePage(pPage1); pBt->pPage1 = 0; return rc; } /* ** If there are no outstanding cursors and we are not in the middle ** of a transaction but there is a read lock on the database, then ** this routine unrefs the first page of the database file which ** has the effect of releasing the read lock. ** ** If there is a transaction in progress, this routine is a no-op. */ static void unlockBtreeIfUnused(BtShared *pBt){ assert( sqlite3_mutex_held(pBt->mutex) ); assert( pBt->pCursor==0 || pBt->inTransaction>TRANS_NONE ); if( pBt->inTransaction==TRANS_NONE && pBt->pPage1!=0 ){ assert( pBt->pPage1->aData ); assert( sqlite3PagerRefcount(pBt->pPager)==1 ); assert( pBt->pPage1->aData ); releasePage(pBt->pPage1); pBt->pPage1 = 0; } |
︙ | ︙ | |||
52146 52147 52148 52149 52150 52151 52152 | put4byte(&data[36 + 7*4], pBt->incrVacuum); #endif pBt->nPage = 1; data[31] = 1; return SQLITE_OK; } | < < < < < < < < < < < < < < | 50654 50655 50656 50657 50658 50659 50660 50661 50662 50663 50664 50665 50666 50667 | put4byte(&data[36 + 7*4], pBt->incrVacuum); #endif pBt->nPage = 1; data[31] = 1; return SQLITE_OK; } /* ** Attempt to start a new transaction. A write-transaction ** is started if the second argument is nonzero, otherwise a read- ** transaction. If the second argument is 2 or more and exclusive ** transaction is started, meaning that no other process is allowed ** to access the database. A preexisting transaction may not be ** upgraded to exclusive by calling this routine a second time - the |
︙ | ︙ | |||
52210 52211 52212 52213 52214 52215 52216 | /* If the btree is already in a write-transaction, or it ** is already in a read-transaction and a read-transaction ** is requested, this is a no-op. */ if( p->inTrans==TRANS_WRITE || (p->inTrans==TRANS_READ && !wrflag) ){ goto trans_begun; } | < | 50704 50705 50706 50707 50708 50709 50710 50711 50712 50713 50714 50715 50716 50717 | /* If the btree is already in a write-transaction, or it ** is already in a read-transaction and a read-transaction ** is requested, this is a no-op. */ if( p->inTrans==TRANS_WRITE || (p->inTrans==TRANS_READ && !wrflag) ){ goto trans_begun; } /* Write transactions are not possible on a read-only database */ if( (pBt->btsFlags & BTS_READ_ONLY)!=0 && wrflag ){ rc = SQLITE_READONLY; goto trans_begun; } |
︙ | ︙ | |||
52505 52506 52507 52508 52509 52510 52511 | } /* Fix the database pointer on page iPtrPage that pointed at iDbPage so ** that it points at iFreePage. Also fix the pointer map entry for ** iPtrPage. */ if( eType!=PTRMAP_ROOTPAGE ){ | | | 50998 50999 51000 51001 51002 51003 51004 51005 51006 51007 51008 51009 51010 51011 51012 | } /* Fix the database pointer on page iPtrPage that pointed at iDbPage so ** that it points at iFreePage. Also fix the pointer map entry for ** iPtrPage. */ if( eType!=PTRMAP_ROOTPAGE ){ rc = btreeGetPage(pBt, iPtrPage, &pPtrPage, 0); if( rc!=SQLITE_OK ){ return rc; } rc = sqlite3PagerWrite(pPtrPage->pDbPage); if( rc!=SQLITE_OK ){ releasePage(pPtrPage); return rc; |
︙ | ︙ | |||
52527 52528 52529 52530 52531 52532 52533 | return rc; } /* Forward declaration required by incrVacuumStep(). */ static int allocateBtreePage(BtShared *, MemPage **, Pgno *, Pgno, u8); /* | | | | < | | | < < | | | > > > > | | | 51020 51021 51022 51023 51024 51025 51026 51027 51028 51029 51030 51031 51032 51033 51034 51035 51036 51037 51038 51039 51040 51041 51042 51043 51044 51045 51046 51047 51048 51049 51050 51051 | return rc; } /* Forward declaration required by incrVacuumStep(). */ static int allocateBtreePage(BtShared *, MemPage **, Pgno *, Pgno, u8); /* ** Perform a single step of an incremental-vacuum. If successful, ** return SQLITE_OK. If there is no work to do (and therefore no ** point in calling this function again), return SQLITE_DONE. ** ** More specificly, this function attempts to re-organize the ** database so that the last page of the file currently in use ** is no longer in use. ** ** If the nFin parameter is non-zero, this function assumes ** that the caller will keep calling incrVacuumStep() until ** it returns SQLITE_DONE or an error, and that nFin is the ** number of pages the database file will contain after this ** process is complete. If nFin is zero, it is assumed that ** incrVacuumStep() will be called a finite amount of times ** which may or may not empty the freelist. A full autovacuum ** has nFin>0. A "PRAGMA incremental_vacuum" has nFin==0. */ static int incrVacuumStep(BtShared *pBt, Pgno nFin, Pgno iLastPg){ Pgno nFreeList; /* Number of pages still on the free-list */ int rc; assert( sqlite3_mutex_held(pBt->mutex) ); assert( iLastPg>nFin ); if( !PTRMAP_ISPAGE(pBt, iLastPg) && iLastPg!=PENDING_BYTE_PAGE(pBt) ){ |
︙ | ︙ | |||
52568 52569 52570 52571 52572 52573 52574 | return rc; } if( eType==PTRMAP_ROOTPAGE ){ return SQLITE_CORRUPT_BKPT; } if( eType==PTRMAP_FREEPAGE ){ | | | | < < | | | < < < < | | > > | > | < | > | > > > > > > > > > > > > > | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | < | | | < < < | 51062 51063 51064 51065 51066 51067 51068 51069 51070 51071 51072 51073 51074 51075 51076 51077 51078 51079 51080 51081 51082 51083 51084 51085 51086 51087 51088 51089 51090 51091 51092 51093 51094 51095 51096 51097 51098 51099 51100 51101 51102 51103 51104 51105 51106 51107 51108 51109 51110 51111 51112 51113 51114 51115 51116 51117 51118 51119 51120 51121 51122 51123 51124 51125 51126 51127 51128 51129 51130 51131 51132 51133 51134 51135 51136 51137 51138 51139 51140 51141 51142 51143 51144 51145 51146 51147 51148 51149 51150 51151 51152 51153 51154 51155 51156 51157 51158 51159 51160 51161 51162 51163 51164 51165 51166 51167 51168 51169 51170 51171 51172 51173 | return rc; } if( eType==PTRMAP_ROOTPAGE ){ return SQLITE_CORRUPT_BKPT; } if( eType==PTRMAP_FREEPAGE ){ if( nFin==0 ){ /* Remove the page from the files free-list. This is not required ** if nFin is non-zero. In that case, the free-list will be ** truncated to zero after this function returns, so it doesn't ** matter if it still contains some garbage entries. */ Pgno iFreePg; MemPage *pFreePg; rc = allocateBtreePage(pBt, &pFreePg, &iFreePg, iLastPg, 1); if( rc!=SQLITE_OK ){ return rc; } assert( iFreePg==iLastPg ); releasePage(pFreePg); } } else { Pgno iFreePg; /* Index of free page to move pLastPg to */ MemPage *pLastPg; rc = btreeGetPage(pBt, iLastPg, &pLastPg, 0); if( rc!=SQLITE_OK ){ return rc; } /* If nFin is zero, this loop runs exactly once and page pLastPg ** is swapped with the first free page pulled off the free list. ** ** On the other hand, if nFin is greater than zero, then keep ** looping until a free-page located within the first nFin pages ** of the file is found. */ do { MemPage *pFreePg; rc = allocateBtreePage(pBt, &pFreePg, &iFreePg, 0, 0); if( rc!=SQLITE_OK ){ releasePage(pLastPg); return rc; } releasePage(pFreePg); }while( nFin!=0 && iFreePg>nFin ); assert( iFreePg<iLastPg ); rc = sqlite3PagerWrite(pLastPg->pDbPage); if( rc==SQLITE_OK ){ rc = relocatePage(pBt, pLastPg, eType, iPtrPage, iFreePg, nFin!=0); } releasePage(pLastPg); if( rc!=SQLITE_OK ){ return rc; } } } if( nFin==0 ){ iLastPg--; while( iLastPg==PENDING_BYTE_PAGE(pBt)||PTRMAP_ISPAGE(pBt, iLastPg) ){ if( PTRMAP_ISPAGE(pBt, iLastPg) ){ MemPage *pPg; rc = btreeGetPage(pBt, iLastPg, &pPg, 0); if( rc!=SQLITE_OK ){ return rc; } rc = sqlite3PagerWrite(pPg->pDbPage); releasePage(pPg); if( rc!=SQLITE_OK ){ return rc; } } iLastPg--; } sqlite3PagerTruncateImage(pBt->pPager, iLastPg); pBt->nPage = iLastPg; } return SQLITE_OK; } /* ** A write-transaction must be opened before calling this function. ** It performs a single unit of work towards an incremental vacuum. ** ** If the incremental vacuum is finished after this function has run, ** SQLITE_DONE is returned. If it is not finished, but no error occurred, ** SQLITE_OK is returned. Otherwise an SQLite error code. */ SQLITE_PRIVATE int sqlite3BtreeIncrVacuum(Btree *p){ int rc; BtShared *pBt = p->pBt; sqlite3BtreeEnter(p); assert( pBt->inTransaction==TRANS_WRITE && p->inTrans==TRANS_WRITE ); if( !pBt->autoVacuum ){ rc = SQLITE_DONE; }else{ invalidateAllOverflowCache(pBt); rc = incrVacuumStep(pBt, 0, btreePagecount(pBt)); if( rc==SQLITE_OK ){ rc = sqlite3PagerWrite(pBt->pPage1->pDbPage); put4byte(&pBt->pPage1->aData[28], pBt->nPage); } } sqlite3BtreeLeave(p); return rc; } /* |
︙ | ︙ | |||
52718 52719 52720 52721 52722 52723 52724 52725 52726 52727 52728 52729 52730 52731 52732 52733 52734 52735 52736 52737 | assert( sqlite3_mutex_held(pBt->mutex) ); invalidateAllOverflowCache(pBt); assert(pBt->autoVacuum); if( !pBt->incrVacuum ){ Pgno nFin; /* Number of pages in database after autovacuuming */ Pgno nFree; /* Number of pages on the freelist initially */ Pgno iFree; /* The next page to be freed */ Pgno nOrig; /* Database size before freeing */ nOrig = btreePagecount(pBt); if( PTRMAP_ISPAGE(pBt, nOrig) || nOrig==PENDING_BYTE_PAGE(pBt) ){ /* It is not possible to create a database for which the final page ** is either a pointer-map page or the pending-byte page. If one ** is encountered, this indicates corruption. */ return SQLITE_CORRUPT_BKPT; } nFree = get4byte(&pBt->pPage1->aData[36]); | > > > > | > > > > > > < < | | | | | 51186 51187 51188 51189 51190 51191 51192 51193 51194 51195 51196 51197 51198 51199 51200 51201 51202 51203 51204 51205 51206 51207 51208 51209 51210 51211 51212 51213 51214 51215 51216 51217 51218 51219 51220 51221 51222 51223 51224 51225 51226 51227 51228 51229 51230 51231 51232 51233 51234 51235 51236 51237 51238 51239 51240 51241 51242 | assert( sqlite3_mutex_held(pBt->mutex) ); invalidateAllOverflowCache(pBt); assert(pBt->autoVacuum); if( !pBt->incrVacuum ){ Pgno nFin; /* Number of pages in database after autovacuuming */ Pgno nFree; /* Number of pages on the freelist initially */ Pgno nPtrmap; /* Number of PtrMap pages to be freed */ Pgno iFree; /* The next page to be freed */ int nEntry; /* Number of entries on one ptrmap page */ Pgno nOrig; /* Database size before freeing */ nOrig = btreePagecount(pBt); if( PTRMAP_ISPAGE(pBt, nOrig) || nOrig==PENDING_BYTE_PAGE(pBt) ){ /* It is not possible to create a database for which the final page ** is either a pointer-map page or the pending-byte page. If one ** is encountered, this indicates corruption. */ return SQLITE_CORRUPT_BKPT; } nFree = get4byte(&pBt->pPage1->aData[36]); nEntry = pBt->usableSize/5; nPtrmap = (nFree-nOrig+PTRMAP_PAGENO(pBt, nOrig)+nEntry)/nEntry; nFin = nOrig - nFree - nPtrmap; if( nOrig>PENDING_BYTE_PAGE(pBt) && nFin<PENDING_BYTE_PAGE(pBt) ){ nFin--; } while( PTRMAP_ISPAGE(pBt, nFin) || nFin==PENDING_BYTE_PAGE(pBt) ){ nFin--; } if( nFin>nOrig ) return SQLITE_CORRUPT_BKPT; for(iFree=nOrig; iFree>nFin && rc==SQLITE_OK; iFree--){ rc = incrVacuumStep(pBt, nFin, iFree); } if( (rc==SQLITE_DONE || rc==SQLITE_OK) && nFree>0 ){ rc = sqlite3PagerWrite(pBt->pPage1->pDbPage); put4byte(&pBt->pPage1->aData[32], 0); put4byte(&pBt->pPage1->aData[36], 0); put4byte(&pBt->pPage1->aData[28], nFin); sqlite3PagerTruncateImage(pBt->pPager, nFin); pBt->nPage = nFin; } if( rc!=SQLITE_OK ){ sqlite3PagerRollback(pPager); } } assert( nRef==sqlite3PagerRefcount(pPager) ); return rc; } #else /* ifndef SQLITE_OMIT_AUTOVACUUM */ # define setChildPtrmaps(x) SQLITE_OK #endif |
︙ | ︙ | |||
52799 52800 52801 52802 52803 52804 52805 | if( pBt->autoVacuum ){ rc = autoVacuumCommit(pBt); if( rc!=SQLITE_OK ){ sqlite3BtreeLeave(p); return rc; } } | < < < < | < | 51275 51276 51277 51278 51279 51280 51281 51282 51283 51284 51285 51286 51287 51288 51289 51290 51291 51292 51293 51294 51295 51296 51297 51298 51299 51300 51301 51302 51303 51304 | if( pBt->autoVacuum ){ rc = autoVacuumCommit(pBt); if( rc!=SQLITE_OK ){ sqlite3BtreeLeave(p); return rc; } } #endif rc = sqlite3PagerCommitPhaseOne(pBt->pPager, zMaster, 0); sqlite3BtreeLeave(p); } return rc; } /* ** This function is called from both BtreeCommitPhaseTwo() and BtreeRollback() ** at the conclusion of a transaction. */ static void btreeEndTransaction(Btree *p){ BtShared *pBt = p->pBt; assert( sqlite3BtreeHoldsMutex(p) ); btreeClearHasContent(pBt); if( p->inTrans>TRANS_NONE && p->db->activeVdbeCnt>1 ){ /* If there are other active statements that belong to this database ** handle, downgrade to a read-only transaction. The other statements ** may still be reading from the database. */ downgradeAllSharedCacheTableLocks(p); p->inTrans = TRANS_READ; }else{ |
︙ | ︙ | |||
52894 52895 52896 52897 52898 52899 52900 | assert( pBt->nTransaction>0 ); rc = sqlite3PagerCommitPhaseTwo(pBt->pPager); if( rc!=SQLITE_OK && bCleanup==0 ){ sqlite3BtreeLeave(p); return rc; } pBt->inTransaction = TRANS_READ; | < > > > > > > > > > > > > > > > > > > > > > | 51365 51366 51367 51368 51369 51370 51371 51372 51373 51374 51375 51376 51377 51378 51379 51380 51381 51382 51383 51384 51385 51386 51387 51388 51389 51390 51391 51392 51393 51394 51395 51396 51397 51398 51399 51400 51401 51402 51403 51404 51405 51406 51407 51408 51409 51410 51411 51412 51413 51414 51415 51416 51417 51418 51419 | assert( pBt->nTransaction>0 ); rc = sqlite3PagerCommitPhaseTwo(pBt->pPager); if( rc!=SQLITE_OK && bCleanup==0 ){ sqlite3BtreeLeave(p); return rc; } pBt->inTransaction = TRANS_READ; } btreeEndTransaction(p); sqlite3BtreeLeave(p); return SQLITE_OK; } /* ** Do both phases of a commit. */ SQLITE_PRIVATE int sqlite3BtreeCommit(Btree *p){ int rc; sqlite3BtreeEnter(p); rc = sqlite3BtreeCommitPhaseOne(p, 0); if( rc==SQLITE_OK ){ rc = sqlite3BtreeCommitPhaseTwo(p, 0); } sqlite3BtreeLeave(p); return rc; } #ifndef NDEBUG /* ** Return the number of write-cursors open on this handle. This is for use ** in assert() expressions, so it is only compiled if NDEBUG is not ** defined. ** ** For the purposes of this routine, a write-cursor is any cursor that ** is capable of writing to the databse. That means the cursor was ** originally opened for writing and the cursor has not be disabled ** by having its state changed to CURSOR_FAULT. */ static int countWriteCursors(BtShared *pBt){ BtCursor *pCur; int r = 0; for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){ if( pCur->wrFlag && pCur->eState!=CURSOR_FAULT ) r++; } return r; } #endif /* ** This routine sets the state to CURSOR_FAULT and the error ** code to errCode for every cursor on BtShared that pBtree ** references. ** ** Every cursor is tripped, including cursors that belong |
︙ | ︙ | |||
52987 52988 52989 52990 52991 52992 52993 | if( rc2!=SQLITE_OK ){ rc = rc2; } /* The rollback may have destroyed the pPage1->aData value. So ** call btreeGetPage() on page 1 again to make ** sure pPage1->aData is set correctly. */ | | | < | 51478 51479 51480 51481 51482 51483 51484 51485 51486 51487 51488 51489 51490 51491 51492 51493 51494 51495 51496 51497 51498 51499 51500 51501 | if( rc2!=SQLITE_OK ){ rc = rc2; } /* The rollback may have destroyed the pPage1->aData value. So ** call btreeGetPage() on page 1 again to make ** sure pPage1->aData is set correctly. */ if( btreeGetPage(pBt, 1, &pPage1, 0)==SQLITE_OK ){ int nPage = get4byte(28+(u8*)pPage1->aData); testcase( nPage==0 ); if( nPage==0 ) sqlite3PagerPagecount(pBt->pPager, &nPage); testcase( pBt->nPage!=nPage ); pBt->nPage = nPage; releasePage(pPage1); } assert( countWriteCursors(pBt)==0 ); pBt->inTransaction = TRANS_READ; } btreeEndTransaction(p); sqlite3BtreeLeave(p); return rc; } |
︙ | ︙ | |||
53422 53423 53424 53425 53426 53427 53428 | } } } #endif assert( next==0 || rc==SQLITE_DONE ); if( rc==SQLITE_OK ){ | | | 51912 51913 51914 51915 51916 51917 51918 51919 51920 51921 51922 51923 51924 51925 51926 | } } } #endif assert( next==0 || rc==SQLITE_DONE ); if( rc==SQLITE_OK ){ rc = btreeGetPage(pBt, ovfl, &pPage, 0); assert( rc==SQLITE_OK || pPage==0 ); if( rc==SQLITE_OK ){ next = get4byte(pPage->aData); } } *pPgnoNext = next; |
︙ | ︙ | |||
53643 53644 53645 53646 53647 53648 53649 | nextPage = get4byte(aWrite); memcpy(aWrite, aSave, 4); }else #endif { DbPage *pDbPage; | | < < | 52133 52134 52135 52136 52137 52138 52139 52140 52141 52142 52143 52144 52145 52146 52147 | nextPage = get4byte(aWrite); memcpy(aWrite, aSave, 4); }else #endif { DbPage *pDbPage; rc = sqlite3PagerGet(pBt->pPager, nextPage, &pDbPage); if( rc==SQLITE_OK ){ aPayload = sqlite3PagerGetData(pDbPage); nextPage = get4byte(aPayload); rc = copyPayload(&aPayload[offset+4], pBuf, a, eOp, pDbPage); sqlite3PagerUnref(pDbPage); offset = 0; } |
︙ | ︙ | |||
53824 53825 53826 53827 53828 53829 53830 | int i = pCur->iPage; MemPage *pNewPage; BtShared *pBt = pCur->pBt; assert( cursorHoldsMutex(pCur) ); assert( pCur->eState==CURSOR_VALID ); assert( pCur->iPage<BTCURSOR_MAX_DEPTH ); | < | | 52312 52313 52314 52315 52316 52317 52318 52319 52320 52321 52322 52323 52324 52325 52326 52327 52328 52329 | int i = pCur->iPage; MemPage *pNewPage; BtShared *pBt = pCur->pBt; assert( cursorHoldsMutex(pCur) ); assert( pCur->eState==CURSOR_VALID ); assert( pCur->iPage<BTCURSOR_MAX_DEPTH ); if( pCur->iPage>=(BTCURSOR_MAX_DEPTH-1) ){ return SQLITE_CORRUPT_BKPT; } rc = getAndInitPage(pBt, newPgno, &pNewPage); if( rc ) return rc; pCur->apPage[i+1] = pNewPage; pCur->aiIdx[i+1] = 0; pCur->iPage++; pCur->info.nSize = 0; pCur->validNKey = 0; |
︙ | ︙ | |||
53945 53946 53947 53948 53949 53950 53951 | releasePage(pCur->apPage[i]); } pCur->iPage = 0; }else if( pCur->pgnoRoot==0 ){ pCur->eState = CURSOR_INVALID; return SQLITE_OK; }else{ | | | 52432 52433 52434 52435 52436 52437 52438 52439 52440 52441 52442 52443 52444 52445 52446 | 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; /* If pCur->pKeyInfo is not NULL, then the caller that opened this cursor |
︙ | ︙ | |||
54475 54476 54477 54478 54479 54480 54481 | ** been referenced and the calling routine is responsible for calling ** sqlite3PagerUnref() on the new page when it is done. ** ** SQLITE_OK is returned on success. Any other return value indicates ** an error. *ppPage and *pPgno are undefined in the event of an error. ** Do not invoke sqlite3PagerUnref() on *ppPage if an error is returned. ** | | | | | < < | | | | | < | < | | | | | | | | | < < | | < | | 52962 52963 52964 52965 52966 52967 52968 52969 52970 52971 52972 52973 52974 52975 52976 52977 52978 52979 52980 52981 52982 52983 52984 52985 52986 52987 52988 52989 52990 52991 52992 52993 52994 52995 52996 52997 52998 52999 53000 53001 53002 53003 53004 53005 53006 53007 53008 53009 53010 53011 53012 53013 53014 53015 53016 53017 53018 53019 53020 53021 53022 53023 53024 53025 53026 53027 53028 53029 53030 53031 53032 53033 53034 53035 53036 53037 53038 53039 53040 53041 53042 53043 53044 53045 53046 53047 53048 53049 53050 53051 53052 53053 | ** been referenced and the calling routine is responsible for calling ** sqlite3PagerUnref() on the new page when it is done. ** ** SQLITE_OK is returned on success. Any other return value indicates ** an error. *ppPage and *pPgno are undefined in the event of an error. ** Do not invoke sqlite3PagerUnref() on *ppPage if an error is returned. ** ** If the "nearby" parameter is not 0, then a (feeble) effort is made to ** locate a page close to the page number "nearby". This can be used in an ** attempt to keep related pages close to each other in the database file, ** which in turn can make database access faster. ** ** If the "exact" parameter is not 0, and the page-number nearby exists ** anywhere on the free-list, then it is guarenteed to be returned. This ** is only used by auto-vacuum databases when allocating a new table. */ static int allocateBtreePage( BtShared *pBt, MemPage **ppPage, Pgno *pPgno, Pgno nearby, u8 exact ){ MemPage *pPage1; int rc; u32 n; /* Number of pages on the freelist */ u32 k; /* Number of leaves on the trunk of the freelist */ MemPage *pTrunk = 0; MemPage *pPrevTrunk = 0; Pgno mxPage; /* Total size of the database file */ assert( sqlite3_mutex_held(pBt->mutex) ); pPage1 = pBt->pPage1; mxPage = btreePagecount(pBt); n = get4byte(&pPage1->aData[36]); testcase( n==mxPage-1 ); if( n>=mxPage ){ return SQLITE_CORRUPT_BKPT; } if( n>0 ){ /* There are pages on the freelist. Reuse one of those pages. */ Pgno iTrunk; u8 searchList = 0; /* If the free-list must be searched for 'nearby' */ /* If the 'exact' parameter was true and a query of the pointer-map ** shows that the page 'nearby' is somewhere on the free-list, then ** the entire-list will be searched for that page. */ #ifndef SQLITE_OMIT_AUTOVACUUM if( exact && nearby<=mxPage ){ u8 eType; assert( nearby>0 ); assert( pBt->autoVacuum ); rc = ptrmapGet(pBt, nearby, &eType, 0); if( rc ) return rc; if( eType==PTRMAP_FREEPAGE ){ searchList = 1; } *pPgno = nearby; } #endif /* Decrement the free-list count by 1. Set iTrunk to the index of the ** first free-list trunk page. iPrevTrunk is initially 1. */ rc = sqlite3PagerWrite(pPage1->pDbPage); if( rc ) return rc; put4byte(&pPage1->aData[36], n-1); /* The code within this loop is run only once if the 'searchList' variable ** is not true. Otherwise, it runs once for each trunk-page on the ** free-list until the page 'nearby' is located. */ do { pPrevTrunk = pTrunk; if( pPrevTrunk ){ iTrunk = get4byte(&pPrevTrunk->aData[0]); }else{ iTrunk = get4byte(&pPage1->aData[32]); } testcase( iTrunk==mxPage ); if( iTrunk>mxPage ){ rc = SQLITE_CORRUPT_BKPT; }else{ rc = btreeGetPage(pBt, iTrunk, &pTrunk, 0); } if( rc ){ pTrunk = 0; goto end_allocate_page; } assert( pTrunk!=0 ); assert( pTrunk->aData!=0 ); |
︙ | ︙ | |||
54588 54589 54590 54591 54592 54593 54594 | pTrunk = 0; TRACE(("ALLOCATE: %d trunk - %d free pages left\n", *pPgno, n-1)); }else if( k>(u32)(pBt->usableSize/4 - 2) ){ /* Value of k is out of range. Database corruption */ rc = SQLITE_CORRUPT_BKPT; goto end_allocate_page; #ifndef SQLITE_OMIT_AUTOVACUUM | | < < | | 53068 53069 53070 53071 53072 53073 53074 53075 53076 53077 53078 53079 53080 53081 53082 53083 53084 53085 53086 | pTrunk = 0; TRACE(("ALLOCATE: %d trunk - %d free pages left\n", *pPgno, n-1)); }else if( k>(u32)(pBt->usableSize/4 - 2) ){ /* Value of k is out of range. Database corruption */ rc = SQLITE_CORRUPT_BKPT; goto end_allocate_page; #ifndef SQLITE_OMIT_AUTOVACUUM }else if( searchList && nearby==iTrunk ){ /* The list is being searched and this trunk page is the page ** to allocate, regardless of whether it has leaves. */ assert( *pPgno==iTrunk ); *ppPage = pTrunk; searchList = 0; rc = sqlite3PagerWrite(pTrunk->pDbPage); if( rc ){ goto end_allocate_page; } if( k==0 ){ |
︙ | ︙ | |||
54623 54624 54625 54626 54627 54628 54629 | MemPage *pNewTrunk; Pgno iNewTrunk = get4byte(&pTrunk->aData[8]); if( iNewTrunk>mxPage ){ rc = SQLITE_CORRUPT_BKPT; goto end_allocate_page; } testcase( iNewTrunk==mxPage ); | | | 53101 53102 53103 53104 53105 53106 53107 53108 53109 53110 53111 53112 53113 53114 53115 | MemPage *pNewTrunk; Pgno iNewTrunk = get4byte(&pTrunk->aData[8]); if( iNewTrunk>mxPage ){ rc = SQLITE_CORRUPT_BKPT; goto end_allocate_page; } testcase( iNewTrunk==mxPage ); rc = btreeGetPage(pBt, iNewTrunk, &pNewTrunk, 0); if( rc!=SQLITE_OK ){ goto end_allocate_page; } rc = sqlite3PagerWrite(pNewTrunk->pDbPage); if( rc!=SQLITE_OK ){ releasePage(pNewTrunk); goto end_allocate_page; |
︙ | ︙ | |||
54657 54658 54659 54660 54661 54662 54663 | }else if( k>0 ){ /* Extract a leaf from the trunk */ u32 closest; Pgno iPage; unsigned char *aData = pTrunk->aData; if( nearby>0 ){ u32 i; | < < < < < < < < < < | > | | | | | | < | < < | | < < < < < < < < < < < < < < < | < < < | | | 53135 53136 53137 53138 53139 53140 53141 53142 53143 53144 53145 53146 53147 53148 53149 53150 53151 53152 53153 53154 53155 53156 53157 53158 53159 53160 53161 53162 53163 53164 53165 53166 53167 53168 53169 53170 53171 53172 53173 53174 53175 53176 53177 53178 53179 53180 53181 53182 53183 53184 53185 53186 53187 53188 53189 53190 53191 53192 53193 53194 53195 53196 53197 53198 53199 53200 53201 53202 53203 53204 53205 53206 53207 53208 53209 53210 53211 53212 53213 53214 53215 53216 53217 53218 53219 53220 53221 53222 53223 53224 53225 53226 53227 | }else if( k>0 ){ /* Extract a leaf from the trunk */ u32 closest; Pgno iPage; unsigned char *aData = pTrunk->aData; if( nearby>0 ){ u32 i; int dist; closest = 0; dist = sqlite3AbsInt32(get4byte(&aData[8]) - nearby); for(i=1; i<k; i++){ int d2 = sqlite3AbsInt32(get4byte(&aData[8+i*4]) - nearby); if( d2<dist ){ closest = i; dist = d2; } } }else{ closest = 0; } iPage = get4byte(&aData[8+closest*4]); testcase( iPage==mxPage ); if( iPage>mxPage ){ rc = SQLITE_CORRUPT_BKPT; goto end_allocate_page; } testcase( iPage==mxPage ); if( !searchList || iPage==nearby ){ int noContent; *pPgno = iPage; TRACE(("ALLOCATE: %d was leaf %d of %d on trunk %d" ": %d more free pages\n", *pPgno, closest+1, k, pTrunk->pgno, n-1)); rc = sqlite3PagerWrite(pTrunk->pDbPage); if( rc ) goto end_allocate_page; if( closest<k-1 ){ memcpy(&aData[8+closest*4], &aData[4+k*4], 4); } put4byte(&aData[4], k-1); noContent = !btreeGetHasContent(pBt, *pPgno); rc = btreeGetPage(pBt, *pPgno, ppPage, noContent); if( rc==SQLITE_OK ){ rc = sqlite3PagerWrite((*ppPage)->pDbPage); if( rc!=SQLITE_OK ){ releasePage(*ppPage); } } searchList = 0; } } releasePage(pPrevTrunk); pPrevTrunk = 0; }while( searchList ); }else{ /* There are no pages on the freelist, so create a new page at the ** end of the file */ rc = sqlite3PagerWrite(pBt->pPage1->pDbPage); if( rc ) return rc; pBt->nPage++; if( pBt->nPage==PENDING_BYTE_PAGE(pBt) ) pBt->nPage++; #ifndef SQLITE_OMIT_AUTOVACUUM if( pBt->autoVacuum && PTRMAP_ISPAGE(pBt, pBt->nPage) ){ /* If *pPgno refers to a pointer-map page, allocate two new pages ** at the end of the file instead of one. The first allocated page ** becomes a new pointer-map page, the second is used by the caller. */ MemPage *pPg = 0; TRACE(("ALLOCATE: %d from end of file (pointer-map page)\n", pBt->nPage)); assert( pBt->nPage!=PENDING_BYTE_PAGE(pBt) ); rc = btreeGetPage(pBt, pBt->nPage, &pPg, 1); if( rc==SQLITE_OK ){ rc = sqlite3PagerWrite(pPg->pDbPage); releasePage(pPg); } if( rc ) return rc; pBt->nPage++; if( pBt->nPage==PENDING_BYTE_PAGE(pBt) ){ pBt->nPage++; } } #endif put4byte(28 + (u8*)pBt->pPage1->aData, pBt->nPage); *pPgno = pBt->nPage; assert( *pPgno!=PENDING_BYTE_PAGE(pBt) ); rc = btreeGetPage(pBt, *pPgno, ppPage, 1); if( rc ) return rc; rc = sqlite3PagerWrite((*ppPage)->pDbPage); if( rc!=SQLITE_OK ){ releasePage(*ppPage); } TRACE(("ALLOCATE: %d from end of file\n", *pPgno)); } |
︙ | ︙ | |||
54833 54834 54835 54836 54837 54838 54839 | nFree = get4byte(&pPage1->aData[36]); put4byte(&pPage1->aData[36], nFree+1); if( pBt->btsFlags & BTS_SECURE_DELETE ){ /* If the secure_delete option is enabled, then ** always fully overwrite deleted information with zeros. */ | | | 53281 53282 53283 53284 53285 53286 53287 53288 53289 53290 53291 53292 53293 53294 53295 | nFree = get4byte(&pPage1->aData[36]); put4byte(&pPage1->aData[36], nFree+1); if( pBt->btsFlags & BTS_SECURE_DELETE ){ /* If the secure_delete option is enabled, then ** always fully overwrite deleted information with zeros. */ if( (!pPage && ((rc = btreeGetPage(pBt, iPage, &pPage, 0))!=0) ) || ((rc = sqlite3PagerWrite(pPage->pDbPage))!=0) ){ goto freepage_out; } memset(pPage->aData, 0, pPage->pBt->pageSize); } |
︙ | ︙ | |||
54860 54861 54862 54863 54864 54865 54866 | ** first trunk page in the current free-list. This block tests if it ** is possible to add the page as a new free-list leaf. */ if( nFree!=0 ){ u32 nLeaf; /* Initial number of leaf cells on trunk page */ iTrunk = get4byte(&pPage1->aData[32]); | | | 53308 53309 53310 53311 53312 53313 53314 53315 53316 53317 53318 53319 53320 53321 53322 | ** first trunk page in the current free-list. This block tests if it ** is possible to add the page as a new free-list leaf. */ if( nFree!=0 ){ u32 nLeaf; /* Initial number of leaf cells on trunk page */ iTrunk = get4byte(&pPage1->aData[32]); rc = btreeGetPage(pBt, iTrunk, &pTrunk, 0); if( rc!=SQLITE_OK ){ goto freepage_out; } nLeaf = get4byte(&pTrunk->aData[4]); assert( pBt->usableSize>32 ); if( nLeaf > (u32)pBt->usableSize/4 - 2 ){ |
︙ | ︙ | |||
54906 54907 54908 54909 54910 54911 54912 | /* If control flows to this point, then it was not possible to add the ** the page being freed as a leaf page of the first trunk in the free-list. ** Possibly because the free-list is empty, or possibly because the ** first trunk in the free-list is full. Either way, the page being freed ** will become the new first trunk page in the free-list. */ | | | 53354 53355 53356 53357 53358 53359 53360 53361 53362 53363 53364 53365 53366 53367 53368 | /* If control flows to this point, then it was not possible to add the ** the page being freed as a leaf page of the first trunk in the free-list. ** Possibly because the free-list is empty, or possibly because the ** first trunk in the free-list is full. Either way, the page being freed ** will become the new first trunk page in the free-list. */ if( pPage==0 && SQLITE_OK!=(rc = btreeGetPage(pBt, iPage, &pPage, 0)) ){ goto freepage_out; } rc = sqlite3PagerWrite(pPage->pDbPage); if( rc!=SQLITE_OK ){ goto freepage_out; } put4byte(pPage->aData, iTrunk); |
︙ | ︙ | |||
55093 55094 55095 55096 55097 55098 55099 | /* If the database supports auto-vacuum, and the second or subsequent ** overflow page is being allocated, add an entry to the pointer-map ** for that page now. ** ** If this is the first overflow page, then write a partial entry ** to the pointer-map. If we write nothing to this pointer-map slot, ** then the optimistic overflow chain processing in clearCell() | | | 53541 53542 53543 53544 53545 53546 53547 53548 53549 53550 53551 53552 53553 53554 53555 | /* If the database supports auto-vacuum, and the second or subsequent ** overflow page is being allocated, add an entry to the pointer-map ** for that page now. ** ** If this is the first overflow page, then write a partial entry ** to the pointer-map. If we write nothing to this pointer-map slot, ** then the optimistic overflow chain processing in clearCell() ** may misinterpret the uninitialised values and delete the ** wrong pages from the database. */ if( pBt->autoVacuum && rc==SQLITE_OK ){ u8 eType = (pgnoPtrmap?PTRMAP_OVERFLOW2:PTRMAP_OVERFLOW1); ptrmapPut(pBt, pgnoOvfl, eType, pgnoPtrmap, &rc); if( rc ){ releasePage(pOvfl); |
︙ | ︙ | |||
55405 55406 55407 55408 55409 55410 55411 | Pgno pgnoNew; /* Page number of pNew */ assert( sqlite3_mutex_held(pPage->pBt->mutex) ); assert( sqlite3PagerIswriteable(pParent->pDbPage) ); assert( pPage->nOverflow==1 ); /* This error condition is now caught prior to reaching this function */ | | | 53853 53854 53855 53856 53857 53858 53859 53860 53861 53862 53863 53864 53865 53866 53867 | Pgno pgnoNew; /* Page number of pNew */ assert( sqlite3_mutex_held(pPage->pBt->mutex) ); assert( sqlite3PagerIswriteable(pParent->pDbPage) ); assert( pPage->nOverflow==1 ); /* This error condition is now caught prior to reaching this function */ if( pPage->nCell<=0 ) return SQLITE_CORRUPT_BKPT; /* Allocate a new page. This page will become the right-sibling of ** pPage. Make the parent page writable, so that the new divider cell ** may be inserted. If both these operations are successful, proceed. */ rc = allocateBtreePage(pBt, &pNew, &pgnoNew, 0, 0); |
︙ | ︙ | |||
55707 55708 55709 55710 55711 55712 55713 | if( (i+nxDiv-pParent->nOverflow)==pParent->nCell ){ pRight = &pParent->aData[pParent->hdrOffset+8]; }else{ pRight = findCell(pParent, i+nxDiv-pParent->nOverflow); } pgno = get4byte(pRight); while( 1 ){ | | | 54155 54156 54157 54158 54159 54160 54161 54162 54163 54164 54165 54166 54167 54168 54169 | if( (i+nxDiv-pParent->nOverflow)==pParent->nCell ){ pRight = &pParent->aData[pParent->hdrOffset+8]; }else{ pRight = findCell(pParent, i+nxDiv-pParent->nOverflow); } pgno = get4byte(pRight); while( 1 ){ rc = getAndInitPage(pBt, pgno, &apOld[i]); if( rc ){ memset(apOld, 0, (i+1)*sizeof(MemPage*)); goto balance_cleanup; } nMaxCells += 1+apOld[i]->nCell+apOld[i]->nOverflow; if( (i--)==0 ) break; |
︙ | ︙ | |||
56566 56567 56568 56569 56570 56571 56572 | idx = ++pCur->aiIdx[pCur->iPage]; }else{ assert( pPage->leaf ); } insertCell(pPage, idx, newCell, szNew, 0, 0, &rc); assert( rc!=SQLITE_OK || pPage->nCell>0 || pPage->nOverflow>0 ); | | | 55014 55015 55016 55017 55018 55019 55020 55021 55022 55023 55024 55025 55026 55027 55028 | idx = ++pCur->aiIdx[pCur->iPage]; }else{ assert( pPage->leaf ); } insertCell(pPage, idx, newCell, szNew, 0, 0, &rc); assert( rc!=SQLITE_OK || pPage->nCell>0 || pPage->nOverflow>0 ); /* If no error has occured and pPage has an overflow cell, call balance() ** to redistribute the cells within the tree. Since balance() may move ** the cursor, zero the BtCursor.info.nSize and BtCursor.validNKey ** variables. ** ** Previous versions of SQLite called moveToRoot() to move the cursor ** back to the root page as balance() used to invalidate the contents ** of BtCursor.apPage[] and BtCursor.aiIdx[]. Instead of doing that, |
︙ | ︙ | |||
56780 56781 56782 56783 56784 56785 56786 | } assert( pgnoRoot>=3 ); /* Allocate a page. The page that currently resides at pgnoRoot will ** be moved to the allocated page (unless the allocated page happens ** to reside at pgnoRoot). */ | | < < < < < < | < | | | 55228 55229 55230 55231 55232 55233 55234 55235 55236 55237 55238 55239 55240 55241 55242 55243 55244 55245 55246 55247 55248 55249 55250 55251 55252 55253 55254 55255 55256 55257 55258 55259 55260 55261 55262 55263 55264 55265 55266 55267 55268 55269 55270 55271 55272 55273 55274 55275 55276 55277 55278 55279 55280 55281 | } assert( pgnoRoot>=3 ); /* Allocate a page. The page that currently resides at pgnoRoot will ** be moved to the allocated page (unless the allocated page happens ** to reside at pgnoRoot). */ rc = allocateBtreePage(pBt, &pPageMove, &pgnoMove, pgnoRoot, 1); if( rc!=SQLITE_OK ){ return rc; } if( pgnoMove!=pgnoRoot ){ /* pgnoRoot is the page that will be used for the root-page of ** the new table (assuming an error did not occur). But we were ** allocated pgnoMove. If required (i.e. if it was not allocated ** by extending the file), the current page at position pgnoMove ** is already journaled. */ u8 eType = 0; Pgno iPtrPage = 0; releasePage(pPageMove); /* Move the page currently at pgnoRoot to pgnoMove. */ rc = btreeGetPage(pBt, pgnoRoot, &pRoot, 0); if( rc!=SQLITE_OK ){ return rc; } rc = ptrmapGet(pBt, pgnoRoot, &eType, &iPtrPage); if( eType==PTRMAP_ROOTPAGE || eType==PTRMAP_FREEPAGE ){ rc = SQLITE_CORRUPT_BKPT; } if( rc!=SQLITE_OK ){ releasePage(pRoot); return rc; } assert( eType!=PTRMAP_ROOTPAGE ); assert( eType!=PTRMAP_FREEPAGE ); rc = relocatePage(pBt, pRoot, eType, iPtrPage, pgnoMove, 0); releasePage(pRoot); /* Obtain the page at pgnoRoot */ if( rc!=SQLITE_OK ){ return rc; } rc = btreeGetPage(pBt, pgnoRoot, &pRoot, 0); if( rc!=SQLITE_OK ){ return rc; } rc = sqlite3PagerWrite(pRoot->pDbPage); if( rc!=SQLITE_OK ){ releasePage(pRoot); return rc; |
︙ | ︙ | |||
56902 56903 56904 56905 56906 56907 56908 | int i; assert( sqlite3_mutex_held(pBt->mutex) ); if( pgno>btreePagecount(pBt) ){ return SQLITE_CORRUPT_BKPT; } | | | 55343 55344 55345 55346 55347 55348 55349 55350 55351 55352 55353 55354 55355 55356 55357 | int i; assert( sqlite3_mutex_held(pBt->mutex) ); if( pgno>btreePagecount(pBt) ){ return SQLITE_CORRUPT_BKPT; } rc = getAndInitPage(pBt, pgno, &pPage); if( rc ) return rc; for(i=0; i<pPage->nCell; i++){ pCell = findCell(pPage, i); if( !pPage->leaf ){ rc = clearDatabasePage(pBt, get4byte(pCell), 1, pnChange); if( rc ) goto cleardatabasepage_out; } |
︙ | ︙ | |||
57004 57005 57006 57007 57008 57009 57010 | ** This error is caught long before control reaches this point. */ if( NEVER(pBt->pCursor) ){ sqlite3ConnectionBlocked(p->db, pBt->pCursor->pBtree->db); return SQLITE_LOCKED_SHAREDCACHE; } | | | 55445 55446 55447 55448 55449 55450 55451 55452 55453 55454 55455 55456 55457 55458 55459 | ** This error is caught long before control reaches this point. */ if( NEVER(pBt->pCursor) ){ sqlite3ConnectionBlocked(p->db, pBt->pCursor->pBtree->db); return SQLITE_LOCKED_SHAREDCACHE; } rc = btreeGetPage(pBt, (Pgno)iTable, &pPage, 0); if( rc ) return rc; rc = sqlite3BtreeClearTable(p, iTable, 0); if( rc ){ releasePage(pPage); return rc; } |
︙ | ︙ | |||
57039 57040 57041 57042 57043 57044 57045 | }else{ /* The table being dropped does not have the largest root-page ** number in the database. So move the page that does into the ** gap left by the deleted root-page. */ MemPage *pMove; releasePage(pPage); | | | | 55480 55481 55482 55483 55484 55485 55486 55487 55488 55489 55490 55491 55492 55493 55494 55495 55496 55497 55498 55499 55500 55501 55502 55503 55504 | }else{ /* The table being dropped does not have the largest root-page ** number in the database. So move the page that does into the ** gap left by the deleted root-page. */ MemPage *pMove; releasePage(pPage); rc = btreeGetPage(pBt, maxRootPgno, &pMove, 0); if( rc!=SQLITE_OK ){ return rc; } rc = relocatePage(pBt, pMove, PTRMAP_ROOTPAGE, 0, iTable, 0); releasePage(pMove); if( rc!=SQLITE_OK ){ return rc; } pMove = 0; rc = btreeGetPage(pBt, maxRootPgno, &pMove, 0); freePage(pMove, &rc); releasePage(pMove); if( rc!=SQLITE_OK ){ return rc; } *piMoved = maxRootPgno; } |
︙ | ︙ | |||
57461 57462 57463 57464 57465 57466 57467 | /* Check that the page exists */ pBt = pCheck->pBt; usableSize = pBt->usableSize; if( iPage==0 ) return 0; if( checkRef(pCheck, iPage, zParentContext) ) return 0; | | | 55902 55903 55904 55905 55906 55907 55908 55909 55910 55911 55912 55913 55914 55915 55916 | /* Check that the page exists */ pBt = pCheck->pBt; usableSize = pBt->usableSize; if( iPage==0 ) return 0; if( checkRef(pCheck, iPage, zParentContext) ) return 0; if( (rc = btreeGetPage(pBt, (Pgno)iPage, &pPage, 0))!=0 ){ checkAppendMsg(pCheck, zContext, "unable to get the page. error code=%d", rc); return 0; } /* Clear MemPage.isInit to make sure the corruption detection code in ** btreeInitPage() is executed. */ |
︙ | ︙ | |||
57694 57695 57696 57697 57698 57699 57700 | if( !sCheck.aPgRef ){ *pnErr = 1; sqlite3BtreeLeave(p); return 0; } i = PENDING_BYTE_PAGE(pBt); if( i<=sCheck.nPage ) setPageReferenced(&sCheck, i); | | | 56135 56136 56137 56138 56139 56140 56141 56142 56143 56144 56145 56146 56147 56148 56149 | if( !sCheck.aPgRef ){ *pnErr = 1; sqlite3BtreeLeave(p); return 0; } i = PENDING_BYTE_PAGE(pBt); if( i<=sCheck.nPage ) setPageReferenced(&sCheck, i); sqlite3StrAccumInit(&sCheck.errMsg, zErr, sizeof(zErr), 20000); sCheck.errMsg.useMalloc = 2; /* Check the integrity of the freelist */ checkList(&sCheck, 1, get4byte(&pBt->pPage1->aData[32]), get4byte(&pBt->pPage1->aData[36]), "Main freelist: "); |
︙ | ︙ | |||
57933 57934 57935 57936 57937 57938 57939 | return rc; } assert( pCsr->eState!=CURSOR_REQUIRESEEK ); if( pCsr->eState!=CURSOR_VALID ){ return SQLITE_ABORT; } | < < < < < < < < < < < | 56374 56375 56376 56377 56378 56379 56380 56381 56382 56383 56384 56385 56386 56387 | return rc; } assert( pCsr->eState!=CURSOR_REQUIRESEEK ); if( pCsr->eState!=CURSOR_VALID ){ return SQLITE_ABORT; } /* Check some assumptions: ** (a) the cursor is open for writing, ** (b) there is a read/write transaction open, ** (c) the connection holds a write-lock on the table (if required), ** (d) there are no conflicting read-locks, and ** (e) the cursor points at a valid row of an intKey table. */ |
︙ | ︙ | |||
58240 58241 58242 58243 58244 58245 58246 | } /* ** Parameter zSrcData points to a buffer containing the data for ** page iSrcPg from the source database. Copy this data into the ** destination database. */ | | < < < < < | 56670 56671 56672 56673 56674 56675 56676 56677 56678 56679 56680 56681 56682 56683 56684 | } /* ** Parameter zSrcData points to a buffer containing the data for ** page iSrcPg from the source database. Copy this data into the ** destination database. */ static int backupOnePage(sqlite3_backup *p, Pgno iSrcPg, const u8 *zSrcData){ Pager * const pDestPager = sqlite3BtreePager(p->pDest); const int nSrcPgsz = sqlite3BtreeGetPageSize(p->pSrc); int nDestPgsz = sqlite3BtreeGetPageSize(p->pDest); const int nCopy = MIN(nSrcPgsz, nDestPgsz); const i64 iEnd = (i64)iSrcPg*(i64)nSrcPgsz; #ifdef SQLITE_HAS_CODEC /* Use BtreeGetReserveNoMutex() for the source b-tree, as although it is |
︙ | ︙ | |||
58318 58319 58320 58321 58322 58323 58324 | ** and the pager code use this trick (clearing the first byte ** of the page 'extra' space to invalidate the Btree layers ** cached parse of the page). MemPage.isInit is marked ** "MUST BE FIRST" for this purpose. */ memcpy(zOut, zIn, nCopy); ((u8 *)sqlite3PagerGetExtra(pDestPg))[0] = 0; | < < < | 56743 56744 56745 56746 56747 56748 56749 56750 56751 56752 56753 56754 56755 56756 | ** and the pager code use this trick (clearing the first byte ** of the page 'extra' space to invalidate the Btree layers ** cached parse of the page). MemPage.isInit is marked ** "MUST BE FIRST" for this purpose. */ memcpy(zOut, zIn, nCopy); ((u8 *)sqlite3PagerGetExtra(pDestPg))[0] = 0; } sqlite3PagerUnref(pDestPg); } return rc; } |
︙ | ︙ | |||
58425 58426 58427 58428 58429 58430 58431 | */ nSrcPage = (int)sqlite3BtreeLastPage(p->pSrc); assert( nSrcPage>=0 ); for(ii=0; (nPage<0 || ii<nPage) && p->iNext<=(Pgno)nSrcPage && !rc; ii++){ const Pgno iSrcPg = p->iNext; /* Source page number */ if( iSrcPg!=PENDING_BYTE_PAGE(p->pSrc->pBt) ){ DbPage *pSrcPg; /* Source page object */ | | < | | 56847 56848 56849 56850 56851 56852 56853 56854 56855 56856 56857 56858 56859 56860 56861 56862 56863 | */ nSrcPage = (int)sqlite3BtreeLastPage(p->pSrc); assert( nSrcPage>=0 ); for(ii=0; (nPage<0 || ii<nPage) && p->iNext<=(Pgno)nSrcPage && !rc; ii++){ const Pgno iSrcPg = p->iNext; /* Source page number */ if( iSrcPg!=PENDING_BYTE_PAGE(p->pSrc->pBt) ){ DbPage *pSrcPg; /* Source page object */ rc = sqlite3PagerGet(pSrcPager, iSrcPg, &pSrcPg); if( rc==SQLITE_OK ){ rc = backupOnePage(p, iSrcPg, sqlite3PagerGetData(pSrcPg)); sqlite3PagerUnref(pSrcPg); } } p->iNext++; } if( rc==SQLITE_OK ){ p->nPagecount = nSrcPage; |
︙ | ︙ | |||
58450 58451 58452 58453 58454 58455 58456 | /* 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 ){ | < < < < < | < | 56871 56872 56873 56874 56875 56876 56877 56878 56879 56880 56881 56882 56883 56884 56885 | /* Update the schema version field in the destination database. This ** is to make sure that the schema-version really does change in ** the case where the source and destination databases have the ** same schema version. */ if( rc==SQLITE_DONE ){ rc = sqlite3BtreeUpdateMeta(p->pDest,1,p->iDestSchema+1); if( rc==SQLITE_OK ){ if( p->pDestDb ){ sqlite3ResetAllSchemasOfConnection(p->pDestDb); } if( destMode==PAGER_JOURNALMODE_WAL ){ rc = sqlite3BtreeSetVersion(p->pDest, 2); } |
︙ | ︙ | |||
58490 58491 58492 58493 58494 58495 58496 | nDestTruncate = (nSrcPage+ratio-1)/ratio; if( nDestTruncate==(int)PENDING_BYTE_PAGE(p->pDest->pBt) ){ nDestTruncate--; } }else{ nDestTruncate = nSrcPage * (pgszSrc/pgszDest); } | | < < < | | < < < < < < < < < < < < | < | 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 | 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 |
︙ | ︙ | |||
58562 58563 58564 58565 58566 58567 58568 | } /* Sync the database file to disk. */ if( rc==SQLITE_OK ){ rc = sqlite3PagerSync(pDestPager); } }else{ | < | 56961 56962 56963 56964 56965 56966 56967 56968 56969 56970 56971 56972 56973 56974 | } /* 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)) ){ |
︙ | ︙ | |||
58691 58692 58693 58694 58695 58696 58697 | /* The backup process p has already copied page iPage. But now it ** has been modified by a transaction on the source pager. Copy ** the new data into the backup. */ int rc; assert( p->pDestDb ); sqlite3_mutex_enter(p->pDestDb->mutex); | | | 57089 57090 57091 57092 57093 57094 57095 57096 57097 57098 57099 57100 57101 57102 57103 | /* The backup process p has already copied page iPage. But now it ** has been modified by a transaction on the source pager. Copy ** the new data into the backup. */ int rc; assert( p->pDestDb ); sqlite3_mutex_enter(p->pDestDb->mutex); rc = backupOnePage(p, iPage, aData); sqlite3_mutex_leave(p->pDestDb->mutex); assert( rc!=SQLITE_BUSY && rc!=SQLITE_LOCKED ); if( rc!=SQLITE_OK ){ p->rc = rc; } } } |
︙ | ︙ | |||
58814 58815 58816 58817 58818 58819 58820 | ** routine is a no-op. ** ** SQLITE_OK is returned if the conversion is successful (or not required). ** SQLITE_NOMEM may be returned if a malloc() fails during conversion ** between formats. */ SQLITE_PRIVATE int sqlite3VdbeChangeEncoding(Mem *pMem, int desiredEnc){ | < < | 57212 57213 57214 57215 57216 57217 57218 57219 57220 57221 57222 57223 57224 57225 57226 | ** routine is a no-op. ** ** SQLITE_OK is returned if the conversion is successful (or not required). ** SQLITE_NOMEM may be returned if a malloc() fails during conversion ** between formats. */ SQLITE_PRIVATE int sqlite3VdbeChangeEncoding(Mem *pMem, int desiredEnc){ int rc; assert( (pMem->flags&MEM_RowSet)==0 ); assert( desiredEnc==SQLITE_UTF8 || desiredEnc==SQLITE_UTF16LE || desiredEnc==SQLITE_UTF16BE ); if( !(pMem->flags&MEM_Str) || pMem->enc==desiredEnc ){ return SQLITE_OK; } assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); |
︙ | ︙ | |||
59960 59961 59962 59963 59964 59965 59966 59967 59968 59969 59970 59971 59972 59973 | ** ************************************************************************* ** This file contains code used for creating, destroying, and populating ** a VDBE (or an "sqlite3_stmt" as it is known to the outside world.) Prior ** to version 2.8.7, all this code was combined into the vdbe.c source file. ** But that file was getting too big so this subroutines were split out. */ /* ** Create a new virtual database engine. */ SQLITE_PRIVATE Vdbe *sqlite3VdbeCreate(sqlite3 *db){ Vdbe *p; p = sqlite3DbMallocZero(db, sizeof(Vdbe) ); | > > > > > > > > > > > > | 58356 58357 58358 58359 58360 58361 58362 58363 58364 58365 58366 58367 58368 58369 58370 58371 58372 58373 58374 58375 58376 58377 58378 58379 58380 58381 | ** ************************************************************************* ** This file contains code used for creating, destroying, and populating ** a VDBE (or an "sqlite3_stmt" as it is known to the outside world.) Prior ** to version 2.8.7, all this code was combined into the vdbe.c source file. ** But that file was getting too big so this subroutines were split out. */ /* ** When debugging the code generator in a symbolic debugger, one can ** set the sqlite3VdbeAddopTrace to 1 and all opcodes will be printed ** as they are added to the instruction stream. */ #ifdef SQLITE_DEBUG SQLITE_PRIVATE int sqlite3VdbeAddopTrace = 0; #endif /* ** Create a new virtual database engine. */ SQLITE_PRIVATE Vdbe *sqlite3VdbeCreate(sqlite3 *db){ Vdbe *p; p = sqlite3DbMallocZero(db, sizeof(Vdbe) ); |
︙ | ︙ | |||
59985 59986 59987 59988 59989 59990 59991 | /* ** Remember the SQL string for a prepared statement. */ SQLITE_PRIVATE void sqlite3VdbeSetSql(Vdbe *p, const char *z, int n, int isPrepareV2){ assert( isPrepareV2==1 || isPrepareV2==0 ); if( p==0 ) return; | | | 58393 58394 58395 58396 58397 58398 58399 58400 58401 58402 58403 58404 58405 58406 58407 | /* ** Remember the SQL string for a prepared statement. */ SQLITE_PRIVATE void sqlite3VdbeSetSql(Vdbe *p, const char *z, int n, int isPrepareV2){ assert( isPrepareV2==1 || isPrepareV2==0 ); if( p==0 ) return; #ifdef SQLITE_OMIT_TRACE if( !isPrepareV2 ) return; #endif assert( p->zSql==0 ); p->zSql = sqlite3DbStrNDup(p->db, z, n); p->isPrepareV2 = (u8)isPrepareV2; } |
︙ | ︙ | |||
60090 60091 60092 60093 60094 60095 60096 | pOp->p1 = p1; pOp->p2 = p2; pOp->p3 = p3; pOp->p4.p = 0; pOp->p4type = P4_NOTUSED; #ifdef SQLITE_DEBUG pOp->zComment = 0; | < | < | 58498 58499 58500 58501 58502 58503 58504 58505 58506 58507 58508 58509 58510 58511 58512 | pOp->p1 = p1; pOp->p2 = p2; pOp->p3 = p3; pOp->p4.p = 0; pOp->p4type = P4_NOTUSED; #ifdef SQLITE_DEBUG pOp->zComment = 0; if( sqlite3VdbeAddopTrace ) sqlite3VdbePrintOp(0, i, &p->aOp[i]); #endif #ifdef VDBE_PROFILE pOp->cycles = 0; pOp->cnt = 0; #endif return i; } |
︙ | ︙ | |||
60311 60312 60313 60314 60315 60316 60317 | while( (pOp = opIterNext(&sIter))!=0 ){ int opcode = pOp->opcode; if( opcode==OP_Destroy || opcode==OP_VUpdate || opcode==OP_VRename #ifndef SQLITE_OMIT_FOREIGN_KEY || (opcode==OP_FkCounter && pOp->p1==0 && pOp->p2==1) #endif || ((opcode==OP_Halt || opcode==OP_HaltIfNull) | | | | 58717 58718 58719 58720 58721 58722 58723 58724 58725 58726 58727 58728 58729 58730 58731 58732 58733 58734 58735 58736 58737 58738 58739 | while( (pOp = opIterNext(&sIter))!=0 ){ int opcode = pOp->opcode; if( opcode==OP_Destroy || opcode==OP_VUpdate || opcode==OP_VRename #ifndef SQLITE_OMIT_FOREIGN_KEY || (opcode==OP_FkCounter && pOp->p1==0 && pOp->p2==1) #endif || ((opcode==OP_Halt || opcode==OP_HaltIfNull) && (pOp->p1==SQLITE_CONSTRAINT && pOp->p2==OE_Abort)) ){ hasAbort = 1; break; } } sqlite3DbFree(v->db, sIter.apSub); /* Return true if hasAbort==mayAbort. Or if a malloc failure occured. ** If malloc failed, then the while() loop above may not have iterated ** through all opcodes and hasAbort may be set incorrectly. Return ** true for this case to prevent the assert() in the callers frame ** from failing. */ return ( v->db->mallocFailed || hasAbort==mayAbort ); } #endif /* SQLITE_DEBUG - the sqlite3AssertMayAbort() function */ |
︙ | ︙ | |||
60446 60447 60448 60449 60450 60451 60452 | } pOut->p3 = pIn->p3; pOut->p4type = P4_NOTUSED; pOut->p4.p = 0; pOut->p5 = 0; #ifdef SQLITE_DEBUG pOut->zComment = 0; | | | 58852 58853 58854 58855 58856 58857 58858 58859 58860 58861 58862 58863 58864 58865 58866 | } pOut->p3 = pIn->p3; pOut->p4type = P4_NOTUSED; pOut->p4.p = 0; pOut->p5 = 0; #ifdef SQLITE_DEBUG pOut->zComment = 0; if( sqlite3VdbeAddopTrace ){ sqlite3VdbePrintOp(0, i+addr, &p->aOp[i+addr]); } #endif } p->nOp += nOp; } return addr; |
︙ | ︙ | |||
60657 60658 60659 60660 60661 60662 60663 | } assert( p->nOp>0 ); assert( addr<p->nOp ); if( addr<0 ){ addr = p->nOp - 1; } pOp = &p->aOp[addr]; | < | 59063 59064 59065 59066 59067 59068 59069 59070 59071 59072 59073 59074 59075 59076 | } assert( p->nOp>0 ); assert( addr<p->nOp ); if( addr<0 ){ addr = p->nOp - 1; } pOp = &p->aOp[addr]; freeP4(db, pOp->p4type, pOp->p4.p); pOp->p4.p = 0; if( n==P4_INT32 ){ /* Note: this cast is safe, because the origin data point was an int ** that was cast to a (const char *). */ pOp->p4.i = SQLITE_PTR_TO_INT(zP4); pOp->p4type = P4_INT32; |
︙ | ︙ | |||
60800 60801 60802 60803 60804 60805 60806 | int i, j; KeyInfo *pKeyInfo = pOp->p4.pKeyInfo; assert( pKeyInfo->aSortOrder!=0 ); sqlite3_snprintf(nTemp, zTemp, "keyinfo(%d", pKeyInfo->nField); i = sqlite3Strlen30(zTemp); for(j=0; j<pKeyInfo->nField; j++){ CollSeq *pColl = pKeyInfo->aColl[j]; | | | | | | | | | | | | | > > > > | 59205 59206 59207 59208 59209 59210 59211 59212 59213 59214 59215 59216 59217 59218 59219 59220 59221 59222 59223 59224 59225 59226 59227 59228 59229 59230 59231 59232 59233 59234 | int i, j; KeyInfo *pKeyInfo = pOp->p4.pKeyInfo; assert( pKeyInfo->aSortOrder!=0 ); sqlite3_snprintf(nTemp, zTemp, "keyinfo(%d", pKeyInfo->nField); i = sqlite3Strlen30(zTemp); for(j=0; j<pKeyInfo->nField; j++){ CollSeq *pColl = pKeyInfo->aColl[j]; if( pColl ){ int n = sqlite3Strlen30(pColl->zName); if( i+n>nTemp-6 ){ memcpy(&zTemp[i],",...",4); break; } zTemp[i++] = ','; if( pKeyInfo->aSortOrder[j] ){ zTemp[i++] = '-'; } memcpy(&zTemp[i], pColl->zName,n+1); i += n; }else if( i+4<nTemp-6 ){ memcpy(&zTemp[i],",nil",4); i += 4; } } zTemp[i++] = ')'; zTemp[i] = 0; assert( i<nTemp ); break; } case P4_COLLSEQ: { |
︙ | ︙ | |||
61472 61473 61474 61475 61476 61477 61478 | if( nByte ){ p->pFree = sqlite3DbMallocZero(db, nByte); } zCsr = p->pFree; zEnd = &zCsr[nByte]; }while( nByte && !db->mallocFailed ); | | | 59881 59882 59883 59884 59885 59886 59887 59888 59889 59890 59891 59892 59893 59894 59895 | if( nByte ){ p->pFree = sqlite3DbMallocZero(db, nByte); } zCsr = p->pFree; zEnd = &zCsr[nByte]; }while( nByte && !db->mallocFailed ); p->nCursor = (u16)nCursor; p->nOnceFlag = nOnce; if( p->aVar ){ p->nVar = (ynVar)nVar; for(n=0; n<nVar; n++){ p->aVar[n].flags = MEM_Null; p->aVar[n].db = db; } |
︙ | ︙ | |||
61714 61715 61716 61717 61718 61719 61720 | return rc; } /* If there are any write-transactions at all, invoke the commit hook */ if( needXcommit && db->xCommitCallback ){ rc = db->xCommitCallback(db->pCommitArg); if( rc ){ | | | 60123 60124 60125 60126 60127 60128 60129 60130 60131 60132 60133 60134 60135 60136 60137 | return rc; } /* If there are any write-transactions at all, invoke the commit hook */ if( needXcommit && db->xCommitCallback ){ rc = db->xCommitCallback(db->pCommitArg); if( rc ){ return SQLITE_CONSTRAINT; } } /* The simple case - no more than one database file (not counting the ** TEMP database) has a transaction active. There is no need for the ** master-journal. ** |
︙ | ︙ | |||
61951 61952 61953 61954 61955 61956 61957 | */ SQLITE_PRIVATE int sqlite3VdbeCloseStatement(Vdbe *p, int eOp){ sqlite3 *const db = p->db; int rc = SQLITE_OK; /* If p->iStatement is greater than zero, then this Vdbe opened a ** statement transaction that should be closed here. The only exception | | | 60360 60361 60362 60363 60364 60365 60366 60367 60368 60369 60370 60371 60372 60373 60374 | */ SQLITE_PRIVATE int sqlite3VdbeCloseStatement(Vdbe *p, int eOp){ sqlite3 *const db = p->db; int rc = SQLITE_OK; /* If p->iStatement is greater than zero, then this Vdbe opened a ** statement transaction that should be closed here. The only exception ** is that an IO error may have occured, causing an emergency rollback. ** In this case (db->nStatement==0), and there is nothing to do. */ if( db->nStatement && p->iStatement ){ int i; const int iSavepoint = p->iStatement-1; assert( eOp==SAVEPOINT_ROLLBACK || eOp==SAVEPOINT_RELEASE); |
︙ | ︙ | |||
62006 62007 62008 62009 62010 62011 62012 | /* ** This function is called when a transaction opened by the database ** handle associated with the VM passed as an argument is about to be ** committed. If there are outstanding deferred foreign key constraint ** violations, return SQLITE_ERROR. Otherwise, SQLITE_OK. ** ** If there are outstanding FK violations and this function returns | | | | | 60415 60416 60417 60418 60419 60420 60421 60422 60423 60424 60425 60426 60427 60428 60429 60430 60431 60432 60433 60434 60435 60436 | /* ** This function is called when a transaction opened by the database ** handle associated with the VM passed as an argument is about to be ** committed. If there are outstanding deferred foreign key constraint ** violations, return SQLITE_ERROR. Otherwise, SQLITE_OK. ** ** If there are outstanding FK violations and this function returns ** SQLITE_ERROR, set the result of the VM to SQLITE_CONSTRAINT and write ** an error message to it. Then return SQLITE_ERROR. */ #ifndef SQLITE_OMIT_FOREIGN_KEY SQLITE_PRIVATE int sqlite3VdbeCheckFk(Vdbe *p, int deferred){ sqlite3 *db = p->db; if( (deferred && db->nDeferredCons>0) || (!deferred && p->nFkConstraint>0) ){ p->rc = SQLITE_CONSTRAINT; p->errorAction = OE_Abort; sqlite3SetString(&p->zErrMsg, db, "foreign key constraint failed"); return SQLITE_ERROR; } return SQLITE_OK; } #endif |
︙ | ︙ | |||
62087 62088 62089 62090 62091 62092 62093 | /* If the query was read-only and the error code is SQLITE_INTERRUPT, ** no rollback is necessary. Otherwise, at least a savepoint ** transaction must be rolled back to restore the database to a ** consistent state. ** ** Even if the statement is read-only, it is important to perform ** a statement or transaction rollback operation. If the error | | | 60496 60497 60498 60499 60500 60501 60502 60503 60504 60505 60506 60507 60508 60509 60510 | /* If the query was read-only and the error code is SQLITE_INTERRUPT, ** no rollback is necessary. Otherwise, at least a savepoint ** transaction must be rolled back to restore the database to a ** consistent state. ** ** Even if the statement is read-only, it is important to perform ** a statement or transaction rollback operation. If the error ** occured while writing to the journal, sub-journal or database ** file as part of an effort to free up cache space (see function ** pagerStress() in pager.c), the rollback is required to restore ** the pager to a consistent state. */ if( !p->readOnly || mrc!=SQLITE_INTERRUPT ){ if( (mrc==SQLITE_NOMEM || mrc==SQLITE_FULL) && p->usesStmtJournal ){ eStatementOp = SAVEPOINT_ROLLBACK; |
︙ | ︙ | |||
62128 62129 62130 62131 62132 62133 62134 | if( p->rc==SQLITE_OK || (p->errorAction==OE_Fail && !isSpecialError) ){ rc = sqlite3VdbeCheckFk(p, 1); if( rc!=SQLITE_OK ){ if( NEVER(p->readOnly) ){ sqlite3VdbeLeave(p); return SQLITE_ERROR; } | | | 60537 60538 60539 60540 60541 60542 60543 60544 60545 60546 60547 60548 60549 60550 60551 | if( p->rc==SQLITE_OK || (p->errorAction==OE_Fail && !isSpecialError) ){ rc = sqlite3VdbeCheckFk(p, 1); if( rc!=SQLITE_OK ){ if( NEVER(p->readOnly) ){ sqlite3VdbeLeave(p); return SQLITE_ERROR; } rc = SQLITE_CONSTRAINT; }else{ /* The auto-commit flag is true, the vdbe program was successful ** or hit an 'OR FAIL' constraint and there are no deferred foreign ** key constraints to hold up the transaction. This means a commit ** is required. */ rc = vdbeCommit(db, p); } |
︙ | ︙ | |||
62171 62172 62173 62174 62175 62176 62177 | ** do so. If this operation returns an error, and the current statement ** error code is SQLITE_OK or SQLITE_CONSTRAINT, then promote the ** current statement error code. */ if( eStatementOp ){ rc = sqlite3VdbeCloseStatement(p, eStatementOp); if( rc ){ | | | 60580 60581 60582 60583 60584 60585 60586 60587 60588 60589 60590 60591 60592 60593 60594 | ** do so. If this operation returns an error, and the current statement ** error code is SQLITE_OK or SQLITE_CONSTRAINT, then promote the ** current statement error code. */ if( eStatementOp ){ rc = sqlite3VdbeCloseStatement(p, eStatementOp); if( rc ){ if( p->rc==SQLITE_OK || p->rc==SQLITE_CONSTRAINT ){ p->rc = rc; sqlite3DbFree(db, p->zErrMsg); p->zErrMsg = 0; } sqlite3RollbackAll(db, SQLITE_ABORT_ROLLBACK); sqlite3CloseSavepoints(db); db->autoCommit = 1; |
︙ | ︙ | |||
62257 62258 62259 62260 62261 62262 62263 | db->errCode = rc; }else{ sqlite3Error(db, rc, 0); } return rc; } | < < < < < < < < < < < < < < < < < < < < < | 60666 60667 60668 60669 60670 60671 60672 60673 60674 60675 60676 60677 60678 60679 | db->errCode = rc; }else{ sqlite3Error(db, rc, 0); } return rc; } /* ** Clean up a VDBE after execution but do not delete the VDBE just yet. ** Write any error messages into *pzErrMsg. Return the result code. ** ** After this routine is run, the VDBE should be ready to be executed ** again. ** |
︙ | ︙ | |||
62305 62306 62307 62308 62309 62310 62311 | /* If the VDBE has be run even partially, then transfer the error code ** and error message from the VDBE into the main database structure. But ** if the VDBE has just been set to run but has not actually executed any ** instructions yet, leave the main database error information unchanged. */ if( p->pc>=0 ){ | < | 60693 60694 60695 60696 60697 60698 60699 60700 60701 60702 60703 60704 60705 60706 | /* If the VDBE has be run even partially, then transfer the error code ** and error message from the VDBE into the main database structure. But ** if the VDBE has just been set to run but has not actually executed any ** instructions yet, leave the main database error information unchanged. */ if( p->pc>=0 ){ sqlite3VdbeTransferError(p); sqlite3DbFree(db, p->zErrMsg); p->zErrMsg = 0; if( p->runOnlyOnce ) p->expired = 1; }else if( p->rc && p->expired ){ /* The expired flag was set on the VDBE before the first call ** to sqlite3_step(). For consistency (since sqlite3_step() was |
︙ | ︙ | |||
62387 62388 62389 62390 62391 62392 62393 | } pAux->pAux = 0; } } } /* | | < < | | > < | | 60774 60775 60776 60777 60778 60779 60780 60781 60782 60783 60784 60785 60786 60787 60788 60789 60790 60791 60792 60793 60794 60795 60796 60797 60798 60799 60800 60801 60802 60803 60804 60805 60806 60807 60808 60809 60810 60811 60812 60813 60814 60815 60816 60817 60818 60819 60820 60821 60822 60823 60824 60825 60826 60827 60828 60829 60830 60831 60832 60833 60834 60835 60836 60837 | } pAux->pAux = 0; } } } /* ** Free all memory associated with the Vdbe passed as the second argument. ** The difference between this function and sqlite3VdbeDelete() is that ** VdbeDelete() also unlinks the Vdbe from the list of VMs associated with ** the database connection. */ SQLITE_PRIVATE void sqlite3VdbeDeleteObject(sqlite3 *db, Vdbe *p){ SubProgram *pSub, *pNext; int i; assert( p->db==0 || p->db==db ); releaseMemArray(p->aVar, p->nVar); releaseMemArray(p->aColName, p->nResColumn*COLNAME_N); for(pSub=p->pProgram; pSub; pSub=pNext){ pNext = pSub->pNext; vdbeFreeOpArray(db, pSub->aOp, pSub->nOp); sqlite3DbFree(db, pSub); } for(i=p->nzVar-1; i>=0; i--) sqlite3DbFree(db, p->azVar[i]); vdbeFreeOpArray(db, p->aOp, p->nOp); sqlite3DbFree(db, p->aLabel); sqlite3DbFree(db, p->aColName); sqlite3DbFree(db, p->zSql); sqlite3DbFree(db, p->pFree); #if defined(SQLITE_ENABLE_TREE_EXPLAIN) sqlite3DbFree(db, p->zExplain); sqlite3DbFree(db, p->pExplain); #endif sqlite3DbFree(db, p); } /* ** Delete an entire VDBE. */ SQLITE_PRIVATE void sqlite3VdbeDelete(Vdbe *p){ sqlite3 *db; if( NEVER(p==0) ) return; db = p->db; assert( sqlite3_mutex_held(db->mutex) ); if( p->pPrev ){ p->pPrev->pNext = p->pNext; }else{ assert( db->pVdbe==p ); db->pVdbe = p->pNext; } if( p->pNext ){ p->pNext->pPrev = p->pPrev; } p->magic = VDBE_MAGIC_DEAD; p->db = 0; sqlite3VdbeDeleteObject(db, p); } /* ** Make sure the cursor p is ready to read or write the row to which it ** was last positioned. Return an error code if an OOM fault or I/O error ** prevents us from positioning the cursor to its correct position. ** |
︙ | ︙ | |||
62501 62502 62503 62504 62505 62506 62507 | ** 'serial-type' and a blob of data. The serial type is an 8-byte unsigned ** integer, stored as a varint. ** ** In an SQLite index record, the serial type is stored directly before ** the blob of data that it corresponds to. In a table record, all serial ** types are stored at the start of the record, and the blobs of data at ** the end. Hence these functions allow the caller to handle the | | | 60886 60887 60888 60889 60890 60891 60892 60893 60894 60895 60896 60897 60898 60899 60900 | ** 'serial-type' and a blob of data. The serial type is an 8-byte unsigned ** integer, stored as a varint. ** ** In an SQLite index record, the serial type is stored directly before ** the blob of data that it corresponds to. In a table record, all serial ** types are stored at the start of the record, and the blobs of data at ** the end. Hence these functions allow the caller to handle the ** serial-type and data blob seperately. ** ** The following table describes the various storage classes for data: ** ** serial type bytes of data type ** -------------- --------------- --------------- ** 0 0 NULL ** 1 1 signed integer |
︙ | ︙ | |||
63641 63642 63643 63644 63645 63646 63647 | */ assert( rc==SQLITE_ROW || rc==SQLITE_DONE || rc==SQLITE_ERROR || rc==SQLITE_BUSY || rc==SQLITE_MISUSE ); assert( p->rc!=SQLITE_ROW && p->rc!=SQLITE_DONE ); if( p->isPrepareV2 && rc!=SQLITE_ROW && rc!=SQLITE_DONE ){ /* If this statement was prepared using sqlite3_prepare_v2(), and an | | > > > > > > > > | 62026 62027 62028 62029 62030 62031 62032 62033 62034 62035 62036 62037 62038 62039 62040 62041 62042 62043 62044 62045 62046 62047 62048 62049 62050 62051 62052 62053 62054 62055 | */ assert( rc==SQLITE_ROW || rc==SQLITE_DONE || rc==SQLITE_ERROR || rc==SQLITE_BUSY || rc==SQLITE_MISUSE ); assert( p->rc!=SQLITE_ROW && p->rc!=SQLITE_DONE ); if( p->isPrepareV2 && rc!=SQLITE_ROW && rc!=SQLITE_DONE ){ /* If this statement was prepared using sqlite3_prepare_v2(), and an ** error has occured, then return the error code in p->rc to the ** caller. Set the error code in the database handle to the same value. */ rc = sqlite3VdbeTransferError(p); } return (rc&db->errMask); } /* ** The maximum number of times that a statement will try to reparse ** itself before giving up and returning SQLITE_SCHEMA. */ #ifndef SQLITE_MAX_SCHEMA_RETRY # define SQLITE_MAX_SCHEMA_RETRY 5 #endif /* ** This is the top-level implementation of sqlite3_step(). Call ** sqlite3Step() to do most of the work. If a schema error occurs, ** call sqlite3Reprepare() and try again. */ SQLITE_API int sqlite3_step(sqlite3_stmt *pStmt){ int rc = SQLITE_OK; /* Result from sqlite3Step() */ |
︙ | ︙ | |||
64386 64387 64388 64389 64390 64391 64392 | int i; if( p==0 ){ return 0; } if( zName ){ for(i=0; i<p->nzVar; i++){ const char *z = p->azVar[i]; | | | 62779 62780 62781 62782 62783 62784 62785 62786 62787 62788 62789 62790 62791 62792 62793 | int i; if( p==0 ){ return 0; } if( zName ){ for(i=0; i<p->nzVar; i++){ const char *z = p->azVar[i]; if( z && memcmp(z,zName,nName)==0 && z[nName]==0 ){ return i+1; } } } return 0; } SQLITE_API int sqlite3_bind_parameter_index(sqlite3_stmt *pStmt, const char *zName){ |
︙ | ︙ | |||
64552 64553 64554 64555 64556 64557 64558 | ** This function returns a pointer to a nul-terminated string in memory ** obtained from sqlite3DbMalloc(). If sqlite3.vdbeExecCnt is 1, then the ** string contains a copy of zRawSql but with host parameters expanded to ** their current bindings. Or, if sqlite3.vdbeExecCnt is greater than 1, ** then the returned string holds a copy of zRawSql with "-- " prepended ** to each line of text. ** | < < < < < | 62945 62946 62947 62948 62949 62950 62951 62952 62953 62954 62955 62956 62957 62958 | ** This function returns a pointer to a nul-terminated string in memory ** obtained from sqlite3DbMalloc(). If sqlite3.vdbeExecCnt is 1, then the ** string contains a copy of zRawSql but with host parameters expanded to ** their current bindings. Or, if sqlite3.vdbeExecCnt is greater than 1, ** then the returned string holds a copy of zRawSql with "-- " prepended ** to each line of text. ** ** The calling function is responsible for making sure the memory returned ** is eventually freed. ** ** ALGORITHM: Scan the input string looking for host parameters in any of ** these forms: ?, ?N, $A, @A, :A. Take care to avoid text within ** string literals, quoted identifier names, and comments. For text forms, ** the host parameter index is found by scanning the perpared |
︙ | ︙ | |||
64627 64628 64629 64630 64631 64632 64633 | if( pVar->flags & MEM_Null ){ sqlite3StrAccumAppend(&out, "NULL", 4); }else if( pVar->flags & MEM_Int ){ sqlite3XPrintf(&out, "%lld", pVar->u.i); }else if( pVar->flags & MEM_Real ){ sqlite3XPrintf(&out, "%!.15g", pVar->r); }else if( pVar->flags & MEM_Str ){ | < < > > | | > | < < < < < < < < < < < < < < < < < | < < < | 63015 63016 63017 63018 63019 63020 63021 63022 63023 63024 63025 63026 63027 63028 63029 63030 63031 63032 63033 63034 63035 63036 63037 63038 63039 63040 63041 63042 63043 63044 63045 63046 63047 63048 63049 63050 63051 63052 | if( pVar->flags & MEM_Null ){ sqlite3StrAccumAppend(&out, "NULL", 4); }else if( pVar->flags & MEM_Int ){ sqlite3XPrintf(&out, "%lld", pVar->u.i); }else if( pVar->flags & MEM_Real ){ sqlite3XPrintf(&out, "%!.15g", pVar->r); }else if( pVar->flags & MEM_Str ){ #ifndef SQLITE_OMIT_UTF16 u8 enc = ENC(db); if( enc!=SQLITE_UTF8 ){ Mem utf8; memset(&utf8, 0, sizeof(utf8)); utf8.db = db; sqlite3VdbeMemSetStr(&utf8, pVar->z, pVar->n, enc, SQLITE_STATIC); sqlite3VdbeChangeEncoding(&utf8, SQLITE_UTF8); sqlite3XPrintf(&out, "'%.*q'", utf8.n, utf8.z); sqlite3VdbeMemRelease(&utf8); }else #endif { sqlite3XPrintf(&out, "'%.*q'", pVar->n, pVar->z); } }else if( pVar->flags & MEM_Zero ){ sqlite3XPrintf(&out, "zeroblob(%d)", pVar->u.nZero); }else{ assert( pVar->flags & MEM_Blob ); sqlite3StrAccumAppend(&out, "x'", 2); for(i=0; i<pVar->n; i++){ sqlite3XPrintf(&out, "%02x", pVar->z[i]&0xff); } sqlite3StrAccumAppend(&out, "'", 1); } } } return sqlite3StrAccumFinish(&out); } #endif /* #ifndef SQLITE_OMIT_TRACE */ |
︙ | ︙ | |||
64947 64948 64949 64950 64951 64952 64953 64954 64955 64956 64957 64958 64959 64960 64961 | ** converts an MEM_Ephem string into an MEM_Dyn string. */ #define Deephemeralize(P) \ if( ((P)->flags&MEM_Ephem)!=0 \ && sqlite3VdbeMemMakeWriteable(P) ){ goto no_mem;} /* Return true if the cursor was opened using the OP_OpenSorter opcode. */ # define isSorter(x) ((x)->pSorter!=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. */ | > > > > | 63316 63317 63318 63319 63320 63321 63322 63323 63324 63325 63326 63327 63328 63329 63330 63331 63332 63333 63334 | ** converts an MEM_Ephem string into an MEM_Dyn string. */ #define Deephemeralize(P) \ if( ((P)->flags&MEM_Ephem)!=0 \ && sqlite3VdbeMemMakeWriteable(P) ){ goto no_mem;} /* 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. */ |
︙ | ︙ | |||
65213 65214 65215 65216 65217 65218 65219 | #endif #ifdef SQLITE_DEBUG /* ** Print the value of a register for tracing purposes: */ static void memTracePrint(FILE *out, Mem *p){ | | < < | 63586 63587 63588 63589 63590 63591 63592 63593 63594 63595 63596 63597 63598 63599 63600 | #endif #ifdef SQLITE_DEBUG /* ** Print the value of a register for tracing purposes: */ static void memTracePrint(FILE *out, Mem *p){ if( p->flags & MEM_Null ){ fprintf(out, " NULL"); }else if( (p->flags & (MEM_Int|MEM_Str))==(MEM_Int|MEM_Str) ){ fprintf(out, " si:%lld", p->u.i); }else if( p->flags & MEM_Int ){ fprintf(out, " i:%lld", p->u.i); #ifndef SQLITE_OMIT_FLOATING_POINT }else if( p->flags & MEM_Real ){ |
︙ | ︙ | |||
65488 65489 65490 65491 65492 65493 65494 | Mem *pMem; int i; } af; struct OP_Concat_stack_vars { i64 nByte; } ag; struct OP_Remainder_stack_vars { | < | 63859 63860 63861 63862 63863 63864 63865 63866 63867 63868 63869 63870 63871 63872 | Mem *pMem; int i; } af; struct OP_Concat_stack_vars { i64 nByte; } ag; struct OP_Remainder_stack_vars { int flags; /* Combined MEM_* flags from both inputs */ i64 iA; /* Integer value of left operand */ i64 iB; /* Integer value of right operand */ double rA; /* Real value of left operand */ double rB; /* Real value of right operand */ } ah; struct OP_Function_stack_vars { |
︙ | ︙ | |||
66180 66181 66182 66183 66184 66185 66186 | sqlite3_log(pOp->p1, "constraint failed at %d in [%s]", pc, p->zSql); } rc = sqlite3VdbeHalt(p); assert( rc==SQLITE_BUSY || rc==SQLITE_OK || rc==SQLITE_ERROR ); if( rc==SQLITE_BUSY ){ p->rc = rc = SQLITE_BUSY; }else{ | | | 64550 64551 64552 64553 64554 64555 64556 64557 64558 64559 64560 64561 64562 64563 64564 | sqlite3_log(pOp->p1, "constraint failed at %d in [%s]", pc, p->zSql); } rc = sqlite3VdbeHalt(p); assert( rc==SQLITE_BUSY || rc==SQLITE_OK || rc==SQLITE_ERROR ); if( rc==SQLITE_BUSY ){ p->rc = rc = SQLITE_BUSY; }else{ assert( rc==SQLITE_OK || p->rc==SQLITE_CONSTRAINT ); assert( rc==SQLITE_OK || db->nDeferredCons>0 ); rc = p->rc ? SQLITE_ERROR : SQLITE_DONE; } goto vdbe_return; } /* Opcode: Integer P1 P2 * * * |
︙ | ︙ | |||
66398 66399 66400 66401 66402 66403 66404 | u.ae.n = pOp->p3; pIn1 = &aMem[pOp->p1]; pOut = &aMem[pOp->p2]; assert( pOut!=pIn1 ); while( 1 ){ sqlite3VdbeMemShallowCopy(pOut, pIn1, MEM_Ephem); Deephemeralize(pOut); | < < < | 64768 64769 64770 64771 64772 64773 64774 64775 64776 64777 64778 64779 64780 64781 | u.ae.n = pOp->p3; pIn1 = &aMem[pOp->p1]; pOut = &aMem[pOp->p2]; assert( pOut!=pIn1 ); while( 1 ){ sqlite3VdbeMemShallowCopy(pOut, pIn1, MEM_Ephem); Deephemeralize(pOut); REGISTER_TRACE(pOp->p2+pOp->p3-u.ae.n, pOut); if( (u.ae.n--)==0 ) break; pOut++; pIn1++; } break; } |
︙ | ︙ | |||
66594 66595 66596 66597 66598 66599 66600 | */ case OP_Add: /* same as TK_PLUS, in1, in2, out3 */ case OP_Subtract: /* same as TK_MINUS, in1, in2, out3 */ case OP_Multiply: /* same as TK_STAR, in1, in2, out3 */ case OP_Divide: /* same as TK_SLASH, in1, in2, out3 */ case OP_Remainder: { /* same as TK_REM, in1, in2, out3 */ #if 0 /* local variables moved into u.ah */ | < < < | 64961 64962 64963 64964 64965 64966 64967 64968 64969 64970 64971 64972 64973 64974 64975 64976 64977 64978 64979 64980 64981 64982 64983 64984 64985 64986 64987 64988 64989 64990 64991 64992 64993 64994 64995 64996 64997 64998 64999 65000 65001 65002 65003 65004 65005 65006 65007 65008 65009 65010 65011 | */ case OP_Add: /* same as TK_PLUS, in1, in2, out3 */ case OP_Subtract: /* same as TK_MINUS, in1, in2, out3 */ case OP_Multiply: /* same as TK_STAR, in1, in2, out3 */ case OP_Divide: /* same as TK_SLASH, in1, in2, out3 */ case OP_Remainder: { /* same as TK_REM, in1, in2, out3 */ #if 0 /* local variables moved into u.ah */ int flags; /* Combined MEM_* flags from both inputs */ i64 iA; /* Integer value of left operand */ i64 iB; /* Integer value of right operand */ double rA; /* Real value of left operand */ double rB; /* Real value of right operand */ #endif /* local variables moved into u.ah */ pIn1 = &aMem[pOp->p1]; applyNumericAffinity(pIn1); pIn2 = &aMem[pOp->p2]; applyNumericAffinity(pIn2); pOut = &aMem[pOp->p3]; u.ah.flags = pIn1->flags | pIn2->flags; if( (u.ah.flags & MEM_Null)!=0 ) goto arithmetic_result_is_null; if( (pIn1->flags & pIn2->flags & MEM_Int)==MEM_Int ){ u.ah.iA = pIn1->u.i; u.ah.iB = pIn2->u.i; switch( pOp->opcode ){ case OP_Add: if( sqlite3AddInt64(&u.ah.iB,u.ah.iA) ) goto fp_math; break; case OP_Subtract: if( sqlite3SubInt64(&u.ah.iB,u.ah.iA) ) goto fp_math; break; case OP_Multiply: if( sqlite3MulInt64(&u.ah.iB,u.ah.iA) ) goto fp_math; break; case OP_Divide: { if( u.ah.iA==0 ) goto arithmetic_result_is_null; if( u.ah.iA==-1 && u.ah.iB==SMALLEST_INT64 ) goto fp_math; u.ah.iB /= u.ah.iA; break; } default: { if( u.ah.iA==0 ) goto arithmetic_result_is_null; if( u.ah.iA==-1 ) u.ah.iA = 1; u.ah.iB %= u.ah.iA; break; } } pOut->u.i = u.ah.iB; MemSetTypeFlag(pOut, MEM_Int); }else{ fp_math: u.ah.rA = sqlite3VdbeRealValue(pIn1); u.ah.rB = sqlite3VdbeRealValue(pIn2); switch( pOp->opcode ){ case OP_Add: u.ah.rB += u.ah.rA; break; case OP_Subtract: u.ah.rB -= u.ah.rA; break; case OP_Multiply: u.ah.rB *= u.ah.rA; break; |
︙ | ︙ | |||
66665 66666 66667 66668 66669 66670 66671 | MemSetTypeFlag(pOut, MEM_Int); #else if( sqlite3IsNaN(u.ah.rB) ){ goto arithmetic_result_is_null; } pOut->r = u.ah.rB; MemSetTypeFlag(pOut, MEM_Real); | | | 65029 65030 65031 65032 65033 65034 65035 65036 65037 65038 65039 65040 65041 65042 65043 | MemSetTypeFlag(pOut, MEM_Int); #else if( sqlite3IsNaN(u.ah.rB) ){ goto arithmetic_result_is_null; } pOut->r = u.ah.rB; MemSetTypeFlag(pOut, MEM_Real); if( (u.ah.flags & MEM_Real)==0 ){ sqlite3VdbeIntegerAffinity(pOut); } #endif } break; arithmetic_result_is_null: |
︙ | ︙ | |||
67226 67227 67228 67229 67230 67231 67232 | } /* Opcode: Permutation * * * P4 * ** ** Set the permutation used by the OP_Compare operator to be the array ** of integers in P4. ** | | | | | < < < < < < | 65590 65591 65592 65593 65594 65595 65596 65597 65598 65599 65600 65601 65602 65603 65604 65605 65606 65607 65608 65609 65610 65611 65612 65613 65614 65615 65616 65617 65618 65619 65620 65621 65622 65623 65624 65625 65626 65627 65628 65629 65630 65631 65632 65633 65634 65635 65636 65637 65638 65639 65640 | } /* Opcode: Permutation * * * P4 * ** ** Set the permutation used by the OP_Compare operator to be the array ** of integers in P4. ** ** The permutation is only valid until the next OP_Permutation, OP_Compare, ** OP_Halt, or OP_ResultRow. Typically the OP_Permutation should occur ** immediately prior to the OP_Compare. */ case OP_Permutation: { assert( pOp->p4type==P4_INTARRAY ); assert( pOp->p4.ai ); aPermute = pOp->p4.ai; break; } /* Opcode: Compare P1 P2 P3 P4 * ** ** Compare two vectors of registers in reg(P1)..reg(P1+P3-1) (call this ** vector "A") and in reg(P2)..reg(P2+P3-1) ("B"). Save the result of ** the comparison for use by the next OP_Jump instruct. ** ** P4 is a KeyInfo structure that defines collating sequences and sort ** orders for the comparison. The permutation applies to registers ** only. The KeyInfo elements are used sequentially. ** ** The comparison is a sort comparison, so NULLs compare equal, ** NULLs are less than numbers, numbers are less than strings, ** and strings are less than blobs. */ case OP_Compare: { #if 0 /* local variables moved into u.al */ int n; int i; int p1; int p2; const KeyInfo *pKeyInfo; int idx; CollSeq *pColl; /* Collating sequence to use on this term */ int bRev; /* True for DESCENDING sort order */ #endif /* local variables moved into u.al */ u.al.n = pOp->p3; u.al.pKeyInfo = pOp->p4.pKeyInfo; assert( u.al.n>0 ); assert( u.al.pKeyInfo!=0 ); u.al.p1 = pOp->p1; u.al.p2 = pOp->p2; #if SQLITE_DEBUG |
︙ | ︙ | |||
67414 67415 67416 67417 67418 67419 67420 67421 67422 67423 67424 67425 67426 67427 | break; } /* Opcode: Once P1 P2 * * * ** ** Check if OP_Once flag P1 is set. If so, jump to instruction P2. Otherwise, ** set the flag and fall through to the next instruction. */ case OP_Once: { /* jump */ assert( pOp->p1<p->nOnceFlag ); if( p->aOnceFlag[pOp->p1] ){ pc = pOp->p2-1; }else{ p->aOnceFlag[pOp->p1] = 1; | > > | 65772 65773 65774 65775 65776 65777 65778 65779 65780 65781 65782 65783 65784 65785 65786 65787 | break; } /* Opcode: Once P1 P2 * * * ** ** Check if OP_Once flag P1 is set. If so, jump to instruction P2. Otherwise, ** set the flag and fall through to the next instruction. ** ** See also: JumpOnce */ case OP_Once: { /* jump */ assert( pOp->p1<p->nOnceFlag ); if( p->aOnceFlag[pOp->p1] ){ pc = pOp->p2-1; }else{ p->aOnceFlag[pOp->p1] = 1; |
︙ | ︙ | |||
67588 67589 67590 67591 67592 67593 67594 | }else{ assert( sqlite3BtreeCursorIsValid(u.ao.pCrsr) ); VVA_ONLY(rc =) sqlite3BtreeDataSize(u.ao.pCrsr, &u.ao.payloadSize); assert( rc==SQLITE_OK ); /* DataSize() cannot fail */ } }else if( ALWAYS(u.ao.pC->pseudoTableReg>0) ){ u.ao.pReg = &aMem[u.ao.pC->pseudoTableReg]; | < < < < < | 65948 65949 65950 65951 65952 65953 65954 65955 65956 65957 65958 65959 65960 65961 | }else{ assert( sqlite3BtreeCursorIsValid(u.ao.pCrsr) ); VVA_ONLY(rc =) sqlite3BtreeDataSize(u.ao.pCrsr, &u.ao.payloadSize); assert( rc==SQLITE_OK ); /* DataSize() cannot fail */ } }else if( ALWAYS(u.ao.pC->pseudoTableReg>0) ){ u.ao.pReg = &aMem[u.ao.pC->pseudoTableReg]; assert( u.ao.pReg->flags & MEM_Blob ); assert( memIsValid(u.ao.pReg) ); u.ao.payloadSize = u.ao.pReg->n; u.ao.zRec = u.ao.pReg->z; u.ao.pC->cacheStatus = (pOp->p5&OPFLAG_CLEARCACHE) ? CACHE_STALE : p->cacheCtr; assert( u.ao.payloadSize==0 || u.ao.zRec!=0 ); }else{ |
︙ | ︙ | |||
68673 68674 68675 68676 68677 68678 68679 | } } u.az.pCx->isOrdered = (pOp->p5!=BTREE_UNORDERED); u.az.pCx->isIndex = !u.az.pCx->isTable; break; } | | > > > > > | | | < | 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 | } } u.az.pCx->isOrdered = (pOp->p5!=BTREE_UNORDERED); u.az.pCx->isIndex = !u.az.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.ba */ VdbeCursor *pCx; #endif /* local variables moved into u.ba */ #ifndef SQLITE_OMIT_MERGE_SORT u.ba.pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, 1); if( u.ba.pCx==0 ) goto no_mem; u.ba.pCx->pKeyInfo = pOp->p4.pKeyInfo; u.ba.pCx->pKeyInfo->enc = ENC(p->db); u.ba.pCx->isSorter = 1; rc = sqlite3VdbeSorterInit(db, u.ba.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 |
︙ | ︙ | |||
68721 68722 68723 68724 68725 68726 68727 | assert( pOp->p1>=0 ); u.bb.pCx = allocateCursor(p, pOp->p1, pOp->p3, -1, 0); if( u.bb.pCx==0 ) goto no_mem; u.bb.pCx->nullRow = 1; u.bb.pCx->pseudoTableReg = pOp->p2; u.bb.pCx->isTable = 1; u.bb.pCx->isIndex = 0; | < | 67080 67081 67082 67083 67084 67085 67086 67087 67088 67089 67090 67091 67092 67093 | assert( pOp->p1>=0 ); u.bb.pCx = allocateCursor(p, pOp->p1, pOp->p3, -1, 0); if( u.bb.pCx==0 ) goto no_mem; u.bb.pCx->nullRow = 1; u.bb.pCx->pseudoTableReg = pOp->p2; u.bb.pCx->isTable = 1; u.bb.pCx->isIndex = 0; break; } /* Opcode: Close P1 * * * * ** ** Close a cursor previously opened as P1. If P1 is not ** currently open, this instruction is a no-op. |
︙ | ︙ | |||
68886 68887 68888 68889 68890 68891 68892 | /* The next line of code computes as follows, only faster: ** if( u.bc.oc==OP_SeekGt || u.bc.oc==OP_SeekLe ){ ** u.bc.r.flags = UNPACKED_INCRKEY; ** }else{ ** u.bc.r.flags = 0; ** } */ | | | 67244 67245 67246 67247 67248 67249 67250 67251 67252 67253 67254 67255 67256 67257 67258 | /* The next line of code computes as follows, only faster: ** if( u.bc.oc==OP_SeekGt || u.bc.oc==OP_SeekLe ){ ** u.bc.r.flags = UNPACKED_INCRKEY; ** }else{ ** u.bc.r.flags = 0; ** } */ u.bc.r.flags = (u16)(UNPACKED_INCRKEY * (1 & (u.bc.oc - OP_SeekLt))); assert( u.bc.oc!=OP_SeekGt || u.bc.r.flags==UNPACKED_INCRKEY ); assert( u.bc.oc!=OP_SeekLe || u.bc.r.flags==UNPACKED_INCRKEY ); assert( u.bc.oc!=OP_SeekGe || u.bc.r.flags==0 ); assert( u.bc.oc!=OP_SeekLt || u.bc.r.flags==0 ); u.bc.r.aMem = &aMem[pOp->p3]; #ifdef SQLITE_DEBUG |
︙ | ︙ | |||
69594 69595 69596 69597 69598 69599 69600 69601 69602 69603 69604 69605 69606 69607 69608 69609 69610 69611 | ** Write into register P2 the current sorter data for sorter cursor P1. */ case OP_SorterData: { #if 0 /* local variables moved into u.bl */ VdbeCursor *pC; #endif /* local variables moved into u.bl */ pOut = &aMem[pOp->p2]; u.bl.pC = p->apCsr[pOp->p1]; assert( u.bl.pC->isSorter ); rc = sqlite3VdbeSorterRowkey(u.bl.pC, pOut); break; } /* Opcode: RowData P1 P2 * * * ** ** Write into register P2 the complete row data for cursor P1. ** There is no interpretation of the data. | > > > > > | 67952 67953 67954 67955 67956 67957 67958 67959 67960 67961 67962 67963 67964 67965 67966 67967 67968 67969 67970 67971 67972 67973 67974 | ** Write into register P2 the current sorter data for sorter cursor P1. */ case OP_SorterData: { #if 0 /* local variables moved into u.bl */ VdbeCursor *pC; #endif /* local variables moved into u.bl */ #ifndef SQLITE_OMIT_MERGE_SORT pOut = &aMem[pOp->p2]; u.bl.pC = p->apCsr[pOp->p1]; assert( u.bl.pC->isSorter ); rc = sqlite3VdbeSorterRowkey(u.bl.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. |
︙ | ︙ | |||
69705 69706 69707 69708 69709 69710 69711 | sqlite3_vtab *pVtab; const sqlite3_module *pModule; #endif /* local variables moved into u.bn */ assert( pOp->p1>=0 && pOp->p1<p->nCursor ); u.bn.pC = p->apCsr[pOp->p1]; assert( u.bn.pC!=0 ); | | | 68068 68069 68070 68071 68072 68073 68074 68075 68076 68077 68078 68079 68080 68081 68082 | sqlite3_vtab *pVtab; const sqlite3_module *pModule; #endif /* local variables moved into u.bn */ assert( pOp->p1>=0 && pOp->p1<p->nCursor ); u.bn.pC = p->apCsr[pOp->p1]; assert( u.bn.pC!=0 ); assert( u.bn.pC->pseudoTableReg==0 ); if( u.bn.pC->nullRow ){ pOut->flags = MEM_Null; break; }else if( u.bn.pC->deferredMoveto ){ u.bn.v = u.bn.pC->movetoTarget; #ifndef SQLITE_OMIT_VIRTUALTABLE }else if( u.bn.pC->pVtabCursor ){ |
︙ | ︙ | |||
69804 69805 69806 69807 69808 69809 69810 69811 69812 69813 69814 69815 69816 69817 | ** 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 */ 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 */ | > > > | 68167 68168 68169 68170 68171 68172 68173 68174 68175 68176 68177 68178 68179 68180 68181 68182 68183 | ** 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 */ |
︙ | ︙ | |||
69884 69885 69886 69887 69888 69889 69890 69891 69892 69893 69894 69895 69896 69897 | ** 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 */ case OP_Prev: /* jump */ case OP_Next: { /* jump */ #if 0 /* local variables moved into u.br */ VdbeCursor *pC; int res; #endif /* local variables moved into u.br */ | > > > | 68250 68251 68252 68253 68254 68255 68256 68257 68258 68259 68260 68261 68262 68263 68264 68265 68266 | ** 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.br */ VdbeCursor *pC; int res; #endif /* local variables moved into u.br */ |
︙ | ︙ | |||
69936 69937 69938 69939 69940 69941 69942 69943 69944 69945 69946 69947 69948 69949 | ** 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 */ case OP_IdxInsert: { /* in2 */ #if 0 /* local variables moved into u.bs */ VdbeCursor *pC; BtCursor *pCrsr; int nKey; const char *zKey; #endif /* local variables moved into u.bs */ | > > > | 68305 68306 68307 68308 68309 68310 68311 68312 68313 68314 68315 68316 68317 68318 68319 68320 68321 | ** 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.bs */ VdbeCursor *pC; BtCursor *pCrsr; int nKey; const char *zKey; #endif /* local variables moved into u.bs */ |
︙ | ︙ | |||
71204 71205 71206 71207 71208 71209 71210 | assert(u.cm.pVtab && u.cm.pModule); rc = u.cm.pModule->xOpen(u.cm.pVtab, &u.cm.pVtabCursor); importVtabErrMsg(p, u.cm.pVtab); if( SQLITE_OK==rc ){ /* Initialize sqlite3_vtab_cursor base class */ u.cm.pVtabCursor->pVtab = u.cm.pVtab; | | | 69576 69577 69578 69579 69580 69581 69582 69583 69584 69585 69586 69587 69588 69589 69590 | assert(u.cm.pVtab && u.cm.pModule); rc = u.cm.pModule->xOpen(u.cm.pVtab, &u.cm.pVtabCursor); importVtabErrMsg(p, u.cm.pVtab); if( SQLITE_OK==rc ){ /* Initialize sqlite3_vtab_cursor base class */ u.cm.pVtabCursor->pVtab = u.cm.pVtab; /* Initialise vdbe cursor object */ u.cm.pCur = allocateCursor(p, pOp->p1, 0, -1, 0); if( u.cm.pCur ){ u.cm.pCur->pVtabCursor = u.cm.pVtabCursor; u.cm.pCur->pModule = u.cm.pVtabCursor->pVtab->pModule; }else{ db->mallocFailed = 1; u.cm.pModule->xClose(u.cm.pVtabCursor); |
︙ | ︙ | |||
71493 71494 71495 71496 71497 71498 71499 | rc = u.cr.pModule->xUpdate(u.cr.pVtab, u.cr.nArg, u.cr.apArg, &u.cr.rowid); db->vtabOnConflict = vtabOnConflict; importVtabErrMsg(p, u.cr.pVtab); if( rc==SQLITE_OK && pOp->p1 ){ assert( u.cr.nArg>1 && u.cr.apArg[0] && (u.cr.apArg[0]->flags&MEM_Null) ); db->lastRowid = lastRowid = u.cr.rowid; } | | | 69865 69866 69867 69868 69869 69870 69871 69872 69873 69874 69875 69876 69877 69878 69879 | rc = u.cr.pModule->xUpdate(u.cr.pVtab, u.cr.nArg, u.cr.apArg, &u.cr.rowid); db->vtabOnConflict = vtabOnConflict; importVtabErrMsg(p, u.cr.pVtab); if( rc==SQLITE_OK && pOp->p1 ){ assert( u.cr.nArg>1 && u.cr.apArg[0] && (u.cr.apArg[0]->flags&MEM_Null) ); db->lastRowid = lastRowid = u.cr.rowid; } if( rc==SQLITE_CONSTRAINT && pOp->p4.pVtab->bConstraint ){ if( pOp->p5==OE_Ignore ){ rc = SQLITE_OK; }else{ p->errorAction = ((pOp->p5==OE_Replace) ? OE_Abort : pOp->p5); } }else{ p->nChange++; |
︙ | ︙ | |||
72011 72012 72013 72014 72015 72016 72017 | pBlob->db = db; sqlite3BtreeLeaveAll(db); if( db->mallocFailed ){ goto blob_open_out; } sqlite3_bind_int64(pBlob->pStmt, 1, iRow); rc = blobSeekToRow(pBlob, iRow, &zErr); | | | 70383 70384 70385 70386 70387 70388 70389 70390 70391 70392 70393 70394 70395 70396 70397 | pBlob->db = db; sqlite3BtreeLeaveAll(db); if( db->mallocFailed ){ goto blob_open_out; } sqlite3_bind_int64(pBlob->pStmt, 1, iRow); rc = blobSeekToRow(pBlob, iRow, &zErr); } while( (++nAttempt)<5 && rc==SQLITE_SCHEMA ); blob_open_out: if( rc==SQLITE_OK && db->mallocFailed==0 ){ *ppBlob = (sqlite3_blob *)pBlob; }else{ if( pBlob && pBlob->pStmt ) sqlite3VdbeFinalize((Vdbe *)pBlob->pStmt); sqlite3DbFree(db, pBlob); |
︙ | ︙ | |||
72186 72187 72188 72189 72190 72191 72192 72193 72194 72195 72196 72197 72198 72199 | ** 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). */ typedef struct VdbeSorterIter VdbeSorterIter; typedef struct SorterRecord SorterRecord; typedef struct FileWriter FileWriter; /* ** NOTES ON DATA STRUCTURE USED FOR N-WAY MERGES: | > | 70558 70559 70560 70561 70562 70563 70564 70565 70566 70567 70568 70569 70570 70571 70572 | ** 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; typedef struct FileWriter FileWriter; /* ** NOTES ON DATA STRUCTURE USED FOR N-WAY MERGES: |
︙ | ︙ | |||
72362 72363 72364 72365 72366 72367 72368 | ** than p->nBuffer bytes remaining in the PMA, read all remaining data. */ iBuf = p->iReadOff % p->nBuffer; if( iBuf==0 ){ int nRead; /* Bytes to read from disk */ int rc; /* sqlite3OsRead() return code */ /* Determine how many bytes of data to read. */ | < < < | < > | 70735 70736 70737 70738 70739 70740 70741 70742 70743 70744 70745 70746 70747 70748 70749 70750 | ** than p->nBuffer bytes remaining in the PMA, read all remaining data. */ iBuf = p->iReadOff % p->nBuffer; if( iBuf==0 ){ int nRead; /* Bytes to read from disk */ int rc; /* sqlite3OsRead() return code */ /* Determine how many bytes of data to read. */ nRead = (int)(p->iEof - p->iReadOff); if( nRead>p->nBuffer ) nRead = p->nBuffer; assert( nRead>0 ); /* Read data from the file. Return early if an error occurs. */ rc = sqlite3OsRead(p->pFile, p->aBuffer, nRead, p->iReadOff); assert( rc!=SQLITE_IOERR_SHORT_READ ); if( rc!=SQLITE_OK ) return rc; } |
︙ | ︙ | |||
73204 73205 73206 73207 73208 73209 73210 73211 73212 73213 73214 73215 73216 73217 | 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; } /************** End of vdbesort.c ********************************************/ /************** Begin file journal.c *****************************************/ /* ** 2007 August 22 ** ** The author disclaims copyright to this source code. In place of | > > | 71574 71575 71576 71577 71578 71579 71580 71581 71582 71583 71584 71585 71586 71587 71588 71589 | 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 |
︙ | ︙ | |||
73267 73268 73269 73270 73271 73272 73273 | rc = sqlite3OsOpen(p->pVfs, p->zJournal, pReal, p->flags, 0); if( rc==SQLITE_OK ){ p->pReal = pReal; if( p->iSize>0 ){ assert(p->iSize<=p->nBuf); rc = sqlite3OsWrite(p->pReal, p->zBuf, p->iSize, 0); } | < < < < < < < < | 71639 71640 71641 71642 71643 71644 71645 71646 71647 71648 71649 71650 71651 71652 | rc = sqlite3OsOpen(p->pVfs, p->zJournal, pReal, p->flags, 0); if( rc==SQLITE_OK ){ p->pReal = pReal; if( p->iSize>0 ){ assert(p->iSize<=p->nBuf); rc = sqlite3OsWrite(p->pReal, p->zBuf, p->iSize, 0); } } } return rc; } /* ** Close the file. |
︙ | ︙ | |||
73444 73445 73446 73447 73448 73449 73450 | SQLITE_PRIVATE int sqlite3JournalCreate(sqlite3_file *p){ if( p->pMethods!=&JournalFileMethods ){ return SQLITE_OK; } return createFile((JournalFile *)p); } | < < < < < < < < < < | 71808 71809 71810 71811 71812 71813 71814 71815 71816 71817 71818 71819 71820 71821 | SQLITE_PRIVATE int sqlite3JournalCreate(sqlite3_file *p){ if( p->pMethods!=&JournalFileMethods ){ return SQLITE_OK; } return createFile((JournalFile *)p); } /* ** Return the number of bytes required to store a JournalFile that uses vfs ** pVfs to create the underlying on-disk files. */ SQLITE_PRIVATE int sqlite3JournalSize(sqlite3_vfs *pVfs){ return (pVfs->szOsFile+sizeof(JournalFile)); } |
︙ | ︙ | |||
73696 73697 73698 73699 73700 73701 73702 | 0, /* xCheckReservedLock */ 0, /* xFileControl */ 0, /* xSectorSize */ 0, /* xDeviceCharacteristics */ 0, /* xShmMap */ 0, /* xShmLock */ 0, /* xShmBarrier */ | < < | | 72050 72051 72052 72053 72054 72055 72056 72057 72058 72059 72060 72061 72062 72063 72064 | 0, /* xCheckReservedLock */ 0, /* xFileControl */ 0, /* xSectorSize */ 0, /* xDeviceCharacteristics */ 0, /* xShmMap */ 0, /* xShmLock */ 0, /* xShmBarrier */ 0 /* xShmUnlock */ }; /* ** Open a journal file. */ SQLITE_PRIVATE void sqlite3MemJournalOpen(sqlite3_file *pJfd){ MemJournal *p = (MemJournal *)pJfd; |
︙ | ︙ | |||
73842 73843 73844 73845 73846 73847 73848 | } return WRC_Continue; } /* ** Call sqlite3WalkExpr() for every expression in Select statement p. ** Invoke sqlite3WalkSelect() for subqueries in the FROM clause and | | < < < | | < < < < < < < < | 72194 72195 72196 72197 72198 72199 72200 72201 72202 72203 72204 72205 72206 72207 72208 72209 72210 72211 72212 72213 72214 72215 72216 72217 72218 72219 72220 72221 72222 72223 72224 72225 72226 72227 72228 72229 | } return WRC_Continue; } /* ** Call sqlite3WalkExpr() for every expression in Select statement p. ** Invoke sqlite3WalkSelect() for subqueries in the FROM clause and ** on the compound select chain, p->pPrior. ** ** Return WRC_Continue under normal conditions. Return WRC_Abort if ** there is an abort request. ** ** If the Walker does not have an xSelectCallback() then this routine ** is a no-op returning WRC_Continue. */ SQLITE_PRIVATE int sqlite3WalkSelect(Walker *pWalker, Select *p){ int rc; if( p==0 || pWalker->xSelectCallback==0 ) return WRC_Continue; rc = WRC_Continue; pWalker->walkerDepth++; while( p ){ rc = pWalker->xSelectCallback(pWalker, p); if( rc ) break; if( sqlite3WalkSelectExpr(pWalker, p) || sqlite3WalkSelectFrom(pWalker, p) ){ pWalker->walkerDepth--; return WRC_Abort; } p = p->pPrior; } pWalker->walkerDepth--; return rc & WRC_Abort; } /************** End of walker.c **********************************************/ |
︙ | ︙ | |||
73952 73953 73954 73955 73956 73957 73958 | ** ** SELECT random()%5 AS x, count(*) FROM tab GROUP BY random()%5 ** ** The result of random()%5 in the GROUP BY clause is probably different ** from the result in the result-set. We might fix this someday. Or ** then again, we might not... ** | < < < < < < < < < | 72293 72294 72295 72296 72297 72298 72299 72300 72301 72302 72303 72304 72305 72306 | ** ** SELECT random()%5 AS x, count(*) FROM tab GROUP BY random()%5 ** ** The result of random()%5 in the GROUP BY clause is probably different ** from the result in the result-set. We might fix this someday. Or ** then again, we might not... ** ** The nSubquery parameter specifies how many levels of subquery the ** alias is removed from the original expression. The usually value is ** zero but it might be more if the alias is contained within a subquery ** of the original expression. The Expr.op2 field of TK_AGG_FUNCTION ** structures must be increased by the nSubquery amount. */ static void resolveAlias( |
︙ | ︙ | |||
73984 73985 73986 73987 73988 73989 73990 | sqlite3 *db; /* The database connection */ assert( iCol>=0 && iCol<pEList->nExpr ); pOrig = pEList->a[iCol].pExpr; assert( pOrig!=0 ); assert( pOrig->flags & EP_Resolved ); db = pParse->db; | < < > > > > > > > > > > > > > > | > | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 72316 72317 72318 72319 72320 72321 72322 72323 72324 72325 72326 72327 72328 72329 72330 72331 72332 72333 72334 72335 72336 72337 72338 72339 72340 72341 72342 72343 72344 72345 72346 72347 72348 72349 72350 72351 72352 72353 72354 72355 72356 72357 72358 72359 72360 72361 72362 72363 72364 72365 72366 72367 72368 72369 72370 72371 72372 72373 72374 72375 72376 72377 72378 72379 72380 72381 72382 72383 72384 | sqlite3 *db; /* The database connection */ assert( iCol>=0 && iCol<pEList->nExpr ); pOrig = pEList->a[iCol].pExpr; assert( pOrig!=0 ); assert( pOrig->flags & EP_Resolved ); db = pParse->db; if( pOrig->op!=TK_COLUMN && zType[0]!='G' ){ pDup = sqlite3ExprDup(db, pOrig, 0); incrAggFunctionDepth(pDup, nSubquery); pDup = sqlite3PExpr(pParse, TK_AS, pDup, 0, 0); if( pDup==0 ) return; if( pEList->a[iCol].iAlias==0 ){ pEList->a[iCol].iAlias = (u16)(++pParse->nAlias); } pDup->iTable = pEList->a[iCol].iAlias; }else if( ExprHasProperty(pOrig, EP_IntValue) || pOrig->u.zToken==0 ){ pDup = sqlite3ExprDup(db, pOrig, 0); if( pDup==0 ) return; }else{ char *zToken = pOrig->u.zToken; assert( zToken!=0 ); pOrig->u.zToken = 0; pDup = sqlite3ExprDup(db, pOrig, 0); pOrig->u.zToken = zToken; if( pDup==0 ) return; assert( (pDup->flags & (EP_Reduced|EP_TokenOnly))==0 ); pDup->flags2 |= EP2_MallocedToken; pDup->u.zToken = sqlite3DbStrDup(db, zToken); } if( pExpr->flags & EP_ExpCollate ){ pDup->pColl = pExpr->pColl; pDup->flags |= EP_ExpCollate; } /* Before calling sqlite3ExprDelete(), set the EP_Static flag. This ** prevents ExprDelete() from deleting the Expr structure itself, ** allowing it to be repopulated by the memcpy() on the following line. */ ExprSetProperty(pExpr, EP_Static); sqlite3ExprDelete(db, pExpr); memcpy(pExpr, pDup, sizeof(*pExpr)); sqlite3DbFree(db, pDup); } /* ** Return TRUE if the name zCol occurs anywhere in the USING clause. ** ** Return FALSE if the USING clause is NULL or if it does not contain ** zCol. */ static int nameInUsingClause(IdList *pUsing, const char *zCol){ if( pUsing ){ int k; for(k=0; k<pUsing->nId; k++){ if( sqlite3StrICmp(pUsing->a[k].zName, zCol)==0 ) return 1; } } return 0; } /* ** Given the name of a column of the form X.Y.Z or Y.Z or just Z, look up ** that name in the set of source tables in pSrcList and make the pExpr ** expression node refer back to that source column. The following changes ** are made to pExpr: ** |
︙ | ︙ | |||
74119 74120 74121 74122 74123 74124 74125 | assert( !ExprHasAnyProperty(pExpr, EP_TokenOnly|EP_Reduced) ); /* Initialize the node to no-match */ pExpr->iTable = -1; pExpr->pTab = 0; ExprSetIrreducible(pExpr); | < < < < < < < < < < < < < < > > < < < < < < | | < | < < | | | > | | < < < | | > > > > > > > < < < < | < | 72427 72428 72429 72430 72431 72432 72433 72434 72435 72436 72437 72438 72439 72440 72441 72442 72443 72444 72445 72446 72447 72448 72449 72450 72451 72452 72453 72454 72455 72456 72457 72458 72459 72460 72461 72462 72463 72464 72465 72466 72467 72468 72469 72470 72471 72472 72473 72474 72475 72476 72477 72478 72479 72480 72481 72482 72483 72484 72485 72486 72487 72488 72489 72490 72491 72492 72493 72494 72495 72496 72497 | assert( !ExprHasAnyProperty(pExpr, EP_TokenOnly|EP_Reduced) ); /* Initialize the node to no-match */ pExpr->iTable = -1; pExpr->pTab = 0; ExprSetIrreducible(pExpr); /* Start at the inner-most context and move outward until a match is found */ while( pNC && cnt==0 ){ ExprList *pEList; SrcList *pSrcList = pNC->pSrcList; if( pSrcList ){ for(i=0, pItem=pSrcList->a; i<pSrcList->nSrc; i++, pItem++){ Table *pTab; int iDb; Column *pCol; pTab = pItem->pTab; assert( pTab!=0 && pTab->zName!=0 ); iDb = sqlite3SchemaToIndex(db, pTab->pSchema); assert( pTab->nCol>0 ); if( zTab ){ if( pItem->zAlias ){ char *zTabName = pItem->zAlias; if( sqlite3StrICmp(zTabName, zTab)!=0 ) continue; }else{ char *zTabName = pTab->zName; if( NEVER(zTabName==0) || sqlite3StrICmp(zTabName, zTab)!=0 ){ continue; } if( zDb!=0 && sqlite3StrICmp(db->aDb[iDb].zName, zDb)!=0 ){ continue; } } } if( 0==(cntTab++) ){ pExpr->iTable = pItem->iCursor; pExpr->pTab = pTab; pSchema = pTab->pSchema; pMatch = pItem; } for(j=0, pCol=pTab->aCol; j<pTab->nCol; j++, pCol++){ if( sqlite3StrICmp(pCol->zName, zCol)==0 ){ /* If there has been exactly one prior match and this match ** is for the right-hand table of a NATURAL JOIN or is in a ** USING clause, then skip this match. */ if( cnt==1 ){ if( pItem->jointype & JT_NATURAL ) continue; if( nameInUsingClause(pItem->pUsing, zCol) ) continue; } cnt++; pExpr->iTable = pItem->iCursor; pExpr->pTab = pTab; pMatch = pItem; pSchema = pTab->pSchema; /* Substitute the rowid (column -1) for the INTEGER PRIMARY KEY */ pExpr->iColumn = j==pTab->iPKey ? -1 : (i16)j; break; } } } } #ifndef SQLITE_OMIT_TRIGGER /* If we have not already resolved the name, then maybe ** it is a new.* or old.* trigger argument reference */ if( zDb==0 && zTab!=0 && cnt==0 && pParse->pTriggerTab!=0 ){ int op = pParse->eTriggerOp; |
︙ | ︙ | |||
74272 74273 74274 74275 74276 74277 74278 | ** SELECT a+b AS x FROM table WHERE x<10; ** ** In cases like this, replace pExpr with a copy of the expression that ** forms the result set entry ("a+b" in the example) and return immediately. ** Note that the expression in the result set should have already been ** resolved by the time the WHERE clause is resolved. */ | | < < < | 72559 72560 72561 72562 72563 72564 72565 72566 72567 72568 72569 72570 72571 72572 72573 | ** SELECT a+b AS x FROM table WHERE x<10; ** ** In cases like this, replace pExpr with a copy of the expression that ** forms the result set entry ("a+b" in the example) and return immediately. ** Note that the expression in the result set should have already been ** resolved by the time the WHERE clause is resolved. */ if( cnt==0 && (pEList = pNC->pEList)!=0 && zTab==0 ){ for(j=0; j<pEList->nExpr; j++){ char *zAs = pEList->a[j].zName; if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){ Expr *pOrig; assert( pExpr->pLeft==0 && pExpr->pRight==0 ); assert( pExpr->x.pList==0 ); assert( pExpr->x.pSelect==0 ); |
︙ | ︙ | |||
74366 74367 74368 74369 74370 74371 74372 | pExpr->pLeft = 0; sqlite3ExprDelete(db, pExpr->pRight); pExpr->pRight = 0; pExpr->op = (isTrigger ? TK_TRIGGER : TK_COLUMN); lookupname_end: if( cnt==1 ){ assert( pNC!=0 ); | < | < | 72650 72651 72652 72653 72654 72655 72656 72657 72658 72659 72660 72661 72662 72663 72664 | pExpr->pLeft = 0; sqlite3ExprDelete(db, pExpr->pRight); pExpr->pRight = 0; pExpr->op = (isTrigger ? TK_TRIGGER : TK_COLUMN); lookupname_end: if( cnt==1 ){ assert( pNC!=0 ); sqlite3AuthRead(pParse, pExpr, pSchema, pNC->pSrcList); /* Increment the nRef value on all name contexts from TopNC up to ** the point where the name matched. */ for(;;){ assert( pTopNC!=0 ); pTopNC->nRef++; if( pTopNC==pNC ) break; pTopNC = pTopNC->pNext; |
︙ | ︙ | |||
74536 74537 74538 74539 74540 74541 74542 | } } #endif if( is_agg && (pNC->ncFlags & NC_AllowAgg)==0 ){ sqlite3ErrorMsg(pParse, "misuse of aggregate function %.*s()", nId,zId); pNC->nErr++; is_agg = 0; | | | 72818 72819 72820 72821 72822 72823 72824 72825 72826 72827 72828 72829 72830 72831 72832 | } } #endif if( is_agg && (pNC->ncFlags & NC_AllowAgg)==0 ){ sqlite3ErrorMsg(pParse, "misuse of aggregate function %.*s()", nId,zId); pNC->nErr++; is_agg = 0; }else if( no_such_func ){ sqlite3ErrorMsg(pParse, "no such function: %.*s", nId, zId); pNC->nErr++; }else if( wrong_num_args ){ sqlite3ErrorMsg(pParse,"wrong number of arguments to function %.*s()", nId, zId); pNC->nErr++; } |
︙ | ︙ | |||
74755 74756 74757 74758 74759 74760 74761 | moreToDo = 0; pEList = pSelect->pEList; assert( pEList!=0 ); for(i=0, pItem=pOrderBy->a; i<pOrderBy->nExpr; i++, pItem++){ int iCol = -1; Expr *pE, *pDup; if( pItem->done ) continue; | | | | > | | > | | < < < < < < < < | 73037 73038 73039 73040 73041 73042 73043 73044 73045 73046 73047 73048 73049 73050 73051 73052 73053 73054 73055 73056 73057 73058 73059 73060 73061 73062 73063 73064 73065 73066 73067 73068 73069 73070 73071 73072 73073 73074 73075 73076 | moreToDo = 0; pEList = pSelect->pEList; assert( pEList!=0 ); for(i=0, pItem=pOrderBy->a; i<pOrderBy->nExpr; i++, pItem++){ int iCol = -1; Expr *pE, *pDup; if( pItem->done ) continue; pE = pItem->pExpr; if( sqlite3ExprIsInteger(pE, &iCol) ){ if( iCol<=0 || iCol>pEList->nExpr ){ resolveOutOfRangeError(pParse, "ORDER", i+1, pEList->nExpr); return 1; } }else{ iCol = resolveAsName(pParse, pEList, pE); if( iCol==0 ){ pDup = sqlite3ExprDup(db, pE, 0); if( !db->mallocFailed ){ assert(pDup); iCol = resolveOrderByTermToExprList(pParse, pSelect, pDup); } sqlite3ExprDelete(db, pDup); } } if( iCol>0 ){ CollSeq *pColl = pE->pColl; int flags = pE->flags & EP_ExpCollate; sqlite3ExprDelete(db, pE); pItem->pExpr = pE = sqlite3Expr(db, TK_INTEGER, 0); if( pE==0 ) return 1; pE->pColl = pColl; pE->flags |= EP_IntValue | flags; pE->u.iValue = iCol; pItem->iOrderByCol = (u16)iCol; pItem->done = 1; }else{ moreToDo = 1; } } pSelect = pSelect->pNext; |
︙ | ︙ | |||
74891 74892 74893 74894 74895 74896 74897 | /* If an AS-name match is found, mark this ORDER BY column as being ** a copy of the iCol-th result-set column. The subsequent call to ** sqlite3ResolveOrderGroupBy() will convert the expression to a ** copy of the iCol-th result-set expression. */ pItem->iOrderByCol = (u16)iCol; continue; } | | | | 73167 73168 73169 73170 73171 73172 73173 73174 73175 73176 73177 73178 73179 73180 73181 73182 73183 73184 73185 | /* If an AS-name match is found, mark this ORDER BY column as being ** a copy of the iCol-th result-set column. The subsequent call to ** sqlite3ResolveOrderGroupBy() will convert the expression to a ** copy of the iCol-th result-set expression. */ pItem->iOrderByCol = (u16)iCol; continue; } if( sqlite3ExprIsInteger(pE, &iCol) ){ /* The ORDER BY term is an integer constant. Again, set the column ** number so that sqlite3ResolveOrderGroupBy() will convert the ** order-by term to a copy of the result-set expression */ if( iCol<1 ){ resolveOutOfRangeError(pParse, zType, i+1, nResult); return 1; } pItem->iOrderByCol = (u16)iCol; continue; } |
︙ | ︙ | |||
74971 74972 74973 74974 74975 74976 74977 74978 74979 74980 74981 74982 74983 74984 | */ memset(&sNC, 0, sizeof(sNC)); sNC.pParse = pParse; if( sqlite3ResolveExprNames(&sNC, p->pLimit) || sqlite3ResolveExprNames(&sNC, p->pOffset) ){ return WRC_Abort; } /* Recursively resolve names in all subqueries */ for(i=0; i<p->pSrc->nSrc; i++){ struct SrcList_item *pItem = &p->pSrc->a[i]; if( pItem->pSelect ){ NameContext *pNC; /* Used to iterate name contexts */ | > > > > > > > > > > > > > > > > > | 73247 73248 73249 73250 73251 73252 73253 73254 73255 73256 73257 73258 73259 73260 73261 73262 73263 73264 73265 73266 73267 73268 73269 73270 73271 73272 73273 73274 73275 73276 73277 | */ memset(&sNC, 0, sizeof(sNC)); sNC.pParse = pParse; if( sqlite3ResolveExprNames(&sNC, p->pLimit) || sqlite3ResolveExprNames(&sNC, p->pOffset) ){ return WRC_Abort; } /* Set up the local name-context to pass to sqlite3ResolveExprNames() to ** resolve the result-set expression list. */ sNC.ncFlags = NC_AllowAgg; sNC.pSrcList = p->pSrc; sNC.pNext = pOuterNC; /* Resolve names in the result set. */ pEList = p->pEList; assert( pEList!=0 ); for(i=0; i<pEList->nExpr; i++){ Expr *pX = pEList->a[i].pExpr; if( sqlite3ResolveExprNames(&sNC, pX) ){ return WRC_Abort; } } /* Recursively resolve names in all subqueries */ for(i=0; i<p->pSrc->nSrc; i++){ struct SrcList_item *pItem = &p->pSrc->a[i]; if( pItem->pSelect ){ NameContext *pNC; /* Used to iterate name contexts */ |
︙ | ︙ | |||
74999 75000 75001 75002 75003 75004 75005 | for(pNC=pOuterNC; pNC; pNC=pNC->pNext) nRef -= pNC->nRef; assert( pItem->isCorrelated==0 && nRef<=0 ); pItem->isCorrelated = (nRef!=0); } } | < < < < < < < < < < < < < < < < < | 73292 73293 73294 73295 73296 73297 73298 73299 73300 73301 73302 73303 73304 73305 | for(pNC=pOuterNC; pNC; pNC=pNC->pNext) nRef -= pNC->nRef; assert( pItem->isCorrelated==0 && nRef<=0 ); pItem->isCorrelated = (nRef!=0); } } /* If there are no aggregate functions in the result-set, and no GROUP BY ** expression, do not allow aggregates in any of the other expressions. */ assert( (p->selFlags & SF_Aggregate)==0 ); pGroupBy = p->pGroupBy; if( pGroupBy || (sNC.ncFlags & NC_HasAgg)!=0 ){ p->selFlags |= SF_Aggregate; |
︙ | ︙ | |||
75043 75044 75045 75046 75047 75048 75049 | ** expressions in the WHERE clause (etc.) can refer to expressions by ** aliases in the result set. ** ** Minor point: If this is the case, then the expression will be ** re-evaluated for each reference to it. */ sNC.pEList = p->pEList; | < | | > | > | 73319 73320 73321 73322 73323 73324 73325 73326 73327 73328 73329 73330 73331 73332 73333 73334 73335 73336 73337 | ** expressions in the WHERE clause (etc.) can refer to expressions by ** aliases in the result set. ** ** Minor point: If this is the case, then the expression will be ** re-evaluated for each reference to it. */ sNC.pEList = p->pEList; if( sqlite3ResolveExprNames(&sNC, p->pWhere) || sqlite3ResolveExprNames(&sNC, p->pHaving) ){ return WRC_Abort; } /* The ORDER BY and GROUP BY clauses may not refer to terms in ** outer queries */ sNC.pNext = 0; sNC.ncFlags |= NC_AllowAgg; |
︙ | ︙ | |||
75167 75168 75169 75170 75171 75172 75173 | return 1; } pParse->nHeight += pExpr->nHeight; } #endif savedHasAgg = pNC->ncFlags & NC_HasAgg; pNC->ncFlags &= ~NC_HasAgg; | < | 73444 73445 73446 73447 73448 73449 73450 73451 73452 73453 73454 73455 73456 73457 | return 1; } pParse->nHeight += pExpr->nHeight; } #endif savedHasAgg = pNC->ncFlags & NC_HasAgg; pNC->ncFlags &= ~NC_HasAgg; w.xExprCallback = resolveExprStep; w.xSelectCallback = resolveSelectStep; w.pParse = pNC->pParse; w.u.pNC = pNC; sqlite3WalkExpr(&w, pExpr); #if SQLITE_MAX_EXPR_DEPTH>0 pNC->pParse->nHeight -= pExpr->nHeight; |
︙ | ︙ | |||
75208 75209 75210 75211 75212 75213 75214 | Parse *pParse, /* The parser context */ Select *p, /* The SELECT statement being coded. */ NameContext *pOuterNC /* Name context for parent SELECT statement */ ){ Walker w; assert( p!=0 ); | < | 73484 73485 73486 73487 73488 73489 73490 73491 73492 73493 73494 73495 73496 73497 | Parse *pParse, /* The parser context */ Select *p, /* The SELECT statement being coded. */ NameContext *pOuterNC /* Name context for parent SELECT statement */ ){ Walker w; assert( p!=0 ); w.xExprCallback = resolveExprStep; w.xSelectCallback = resolveSelectStep; w.pParse = pParse; w.u.pNC = pOuterNC; sqlite3WalkSelect(&w, p); } |
︙ | ︙ | |||
75250 75251 75252 75253 75254 75255 75256 | ** ** CREATE TABLE t1(a); ** SELECT * FROM t1 WHERE a; ** SELECT a AS b FROM t1 WHERE b; ** SELECT * FROM t1 WHERE (select a from t1); */ SQLITE_PRIVATE char sqlite3ExprAffinity(Expr *pExpr){ | < < | | 73525 73526 73527 73528 73529 73530 73531 73532 73533 73534 73535 73536 73537 73538 73539 | ** ** CREATE TABLE t1(a); ** SELECT * FROM t1 WHERE a; ** SELECT a AS b FROM t1 WHERE b; ** SELECT * FROM t1 WHERE (select a from t1); */ SQLITE_PRIVATE char sqlite3ExprAffinity(Expr *pExpr){ int op = pExpr->op; if( op==TK_SELECT ){ assert( pExpr->flags&EP_xIsSelect ); return sqlite3ExprAffinity(pExpr->x.pSelect->pEList->a[0].pExpr); } #ifndef SQLITE_OMIT_CAST if( op==TK_CAST ){ assert( !ExprHasProperty(pExpr, EP_IntValue) ); |
︙ | ︙ | |||
75277 75278 75279 75280 75281 75282 75283 | assert( pExpr->pTab && j<pExpr->pTab->nCol ); return pExpr->pTab->aCol[j].affinity; } return pExpr->affinity; } /* | | | < < < < | < < | | | < | < < < < < < < | < < > | > > > | < > > > > > | < > < < < < < | > | < | < | < | < < < < < | < > | | < | > > | > | < < < < < < > | 73550 73551 73552 73553 73554 73555 73556 73557 73558 73559 73560 73561 73562 73563 73564 73565 73566 73567 73568 73569 73570 73571 73572 73573 73574 73575 73576 73577 73578 73579 73580 73581 73582 73583 73584 73585 73586 73587 73588 73589 73590 73591 73592 73593 73594 73595 73596 73597 73598 73599 73600 73601 73602 73603 73604 73605 73606 73607 73608 73609 73610 73611 73612 73613 73614 73615 73616 73617 73618 73619 73620 73621 73622 73623 | assert( pExpr->pTab && j<pExpr->pTab->nCol ); return pExpr->pTab->aCol[j].affinity; } return pExpr->affinity; } /* ** Set the explicit collating sequence for an expression to the ** collating sequence supplied in the second argument. */ SQLITE_PRIVATE Expr *sqlite3ExprSetColl(Expr *pExpr, CollSeq *pColl){ if( pExpr && pColl ){ pExpr->pColl = pColl; pExpr->flags |= EP_ExpCollate; } return pExpr; } /* ** Set the collating sequence for expression pExpr to be the collating ** sequence named by pToken. Return a pointer to the revised expression. ** The collating sequence is marked as "explicit" using the EP_ExpCollate ** flag. An explicit collating sequence will override implicit ** collating sequences. */ SQLITE_PRIVATE Expr *sqlite3ExprSetCollByToken(Parse *pParse, Expr *pExpr, Token *pCollName){ char *zColl = 0; /* Dequoted name of collation sequence */ CollSeq *pColl; sqlite3 *db = pParse->db; zColl = sqlite3NameFromToken(db, pCollName); pColl = sqlite3LocateCollSeq(pParse, zColl); sqlite3ExprSetColl(pExpr, pColl); sqlite3DbFree(db, zColl); return pExpr; } /* ** Return the default collation sequence for the expression pExpr. If ** there is no default collation type, return 0. */ SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){ CollSeq *pColl = 0; Expr *p = pExpr; while( p ){ int op; pColl = p->pColl; if( pColl ) break; op = p->op; if( p->pTab!=0 && ( op==TK_AGG_COLUMN || op==TK_COLUMN || op==TK_REGISTER || op==TK_TRIGGER )){ /* op==TK_REGISTER && p->pTab!=0 happens when pExpr was originally ** a TK_COLUMN but was previously evaluated and cached in a register */ const char *zColl; int j = p->iColumn; if( j>=0 ){ sqlite3 *db = pParse->db; zColl = p->pTab->aCol[j].zColl; pColl = sqlite3FindCollSeq(db, ENC(db), zColl, 0); pExpr->pColl = pColl; } break; } if( op!=TK_CAST && op!=TK_UPLUS ){ break; } p = p->pLeft; } if( sqlite3CheckCollSeq(pParse, pColl) ){ pColl = 0; } return pColl; } |
︙ | ︙ | |||
75463 75464 75465 75466 75467 75468 75469 | SQLITE_PRIVATE CollSeq *sqlite3BinaryCompareCollSeq( Parse *pParse, Expr *pLeft, Expr *pRight ){ CollSeq *pColl; assert( pLeft ); | | > | | > | | 73713 73714 73715 73716 73717 73718 73719 73720 73721 73722 73723 73724 73725 73726 73727 73728 73729 73730 73731 73732 | SQLITE_PRIVATE CollSeq *sqlite3BinaryCompareCollSeq( Parse *pParse, Expr *pLeft, Expr *pRight ){ CollSeq *pColl; assert( pLeft ); if( pLeft->flags & EP_ExpCollate ){ assert( pLeft->pColl ); pColl = pLeft->pColl; }else if( pRight && pRight->flags & EP_ExpCollate ){ assert( pRight->pColl ); pColl = pRight->pColl; }else{ pColl = sqlite3ExprCollSeq(pParse, pLeft); if( !pColl ){ pColl = sqlite3ExprCollSeq(pParse, pRight); } } return pColl; |
︙ | ︙ | |||
75696 75697 75698 75699 75700 75701 75702 | if( pRoot==0 ){ assert( db->mallocFailed ); sqlite3ExprDelete(db, pLeft); sqlite3ExprDelete(db, pRight); }else{ if( pRight ){ pRoot->pRight = pRight; | > | > > > | > > | 73948 73949 73950 73951 73952 73953 73954 73955 73956 73957 73958 73959 73960 73961 73962 73963 73964 73965 73966 73967 73968 73969 73970 73971 73972 | if( pRoot==0 ){ assert( db->mallocFailed ); sqlite3ExprDelete(db, pLeft); sqlite3ExprDelete(db, pRight); }else{ if( pRight ){ pRoot->pRight = pRight; if( pRight->flags & EP_ExpCollate ){ pRoot->flags |= EP_ExpCollate; pRoot->pColl = pRight->pColl; } } if( pLeft ){ pRoot->pLeft = pLeft; if( pLeft->flags & EP_ExpCollate ){ pRoot->flags |= EP_ExpCollate; pRoot->pColl = pLeft->pColl; } } exprSetHeight(pRoot); } } /* ** Allocate a Expr node which joins as many as two subtrees. |
︙ | ︙ | |||
75852 75853 75854 75855 75856 75857 75858 | }else{ /* Wildcards like ":aaa", "$aaa" or "@aaa". Reuse the same variable ** number as the prior appearance of the same name, or if the name ** has never appeared before, reuse the same variable number */ ynVar i; for(i=0; i<pParse->nzVar; i++){ | | | 74110 74111 74112 74113 74114 74115 74116 74117 74118 74119 74120 74121 74122 74123 74124 | }else{ /* Wildcards like ":aaa", "$aaa" or "@aaa". Reuse the same variable ** number as the prior appearance of the same name, or if the name ** has never appeared before, reuse the same variable number */ ynVar i; for(i=0; i<pParse->nzVar; i++){ if( pParse->azVar[i] && memcmp(pParse->azVar[i],z,n+1)==0 ){ pExpr->iColumn = x = (ynVar)i+1; break; } } if( x==0 ) x = pExpr->iColumn = (ynVar)(++pParse->nVar); } if( x>0 ){ |
︙ | ︙ | |||
75958 75959 75960 75961 75962 75963 75964 | if( 0==(flags&EXPRDUP_REDUCE) ){ nSize = EXPR_FULLSIZE; }else{ assert( !ExprHasAnyProperty(p, EP_TokenOnly|EP_Reduced) ); assert( !ExprHasProperty(p, EP_FromJoin) ); assert( (p->flags2 & EP2_MallocedToken)==0 ); assert( (p->flags2 & EP2_Irreducible)==0 ); | | | 74216 74217 74218 74219 74220 74221 74222 74223 74224 74225 74226 74227 74228 74229 74230 | if( 0==(flags&EXPRDUP_REDUCE) ){ nSize = EXPR_FULLSIZE; }else{ assert( !ExprHasAnyProperty(p, EP_TokenOnly|EP_Reduced) ); assert( !ExprHasProperty(p, EP_FromJoin) ); assert( (p->flags2 & EP2_MallocedToken)==0 ); assert( (p->flags2 & EP2_Irreducible)==0 ); if( p->pLeft || p->pRight || p->pColl || p->x.pList ){ nSize = EXPR_REDUCEDSIZE | EP_Reduced; }else{ nSize = EXPR_TOKENONLYSIZE | EP_TokenOnly; } } return nSize; } |
︙ | ︙ | |||
76175 76176 76177 76178 76179 76180 76181 | 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; | < | 74433 74434 74435 74436 74437 74438 74439 74440 74441 74442 74443 74444 74445 74446 | pNewItem->zName = sqlite3DbStrDup(db, pOldItem->zName); pNewItem->zAlias = sqlite3DbStrDup(db, pOldItem->zAlias); pNewItem->jointype = pOldItem->jointype; pNewItem->iCursor = pOldItem->iCursor; pNewItem->addrFillSub = pOldItem->addrFillSub; pNewItem->regReturn = pOldItem->regReturn; pNewItem->isCorrelated = pOldItem->isCorrelated; pNewItem->zIndex = sqlite3DbStrDup(db, pOldItem->zIndex); pNewItem->notIndexed = pOldItem->notIndexed; pNewItem->pIndex = pOldItem->pIndex; pTab = pNewItem->pTab = pOldItem->pTab; if( pTab ){ pTab->nRef++; } |
︙ | ︙ | |||
76428 76429 76430 76431 76432 76433 76434 | static int selectNodeIsConstant(Walker *pWalker, Select *NotUsed){ UNUSED_PARAMETER(NotUsed); pWalker->u.i = 0; return WRC_Abort; } static int exprIsConst(Expr *p, int initFlag){ Walker w; | < | 74685 74686 74687 74688 74689 74690 74691 74692 74693 74694 74695 74696 74697 74698 | static int selectNodeIsConstant(Walker *pWalker, Select *NotUsed){ UNUSED_PARAMETER(NotUsed); pWalker->u.i = 0; return WRC_Abort; } static int exprIsConst(Expr *p, int initFlag){ Walker w; w.u.i = initFlag; w.xExprCallback = exprNodeIsConstant; w.xSelectCallback = selectNodeIsConstant; sqlite3WalkExpr(&w, p); return w.u.i; } |
︙ | ︙ | |||
76671 76672 76673 76674 76675 76676 76677 | ** all members of the RHS set, skipping duplicates. ** ** A cursor is opened on the b-tree object that the RHS of the IN operator ** and pX->iTable is set to the index of that cursor. ** ** The returned value of this function indicates the b-tree type, as follows: ** | | < | | | | 74927 74928 74929 74930 74931 74932 74933 74934 74935 74936 74937 74938 74939 74940 74941 74942 74943 74944 | ** all members of the RHS set, skipping duplicates. ** ** A cursor is opened on the b-tree object that the RHS of the IN operator ** and pX->iTable is set to the index of that cursor. ** ** The returned value of this function indicates the b-tree type, as follows: ** ** IN_INDEX_ROWID - The cursor was opened on a database table. ** IN_INDEX_INDEX - The cursor was opened on a database index. ** IN_INDEX_EPH - The cursor was opened on a specially created and ** populated epheremal table. ** ** An existing b-tree might be used if the RHS expression pX is a simple ** subquery such as: ** ** SELECT <column> FROM <table> ** ** If the RHS of the IN operator is a list or a more complex subquery, then |
︙ | ︙ | |||
76798 76799 76800 76801 76802 76803 76804 | pKey = (char *)sqlite3IndexKeyinfo(pParse, pIdx); iAddr = sqlite3CodeOnce(pParse); sqlite3VdbeAddOp4(v, OP_OpenRead, iTab, pIdx->tnum, iDb, pKey,P4_KEYINFO_HANDOFF); VdbeComment((v, "%s", pIdx->zName)); | < | | 75053 75054 75055 75056 75057 75058 75059 75060 75061 75062 75063 75064 75065 75066 75067 | pKey = (char *)sqlite3IndexKeyinfo(pParse, pIdx); iAddr = sqlite3CodeOnce(pParse); sqlite3VdbeAddOp4(v, OP_OpenRead, iTab, pIdx->tnum, iDb, pKey,P4_KEYINFO_HANDOFF); VdbeComment((v, "%s", pIdx->zName)); eType = IN_INDEX_INDEX; sqlite3VdbeJumpHere(v, iAddr); if( prNotFound && !pTab->aCol[iCol].notNull ){ *prNotFound = ++pParse->nMem; sqlite3VdbeAddOp2(v, OP_Null, 0, *prNotFound); } } |
︙ | ︙ | |||
77985 77986 77987 77988 77989 77990 77991 | testcase( regFree2==0 ); codeCompare(pParse, pLeft, pRight, OP_Le, r1, r2, r4, SQLITE_STOREP2); sqlite3VdbeAddOp3(v, OP_And, r3, r4, target); sqlite3ReleaseTempReg(pParse, r3); sqlite3ReleaseTempReg(pParse, r4); break; } | < | 76239 76240 76241 76242 76243 76244 76245 76246 76247 76248 76249 76250 76251 76252 | testcase( regFree2==0 ); codeCompare(pParse, pLeft, pRight, OP_Le, r1, r2, r4, SQLITE_STOREP2); sqlite3VdbeAddOp3(v, OP_And, r3, r4, target); sqlite3ReleaseTempReg(pParse, r3); sqlite3ReleaseTempReg(pParse, r4); break; } case TK_UPLUS: { inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target); break; } case TK_TRIGGER: { /* If the opcode is TK_TRIGGER, then the expression is a reference |
︙ | ︙ | |||
78152 78153 78154 78155 78156 78157 78158 | sqlite3MayAbort(pParse); } assert( !ExprHasProperty(pExpr, EP_IntValue) ); if( pExpr->affinity==OE_Ignore ){ sqlite3VdbeAddOp4( v, OP_Halt, SQLITE_OK, OE_Ignore, 0, pExpr->u.zToken,0); }else{ | | < | 76405 76406 76407 76408 76409 76410 76411 76412 76413 76414 76415 76416 76417 76418 76419 | sqlite3MayAbort(pParse); } assert( !ExprHasProperty(pExpr, EP_IntValue) ); if( pExpr->affinity==OE_Ignore ){ sqlite3VdbeAddOp4( v, OP_Halt, SQLITE_OK, OE_Ignore, 0, pExpr->u.zToken,0); }else{ sqlite3HaltConstraint(pParse, pExpr->affinity, pExpr->u.zToken, 0); } break; } #endif } sqlite3ReleaseTempReg(pParse, regFree1); |
︙ | ︙ | |||
78356 78357 78358 78359 78360 78361 78362 | case TK_UMINUS: zUniOp = "UMINUS"; break; case TK_UPLUS: zUniOp = "UPLUS"; break; case TK_BITNOT: zUniOp = "BITNOT"; break; case TK_NOT: zUniOp = "NOT"; break; case TK_ISNULL: zUniOp = "ISNULL"; break; case TK_NOTNULL: zUniOp = "NOTNULL"; break; | < < < < < < | 76608 76609 76610 76611 76612 76613 76614 76615 76616 76617 76618 76619 76620 76621 | case TK_UMINUS: zUniOp = "UMINUS"; break; case TK_UPLUS: zUniOp = "UPLUS"; break; case TK_BITNOT: zUniOp = "BITNOT"; break; case TK_NOT: zUniOp = "NOT"; break; case TK_ISNULL: zUniOp = "ISNULL"; break; case TK_NOTNULL: zUniOp = "NOTNULL"; break; case TK_AGG_FUNCTION: case TK_CONST_FUNC: case TK_FUNCTION: { ExprList *pFarg; /* List of function arguments */ if( ExprHasAnyProperty(pExpr, EP_TokenOnly) ){ pFarg = 0; }else{ |
︙ | ︙ | |||
78499 78500 78501 78502 78503 78504 78505 | }else{ sqlite3ExplainPush(pOut); for(i=0; i<pList->nExpr; i++){ sqlite3ExplainPrintf(pOut, "item[%d] = ", i); sqlite3ExplainPush(pOut); sqlite3ExplainExpr(pOut, pList->a[i].pExpr); sqlite3ExplainPop(pOut); | < < < < < < | 76745 76746 76747 76748 76749 76750 76751 76752 76753 76754 76755 76756 76757 76758 | }else{ sqlite3ExplainPush(pOut); for(i=0; i<pList->nExpr; i++){ sqlite3ExplainPrintf(pOut, "item[%d] = ", i); sqlite3ExplainPush(pOut); sqlite3ExplainExpr(pOut, pList->a[i].pExpr); sqlite3ExplainPop(pOut); if( i<pList->nExpr-1 ){ sqlite3ExplainNL(pOut); } } sqlite3ExplainPop(pOut); } } |
︙ | ︙ | |||
78586 78587 78588 78589 78590 78591 78592 | static int evalConstExpr(Walker *pWalker, Expr *pExpr){ Parse *pParse = pWalker->pParse; switch( pExpr->op ){ case TK_IN: case TK_REGISTER: { return WRC_Prune; } | < < < | 76826 76827 76828 76829 76830 76831 76832 76833 76834 76835 76836 76837 76838 76839 | static int evalConstExpr(Walker *pWalker, Expr *pExpr){ Parse *pParse = pWalker->pParse; switch( pExpr->op ){ case TK_IN: case TK_REGISTER: { return WRC_Prune; } case TK_FUNCTION: case TK_AGG_FUNCTION: case TK_CONST_FUNC: { /* The arguments to a function have a fixed destination. ** Mark them this way to avoid generated unneeded OP_SCopy ** instructions. */ |
︙ | ︙ | |||
78610 78611 78612 78613 78614 78615 78616 | } } break; } } if( isAppropriateForFactoring(pExpr) ){ int r1 = ++pParse->nMem; | > | < | < < | 76847 76848 76849 76850 76851 76852 76853 76854 76855 76856 76857 76858 76859 76860 76861 76862 76863 | } } break; } } if( isAppropriateForFactoring(pExpr) ){ int r1 = ++pParse->nMem; int r2; r2 = sqlite3ExprCodeTarget(pParse, pExpr, r1); if( NEVER(r1!=r2) ) sqlite3ReleaseTempReg(pParse, r1); pExpr->op2 = pExpr->op; pExpr->op = TK_REGISTER; pExpr->iTable = r2; return WRC_Prune; } return WRC_Continue; } |
︙ | ︙ | |||
78643 78644 78645 78646 78647 78648 78649 | ** obtained for queries regardless of whether or not constants are ** precomputed into registers or if they are inserted in-line. */ SQLITE_PRIVATE void sqlite3ExprCodeConstants(Parse *pParse, Expr *pExpr){ Walker w; if( pParse->cookieGoto ) return; if( OptimizationDisabled(pParse->db, SQLITE_FactorOutConst) ) return; | < > | 76878 76879 76880 76881 76882 76883 76884 76885 76886 76887 76888 76889 76890 76891 76892 76893 | ** obtained for queries regardless of whether or not constants are ** precomputed into registers or if they are inserted in-line. */ SQLITE_PRIVATE void sqlite3ExprCodeConstants(Parse *pParse, Expr *pExpr){ Walker w; if( pParse->cookieGoto ) return; if( OptimizationDisabled(pParse->db, SQLITE_FactorOutConst) ) return; w.xExprCallback = evalConstExpr; w.xSelectCallback = 0; w.pParse = pParse; sqlite3WalkExpr(&w, pExpr); } /* ** Generate code that pushes the value of every element of the given |
︙ | ︙ | |||
78757 78758 78759 78760 78761 78762 78763 | Vdbe *v = pParse->pVdbe; int op = 0; int regFree1 = 0; int regFree2 = 0; int r1, r2; assert( jumpIfNull==SQLITE_JUMPIFNULL || jumpIfNull==0 ); | | | 76992 76993 76994 76995 76996 76997 76998 76999 77000 77001 77002 77003 77004 77005 77006 | Vdbe *v = pParse->pVdbe; int op = 0; int regFree1 = 0; int regFree2 = 0; int r1, r2; assert( jumpIfNull==SQLITE_JUMPIFNULL || jumpIfNull==0 ); if( NEVER(v==0) ) return; /* Existance of VDBE checked by caller */ if( NEVER(pExpr==0) ) return; /* No way this can happen */ op = pExpr->op; switch( op ){ case TK_AND: { int d2 = sqlite3VdbeMakeLabel(v); testcase( jumpIfNull==0 ); sqlite3ExprCachePush(pParse); |
︙ | ︙ | |||
78877 78878 78879 78880 78881 78882 78883 | Vdbe *v = pParse->pVdbe; int op = 0; int regFree1 = 0; int regFree2 = 0; int r1, r2; assert( jumpIfNull==SQLITE_JUMPIFNULL || jumpIfNull==0 ); | | | 77112 77113 77114 77115 77116 77117 77118 77119 77120 77121 77122 77123 77124 77125 77126 | Vdbe *v = pParse->pVdbe; int op = 0; int regFree1 = 0; int regFree2 = 0; int r1, r2; assert( jumpIfNull==SQLITE_JUMPIFNULL || jumpIfNull==0 ); if( NEVER(v==0) ) return; /* Existance of VDBE checked by caller */ if( pExpr==0 ) return; /* The value of pExpr->op and op are related as follows: ** ** pExpr->op op ** --------- ---------- ** TK_ISNULL OP_NotNull |
︙ | ︙ | |||
79031 79032 79033 79034 79035 79036 79037 | } assert( !ExprHasAnyProperty(pA, EP_TokenOnly|EP_Reduced) ); assert( !ExprHasAnyProperty(pB, EP_TokenOnly|EP_Reduced) ); if( ExprHasProperty(pA, EP_xIsSelect) || ExprHasProperty(pB, EP_xIsSelect) ){ return 2; } if( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) return 2; | | < < < < < < < < | > > | 77266 77267 77268 77269 77270 77271 77272 77273 77274 77275 77276 77277 77278 77279 77280 77281 77282 77283 77284 77285 77286 77287 77288 77289 77290 77291 77292 77293 77294 77295 77296 | } assert( !ExprHasAnyProperty(pA, EP_TokenOnly|EP_Reduced) ); assert( !ExprHasAnyProperty(pB, EP_TokenOnly|EP_Reduced) ); if( ExprHasProperty(pA, EP_xIsSelect) || ExprHasProperty(pB, EP_xIsSelect) ){ return 2; } if( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) return 2; if( pA->op!=pB->op ) return 2; if( sqlite3ExprCompare(pA->pLeft, pB->pLeft) ) return 2; if( sqlite3ExprCompare(pA->pRight, pB->pRight) ) return 2; if( sqlite3ExprListCompare(pA->x.pList, pB->x.pList) ) return 2; if( pA->iTable!=pB->iTable || pA->iColumn!=pB->iColumn ) return 2; if( ExprHasProperty(pA, EP_IntValue) ){ if( !ExprHasProperty(pB, EP_IntValue) || pA->u.iValue!=pB->u.iValue ){ return 2; } }else if( pA->op!=TK_COLUMN && ALWAYS(pA->op!=TK_AGG_COLUMN) && pA->u.zToken){ if( ExprHasProperty(pB, EP_IntValue) || NEVER(pB->u.zToken==0) ) return 2; if( strcmp(pA->u.zToken,pB->u.zToken)!=0 ){ return 2; } } if( (pA->flags & EP_ExpCollate)!=(pB->flags & EP_ExpCollate) ) return 1; if( (pA->flags & EP_ExpCollate)!=0 && pA->pColl!=pB->pColl ) return 2; return 0; } /* ** Compare two ExprList objects. Return 0 if they are identical and ** non-zero if they differ in any way. ** |
︙ | ︙ | |||
79294 79295 79296 79297 79298 79299 79300 | } /* Make pExpr point to the appropriate pAggInfo->aFunc[] entry */ assert( !ExprHasAnyProperty(pExpr, EP_TokenOnly|EP_Reduced) ); ExprSetIrreducible(pExpr); pExpr->iAgg = (i16)i; pExpr->pAggInfo = pAggInfo; | < < < > | | | < | 77523 77524 77525 77526 77527 77528 77529 77530 77531 77532 77533 77534 77535 77536 77537 77538 77539 77540 77541 77542 77543 77544 77545 77546 77547 77548 77549 77550 77551 77552 | } /* Make pExpr point to the appropriate pAggInfo->aFunc[] entry */ assert( !ExprHasAnyProperty(pExpr, EP_TokenOnly|EP_Reduced) ); ExprSetIrreducible(pExpr); pExpr->iAgg = (i16)i; pExpr->pAggInfo = pAggInfo; } return WRC_Prune; } } return WRC_Continue; } static int analyzeAggregatesInSelect(Walker *pWalker, Select *pSelect){ UNUSED_PARAMETER(pWalker); UNUSED_PARAMETER(pSelect); return WRC_Continue; } /* ** Analyze the given expression looking for aggregate functions and ** for variables that need to be added to the pParse->aAgg[] array. ** Make additional entries to the pParse->aAgg[] array as necessary. ** ** This routine should only be called after the expression has been ** analyzed by sqlite3ResolveExprNames(). */ SQLITE_PRIVATE void sqlite3ExprAnalyzeAggregates(NameContext *pNC, Expr *pExpr){ Walker w; memset(&w, 0, sizeof(w)); |
︙ | ︙ | |||
80712 80713 80714 80715 80716 80717 80718 | if( v==0 || NEVER(pTab==0) ){ return; } if( pTab->tnum==0 ){ /* Do not gather statistics on views or virtual tables */ return; } | | | 78938 78939 78940 78941 78942 78943 78944 78945 78946 78947 78948 78949 78950 78951 78952 | if( v==0 || NEVER(pTab==0) ){ return; } if( pTab->tnum==0 ){ /* Do not gather statistics on views or virtual tables */ return; } if( memcmp(pTab->zName, "sqlite_", 7)==0 ){ /* Do not gather statistics on system tables */ return; } assert( sqlite3BtreeHoldsAllMutexes(db) ); iDb = sqlite3SchemaToIndex(db, pTab->pSchema); assert( iDb>=0 ); assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); |
︙ | ︙ | |||
81122 81123 81124 81125 81126 81127 81128 | v = v*10 + c - '0'; z++; } if( i==0 ) pTable->nRowEst = v; if( pIndex==0 ) break; pIndex->aiRowEst[i] = v; if( *z==' ' ) z++; | | | 79348 79349 79350 79351 79352 79353 79354 79355 79356 79357 79358 79359 79360 79361 79362 | v = v*10 + c - '0'; z++; } if( i==0 ) pTable->nRowEst = v; if( pIndex==0 ) break; pIndex->aiRowEst[i] = v; if( *z==' ' ) z++; if( memcmp(z, "unordered", 10)==0 ){ pIndex->bUnordered = 1; break; } } return 0; } |
︙ | ︙ | |||
81474 81475 81476 81477 81478 81479 81480 | assert( z && zName ); if( sqlite3StrICmp(z, zName)==0 ){ zErrDyn = sqlite3MPrintf(db, "database %s is already in use", zName); goto attach_error; } } | | | | 79700 79701 79702 79703 79704 79705 79706 79707 79708 79709 79710 79711 79712 79713 79714 79715 79716 79717 79718 79719 79720 79721 79722 79723 79724 79725 79726 79727 79728 79729 79730 79731 | assert( z && zName ); if( sqlite3StrICmp(z, zName)==0 ){ zErrDyn = sqlite3MPrintf(db, "database %s is already in use", zName); goto attach_error; } } /* Allocate the new entry in the db->aDb[] array and initialise the schema ** hash tables. */ if( db->aDb==db->aDbStatic ){ aNew = sqlite3DbMallocRaw(db, sizeof(db->aDb[0])*3 ); if( aNew==0 ) return; memcpy(aNew, db->aDb, sizeof(db->aDb[0])*2); }else{ aNew = sqlite3DbRealloc(db, db->aDb, sizeof(db->aDb[0])*(db->nDb+1) ); if( aNew==0 ) return; } db->aDb = aNew; aNew = &db->aDb[db->nDb]; memset(aNew, 0, sizeof(*aNew)); /* Open the database file. If the btree is successfully opened, use ** it to obtain the database schema. At this point the schema may ** or may not be initialised. */ flags = db->openFlags; rc = sqlite3ParseUri(db->pVfs->zName, zFile, &flags, &pVfs, &zPath, &zErr); if( rc!=SQLITE_OK ){ if( rc==SQLITE_NOMEM ) db->mallocFailed = 1; sqlite3_result_error(context, zErr, -1); sqlite3_free(zErr); |
︙ | ︙ | |||
81836 81837 81838 81839 81840 81841 81842 | for(i=0, pItem=pList->a; i<pList->nSrc; i++, pItem++){ if( pItem->zDatabase && sqlite3StrICmp(pItem->zDatabase, zDb) ){ sqlite3ErrorMsg(pFix->pParse, "%s %T cannot reference objects in database %s", pFix->zType, pFix->pName, pItem->zDatabase); return 1; } | | | 80062 80063 80064 80065 80066 80067 80068 80069 80070 80071 80072 80073 80074 80075 80076 | for(i=0, pItem=pList->a; i<pList->nSrc; i++, pItem++){ if( pItem->zDatabase && sqlite3StrICmp(pItem->zDatabase, zDb) ){ sqlite3ErrorMsg(pFix->pParse, "%s %T cannot reference objects in database %s", pFix->zType, pFix->pName, pItem->zDatabase); return 1; } sqlite3_free(pItem->zDatabase); pItem->zDatabase = 0; pItem->pSchema = pFix->pSchema; #if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER) if( sqlite3FixSelect(pFix, pItem->pSelect) ) return 1; if( sqlite3FixExpr(pFix, pItem->pOn) ) return 1; #endif } |
︙ | ︙ | |||
82304 82305 82306 82307 82308 82309 82310 | ** Note that if an error occurred, it might be the case that ** no VDBE code was generated. */ SQLITE_PRIVATE void sqlite3FinishCoding(Parse *pParse){ sqlite3 *db; Vdbe *v; | < | 80530 80531 80532 80533 80534 80535 80536 80537 80538 80539 80540 80541 80542 80543 | ** Note that if an error occurred, it might be the case that ** no VDBE code was generated. */ SQLITE_PRIVATE void sqlite3FinishCoding(Parse *pParse){ sqlite3 *db; Vdbe *v; db = pParse->db; if( db->mallocFailed ) return; if( pParse->nested ) return; if( pParse->nErr ) return; /* Begin by generating some termination code at the end of the ** vdbe program |
︙ | ︙ | |||
84277 84278 84279 84280 84281 84282 84283 | ); } #endif /* Drop all SQLITE_MASTER table and index entries that refer to the ** table. The program name loops through the master table and deletes ** every row that refers to a table of the same name as the one being | | | 82502 82503 82504 82505 82506 82507 82508 82509 82510 82511 82512 82513 82514 82515 82516 | ); } #endif /* Drop all SQLITE_MASTER table and index entries that refer to the ** table. The program name loops through the master table and deletes ** every row that refers to a table of the same name as the one being ** 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); if( !isView && !IsVirtual(pTab) ){ |
︙ | ︙ | |||
84569 84570 84571 84572 84573 84574 84575 84576 84577 84578 84579 84580 84581 84582 | int iIdx = pParse->nTab++; /* Btree cursor used for pIndex */ int iSorter; /* 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 regRecord; /* Register holding assemblied index record */ sqlite3 *db = pParse->db; /* The database connection */ int iDb = sqlite3SchemaToIndex(db, pIndex->pSchema); #ifndef SQLITE_OMIT_AUTHORIZATION if( sqlite3AuthCheck(pParse, SQLITE_REINDEX, pIndex->zName, 0, db->aDb[iDb].zName ) ){ | > > > | 82794 82795 82796 82797 82798 82799 82800 82801 82802 82803 82804 82805 82806 82807 82808 82809 82810 | int iIdx = pParse->nTab++; /* Btree cursor used for pIndex */ int iSorter; /* 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 */ #ifdef SQLITE_OMIT_MERGE_SORT int regIdxKey; /* Registers containing the index key */ #endif int regRecord; /* Register holding assemblied index record */ sqlite3 *db = pParse->db; /* The database connection */ int iDb = sqlite3SchemaToIndex(db, pIndex->pSchema); #ifndef SQLITE_OMIT_AUTHORIZATION if( sqlite3AuthCheck(pParse, SQLITE_REINDEX, pIndex->zName, 0, db->aDb[iDb].zName ) ){ |
︙ | ︙ | |||
84596 84597 84598 84599 84600 84601 84602 84603 84604 84605 84606 84607 84608 84609 84610 84611 84612 84613 84614 84615 84616 84617 84618 84619 84620 84621 84622 | sqlite3VdbeAddOp2(v, OP_Clear, tnum, iDb); } pKey = sqlite3IndexKeyinfo(pParse, pIndex); sqlite3VdbeAddOp4(v, OP_OpenWrite, iIdx, tnum, iDb, (char *)pKey, P4_KEYINFO_HANDOFF); sqlite3VdbeChangeP5(v, OPFLAG_BULKCSR|((memRootPage>=0)?OPFLAG_P2ISREG:0)); /* Open the sorter cursor if we are to use one. */ iSorter = pParse->nTab++; sqlite3VdbeAddOp4(v, OP_SorterOpen, iSorter, 0, 0, (char*)pKey, P4_KEYINFO); /* 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); regRecord = sqlite3GetTempReg(pParse); sqlite3GenerateIndexKey(pParse, pIndex, iTab, regRecord, 1); 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); | > > > > > | | > > > > > > > > > > > > > > > > > > > > > > > > | 82824 82825 82826 82827 82828 82829 82830 82831 82832 82833 82834 82835 82836 82837 82838 82839 82840 82841 82842 82843 82844 82845 82846 82847 82848 82849 82850 82851 82852 82853 82854 82855 82856 82857 82858 82859 82860 82861 82862 82863 82864 82865 82866 82867 82868 82869 82870 82871 82872 82873 82874 82875 82876 82877 82878 82879 82880 82881 82882 82883 82884 82885 82886 82887 82888 82889 82890 82891 82892 82893 82894 82895 | sqlite3VdbeAddOp2(v, OP_Clear, tnum, iDb); } pKey = sqlite3IndexKeyinfo(pParse, pIndex); sqlite3VdbeAddOp4(v, OP_OpenWrite, iIdx, tnum, iDb, (char *)pKey, P4_KEYINFO_HANDOFF); sqlite3VdbeChangeP5(v, OPFLAG_BULKCSR|((memRootPage>=0)?OPFLAG_P2ISREG:0)); #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); #else iSorter = iTab; #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); regRecord = sqlite3GetTempReg(pParse); #ifndef SQLITE_OMIT_MERGE_SORT sqlite3GenerateIndexKey(pParse, pIndex, iTab, regRecord, 1); 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 regIdxKey = sqlite3GenerateIndexKey(pParse, pIndex, iTab, regRecord, 1); addr2 = addr1 + 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); } 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); |
︙ | ︙ | |||
84739 84740 84741 84742 84743 84744 84745 | iDb = sqlite3SchemaToIndex(db, pTab->pSchema); } pDb = &db->aDb[iDb]; assert( pTab!=0 ); assert( pParse->nErr==0 ); if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0 | | | 82996 82997 82998 82999 83000 83001 83002 83003 83004 83005 83006 83007 83008 83009 83010 | iDb = sqlite3SchemaToIndex(db, pTab->pSchema); } pDb = &db->aDb[iDb]; assert( pTab!=0 ); assert( pParse->nErr==0 ); if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0 && memcmp(&pTab->zName[7],"altertab_",9)!=0 ){ sqlite3ErrorMsg(pParse, "table %s may not be indexed", pTab->zName); goto exit_create_index; } #ifndef SQLITE_OMIT_VIEW if( pTab->pSelect ){ sqlite3ErrorMsg(pParse, "views may not be indexed"); goto exit_create_index; |
︙ | ︙ | |||
84836 84837 84838 84839 84840 84841 84842 | /* Figure out how many bytes of space are required to store explicitly ** specified collation sequence names. */ for(i=0; i<pList->nExpr; i++){ Expr *pExpr = pList->a[i].pExpr; if( pExpr ){ | | > > > | > | 83093 83094 83095 83096 83097 83098 83099 83100 83101 83102 83103 83104 83105 83106 83107 83108 83109 83110 83111 83112 | /* Figure out how many bytes of space are required to store explicitly ** specified collation sequence names. */ for(i=0; i<pList->nExpr; i++){ Expr *pExpr = pList->a[i].pExpr; if( pExpr ){ CollSeq *pColl = pExpr->pColl; /* Either pColl!=0 or there was an OOM failure. But if an OOM ** failure we have quit before reaching this point. */ if( ALWAYS(pColl) ){ nExtra += (1 + sqlite3Strlen30(pColl->zName)); } } } /* ** Allocate the index structure. */ nName = sqlite3Strlen30(zName); |
︙ | ︙ | |||
84910 84911 84912 84913 84914 84915 84916 | if( j>=pTab->nCol ){ sqlite3ErrorMsg(pParse, "table %s has no column named %s", pTab->zName, zColName); pParse->checkSchema = 1; goto exit_create_index; } pIndex->aiColumn[i] = j; | > > > > > | < | | > > | 83171 83172 83173 83174 83175 83176 83177 83178 83179 83180 83181 83182 83183 83184 83185 83186 83187 83188 83189 83190 83191 83192 83193 83194 83195 83196 83197 83198 83199 83200 83201 83202 83203 | if( j>=pTab->nCol ){ sqlite3ErrorMsg(pParse, "table %s has no column named %s", pTab->zName, zColName); pParse->checkSchema = 1; goto exit_create_index; } pIndex->aiColumn[i] = j; /* Justification of the ALWAYS(pListItem->pExpr->pColl): Because of ** the way the "idxlist" non-terminal is constructed by the parser, ** if pListItem->pExpr is not null then either pListItem->pExpr->pColl ** must exist or else there must have been an OOM error. But if there ** was an OOM error, we would never reach this point. */ if( pListItem->pExpr && ALWAYS(pListItem->pExpr->pColl) ){ int nColl; zColl = pListItem->pExpr->pColl->zName; nColl = sqlite3Strlen30(zColl) + 1; assert( nExtra>=nColl ); memcpy(zExtra, zColl, nColl); zColl = zExtra; zExtra += nColl; nExtra -= nColl; }else{ zColl = pTab->aCol[j].zColl; if( !zColl ){ zColl = "BINARY"; } } if( !db->init.busy && !sqlite3LocateCollSeq(pParse, zColl) ){ goto exit_create_index; } pIndex->azColl[i] = zColl; requestedSortOrder = pListItem->sortOrder & sortOrderMask; pIndex->aSortOrder[i] = (u8)requestedSortOrder; |
︙ | ︙ | |||
84978 84979 84980 84981 84982 84983 84984 | if( k==pIdx->nColumn ){ if( pIdx->onError!=pIndex->onError ){ /* This constraint creates the same index as a previous ** constraint specified somewhere in the CREATE TABLE statement. ** However the ON CONFLICT clauses are different. If both this ** constraint and the previous equivalent constraint have explicit ** ON CONFLICT clauses this is an error. Otherwise, use the | | | 83245 83246 83247 83248 83249 83250 83251 83252 83253 83254 83255 83256 83257 83258 83259 | if( k==pIdx->nColumn ){ if( pIdx->onError!=pIndex->onError ){ /* This constraint creates the same index as a previous ** constraint specified somewhere in the CREATE TABLE statement. ** However the ON CONFLICT clauses are different. If both this ** constraint and the previous equivalent constraint have explicit ** ON CONFLICT clauses this is an error. Otherwise, use the ** explicitly specified behaviour for the index. */ if( !(pIdx->onError==OE_Default || pIndex->onError==OE_Default) ){ sqlite3ErrorMsg(pParse, "conflicting ON CONFLICT clauses specified", 0); } if( pIdx->onError==OE_Default ){ pIdx->onError = pIndex->onError; |
︙ | ︙ | |||
85725 85726 85727 85728 85729 85730 85731 | ** If iDb<0 then code the OP_Goto only - don't set flag to verify the ** schema on any databases. This can be used to position the OP_Goto ** early in the code, before we know if any database tables will be used. */ SQLITE_PRIVATE void sqlite3CodeVerifySchema(Parse *pParse, int iDb){ Parse *pToplevel = sqlite3ParseToplevel(pParse); | < < < < < < < < < | 83992 83993 83994 83995 83996 83997 83998 83999 84000 84001 84002 84003 84004 84005 | ** If iDb<0 then code the OP_Goto only - don't set flag to verify the ** schema on any databases. This can be used to position the OP_Goto ** early in the code, before we know if any database tables will be used. */ SQLITE_PRIVATE void sqlite3CodeVerifySchema(Parse *pParse, int iDb){ Parse *pToplevel = sqlite3ParseToplevel(pParse); if( pToplevel->cookieGoto==0 ){ Vdbe *v = sqlite3GetVdbe(pToplevel); if( v==0 ) return; /* This only happens if there was a prior error */ pToplevel->cookieGoto = sqlite3VdbeAddOp2(v, OP_Goto, 0, 0)+1; } if( iDb>=0 ){ sqlite3 *db = pToplevel->db; |
︙ | ︙ | |||
85831 85832 85833 85834 85835 85836 85837 | } /* ** Code an OP_Halt that causes the vdbe to return an SQLITE_CONSTRAINT ** error. The onError parameter determines which (if any) of the statement ** and/or current transaction is rolled back. */ | | < < < < < < < | | 84089 84090 84091 84092 84093 84094 84095 84096 84097 84098 84099 84100 84101 84102 84103 84104 84105 84106 84107 84108 | } /* ** Code an OP_Halt that causes the vdbe to return an SQLITE_CONSTRAINT ** error. The onError parameter determines which (if any) of the statement ** and/or current transaction is rolled back. */ SQLITE_PRIVATE void sqlite3HaltConstraint(Parse *pParse, int onError, char *p4, int p4type){ Vdbe *v = sqlite3GetVdbe(pParse); if( onError==OE_Abort ){ sqlite3MayAbort(pParse); } sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CONSTRAINT, onError, 0, p4, p4type); } /* ** Check to see if pIndex uses the collating sequence pColl. Return ** true if it does and false if it does not. */ #ifndef SQLITE_OMIT_REINDEX |
︙ | ︙ | |||
86588 86589 86590 86591 86592 86593 86594 | SQLITE_PRIVATE void sqlite3MaterializeView( Parse *pParse, /* Parsing context */ Table *pView, /* View definition */ Expr *pWhere, /* Optional WHERE clause to be added */ int iCur /* Cursor number for ephemerial table */ ){ SelectDest dest; | | < | > > > | | | < | | | | | | | > | | < | | | | 84839 84840 84841 84842 84843 84844 84845 84846 84847 84848 84849 84850 84851 84852 84853 84854 84855 84856 84857 84858 84859 84860 84861 84862 84863 84864 84865 84866 84867 84868 84869 84870 84871 84872 84873 84874 84875 | SQLITE_PRIVATE void sqlite3MaterializeView( Parse *pParse, /* Parsing context */ Table *pView, /* View definition */ Expr *pWhere, /* Optional WHERE clause to be added */ int iCur /* Cursor number for ephemerial table */ ){ SelectDest dest; Select *pDup; sqlite3 *db = pParse->db; pDup = sqlite3SelectDup(db, pView->pSelect, 0); if( pWhere ){ SrcList *pFrom; pWhere = sqlite3ExprDup(db, pWhere, 0); pFrom = sqlite3SrcListAppend(db, 0, 0, 0); if( pFrom ){ assert( pFrom->nSrc==1 ); pFrom->a[0].zAlias = sqlite3DbStrDup(db, pView->zName); pFrom->a[0].pSelect = pDup; assert( pFrom->a[0].pOn==0 ); assert( pFrom->a[0].pUsing==0 ); }else{ sqlite3SelectDelete(db, pDup); } pDup = sqlite3SelectNew(pParse, 0, pFrom, pWhere, 0, 0, 0, 0, 0, 0); } sqlite3SelectDestInit(&dest, SRT_EphemTab, iCur); sqlite3Select(pParse, pDup, &dest); sqlite3SelectDelete(db, pDup); } #endif /* !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) */ #if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY) /* ** Generate an expression tree to implement the WHERE, ORDER BY, ** and LIMIT/OFFSET portion of DELETE and UPDATE statements. |
︙ | ︙ | |||
87316 87317 87318 87319 87320 87321 87322 | if( rVal<0 ) rVal = -rVal; sqlite3_result_double(context, rVal); break; } } } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 85568 85569 85570 85571 85572 85573 85574 85575 85576 85577 85578 85579 85580 85581 | if( rVal<0 ) rVal = -rVal; sqlite3_result_double(context, rVal); break; } } } /* ** Implementation of the substr() function. ** ** substr(x,p1,p2) returns p2 characters of x[] beginning with p1. ** p1 is 1-indexed. So substr(x,1,1) returns the first character ** of x. If x is text, then we actually count UTF-8 characters. ** If x is a blob, then we count bytes. |
︙ | ︙ | |||
87841 87842 87843 87844 87845 87846 87847 | } prevEscape = 0; } } return *zString==0; } | < < < < < < < | 86043 86044 86045 86046 86047 86048 86049 86050 86051 86052 86053 86054 86055 86056 | } prevEscape = 0; } } return *zString==0; } /* ** Count the number of times that the LIKE operator (or GLOB which is ** just a variation of LIKE) gets called. This is used for testing ** only. */ #ifdef SQLITE_TEST SQLITE_API int sqlite3_like_count = 0; |
︙ | ︙ | |||
88117 88118 88119 88120 88121 88122 88123 | assert( sqlite3_value_type(argv[0])==SQLITE_NULL ); sqlite3_result_text(context, "NULL", 4, SQLITE_STATIC); break; } } } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 86312 86313 86314 86315 86316 86317 86318 86319 86320 86321 86322 86323 86324 86325 | assert( sqlite3_value_type(argv[0])==SQLITE_NULL ); sqlite3_result_text(context, "NULL", 4, SQLITE_STATIC); break; } } } /* ** The hex() function. Interpret the argument as a blob. Return ** a hexadecimal rendering as text. */ static void hexFunc( sqlite3_context *context, int argc, |
︙ | ︙ | |||
88797 88798 88799 88800 88801 88802 88803 | FUNCTION(min, 0, 0, 1, 0 ), AGGREGATE(min, 1, 0, 1, minmaxStep, minMaxFinalize ), FUNCTION(max, -1, 1, 1, minmaxFunc ), FUNCTION(max, 0, 1, 1, 0 ), AGGREGATE(max, 1, 1, 1, minmaxStep, minMaxFinalize ), FUNCTION2(typeof, 1, 0, 0, typeofFunc, SQLITE_FUNC_TYPEOF), FUNCTION2(length, 1, 0, 0, lengthFunc, SQLITE_FUNC_LENGTH), | < < < | 86936 86937 86938 86939 86940 86941 86942 86943 86944 86945 86946 86947 86948 86949 86950 86951 | FUNCTION(min, 0, 0, 1, 0 ), AGGREGATE(min, 1, 0, 1, minmaxStep, minMaxFinalize ), FUNCTION(max, -1, 1, 1, minmaxFunc ), FUNCTION(max, 0, 1, 1, 0 ), AGGREGATE(max, 1, 1, 1, minmaxStep, minMaxFinalize ), FUNCTION2(typeof, 1, 0, 0, typeofFunc, SQLITE_FUNC_TYPEOF), FUNCTION2(length, 1, 0, 0, lengthFunc, SQLITE_FUNC_LENGTH), FUNCTION(substr, 2, 0, 0, substrFunc ), FUNCTION(substr, 3, 0, 0, substrFunc ), FUNCTION(abs, 1, 0, 0, absFunc ), #ifndef SQLITE_OMIT_FLOATING_POINT FUNCTION(round, 1, 0, 0, roundFunc ), FUNCTION(round, 2, 0, 0, roundFunc ), #endif FUNCTION(upper, 1, 0, 0, upperFunc ), FUNCTION(lower, 1, 0, 0, lowerFunc ), |
︙ | ︙ | |||
88893 88894 88895 88896 88897 88898 88899 | #ifndef SQLITE_OMIT_TRIGGER /* ** Deferred and Immediate FKs ** -------------------------- ** ** Foreign keys in SQLite come in two flavours: deferred and immediate. | | < | | 87029 87030 87031 87032 87033 87034 87035 87036 87037 87038 87039 87040 87041 87042 87043 87044 | #ifndef SQLITE_OMIT_TRIGGER /* ** Deferred and Immediate FKs ** -------------------------- ** ** Foreign keys in SQLite come in two flavours: deferred and immediate. ** If an immediate foreign key constraint is violated, SQLITE_CONSTRAINT ** is returned and the current statement transaction rolled back. If a ** deferred foreign key constraint is violated, no action is taken ** immediately. However if the application attempts to commit the ** transaction before fixing the constraint violation, the attempt fails. ** ** Deferred constraints are implemented using a simple counter associated ** with the database handle. The counter is set to zero each time a ** database transaction is opened. Each time a statement is executed |
︙ | ︙ | |||
88959 88960 88961 88962 88963 88964 88965 | ** If a delete caused by OR REPLACE violates an FK constraint, an exception ** is thrown, even if the FK constraint would be satisfied after the new ** row is inserted. ** ** Immediate constraints are usually handled similarly. The only difference ** is that the counter used is stored as part of each individual statement ** object (struct Vdbe). If, after the statement has run, its immediate | | < | 87094 87095 87096 87097 87098 87099 87100 87101 87102 87103 87104 87105 87106 87107 87108 | ** If a delete caused by OR REPLACE violates an FK constraint, an exception ** is thrown, even if the FK constraint would be satisfied after the new ** row is inserted. ** ** Immediate constraints are usually handled similarly. The only difference ** is that the counter used is stored as part of each individual statement ** object (struct Vdbe). If, after the statement has run, its immediate ** constraint counter is greater than zero, it returns SQLITE_CONSTRAINT ** and the statement transaction is rolled back. An exception is an INSERT ** statement that inserts a single row only (no triggers). In this case, ** instead of using a counter, an exception is thrown immediately if the ** INSERT violates a foreign key constraint. This is necessary as such ** an INSERT does not open a statement transaction. ** ** TODO: How should dropping a table be handled? How should renaming a |
︙ | ︙ | |||
89016 89017 89018 89019 89020 89021 89022 | ** Register (x+3): 3.1 (type real) */ /* ** A foreign key constraint requires that the key columns in the parent ** table are collectively subject to a UNIQUE or PRIMARY KEY constraint. ** Given that pParent is the parent table for foreign key constraint pFKey, | | | 87150 87151 87152 87153 87154 87155 87156 87157 87158 87159 87160 87161 87162 87163 87164 | ** Register (x+3): 3.1 (type real) */ /* ** A foreign key constraint requires that the key columns in the parent ** table are collectively subject to a UNIQUE or PRIMARY KEY constraint. ** Given that pParent is the parent table for foreign key constraint pFKey, ** search the schema a unique index on the parent key columns. ** ** If successful, zero is returned. If the parent key is an INTEGER PRIMARY ** KEY column, then output variable *ppIdx is set to NULL. Otherwise, *ppIdx ** is set to point to the unique index. ** ** If the parent key consists of a single column (the foreign key constraint ** is not a composite foreign key), output variable *paiCol is set to NULL. |
︙ | ︙ | |||
89052 89053 89054 89055 89056 89057 89058 | ** consists of a a different number of columns to the child key in ** the child table. ** ** then non-zero is returned, and a "foreign key mismatch" error loaded ** into pParse. If an OOM error occurs, non-zero is returned and the ** pParse->db->mallocFailed flag is set. */ | | | 87186 87187 87188 87189 87190 87191 87192 87193 87194 87195 87196 87197 87198 87199 87200 | ** consists of a a different number of columns to the child key in ** the child table. ** ** then non-zero is returned, and a "foreign key mismatch" error loaded ** into pParse. If an OOM error occurs, non-zero is returned and the ** pParse->db->mallocFailed flag is set. */ static int locateFkeyIndex( Parse *pParse, /* Parse context to store any error in */ Table *pParent, /* Parent table of FK constraint pFKey */ FKey *pFKey, /* Foreign key to find index for */ Index **ppIdx, /* OUT: Unique index on parent table */ int **paiCol /* OUT: Map of index columns in pFKey */ ){ Index *pIdx = 0; /* Value to return via *ppIdx */ |
︙ | ︙ | |||
89149 89150 89151 89152 89153 89154 89155 | if( i==nCol ) break; /* pIdx is usable */ } } } if( !pIdx ){ if( !pParse->disableTriggers ){ | | < < | 87283 87284 87285 87286 87287 87288 87289 87290 87291 87292 87293 87294 87295 87296 87297 | if( i==nCol ) break; /* pIdx is usable */ } } } if( !pIdx ){ if( !pParse->disableTriggers ){ sqlite3ErrorMsg(pParse, "foreign key mismatch"); } sqlite3DbFree(pParse->db, aiCol); return 1; } *ppIdx = pIdx; return 0; |
︙ | ︙ | |||
89300 89301 89302 89303 89304 89305 89306 | if( !pFKey->isDeferred && !pParse->pToplevel && !pParse->isMultiWrite ){ /* Special case: If this is an INSERT statement that will insert exactly ** one row into the table, raise a constraint immediately instead of ** incrementing a counter. This is necessary as the VM code is being ** generated for will not open a statement transaction. */ assert( nIncr==1 ); | | | | 87432 87433 87434 87435 87436 87437 87438 87439 87440 87441 87442 87443 87444 87445 87446 87447 | if( !pFKey->isDeferred && !pParse->pToplevel && !pParse->isMultiWrite ){ /* Special case: If this is an INSERT statement that will insert exactly ** one row into the table, raise a constraint immediately instead of ** incrementing a counter. This is necessary as the VM code is being ** generated for will not open a statement transaction. */ assert( nIncr==1 ); sqlite3HaltConstraint( pParse, OE_Abort, "foreign key constraint failed", P4_STATIC ); }else{ if( nIncr>0 && pFKey->isDeferred==0 ){ sqlite3ParseToplevel(pParse)->mayAbort = 1; } sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, nIncr); } |
︙ | ︙ | |||
89387 89388 89389 89390 89391 89392 89393 | pLeft = sqlite3Expr(db, TK_REGISTER, 0); if( pLeft ){ /* Set the collation sequence and affinity of the LHS of each TK_EQ ** expression to the parent key column defaults. */ if( pIdx ){ Column *pCol; | < | < < | 87519 87520 87521 87522 87523 87524 87525 87526 87527 87528 87529 87530 87531 87532 87533 87534 87535 87536 87537 87538 | pLeft = sqlite3Expr(db, TK_REGISTER, 0); if( pLeft ){ /* Set the collation sequence and affinity of the LHS of each TK_EQ ** expression to the parent key column defaults. */ if( pIdx ){ Column *pCol; iCol = pIdx->aiColumn[i]; pCol = &pTab->aCol[iCol]; if( pTab->iPKey==iCol ) iCol = -1; pLeft->iTable = regData+iCol+1; pLeft->affinity = pCol->affinity; pLeft->pColl = sqlite3LocateCollSeq(pParse, pCol->zColl); }else{ pLeft->iTable = regData; pLeft->affinity = SQLITE_AFF_INTEGER; } } iCol = aiCol ? aiCol[i] : pFKey->aCol[0].iFrom; assert( iCol>=0 ); |
︙ | ︙ | |||
89541 89542 89543 89544 89545 89546 89547 | pParse->disableTriggers = 0; /* If the DELETE has generated immediate foreign key constraint ** violations, halt the VDBE and return an error at this point, before ** any modifications to the schema are made. This is because statement ** transactions are not able to rollback schema changes. */ sqlite3VdbeAddOp2(v, OP_FkIfZero, 0, sqlite3VdbeCurrentAddr(v)+2); | | | | 87670 87671 87672 87673 87674 87675 87676 87677 87678 87679 87680 87681 87682 87683 87684 87685 | pParse->disableTriggers = 0; /* If the DELETE has generated immediate foreign key constraint ** violations, halt the VDBE and return an error at this point, before ** any modifications to the schema are made. This is because statement ** transactions are not able to rollback schema changes. */ sqlite3VdbeAddOp2(v, OP_FkIfZero, 0, sqlite3VdbeCurrentAddr(v)+2); sqlite3HaltConstraint( pParse, OE_Abort, "foreign key constraint failed", P4_STATIC ); if( iSkip ){ sqlite3VdbeResolveLabel(v, iSkip); } } } |
︙ | ︙ | |||
89612 89613 89614 89615 89616 89617 89618 | ** schema items cannot be located, set an error in pParse and return ** early. */ if( pParse->disableTriggers ){ pTo = sqlite3FindTable(db, pFKey->zTo, zDb); }else{ pTo = sqlite3LocateTable(pParse, 0, pFKey->zTo, zDb); } | | | 87741 87742 87743 87744 87745 87746 87747 87748 87749 87750 87751 87752 87753 87754 87755 | ** schema items cannot be located, set an error in pParse and return ** early. */ if( pParse->disableTriggers ){ pTo = sqlite3FindTable(db, pFKey->zTo, zDb); }else{ pTo = sqlite3LocateTable(pParse, 0, pFKey->zTo, zDb); } if( !pTo || 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 |
︙ | ︙ | |||
89692 89693 89694 89695 89696 89697 89698 | if( !pFKey->isDeferred && !pParse->pToplevel && !pParse->isMultiWrite ){ assert( regOld==0 && regNew!=0 ); /* Inserting a single row into a parent table cannot cause an immediate ** foreign key violation. So do nothing in this case. */ continue; } | | | 87821 87822 87823 87824 87825 87826 87827 87828 87829 87830 87831 87832 87833 87834 87835 | if( !pFKey->isDeferred && !pParse->pToplevel && !pParse->isMultiWrite ){ assert( regOld==0 && regNew!=0 ); /* Inserting a single row into a parent table cannot cause an immediate ** foreign key violation. So do nothing in this case. */ continue; } if( locateFkeyIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ){ if( !isIgnoreErrors || db->mallocFailed ) return; continue; } assert( aiCol || pFKey->nCol==1 ); /* Create a SrcList structure containing a single table (the table ** the foreign key that refers to this table is attached to). This |
︙ | ︙ | |||
89747 89748 89749 89750 89751 89752 89753 | FKey *p; int i; for(p=pTab->pFKey; p; p=p->pNextFrom){ for(i=0; i<p->nCol; i++) mask |= COLUMN_MASK(p->aCol[i].iFrom); } for(p=sqlite3FkReferences(pTab); p; p=p->pNextTo){ Index *pIdx = 0; | | | 87876 87877 87878 87879 87880 87881 87882 87883 87884 87885 87886 87887 87888 87889 87890 | FKey *p; int i; for(p=pTab->pFKey; p; p=p->pNextFrom){ for(i=0; i<p->nCol; i++) mask |= COLUMN_MASK(p->aCol[i].iFrom); } for(p=sqlite3FkReferences(pTab); p; p=p->pNextTo){ Index *pIdx = 0; locateFkeyIndex(pParse, pTab, p, &pIdx, 0); if( pIdx ){ for(i=0; i<pIdx->nColumn; i++) mask |= COLUMN_MASK(pIdx->aiColumn[i]); } } } return mask; } |
︙ | ︙ | |||
89873 89874 89875 89876 89877 89878 89879 | TriggerStep *pStep = 0; /* First (only) step of trigger program */ Expr *pWhere = 0; /* WHERE clause of trigger step */ ExprList *pList = 0; /* Changes list if ON UPDATE CASCADE */ Select *pSelect = 0; /* If RESTRICT, "SELECT RAISE(...)" */ int i; /* Iterator variable */ Expr *pWhen = 0; /* WHEN clause for the trigger */ | | | 88002 88003 88004 88005 88006 88007 88008 88009 88010 88011 88012 88013 88014 88015 88016 | TriggerStep *pStep = 0; /* First (only) step of trigger program */ Expr *pWhere = 0; /* WHERE clause of trigger step */ ExprList *pList = 0; /* Changes list if ON UPDATE CASCADE */ Select *pSelect = 0; /* If RESTRICT, "SELECT RAISE(...)" */ int i; /* Iterator variable */ Expr *pWhen = 0; /* WHEN clause for the trigger */ if( locateFkeyIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ) return 0; assert( aiCol || pFKey->nCol==1 ); for(i=0; i<pFKey->nCol; i++){ Token tOld = { "old", 3 }; /* Literal "old" token */ Token tNew = { "new", 3 }; /* Literal "new" token */ Token tFromCol; /* Name of column in child table */ Token tToCol; /* Name of column in parent table */ |
︙ | ︙ | |||
90126 90127 90128 90129 90130 90131 90132 | Parse *p, /* Generate code into this VDBE */ int iCur, /* The cursor number of the table */ int iDb, /* The database index in sqlite3.aDb[] */ Table *pTab, /* The table to be opened */ int opcode /* OP_OpenRead or OP_OpenWrite */ ){ Vdbe *v; | | | 88255 88256 88257 88258 88259 88260 88261 88262 88263 88264 88265 88266 88267 88268 88269 | Parse *p, /* Generate code into this VDBE */ int iCur, /* The cursor number of the table */ int iDb, /* The database index in sqlite3.aDb[] */ Table *pTab, /* The table to be opened */ int opcode /* OP_OpenRead or OP_OpenWrite */ ){ Vdbe *v; if( IsVirtual(pTab) ) return; v = sqlite3GetVdbe(p); assert( opcode==OP_OpenWrite || opcode==OP_OpenRead ); sqlite3TableLock(p, iDb, pTab->tnum, (opcode==OP_OpenWrite)?1:0, pTab->zName); sqlite3VdbeAddOp3(v, opcode, iCur, pTab->tnum, iDb); sqlite3VdbeChangeP4(v, -1, SQLITE_INT_TO_PTR(pTab->nCol), P4_INT32); VdbeComment((v, "%s", pTab->zName)); } |
︙ | ︙ | |||
91346 91347 91348 91349 91350 91351 91352 | switch( onError ){ case OE_Abort: sqlite3MayAbort(pParse); case OE_Rollback: case OE_Fail: { char *zMsg; sqlite3VdbeAddOp3(v, OP_HaltIfNull, | | | 89475 89476 89477 89478 89479 89480 89481 89482 89483 89484 89485 89486 89487 89488 89489 | switch( onError ){ case OE_Abort: sqlite3MayAbort(pParse); case OE_Rollback: case OE_Fail: { char *zMsg; sqlite3VdbeAddOp3(v, OP_HaltIfNull, SQLITE_CONSTRAINT, onError, regData+i); zMsg = sqlite3MPrintf(db, "%s.%s may not be NULL", pTab->zName, pTab->aCol[i].zName); sqlite3VdbeChangeP4(v, -1, zMsg, P4_DYNAMIC); break; } case OE_Ignore: { sqlite3VdbeAddOp2(v, OP_IsNull, regData+i, ignoreDest); |
︙ | ︙ | |||
91375 91376 91377 91378 91379 91380 91381 | #ifndef SQLITE_OMIT_CHECK if( pTab->pCheck && (db->flags & SQLITE_IgnoreChecks)==0 ){ ExprList *pCheck = pTab->pCheck; pParse->ckBase = regData; onError = overrideError!=OE_Default ? overrideError : OE_Abort; for(i=0; i<pCheck->nExpr; i++){ int allOk = sqlite3VdbeMakeLabel(v); | > > > | | | | | | | | | | | | < | | > > | 89504 89505 89506 89507 89508 89509 89510 89511 89512 89513 89514 89515 89516 89517 89518 89519 89520 89521 89522 89523 89524 89525 89526 89527 89528 89529 89530 89531 89532 89533 89534 89535 89536 | #ifndef SQLITE_OMIT_CHECK if( pTab->pCheck && (db->flags & SQLITE_IgnoreChecks)==0 ){ ExprList *pCheck = pTab->pCheck; pParse->ckBase = regData; onError = overrideError!=OE_Default ? overrideError : OE_Abort; for(i=0; i<pCheck->nExpr; i++){ int allOk = sqlite3VdbeMakeLabel(v); Expr *pDup = sqlite3ExprDup(db, pCheck->a[i].pExpr, 0); if( !db->mallocFailed ){ assert( pDup!=0 ); sqlite3ExprIfTrue(pParse, pDup, allOk, SQLITE_JUMPIFNULL); if( onError==OE_Ignore ){ sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest); }else{ char *zConsName = pCheck->a[i].zName; if( onError==OE_Replace ) onError = OE_Abort; /* IMP: R-15569-63625 */ if( zConsName ){ zConsName = sqlite3MPrintf(db, "constraint %s failed", zConsName); }else{ zConsName = 0; } sqlite3HaltConstraint(pParse, onError, zConsName, P4_DYNAMIC); } sqlite3VdbeResolveLabel(v, allOk); } sqlite3ExprDelete(db, pDup); } } #endif /* !defined(SQLITE_OMIT_CHECK) */ /* If we have an INTEGER PRIMARY KEY, make sure the primary key ** of the new record does not previously exist. Except, if this ** is an UPDATE and the primary key is not changing, that is OK. |
︙ | ︙ | |||
91418 91419 91420 91421 91422 91423 91424 | default: { onError = OE_Abort; /* Fall thru into the next case */ } case OE_Rollback: case OE_Abort: case OE_Fail: { | | | | 89551 89552 89553 89554 89555 89556 89557 89558 89559 89560 89561 89562 89563 89564 89565 89566 | default: { onError = OE_Abort; /* Fall thru into the next case */ } case OE_Rollback: case OE_Abort: case OE_Fail: { sqlite3HaltConstraint( pParse, onError, "PRIMARY KEY must be unique", P4_STATIC); break; } case OE_Replace: { /* If there are DELETE triggers on this table and the ** recursive-triggers flag is set, call GenerateRowDelete() to ** remove the conflicting row from the table. This will fire ** the triggers and remove both the table and index b-tree entries. |
︙ | ︙ | |||
91546 91547 91548 91549 91550 91551 91552 | sqlite3StrAccumAppend(&errMsg, zSep, -1); zSep = ", "; sqlite3StrAccumAppend(&errMsg, zCol, -1); } sqlite3StrAccumAppend(&errMsg, pIdx->nColumn>1 ? " are not unique" : " is not unique", -1); zErr = sqlite3StrAccumFinish(&errMsg); | | < | 89679 89680 89681 89682 89683 89684 89685 89686 89687 89688 89689 89690 89691 89692 89693 | sqlite3StrAccumAppend(&errMsg, zSep, -1); zSep = ", "; sqlite3StrAccumAppend(&errMsg, zCol, -1); } sqlite3StrAccumAppend(&errMsg, pIdx->nColumn>1 ? " are not unique" : " is not unique", -1); zErr = sqlite3StrAccumFinish(&errMsg); sqlite3HaltConstraint(pParse, onError, zErr, 0); sqlite3DbFree(errMsg.db, zErr); break; } case OE_Ignore: { assert( seenReplace==0 ); sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest); break; |
︙ | ︙ | |||
91955 91956 91957 91958 91959 91960 91961 | sqlite3OpenTable(pParse, iSrc, iDbSrc, pSrc, OP_OpenRead); emptySrcTest = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0); regData = sqlite3GetTempReg(pParse); regRowid = sqlite3GetTempReg(pParse); if( pDest->iPKey>=0 ){ addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid); addr2 = sqlite3VdbeAddOp3(v, OP_NotExists, iDest, 0, regRowid); | | | | 90087 90088 90089 90090 90091 90092 90093 90094 90095 90096 90097 90098 90099 90100 90101 90102 | sqlite3OpenTable(pParse, iSrc, iDbSrc, pSrc, OP_OpenRead); emptySrcTest = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0); regData = sqlite3GetTempReg(pParse); regRowid = sqlite3GetTempReg(pParse); if( pDest->iPKey>=0 ){ addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid); addr2 = sqlite3VdbeAddOp3(v, OP_NotExists, iDest, 0, regRowid); sqlite3HaltConstraint( pParse, onError, "PRIMARY KEY must be unique", P4_STATIC); sqlite3VdbeJumpHere(v, addr2); autoIncStep(pParse, regAutoinc, regRowid); }else if( pDest->pIndex==0 ){ addr1 = sqlite3VdbeAddOp2(v, OP_NewRowid, iDest, regRowid); }else{ addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid); assert( (pDest->tabFlags & TF_Autoincrement)==0 ); |
︙ | ︙ | |||
92048 92049 92050 92051 92052 92053 92054 92055 92056 92057 92058 92059 92060 92061 | void *pArg, /* First argument to xCallback() */ char **pzErrMsg /* Write error messages here */ ){ int rc = SQLITE_OK; /* Return code */ const char *zLeftover; /* Tail of unprocessed SQL */ sqlite3_stmt *pStmt = 0; /* The current SQL statement */ char **azCols = 0; /* Names of result columns */ int callbackIsInit; /* True if callback data is initialized */ if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; if( zSql==0 ) zSql = ""; sqlite3_mutex_enter(db->mutex); sqlite3Error(db, SQLITE_OK, 0); | > | | | 90180 90181 90182 90183 90184 90185 90186 90187 90188 90189 90190 90191 90192 90193 90194 90195 90196 90197 90198 90199 90200 90201 90202 90203 90204 90205 90206 90207 | void *pArg, /* First argument to xCallback() */ char **pzErrMsg /* Write error messages here */ ){ int rc = SQLITE_OK; /* Return code */ const char *zLeftover; /* Tail of unprocessed SQL */ sqlite3_stmt *pStmt = 0; /* The current SQL statement */ char **azCols = 0; /* Names of result columns */ int nRetry = 0; /* Number of retry attempts */ int callbackIsInit; /* True if callback data is initialized */ if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; if( zSql==0 ) zSql = ""; sqlite3_mutex_enter(db->mutex); sqlite3Error(db, SQLITE_OK, 0); while( (rc==SQLITE_OK || (rc==SQLITE_SCHEMA && (++nRetry)<2)) && zSql[0] ){ int nCol; char **azVals = 0; pStmt = 0; rc = sqlite3_prepare(db, zSql, -1, &pStmt, &zLeftover); assert( rc==SQLITE_OK || pStmt==0 ); if( rc!=SQLITE_OK ){ continue; } if( !pStmt ){ /* this happens for a comment or white-space */ zSql = zLeftover; |
︙ | ︙ | |||
92117 92118 92119 92120 92121 92122 92123 | goto exec_out; } } if( rc!=SQLITE_ROW ){ rc = sqlite3VdbeFinalize((Vdbe *)pStmt); pStmt = 0; | > > | | > | 90250 90251 90252 90253 90254 90255 90256 90257 90258 90259 90260 90261 90262 90263 90264 90265 90266 90267 90268 | goto exec_out; } } if( rc!=SQLITE_ROW ){ rc = sqlite3VdbeFinalize((Vdbe *)pStmt); pStmt = 0; if( rc!=SQLITE_SCHEMA ){ nRetry = 0; zSql = zLeftover; while( sqlite3Isspace(zSql[0]) ) zSql++; } break; } } sqlite3DbFree(db, azCols); azCols = 0; } |
︙ | ︙ | |||
92409 92410 92411 92412 92413 92414 92415 | 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*); | < < < < < < < < < < < < < < | 90545 90546 90547 90548 90549 90550 90551 90552 90553 90554 90555 90556 90557 90558 | 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 |
︙ | ︙ | |||
92626 92627 92628 92629 92630 92631 92632 | #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 | < < < < < < < < < < < < < < < < < | | < < < < < < | 90748 90749 90750 90751 90752 90753 90754 90755 90756 90757 90758 90759 90760 90761 90762 90763 90764 90765 | #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> */ |
︙ | ︙ | |||
93018 93019 93020 93021 93022 93023 93024 | 0, 0, 0, #endif sqlite3_blob_reopen, sqlite3_vtab_config, sqlite3_vtab_on_conflict, | < < < < < < < < < < < < < | 91117 91118 91119 91120 91121 91122 91123 91124 91125 91126 91127 91128 91129 91130 | 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. |
︙ | ︙ | |||
93055 93056 93057 93058 93059 93060 93061 | const char *zProc, /* Entry point. Use "sqlite3_extension_init" if 0 */ char **pzErrMsg /* Put error message here if not 0 */ ){ sqlite3_vfs *pVfs = db->pVfs; void *handle; int (*xInit)(sqlite3*,char**,const sqlite3_api_routines*); char *zErrmsg = 0; | < < < < < < < < < < < < < < < > | | | < < < < | < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | < | < < | < > | | 91141 91142 91143 91144 91145 91146 91147 91148 91149 91150 91151 91152 91153 91154 91155 91156 91157 91158 91159 91160 91161 91162 91163 91164 91165 91166 91167 91168 91169 91170 91171 91172 91173 91174 91175 91176 91177 91178 91179 91180 91181 91182 91183 91184 91185 91186 91187 91188 91189 91190 91191 91192 91193 91194 91195 91196 91197 91198 91199 91200 91201 91202 91203 | const char *zProc, /* Entry point. Use "sqlite3_extension_init" if 0 */ char **pzErrMsg /* Put error message here if not 0 */ ){ sqlite3_vfs *pVfs = db->pVfs; void *handle; int (*xInit)(sqlite3*,char**,const sqlite3_api_routines*); char *zErrmsg = 0; void **aHandle; int nMsg = 300 + sqlite3Strlen30(zFile); if( pzErrMsg ) *pzErrMsg = 0; /* Ticket #1863. To avoid a creating security problems for older ** applications that relink against newer versions of SQLite, the ** ability to run load_extension is turned off by default. One ** must call sqlite3_enable_load_extension() to turn on extension ** loading. Otherwise you get the following error. */ if( (db->flags & SQLITE_LoadExtension)==0 ){ if( pzErrMsg ){ *pzErrMsg = sqlite3_mprintf("not authorized"); } return SQLITE_ERROR; } if( zProc==0 ){ zProc = "sqlite3_extension_init"; } handle = sqlite3OsDlOpen(pVfs, zFile); if( handle==0 ){ if( pzErrMsg ){ *pzErrMsg = zErrmsg = sqlite3_malloc(nMsg); if( zErrmsg ){ sqlite3_snprintf(nMsg, zErrmsg, "unable to open shared library [%s]", zFile); sqlite3OsDlError(pVfs, nMsg-1, zErrmsg); } } return SQLITE_ERROR; } xInit = (int(*)(sqlite3*,char**,const sqlite3_api_routines*)) sqlite3OsDlSym(pVfs, handle, zProc); if( xInit==0 ){ if( pzErrMsg ){ nMsg += sqlite3Strlen30(zProc); *pzErrMsg = zErrmsg = sqlite3_malloc(nMsg); if( zErrmsg ){ sqlite3_snprintf(nMsg, zErrmsg, "no entry point [%s] in shared library [%s]", zProc,zFile); sqlite3OsDlError(pVfs, nMsg-1, zErrmsg); } sqlite3OsDlClose(pVfs, handle); } return SQLITE_ERROR; }else if( xInit(db, &zErrmsg, &sqlite3Apis) ){ if( pzErrMsg ){ *pzErrMsg = sqlite3_mprintf("error during initialization: %s", zErrmsg); } sqlite3_free(zErrmsg); sqlite3OsDlClose(pVfs, handle); return SQLITE_ERROR; } |
︙ | ︙ | |||
93555 93556 93557 93558 93559 93560 93561 | #ifndef SQLITE_OMIT_AUTOMATIC_INDEX { "automatic_index", SQLITE_AutoIndex }, #endif #ifdef SQLITE_DEBUG { "sql_trace", SQLITE_SqlTrace }, { "vdbe_listing", SQLITE_VdbeListing }, { "vdbe_trace", SQLITE_VdbeTrace }, | < < < | 91583 91584 91585 91586 91587 91588 91589 91590 91591 91592 91593 91594 91595 91596 | #ifndef SQLITE_OMIT_AUTOMATIC_INDEX { "automatic_index", SQLITE_AutoIndex }, #endif #ifdef SQLITE_DEBUG { "sql_trace", SQLITE_SqlTrace }, { "vdbe_listing", SQLITE_VdbeListing }, { "vdbe_trace", SQLITE_VdbeTrace }, #endif #ifndef SQLITE_OMIT_CHECK { "ignore_check_constraints", SQLITE_IgnoreChecks }, #endif /* The following is VERY experimental */ { "writable_schema", SQLITE_WriteSchema|SQLITE_RecoveryMode }, |
︙ | ︙ | |||
93690 93691 93692 93693 93694 93695 93696 | const char *zDb = 0; /* The database name */ Token *pId; /* Pointer to <id> token */ int iDb; /* Database index for <database> */ char *aFcntl[4]; /* Argument to SQLITE_FCNTL_PRAGMA */ int rc; /* return value form SQLITE_FCNTL_PRAGMA */ sqlite3 *db = pParse->db; /* The database connection */ Db *pDb; /* The specific database being pragmaed */ | | | 91715 91716 91717 91718 91719 91720 91721 91722 91723 91724 91725 91726 91727 91728 91729 | const char *zDb = 0; /* The database name */ Token *pId; /* Pointer to <id> token */ int iDb; /* Database index for <database> */ char *aFcntl[4]; /* Argument to SQLITE_FCNTL_PRAGMA */ int rc; /* return value form SQLITE_FCNTL_PRAGMA */ sqlite3 *db = pParse->db; /* The database connection */ Db *pDb; /* The specific database being pragmaed */ Vdbe *v = pParse->pVdbe = sqlite3VdbeCreate(db); /* Prepared statement */ if( v==0 ) return; sqlite3VdbeRunOnlyOnce(v); pParse->nMem = 2; /* Interpret the [database.] part of the pragma statement. iDb is the ** index of the database this pragma is being applied to in db.aDb[]. */ |
︙ | ︙ | |||
93773 93774 93775 93776 93777 93778 93779 | ** size. But continue to take the absolute value of the default cache ** size of historical compatibility. */ if( sqlite3StrICmp(zLeft,"default_cache_size")==0 ){ static const VdbeOpList getCacheSize[] = { { OP_Transaction, 0, 0, 0}, /* 0 */ { OP_ReadCookie, 0, 1, BTREE_DEFAULT_CACHE_SIZE}, /* 1 */ | | | < | 91798 91799 91800 91801 91802 91803 91804 91805 91806 91807 91808 91809 91810 91811 91812 91813 91814 91815 91816 | ** size. But continue to take the absolute value of the default cache ** size of historical compatibility. */ if( sqlite3StrICmp(zLeft,"default_cache_size")==0 ){ static const VdbeOpList getCacheSize[] = { { OP_Transaction, 0, 0, 0}, /* 0 */ { OP_ReadCookie, 0, 1, BTREE_DEFAULT_CACHE_SIZE}, /* 1 */ { OP_IfPos, 1, 7, 0}, { OP_Integer, 0, 2, 0}, { OP_Subtract, 1, 2, 1}, { OP_IfPos, 1, 7, 0}, { OP_Integer, 0, 1, 0}, /* 6 */ { OP_ResultRow, 1, 1, 0}, }; int addr; if( sqlite3ReadSchema(pParse) ) goto pragma_out; sqlite3VdbeUsesBtree(v, iDb); if( !zRight ){ sqlite3VdbeSetNumCols(v, 1); |
︙ | ︙ | |||
94116 94117 94118 94119 94120 94121 94122 | }else{ int size = sqlite3Atoi(zRight); pDb->pSchema->cache_size = size; sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size); } }else | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 92140 92141 92142 92143 92144 92145 92146 92147 92148 92149 92150 92151 92152 92153 | }else{ int size = sqlite3Atoi(zRight); pDb->pSchema->cache_size = size; sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size); } }else /* ** PRAGMA temp_store ** PRAGMA temp_store = "default"|"memory"|"file" ** ** Return or set the local value of the temp_store flag. Changing ** the local value does not make changes to the disk file and the default ** value will be restored the next time the database is opened. |
︙ | ︙ | |||
94360 94361 94362 94363 94364 94365 94366 | ** dflt_value: The default value for the column, if any. */ if( sqlite3StrICmp(zLeft, "table_info")==0 && zRight ){ Table *pTab; if( sqlite3ReadSchema(pParse) ) goto pragma_out; pTab = sqlite3FindTable(db, zRight, zDb); if( pTab ){ | | < < < | 92347 92348 92349 92350 92351 92352 92353 92354 92355 92356 92357 92358 92359 92360 92361 92362 92363 92364 92365 | ** dflt_value: The default value for the column, if any. */ if( sqlite3StrICmp(zLeft, "table_info")==0 && zRight ){ Table *pTab; if( sqlite3ReadSchema(pParse) ) goto pragma_out; pTab = sqlite3FindTable(db, zRight, zDb); if( pTab ){ int i; int nHidden = 0; Column *pCol; sqlite3VdbeSetNumCols(v, 6); pParse->nMem = 6; sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "cid", SQLITE_STATIC); sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE_STATIC); sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "type", SQLITE_STATIC); sqlite3VdbeSetColName(v, 3, COLNAME_NAME, "notnull", SQLITE_STATIC); sqlite3VdbeSetColName(v, 4, COLNAME_NAME, "dflt_value", SQLITE_STATIC); sqlite3VdbeSetColName(v, 5, COLNAME_NAME, "pk", SQLITE_STATIC); sqlite3ViewGetColumnNames(pParse, pTab); |
︙ | ︙ | |||
94390 94391 94392 94393 94394 94395 94396 | pCol->zType ? pCol->zType : "", 0); sqlite3VdbeAddOp2(v, OP_Integer, (pCol->notNull ? 1 : 0), 4); if( pCol->zDflt ){ sqlite3VdbeAddOp4(v, OP_String8, 0, 5, 0, (char*)pCol->zDflt, 0); }else{ sqlite3VdbeAddOp2(v, OP_Null, 0, 5); } | < < < < < < < | > < | 92374 92375 92376 92377 92378 92379 92380 92381 92382 92383 92384 92385 92386 92387 92388 92389 92390 92391 92392 92393 92394 92395 92396 92397 92398 92399 92400 92401 92402 92403 92404 | pCol->zType ? pCol->zType : "", 0); sqlite3VdbeAddOp2(v, OP_Integer, (pCol->notNull ? 1 : 0), 4); if( pCol->zDflt ){ sqlite3VdbeAddOp4(v, OP_String8, 0, 5, 0, (char*)pCol->zDflt, 0); }else{ sqlite3VdbeAddOp2(v, OP_Null, 0, 5); } sqlite3VdbeAddOp2(v, OP_Integer, (pCol->colFlags&COLFLAG_PRIMKEY)!=0, 6); sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 6); } } }else if( sqlite3StrICmp(zLeft, "index_info")==0 && zRight ){ Index *pIdx; Table *pTab; if( sqlite3ReadSchema(pParse) ) goto pragma_out; pIdx = sqlite3FindIndex(db, zRight, zDb); if( pIdx ){ int i; pTab = pIdx->pTable; sqlite3VdbeSetNumCols(v, 3); pParse->nMem = 3; sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seqno", SQLITE_STATIC); sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "cid", SQLITE_STATIC); sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "name", SQLITE_STATIC); for(i=0; i<pIdx->nColumn; i++){ int cnum = pIdx->aiColumn[i]; sqlite3VdbeAddOp2(v, OP_Integer, i, 1); sqlite3VdbeAddOp2(v, OP_Integer, cnum, 2); |
︙ | ︙ | |||
94440 94441 94442 94443 94444 94445 94446 | if( pTab ){ v = sqlite3GetVdbe(pParse); pIdx = pTab->pIndex; if( pIdx ){ int i = 0; sqlite3VdbeSetNumCols(v, 3); pParse->nMem = 3; | < | 92417 92418 92419 92420 92421 92422 92423 92424 92425 92426 92427 92428 92429 92430 | if( pTab ){ v = sqlite3GetVdbe(pParse); pIdx = pTab->pIndex; if( pIdx ){ int i = 0; sqlite3VdbeSetNumCols(v, 3); pParse->nMem = 3; sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", SQLITE_STATIC); sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE_STATIC); sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "unique", SQLITE_STATIC); while(pIdx){ sqlite3VdbeAddOp2(v, OP_Integer, i, 1); sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, pIdx->zName, 0); sqlite3VdbeAddOp2(v, OP_Integer, pIdx->onError!=OE_None, 3); |
︙ | ︙ | |||
94504 94505 94506 94507 94508 94509 94510 | if( pTab ){ v = sqlite3GetVdbe(pParse); pFK = pTab->pFKey; if( pFK ){ int i = 0; sqlite3VdbeSetNumCols(v, 8); pParse->nMem = 8; | < | 92480 92481 92482 92483 92484 92485 92486 92487 92488 92489 92490 92491 92492 92493 | if( pTab ){ v = sqlite3GetVdbe(pParse); pFK = pTab->pFKey; if( pFK ){ int i = 0; sqlite3VdbeSetNumCols(v, 8); pParse->nMem = 8; sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "id", SQLITE_STATIC); sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "seq", SQLITE_STATIC); sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "table", SQLITE_STATIC); sqlite3VdbeSetColName(v, 3, COLNAME_NAME, "from", SQLITE_STATIC); sqlite3VdbeSetColName(v, 4, COLNAME_NAME, "to", SQLITE_STATIC); sqlite3VdbeSetColName(v, 5, COLNAME_NAME, "on_update", SQLITE_STATIC); sqlite3VdbeSetColName(v, 6, COLNAME_NAME, "on_delete", SQLITE_STATIC); |
︙ | ︙ | |||
94536 94537 94538 94539 94540 94541 94542 | } ++i; pFK = pFK->pNextFrom; } } } }else | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 92511 92512 92513 92514 92515 92516 92517 92518 92519 92520 92521 92522 92523 92524 | } ++i; pFK = pFK->pNextFrom; } } } }else #endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */ #ifndef NDEBUG if( sqlite3StrICmp(zLeft, "parser_trace")==0 ){ if( zRight ){ if( sqlite3GetBoolean(zRight, 0) ){ sqlite3ParserTrace(stderr, "parser: "); |
︙ | ︙ | |||
94938 94939 94940 94941 94942 94943 94944 | /* ** PRAGMA [database.]schema_version ** PRAGMA [database.]schema_version = <integer> ** ** PRAGMA [database.]user_version ** PRAGMA [database.]user_version = <integer> ** | < < < < < | 92797 92798 92799 92800 92801 92802 92803 92804 92805 92806 92807 92808 92809 92810 | /* ** PRAGMA [database.]schema_version ** PRAGMA [database.]schema_version = <integer> ** ** PRAGMA [database.]user_version ** PRAGMA [database.]user_version = <integer> ** ** The pragma's schema_version and user_version are used to set or get ** the value of the schema-version and user-version, respectively. Both ** the schema-version and the user-version are 32-bit signed integers ** stored in the database header. ** ** The schema-cookie is usually only manipulated internally by SQLite. It ** is incremented by SQLite whenever the database schema is modified (by |
︙ | ︙ | |||
94964 94965 94966 94967 94968 94969 94970 | ** ** The user-version is not used internally by SQLite. It may be used by ** applications for any purpose. */ if( sqlite3StrICmp(zLeft, "schema_version")==0 || sqlite3StrICmp(zLeft, "user_version")==0 || sqlite3StrICmp(zLeft, "freelist_count")==0 | < < < < | 92818 92819 92820 92821 92822 92823 92824 92825 92826 92827 92828 92829 92830 92831 92832 92833 92834 92835 | ** ** The user-version is not used internally by SQLite. It may be used by ** applications for any purpose. */ if( sqlite3StrICmp(zLeft, "schema_version")==0 || sqlite3StrICmp(zLeft, "user_version")==0 || sqlite3StrICmp(zLeft, "freelist_count")==0 ){ int iCookie; /* Cookie index. 1 for schema-cookie, 6 for user-cookie. */ sqlite3VdbeUsesBtree(v, iDb); switch( zLeft[0] ){ case 'f': case 'F': iCookie = BTREE_FREE_PAGE_COUNT; break; case 's': case 'S': iCookie = BTREE_SCHEMA_VERSION; break; default: |
︙ | ︙ | |||
95160 95161 95162 95163 95164 95165 95166 | sqlite3_key(db, zKey, i/2); }else{ sqlite3_rekey(db, zKey, i/2); } }else #endif #if defined(SQLITE_HAS_CODEC) || defined(SQLITE_ENABLE_CEROD) | | | 93010 93011 93012 93013 93014 93015 93016 93017 93018 93019 93020 93021 93022 93023 93024 | sqlite3_key(db, zKey, i/2); }else{ sqlite3_rekey(db, zKey, i/2); } }else #endif #if defined(SQLITE_HAS_CODEC) || defined(SQLITE_ENABLE_CEROD) if( sqlite3StrICmp(zLeft, "activate_extensions")==0 ){ #ifdef SQLITE_HAS_CODEC if( sqlite3StrNICmp(zRight, "see-", 4)==0 ){ sqlite3_activate_see(&zRight[4]); } #endif #ifdef SQLITE_ENABLE_CEROD if( sqlite3StrNICmp(zRight, "cerod-", 6)==0 ){ |
︙ | ︙ | |||
95377 95378 95379 95380 95381 95382 95383 | assert( iDb>=0 && iDb<db->nDb ); assert( db->aDb[iDb].pSchema ); assert( sqlite3_mutex_held(db->mutex) ); assert( iDb==1 || sqlite3BtreeHoldsMutex(db->aDb[iDb].pBt) ); /* zMasterSchema and zInitScript are set to point at the master schema ** and initialisation script appropriate for the database being | | | 93227 93228 93229 93230 93231 93232 93233 93234 93235 93236 93237 93238 93239 93240 93241 | assert( iDb>=0 && iDb<db->nDb ); assert( db->aDb[iDb].pSchema ); assert( sqlite3_mutex_held(db->mutex) ); assert( iDb==1 || sqlite3BtreeHoldsMutex(db->aDb[iDb].pBt) ); /* zMasterSchema and zInitScript are set to point at the master schema ** and initialisation script appropriate for the database being ** initialised. zMasterName is the name of the master table. */ if( !OMIT_TEMPDB && iDb==1 ){ zMasterSchema = temp_master_schema; }else{ zMasterSchema = master_schema; } zMasterName = SCHEMA_TABLE(iDb); |
︙ | ︙ | |||
95457 95458 95459 95460 95461 95462 95463 | /* If opening a non-empty database, check the text encoding. For the ** main database, set sqlite3.enc to the encoding of the main database. ** For an attached db, it is an error if the encoding is not the same ** as sqlite3.enc. */ if( meta[BTREE_TEXT_ENCODING-1] ){ /* text encoding */ if( iDb==0 ){ | < < < < | 93307 93308 93309 93310 93311 93312 93313 93314 93315 93316 93317 93318 93319 93320 93321 93322 93323 93324 93325 | /* If opening a non-empty database, check the text encoding. For the ** main database, set sqlite3.enc to the encoding of the main database. ** For an attached db, it is an error if the encoding is not the same ** as sqlite3.enc. */ if( meta[BTREE_TEXT_ENCODING-1] ){ /* text encoding */ if( iDb==0 ){ u8 encoding; /* If opening the main database, set ENC(db). */ encoding = (u8)meta[BTREE_TEXT_ENCODING-1] & 3; if( encoding==0 ) encoding = SQLITE_UTF8; ENC(db) = encoding; }else{ /* If opening an attached database, the encoding much match ENC(db) */ if( meta[BTREE_TEXT_ENCODING-1]!=ENC(db) ){ sqlite3SetString(pzErrMsg, db, "attached databases must use the same" " text encoding as main database"); rc = SQLITE_ERROR; goto initone_error_out; |
︙ | ︙ | |||
95602 95603 95604 95605 95606 95607 95608 | if( DbHasProperty(db, i, DB_SchemaLoaded) || i==1 ) continue; rc = sqlite3InitOne(db, i, pzErrMsg); if( rc ){ sqlite3ResetOneSchema(db, i); } } | | | 93448 93449 93450 93451 93452 93453 93454 93455 93456 93457 93458 93459 93460 93461 93462 | if( DbHasProperty(db, i, DB_SchemaLoaded) || i==1 ) continue; rc = sqlite3InitOne(db, i, pzErrMsg); if( rc ){ sqlite3ResetOneSchema(db, i); } } /* Once all the other databases have been initialised, load the schema ** for the TEMP database. This is loaded last, as the TEMP database ** schema may contain references to objects in other databases. */ #ifndef SQLITE_OMIT_TEMPDB if( rc==SQLITE_OK && ALWAYS(db->nDb>1) && !DbHasProperty(db, 1, DB_SchemaLoaded) ){ rc = sqlite3InitOne(db, 1, pzErrMsg); |
︙ | ︙ | |||
95625 95626 95627 95628 95629 95630 95631 | sqlite3CommitInternalChanges(db); } return rc; } /* | | | 93471 93472 93473 93474 93475 93476 93477 93478 93479 93480 93481 93482 93483 93484 93485 | sqlite3CommitInternalChanges(db); } return rc; } /* ** This routine is a no-op if the database schema is already initialised. ** Otherwise, the schema is loaded. An error code is returned. */ SQLITE_PRIVATE int sqlite3ReadSchema(Parse *pParse){ int rc = SQLITE_OK; sqlite3 *db = pParse->db; assert( sqlite3_mutex_held(db->mutex) ); if( !db->init.busy ){ |
︙ | ︙ | |||
95852 95853 95854 95855 95856 95857 95858 95859 95860 95861 95862 95863 95864 95865 | for(i=iFirst; i<mx; i++){ sqlite3VdbeSetColName(pParse->pVdbe, i-iFirst, COLNAME_NAME, azColName[i], SQLITE_STATIC); } } #endif if( db->init.busy==0 ){ Vdbe *pVdbe = pParse->pVdbe; sqlite3VdbeSetSql(pVdbe, zSql, (int)(pParse->zTail-zSql), saveSqlFlag); } if( pParse->pVdbe && (rc!=SQLITE_OK || db->mallocFailed) ){ sqlite3VdbeFinalize(pParse->pVdbe); assert(!(*ppStmt)); | > | 93698 93699 93700 93701 93702 93703 93704 93705 93706 93707 93708 93709 93710 93711 93712 | for(i=iFirst; i<mx; i++){ sqlite3VdbeSetColName(pParse->pVdbe, i-iFirst, COLNAME_NAME, azColName[i], SQLITE_STATIC); } } #endif assert( db->init.busy==0 || saveSqlFlag==0 ); if( db->init.busy==0 ){ Vdbe *pVdbe = pParse->pVdbe; sqlite3VdbeSetSql(pVdbe, zSql, (int)(pParse->zTail-zSql), saveSqlFlag); } if( pParse->pVdbe && (rc!=SQLITE_OK || db->mallocFailed) ){ sqlite3VdbeFinalize(pParse->pVdbe); assert(!(*ppStmt)); |
︙ | ︙ | |||
96122 96123 96124 96125 96126 96127 96128 | Parse *pParse, /* Parsing context */ ExprList *pEList, /* which columns to include in the result */ SrcList *pSrc, /* the FROM clause -- which tables to scan */ Expr *pWhere, /* the WHERE clause */ ExprList *pGroupBy, /* the GROUP BY clause */ Expr *pHaving, /* the HAVING clause */ ExprList *pOrderBy, /* the ORDER BY clause */ | | | 93969 93970 93971 93972 93973 93974 93975 93976 93977 93978 93979 93980 93981 93982 93983 | Parse *pParse, /* Parsing context */ ExprList *pEList, /* which columns to include in the result */ SrcList *pSrc, /* the FROM clause -- which tables to scan */ Expr *pWhere, /* the WHERE clause */ ExprList *pGroupBy, /* the GROUP BY clause */ Expr *pHaving, /* the HAVING clause */ ExprList *pOrderBy, /* the ORDER BY clause */ int isDistinct, /* true if the DISTINCT keyword is present */ Expr *pLimit, /* LIMIT value. NULL means not used */ Expr *pOffset /* OFFSET value. NULL means no offset */ ){ Select *pNew; Select standin; sqlite3 *db = pParse->db; pNew = sqlite3DbMallocZero(db, sizeof(*pNew) ); |
︙ | ︙ | |||
96146 96147 96148 96149 96150 96151 96152 | pNew->pEList = pEList; if( pSrc==0 ) pSrc = sqlite3DbMallocZero(db, sizeof(*pSrc)); pNew->pSrc = pSrc; pNew->pWhere = pWhere; pNew->pGroupBy = pGroupBy; pNew->pHaving = pHaving; pNew->pOrderBy = pOrderBy; | | | 93993 93994 93995 93996 93997 93998 93999 94000 94001 94002 94003 94004 94005 94006 94007 | pNew->pEList = pEList; if( pSrc==0 ) pSrc = sqlite3DbMallocZero(db, sizeof(*pSrc)); pNew->pSrc = pSrc; pNew->pWhere = pWhere; pNew->pGroupBy = pGroupBy; pNew->pHaving = pHaving; pNew->pOrderBy = pOrderBy; pNew->selFlags = isDistinct ? SF_Distinct : 0; pNew->op = TK_SELECT; pNew->pLimit = pLimit; pNew->pOffset = pOffset; assert( pOffset==0 || pLimit!=0 ); pNew->addrOpenEphm[0] = -1; pNew->addrOpenEphm[1] = -1; pNew->addrOpenEphm[2] = -1; |
︙ | ︙ | |||
97402 97403 97404 97405 97406 97407 97408 | } *pnCol = nCol; *paCol = aCol; for(i=0, pCol=aCol; i<nCol; i++, pCol++){ /* Get an appropriate name for the column */ | | > > | 95249 95250 95251 95252 95253 95254 95255 95256 95257 95258 95259 95260 95261 95262 95263 95264 95265 | } *pnCol = nCol; *paCol = aCol; for(i=0, pCol=aCol; i<nCol; i++, pCol++){ /* Get an appropriate name for the column */ p = pEList->a[i].pExpr; assert( p->pRight==0 || ExprHasProperty(p->pRight, EP_IntValue) || p->pRight->u.zToken==0 || p->pRight->u.zToken[0]!=0 ); if( (zName = pEList->a[i].zName)!=0 ){ /* If the column contains an "AS <name>" phrase, use <name> as the name */ zName = sqlite3DbStrDup(db, zName); }else{ Expr *pColExpr = p; /* The expression that is the result column name */ Table *pTab; /* Table associated with this expression */ while( pColExpr->op==TK_DOT ){ |
︙ | ︙ | |||
97440 97441 97442 97443 97444 97445 97446 | /* Make sure the column name is unique. If the name is not unique, ** append a integer to the name so that it becomes unique. */ nName = sqlite3Strlen30(zName); for(j=cnt=0; j<i; j++){ if( sqlite3StrICmp(aCol[j].zName, zName)==0 ){ char *zNewName; | < < < | 95289 95290 95291 95292 95293 95294 95295 95296 95297 95298 95299 95300 95301 95302 | /* Make sure the column name is unique. If the name is not unique, ** append a integer to the name so that it becomes unique. */ nName = sqlite3Strlen30(zName); for(j=cnt=0; j<i; j++){ if( sqlite3StrICmp(aCol[j].zName, zName)==0 ){ char *zNewName; zName[nName] = 0; zNewName = sqlite3MPrintf(db, "%s:%d", zName, ++cnt); sqlite3DbFree(db, zName); zName = zNewName; j = -1; if( zName==0 ) break; } |
︙ | ︙ | |||
97774 97775 97776 97777 97778 97779 97780 | /* Generate code for the left and right SELECT statements. */ switch( p->op ){ case TK_ALL: { int addr = 0; int nLimit; assert( !pPrior->pLimit ); | < < | 95620 95621 95622 95623 95624 95625 95626 95627 95628 95629 95630 95631 95632 95633 | /* Generate code for the left and right SELECT statements. */ switch( p->op ){ case TK_ALL: { int addr = 0; int nLimit; assert( !pPrior->pLimit ); pPrior->pLimit = p->pLimit; pPrior->pOffset = p->pOffset; explainSetInteger(iSub1, pParse->iNextSelectId); rc = sqlite3Select(pParse, pPrior, &dest); p->pLimit = 0; p->pOffset = 0; if( rc ){ |
︙ | ︙ | |||
98403 98404 98405 98406 98407 98408 98409 | if( pKeyMerge ){ pKeyMerge->aSortOrder = (u8*)&pKeyMerge->aColl[nOrderBy]; pKeyMerge->nField = (u16)nOrderBy; pKeyMerge->enc = ENC(db); for(i=0; i<nOrderBy; i++){ CollSeq *pColl; Expr *pTerm = pOrderBy->a[i].pExpr; | | | | < | | 96247 96248 96249 96250 96251 96252 96253 96254 96255 96256 96257 96258 96259 96260 96261 96262 96263 96264 96265 96266 | if( pKeyMerge ){ pKeyMerge->aSortOrder = (u8*)&pKeyMerge->aColl[nOrderBy]; pKeyMerge->nField = (u16)nOrderBy; pKeyMerge->enc = ENC(db); for(i=0; i<nOrderBy; i++){ CollSeq *pColl; Expr *pTerm = pOrderBy->a[i].pExpr; if( pTerm->flags & EP_ExpCollate ){ pColl = pTerm->pColl; }else{ pColl = multiSelectCollSeq(pParse, p, aPermute[i]); pTerm->flags |= EP_ExpCollate; pTerm->pColl = pColl; } pKeyMerge->aColl[i] = pColl; pKeyMerge->aSortOrder[i] = pOrderBy->a[i].sortOrder; } } }else{ pKeyMerge = 0; |
︙ | ︙ | |||
98433 98434 98435 98436 98437 98438 98439 | ** operator is UNION, EXCEPT, or INTERSECT (but not UNION ALL). */ if( op==TK_ALL ){ regPrev = 0; }else{ int nExpr = p->pEList->nExpr; assert( nOrderBy>=nExpr || db->mallocFailed ); | | < | 96276 96277 96278 96279 96280 96281 96282 96283 96284 96285 96286 96287 96288 96289 96290 | ** operator is UNION, EXCEPT, or INTERSECT (but not UNION ALL). */ if( op==TK_ALL ){ regPrev = 0; }else{ int nExpr = p->pEList->nExpr; assert( nOrderBy>=nExpr || db->mallocFailed ); regPrev = sqlite3GetTempRange(pParse, nExpr+1); sqlite3VdbeAddOp2(v, OP_Integer, 0, regPrev); pKeyDup = sqlite3DbMallocZero(db, sizeof(*pKeyDup) + nExpr*(sizeof(CollSeq*)+1) ); if( pKeyDup ){ pKeyDup->aSortOrder = (u8*)&pKeyDup->aColl[nExpr]; pKeyDup->nField = (u16)nExpr; pKeyDup->enc = ENC(db); |
︙ | ︙ | |||
98613 98614 98615 98616 98617 98618 98619 | /* Implement the main merge loop */ sqlite3VdbeResolveLabel(v, labelCmpr); sqlite3VdbeAddOp4(v, OP_Permutation, 0, 0, 0, (char*)aPermute, P4_INTARRAY); sqlite3VdbeAddOp4(v, OP_Compare, destA.iSdst, destB.iSdst, nOrderBy, (char*)pKeyMerge, P4_KEYINFO_HANDOFF); | < > > > > > > | 96455 96456 96457 96458 96459 96460 96461 96462 96463 96464 96465 96466 96467 96468 96469 96470 96471 96472 96473 96474 96475 | /* Implement the main merge loop */ sqlite3VdbeResolveLabel(v, labelCmpr); sqlite3VdbeAddOp4(v, OP_Permutation, 0, 0, 0, (char*)aPermute, P4_INTARRAY); sqlite3VdbeAddOp4(v, OP_Compare, destA.iSdst, destB.iSdst, nOrderBy, (char*)pKeyMerge, P4_KEYINFO_HANDOFF); sqlite3VdbeAddOp3(v, OP_Jump, addrAltB, addrAeqB, addrAgtB); /* Release temporary registers */ if( regPrev ){ sqlite3ReleaseTempRange(pParse, regPrev, nOrderBy+1); } /* Jump to the this point in order to terminate the query. */ sqlite3VdbeResolveLabel(v, labelEnd); /* Set the number of output columns */ |
︙ | ︙ | |||
98675 98676 98677 98678 98679 98680 98681 98682 98683 98684 98685 98686 98687 98688 | if( pExpr->iColumn<0 ){ pExpr->op = TK_NULL; }else{ Expr *pNew; assert( pEList!=0 && pExpr->iColumn<pEList->nExpr ); assert( pExpr->pLeft==0 && pExpr->pRight==0 ); pNew = sqlite3ExprDup(db, pEList->a[pExpr->iColumn].pExpr, 0); sqlite3ExprDelete(db, pExpr); pExpr = pNew; } }else{ pExpr->pLeft = substExpr(db, pExpr->pLeft, iTable, pEList); pExpr->pRight = substExpr(db, pExpr->pRight, iTable, pEList); if( ExprHasProperty(pExpr, EP_xIsSelect) ){ | > > > | 96522 96523 96524 96525 96526 96527 96528 96529 96530 96531 96532 96533 96534 96535 96536 96537 96538 | if( pExpr->iColumn<0 ){ pExpr->op = TK_NULL; }else{ Expr *pNew; assert( pEList!=0 && pExpr->iColumn<pEList->nExpr ); assert( pExpr->pLeft==0 && pExpr->pRight==0 ); pNew = sqlite3ExprDup(db, pEList->a[pExpr->iColumn].pExpr, 0); if( pNew && pExpr->pColl ){ pNew->pColl = pExpr->pColl; } sqlite3ExprDelete(db, pExpr); pExpr = pNew; } }else{ pExpr->pLeft = substExpr(db, pExpr->pLeft, iTable, pEList); pExpr->pRight = substExpr(db, pExpr->pRight, iTable, pEList); if( ExprHasProperty(pExpr, EP_xIsSelect) ){ |
︙ | ︙ | |||
99027 99028 99029 99030 99031 99032 99033 | ** ** We call this the "compound-subquery flattening". */ for(pSub=pSub->pPrior; pSub; pSub=pSub->pPrior){ Select *pNew; ExprList *pOrderBy = p->pOrderBy; Expr *pLimit = p->pLimit; | < < < | 96877 96878 96879 96880 96881 96882 96883 96884 96885 96886 96887 96888 96889 96890 96891 96892 96893 96894 96895 96896 | ** ** We call this the "compound-subquery flattening". */ for(pSub=pSub->pPrior; pSub; pSub=pSub->pPrior){ Select *pNew; ExprList *pOrderBy = p->pOrderBy; Expr *pLimit = p->pLimit; Select *pPrior = p->pPrior; p->pOrderBy = 0; p->pSrc = 0; p->pPrior = 0; p->pLimit = 0; pNew = sqlite3SelectDup(db, p, 0); p->pLimit = pLimit; p->pOrderBy = pOrderBy; p->pSrc = pSrc; p->op = TK_ALL; p->pRightmost = 0; if( pNew==0 ){ pNew = pPrior; |
︙ | ︙ | |||
99165 99166 99167 99168 99169 99170 99171 | ** ** We look at every expression in the outer query and every place we see ** "a" we substitute "x*3" and every place we see "b" we substitute "y+10". */ pList = pParent->pEList; for(i=0; i<pList->nExpr; i++){ if( pList->a[i].zName==0 ){ | | | | > | 97012 97013 97014 97015 97016 97017 97018 97019 97020 97021 97022 97023 97024 97025 97026 97027 97028 97029 | ** ** We look at every expression in the outer query and every place we see ** "a" we substitute "x*3" and every place we see "b" we substitute "y+10". */ pList = pParent->pEList; for(i=0; i<pList->nExpr; i++){ if( pList->a[i].zName==0 ){ const char *zSpan = pList->a[i].zSpan; if( ALWAYS(zSpan) ){ pList->a[i].zName = sqlite3DbStrDup(db, zSpan); } } } substExprList(db, pParent->pEList, iParent, pSub->pEList); if( isAgg ){ substExprList(db, pParent->pGroupBy, iParent, pSub->pEList); pParent->pHaving = substExpr(db, pParent->pHaving, iParent, pSub->pEList); } |
︙ | ︙ | |||
99228 99229 99230 99231 99232 99233 99234 | sqlite3SelectDelete(db, pSub1); return 1; } #endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */ /* | < | > > > | < < | | < < < < | < < < < | | > > | > > > | | | | < | | < | < < < < | | 97076 97077 97078 97079 97080 97081 97082 97083 97084 97085 97086 97087 97088 97089 97090 97091 97092 97093 97094 97095 97096 97097 97098 97099 97100 97101 97102 97103 97104 97105 97106 97107 97108 97109 97110 97111 97112 97113 97114 97115 97116 97117 | sqlite3SelectDelete(db, pSub1); return 1; } #endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */ /* ** Analyze the SELECT statement passed as an argument to see if it ** is a min() or max() query. Return WHERE_ORDERBY_MIN or WHERE_ORDERBY_MAX if ** it is, or 0 otherwise. At present, a query is considered to be ** a min()/max() query if: ** ** 1. There is a single object in the FROM clause. ** ** 2. There is a single expression in the result set, and it is ** either min(x) or max(x), where x is a column reference. */ static u8 minMaxQuery(Select *p){ Expr *pExpr; ExprList *pEList = p->pEList; if( pEList->nExpr!=1 ) return WHERE_ORDERBY_NORMAL; pExpr = pEList->a[0].pExpr; if( pExpr->op!=TK_AGG_FUNCTION ) return 0; if( NEVER(ExprHasProperty(pExpr, EP_xIsSelect)) ) return 0; pEList = pExpr->x.pList; if( pEList==0 || pEList->nExpr!=1 ) return 0; if( pEList->a[0].pExpr->op!=TK_AGG_COLUMN ) return WHERE_ORDERBY_NORMAL; assert( !ExprHasProperty(pExpr, EP_IntValue) ); if( sqlite3StrICmp(pExpr->u.zToken,"min")==0 ){ return WHERE_ORDERBY_MIN; }else if( sqlite3StrICmp(pExpr->u.zToken,"max")==0 ){ return WHERE_ORDERBY_MAX; } return WHERE_ORDERBY_NORMAL; } /* ** The select statement passed as the first argument is an aggregate query. ** The second argment is the associated aggregate-info object. This ** function tests if the SELECT is of the form: ** |
︙ | ︙ | |||
99327 99328 99329 99330 99331 99332 99333 | pParse->checkSchema = 1; return SQLITE_ERROR; } pFrom->pIndex = pIdx; } return SQLITE_OK; } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 97166 97167 97168 97169 97170 97171 97172 97173 97174 97175 97176 97177 97178 97179 | pParse->checkSchema = 1; return SQLITE_ERROR; } pFrom->pIndex = pIdx; } return SQLITE_OK; } /* ** This routine is a Walker callback for "expanding" a SELECT statement. ** "Expanding" means to do the following: ** ** (1) Make sure VDBE cursor numbers have been assigned to every ** element of the FROM clause. |
︙ | ︙ | |||
99422 99423 99424 99425 99426 99427 99428 | static int selectExpander(Walker *pWalker, Select *p){ Parse *pParse = pWalker->pParse; int i, j, k; SrcList *pTabList; ExprList *pEList; struct SrcList_item *pFrom; sqlite3 *db = pParse->db; | < < < | > | 97198 97199 97200 97201 97202 97203 97204 97205 97206 97207 97208 97209 97210 97211 97212 97213 97214 97215 97216 97217 97218 97219 | static int selectExpander(Walker *pWalker, Select *p){ Parse *pParse = pWalker->pParse; int i, j, k; SrcList *pTabList; ExprList *pEList; struct SrcList_item *pFrom; sqlite3 *db = pParse->db; if( db->mallocFailed ){ return WRC_Abort; } if( NEVER(p->pSrc==0) || (p->selFlags & SF_Expanded)!=0 ){ return WRC_Prune; } p->selFlags |= SF_Expanded; pTabList = p->pSrc; pEList = p->pEList; /* Make sure cursor numbers have been assigned to all entries in ** the FROM clause of the SELECT statement. */ sqlite3SrcListAssignCursors(pParse, pTabList); |
︙ | ︙ | |||
99474 99475 99476 99477 99478 99479 99480 | pTab->tabFlags |= TF_Ephemeral; #endif }else{ /* An ordinary table or view name in the FROM clause */ assert( pFrom->pTab==0 ); pFrom->pTab = pTab = sqlite3LocateTableItem(pParse, 0, pFrom); if( pTab==0 ) return WRC_Abort; | < < < < < < | 97248 97249 97250 97251 97252 97253 97254 97255 97256 97257 97258 97259 97260 97261 | pTab->tabFlags |= TF_Ephemeral; #endif }else{ /* An ordinary table or view name in the FROM clause */ assert( pFrom->pTab==0 ); pFrom->pTab = pTab = sqlite3LocateTableItem(pParse, 0, pFrom); if( pTab==0 ) return WRC_Abort; pTab->nRef++; #if !defined(SQLITE_OMIT_VIEW) || !defined (SQLITE_OMIT_VIRTUALTABLE) if( pTab->pSelect || IsVirtual(pTab) ){ /* We reach here if the named table is a really a view */ if( sqlite3ViewGetColumnNames(pParse, pTab) ) return WRC_Abort; assert( pFrom->pSelect==0 ); pFrom->pSelect = sqlite3SelectDup(db, pTab->pSelect, 0); |
︙ | ︙ | |||
99515 99516 99517 99518 99519 99520 99521 | ** The following code just has to locate the TK_ALL expressions and expand ** each one to the list of all columns in all tables. ** ** The first loop just checks to see if there are any "*" operators ** that need expanding. */ for(k=0; k<pEList->nExpr; k++){ | | < < < < < < < | < | | | > > < < < < < | | | | < < > < < < < < < < < | 97283 97284 97285 97286 97287 97288 97289 97290 97291 97292 97293 97294 97295 97296 97297 97298 97299 97300 97301 97302 97303 97304 97305 97306 97307 97308 97309 97310 97311 97312 97313 97314 97315 97316 97317 97318 97319 97320 97321 97322 97323 97324 97325 97326 97327 97328 97329 97330 97331 97332 97333 97334 97335 97336 97337 97338 97339 97340 97341 97342 97343 97344 97345 97346 97347 97348 97349 97350 97351 97352 97353 97354 97355 97356 97357 97358 97359 97360 97361 97362 97363 97364 97365 97366 | ** The following code just has to locate the TK_ALL expressions and expand ** each one to the list of all columns in all tables. ** ** The first loop just checks to see if there are any "*" operators ** that need expanding. */ for(k=0; k<pEList->nExpr; k++){ Expr *pE = pEList->a[k].pExpr; if( pE->op==TK_ALL ) break; assert( pE->op!=TK_DOT || pE->pRight!=0 ); assert( pE->op!=TK_DOT || (pE->pLeft!=0 && pE->pLeft->op==TK_ID) ); if( pE->op==TK_DOT && pE->pRight->op==TK_ALL ) break; } if( k<pEList->nExpr ){ /* ** If we get here it means the result set contains one or more "*" ** operators that need to be expanded. Loop through each expression ** in the result set and expand them one by one. */ struct ExprList_item *a = pEList->a; ExprList *pNew = 0; int flags = pParse->db->flags; int longNames = (flags & SQLITE_FullColNames)!=0 && (flags & SQLITE_ShortColNames)==0; for(k=0; k<pEList->nExpr; k++){ Expr *pE = a[k].pExpr; assert( pE->op!=TK_DOT || pE->pRight!=0 ); if( pE->op!=TK_ALL && (pE->op!=TK_DOT || pE->pRight->op!=TK_ALL) ){ /* This particular expression does not need to be expanded. */ pNew = sqlite3ExprListAppend(pParse, pNew, a[k].pExpr); if( pNew ){ pNew->a[pNew->nExpr-1].zName = a[k].zName; pNew->a[pNew->nExpr-1].zSpan = a[k].zSpan; a[k].zName = 0; a[k].zSpan = 0; } a[k].pExpr = 0; }else{ /* This expression is a "*" or a "TABLE.*" and needs to be ** expanded. */ int tableSeen = 0; /* Set to 1 when TABLE matches */ char *zTName; /* text of name of TABLE */ if( pE->op==TK_DOT ){ assert( pE->pLeft!=0 ); assert( !ExprHasProperty(pE->pLeft, EP_IntValue) ); zTName = pE->pLeft->u.zToken; }else{ zTName = 0; } for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){ Table *pTab = pFrom->pTab; char *zTabName = pFrom->zAlias; if( zTabName==0 ){ zTabName = pTab->zName; } if( db->mallocFailed ) break; if( zTName && sqlite3StrICmp(zTName, zTabName)!=0 ){ continue; } tableSeen = 1; for(j=0; j<pTab->nCol; j++){ Expr *pExpr, *pRight; char *zName = pTab->aCol[j].zName; char *zColname; /* The computed column name */ char *zToFree; /* Malloced string that needs to be freed */ Token sColname; /* Computed column name as a token */ /* If a column is marked as 'hidden' (currently only possible ** for virtual tables), do not include it in the expanded ** result-set list. */ if( IsHiddenColumn(&pTab->aCol[j]) ){ assert(IsVirtual(pTab)); continue; } if( i>0 && zTName==0 ){ if( (pFrom->jointype & JT_NATURAL)!=0 && tableAndColumnIndex(pTabList, i, zName, 0, 0) ){ /* In a NATURAL join, omit the join columns from the ** table to the right of the join */ |
︙ | ︙ | |||
99627 99628 99629 99630 99631 99632 99633 | pRight = sqlite3Expr(db, TK_ID, zName); zColname = zName; zToFree = 0; if( longNames || pTabList->nSrc>1 ){ Expr *pLeft; pLeft = sqlite3Expr(db, TK_ID, zTabName); pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight, 0); | < < < < < < < < < < < < < < < < | 97375 97376 97377 97378 97379 97380 97381 97382 97383 97384 97385 97386 97387 97388 97389 97390 97391 97392 97393 97394 97395 97396 97397 97398 97399 | pRight = sqlite3Expr(db, TK_ID, zName); zColname = zName; zToFree = 0; if( longNames || pTabList->nSrc>1 ){ Expr *pLeft; pLeft = sqlite3Expr(db, TK_ID, zTabName); pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight, 0); if( longNames ){ zColname = sqlite3MPrintf(db, "%s.%s", zTabName, zName); zToFree = zColname; } }else{ pExpr = pRight; } pNew = sqlite3ExprListAppend(pParse, pNew, pExpr); sColname.z = zColname; sColname.n = sqlite3Strlen30(zColname); sqlite3ExprListSetName(pParse, pNew, &sColname, 0); sqlite3DbFree(db, zToFree); } } if( !tableSeen ){ if( zTName ){ sqlite3ErrorMsg(pParse, "no such table: %s", zTName); }else{ |
︙ | ︙ | |||
99706 99707 99708 99709 99710 99711 99712 | ** ** If anything goes wrong, an error message is written into pParse. ** The calling function can detect the problem by looking at pParse->nErr ** and/or pParse->db->mallocFailed. */ static void sqlite3SelectExpand(Parse *pParse, Select *pSelect){ Walker w; | < | < < | 97438 97439 97440 97441 97442 97443 97444 97445 97446 97447 97448 97449 97450 97451 97452 97453 97454 97455 | ** ** If anything goes wrong, an error message is written into pParse. ** The calling function can detect the problem by looking at pParse->nErr ** and/or pParse->db->mallocFailed. */ static void sqlite3SelectExpand(Parse *pParse, Select *pSelect){ Walker w; w.xSelectCallback = selectExpander; w.xExprCallback = exprWalkNoop; w.pParse = pParse; sqlite3WalkSelect(&w, pSelect); } #ifndef SQLITE_OMIT_SUBQUERY /* ** This is a Walker.xSelectCallback callback for the sqlite3SelectTypeInfo() ** interface. |
︙ | ︙ | |||
99767 99768 99769 99770 99771 99772 99773 | ** SELECT statement. ** ** Use this routine after name resolution. */ static void sqlite3SelectAddTypeInfo(Parse *pParse, Select *pSelect){ #ifndef SQLITE_OMIT_SUBQUERY Walker w; | < < | 97496 97497 97498 97499 97500 97501 97502 97503 97504 97505 97506 97507 97508 97509 97510 97511 97512 | ** SELECT statement. ** ** Use this routine after name resolution. */ static void sqlite3SelectAddTypeInfo(Parse *pParse, Select *pSelect){ #ifndef SQLITE_OMIT_SUBQUERY Walker w; w.xSelectCallback = selectAddSubqueryTypeInfo; w.xExprCallback = exprWalkNoop; w.pParse = pParse; sqlite3WalkSelect(&w, pSelect); #endif } /* ** This routine sets up a SELECT statement for processing. The |
︙ | ︙ | |||
99797 99798 99799 99800 99801 99802 99803 | Parse *pParse, /* The parser context */ Select *p, /* The SELECT statement being coded. */ NameContext *pOuterNC /* Name context for container */ ){ sqlite3 *db; if( NEVER(p==0) ) return; db = pParse->db; | < | 97524 97525 97526 97527 97528 97529 97530 97531 97532 97533 97534 97535 97536 97537 | Parse *pParse, /* The parser context */ Select *p, /* The SELECT statement being coded. */ NameContext *pOuterNC /* Name context for container */ ){ sqlite3 *db; if( NEVER(p==0) ) return; db = pParse->db; if( p->selFlags & SF_HasTypeInfo ) return; sqlite3SelectExpand(pParse, p); if( pParse->nErr || db->mallocFailed ) return; sqlite3ResolveSelectNames(pParse, p, pOuterNC); if( pParse->nErr || db->mallocFailed ) return; sqlite3SelectAddTypeInfo(pParse, p); } |
︙ | ︙ | |||
100098 100099 100100 100101 100102 100103 100104 | 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; | < < < < < < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | 97824 97825 97826 97827 97828 97829 97830 97831 97832 97833 97834 97835 97836 97837 97838 97839 97840 97841 97842 97843 97844 97845 97846 97847 97848 97849 97850 97851 97852 97853 97854 97855 97856 97857 97858 97859 97860 97861 97862 97863 97864 97865 97866 97867 97868 97869 97870 97871 97872 97873 97874 97875 | 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 ){ /* 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. */ onceAddr = sqlite3CodeOnce(pParse); } sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor); explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId); sqlite3Select(pParse, pSub, &dest); |
︙ | ︙ | |||
100705 100706 100707 100708 100709 100710 100711 | ** If where.c is able to produce results sorted in this order, then ** add vdbe code to break out of the processing loop after the ** first iteration (since the first iteration of the loop is ** guaranteed to operate on the row with the minimum or maximum ** value of x, the only row required). ** ** A special flag must be passed to sqlite3WhereBegin() to slightly | | < < < < < | < < < > > | | 98384 98385 98386 98387 98388 98389 98390 98391 98392 98393 98394 98395 98396 98397 98398 98399 98400 98401 98402 98403 98404 98405 98406 98407 98408 98409 98410 98411 98412 98413 98414 | ** If where.c is able to produce results sorted in this order, then ** add vdbe code to break out of the processing loop after the ** first iteration (since the first iteration of the loop is ** guaranteed to operate on the row with the minimum or maximum ** value of x, the only row required). ** ** A special flag must be passed to sqlite3WhereBegin() to slightly ** modify behaviour as follows: ** ** + If the query is a "SELECT min(x)", then the loop coded by ** where.c should not iterate over any values with a NULL value ** for x. ** ** + The optimizer code in where.c (the thing that decides which ** index or indices to use) should place a different priority on ** satisfying the 'ORDER BY' clause than it does in other cases. ** Refer to code and comments in where.c for details. */ ExprList *pMinMax = 0; u8 flag = minMaxQuery(p); if( flag ){ assert( !ExprHasProperty(p->pEList->a[0].pExpr, EP_xIsSelect) ); assert( p->pEList->a[0].pExpr->x.pList->nExpr==1 ); pMinMax = sqlite3ExprListDup(db, p->pEList->a[0].pExpr->x.pList,0); pDel = pMinMax; if( pMinMax && !db->mallocFailed ){ pMinMax->a[0].sortOrder = flag!=WHERE_ORDERBY_MIN ?1:0; pMinMax->a[0].pExpr->op = TK_COLUMN; } } |
︙ | ︙ | |||
100883 100884 100885 100886 100887 100888 100889 | } } SQLITE_PRIVATE void sqlite3ExplainSelect(Vdbe *pVdbe, Select *p){ if( p==0 ){ sqlite3ExplainPrintf(pVdbe, "(null-select)"); return; } | | < < < | 98556 98557 98558 98559 98560 98561 98562 98563 98564 98565 98566 98567 98568 98569 98570 | } } SQLITE_PRIVATE void sqlite3ExplainSelect(Vdbe *pVdbe, Select *p){ if( p==0 ){ sqlite3ExplainPrintf(pVdbe, "(null-select)"); return; } while( p->pPrior ) p = p->pPrior; sqlite3ExplainPush(pVdbe); while( p ){ explainOneSelect(pVdbe, p); p = p->pNext; if( p==0 ) break; sqlite3ExplainNL(pVdbe); sqlite3ExplainPrintf(pVdbe, "%s\n", selectOpName(p->op)); |
︙ | ︙ | |||
101834 101835 101836 101837 101838 101839 101840 | ** END; ** ** INSERT INTO t1 ... ; -- insert into t2 uses REPLACE policy ** INSERT OR IGNORE INTO t1 ... ; -- insert into t2 uses IGNORE policy */ pParse->eOrconf = (orconf==OE_Default)?pStep->orconf:(u8)orconf; | < < < < < < < < < | 99504 99505 99506 99507 99508 99509 99510 99511 99512 99513 99514 99515 99516 99517 | ** END; ** ** INSERT INTO t1 ... ; -- insert into t2 uses REPLACE policy ** INSERT OR IGNORE INTO t1 ... ; -- insert into t2 uses IGNORE policy */ pParse->eOrconf = (orconf==OE_Default)?pStep->orconf:(u8)orconf; switch( pStep->op ){ case TK_UPDATE: { sqlite3Update(pParse, targetSrcList(pParse, pStep), sqlite3ExprListDup(db, pStep->pExprList, 0), sqlite3ExprDup(db, pStep->pWhere, 0), pParse->eOrconf |
︙ | ︙ | |||
102448 102449 102450 102451 102452 102453 102454 | } aXRef[j] = i; break; } } if( j>=pTab->nCol ){ if( sqlite3IsRowid(pChanges->a[i].zName) ){ | < < | | 100109 100110 100111 100112 100113 100114 100115 100116 100117 100118 100119 100120 100121 100122 100123 100124 100125 100126 100127 100128 100129 100130 100131 100132 100133 100134 100135 | } aXRef[j] = i; break; } } if( j>=pTab->nCol ){ if( sqlite3IsRowid(pChanges->a[i].zName) ){ chngRowid = 1; pRowidExpr = pChanges->a[i].pExpr; }else{ sqlite3ErrorMsg(pParse, "no such column: %s", pChanges->a[i].zName); pParse->checkSchema = 1; goto update_cleanup; } } #ifndef SQLITE_OMIT_AUTHORIZATION { int rc; rc = sqlite3AuthCheck(pParse, SQLITE_UPDATE, pTab->zName, pTab->aCol[j].zName, db->aDb[iDb].zName); if( rc==SQLITE_DENY ){ goto update_cleanup; }else if( rc==SQLITE_IGNORE ){ aXRef[j] = -1; } } #endif |
︙ | ︙ | |||
102700 102701 102702 102703 102704 102705 102706 | sqlite3VdbeAddOp2(v, OP_Affinity, regNew, pTab->nCol); sqlite3TableAffinityStr(v, pTab); sqlite3CodeRowTrigger(pParse, pTrigger, TK_UPDATE, pChanges, TRIGGER_BEFORE, pTab, regOldRowid, onError, addr); /* The row-trigger may have deleted the row being updated. In this ** case, jump to the next row. No updates or AFTER triggers are | | | 100359 100360 100361 100362 100363 100364 100365 100366 100367 100368 100369 100370 100371 100372 100373 | sqlite3VdbeAddOp2(v, OP_Affinity, regNew, pTab->nCol); sqlite3TableAffinityStr(v, pTab); sqlite3CodeRowTrigger(pParse, pTrigger, TK_UPDATE, pChanges, TRIGGER_BEFORE, pTab, regOldRowid, onError, addr); /* The row-trigger may have deleted the row being updated. In this ** case, jump to the next row. No updates or AFTER triggers are ** required. This behaviour - what happens when the row being updated ** is deleted or renamed by a BEFORE trigger - is left undefined in the ** documentation. */ sqlite3VdbeAddOp3(v, OP_NotExists, iCur, addr, regOldRowid); /* If it did not delete it, the row-trigger may still have modified ** some of the columns of the row being updated. Load the values for |
︙ | ︙ | |||
103001 103002 103003 103004 103005 103006 103007 | ** with 2.0.0, SQLite no longer uses GDBM so this command has ** become a no-op. */ SQLITE_PRIVATE void sqlite3Vacuum(Parse *pParse){ Vdbe *v = sqlite3GetVdbe(pParse); if( v ){ sqlite3VdbeAddOp2(v, OP_Vacuum, 0, 0); | < | 100660 100661 100662 100663 100664 100665 100666 100667 100668 100669 100670 100671 100672 100673 | ** with 2.0.0, SQLite no longer uses GDBM so this command has ** become a no-op. */ SQLITE_PRIVATE void sqlite3Vacuum(Parse *pParse){ Vdbe *v = sqlite3GetVdbe(pParse); if( v ){ sqlite3VdbeAddOp2(v, OP_Vacuum, 0, 0); } return; } /* ** This routine implements the OP_Vacuum opcode of the VDBE. */ |
︙ | ︙ | |||
103205 103206 103207 103208 103209 103210 103211 | ** connections to the same database will know to reread the schema. */ static const unsigned char aCopy[] = { BTREE_SCHEMA_VERSION, 1, /* Add one to the old schema cookie */ BTREE_DEFAULT_CACHE_SIZE, 0, /* Preserve the default page cache size */ BTREE_TEXT_ENCODING, 0, /* Preserve the text encoding */ BTREE_USER_VERSION, 0, /* Preserve the user version */ | < | 100863 100864 100865 100866 100867 100868 100869 100870 100871 100872 100873 100874 100875 100876 | ** connections to the same database will know to reread the schema. */ static const unsigned char aCopy[] = { BTREE_SCHEMA_VERSION, 1, /* Add one to the old schema cookie */ BTREE_DEFAULT_CACHE_SIZE, 0, /* Preserve the default page cache size */ BTREE_TEXT_ENCODING, 0, /* Preserve the text encoding */ BTREE_USER_VERSION, 0, /* Preserve the user version */ }; assert( 1==sqlite3BtreeIsInTrans(pTemp) ); assert( 1==sqlite3BtreeIsInTrans(pMain) ); /* Copy Btree meta values */ for(i=0; i<ArraySize(aCopy); i+=2){ |
︙ | ︙ | |||
103762 103763 103764 103765 103766 103767 103768 103769 103770 103771 103772 103773 103774 103775 103776 103777 103778 103779 103780 103781 103782 103783 103784 103785 103786 103787 103788 | if( !pVTable ){ sqlite3DbFree(db, zModuleName); return SQLITE_NOMEM; } pVTable->db = db; pVTable->pMod = pMod; iDb = sqlite3SchemaToIndex(db, pTab->pSchema); pTab->azModuleArg[1] = db->aDb[iDb].zName; /* Invoke the virtual table constructor */ assert( &db->pVtabCtx ); assert( xConstruct ); sCtx.pTab = pTab; sCtx.pVTable = pVTable; pPriorCtx = db->pVtabCtx; db->pVtabCtx = &sCtx; rc = xConstruct(db, pMod->pAux, nArg, azArg, &pVTable->pVtab, &zErr); db->pVtabCtx = pPriorCtx; if( rc==SQLITE_NOMEM ) db->mallocFailed = 1; if( SQLITE_OK!=rc ){ if( zErr==0 ){ *pzErr = sqlite3MPrintf(db, "vtable constructor failed: %s", zModuleName); }else { *pzErr = sqlite3MPrintf(db, "%s", zErr); sqlite3_free(zErr); | > > | 101419 101420 101421 101422 101423 101424 101425 101426 101427 101428 101429 101430 101431 101432 101433 101434 101435 101436 101437 101438 101439 101440 101441 101442 101443 101444 101445 101446 101447 | if( !pVTable ){ sqlite3DbFree(db, zModuleName); return SQLITE_NOMEM; } pVTable->db = db; pVTable->pMod = pMod; assert( pTab->azModuleArg[1]==0 ); iDb = sqlite3SchemaToIndex(db, pTab->pSchema); pTab->azModuleArg[1] = db->aDb[iDb].zName; /* Invoke the virtual table constructor */ assert( &db->pVtabCtx ); assert( xConstruct ); sCtx.pTab = pTab; sCtx.pVTable = pVTable; pPriorCtx = db->pVtabCtx; db->pVtabCtx = &sCtx; rc = xConstruct(db, pMod->pAux, nArg, azArg, &pVTable->pVtab, &zErr); db->pVtabCtx = pPriorCtx; if( rc==SQLITE_NOMEM ) db->mallocFailed = 1; pTab->azModuleArg[1] = 0; if( SQLITE_OK!=rc ){ if( zErr==0 ){ *pzErr = sqlite3MPrintf(db, "vtable constructor failed: %s", zModuleName); }else { *pzErr = sqlite3MPrintf(db, "%s", zErr); sqlite3_free(zErr); |
︙ | ︙ | |||
104466 104467 104468 104469 104470 104471 104472 | typedef struct WhereTerm WhereTerm; struct WhereTerm { Expr *pExpr; /* Pointer to the subexpression that is this term */ int iParent; /* Disable pWC->a[iParent] when this term disabled */ int leftCursor; /* Cursor number of X in "X <op> <expr>" */ union { int leftColumn; /* Column number of X in "X <op> <expr>" */ | | | | 102125 102126 102127 102128 102129 102130 102131 102132 102133 102134 102135 102136 102137 102138 102139 102140 | typedef struct WhereTerm WhereTerm; struct WhereTerm { Expr *pExpr; /* Pointer to the subexpression that is this term */ int iParent; /* Disable pWC->a[iParent] when this term disabled */ int leftCursor; /* Cursor number of X in "X <op> <expr>" */ union { int leftColumn; /* Column number of X in "X <op> <expr>" */ WhereOrInfo *pOrInfo; /* Extra information if eOperator==WO_OR */ WhereAndInfo *pAndInfo; /* Extra information if eOperator==WO_AND */ } u; u16 eOperator; /* A WO_xx value describing <op> */ u8 wtFlags; /* TERM_xxx bit flags. See below */ u8 nChild; /* Number of children that must disable us */ WhereClause *pWC; /* The clause this term is part of */ Bitmask prereqRight; /* Bitmask of tables used by pExpr->pRight */ Bitmask prereqAll; /* Bitmask of tables referenced by pExpr */ |
︙ | ︙ | |||
104508 104509 104510 104511 104512 104513 104514 104515 104516 104517 104518 104519 104520 104521 | ** There are separate WhereClause objects for the whole clause and for ** the subclauses "(b AND c)" and "(d AND e)". The pOuter field of the ** subclauses points to the WhereClause object for the whole clause. */ struct WhereClause { Parse *pParse; /* The parser context */ WhereMaskSet *pMaskSet; /* Mapping of table cursor numbers to bitmasks */ WhereClause *pOuter; /* Outer conjunction */ u8 op; /* Split operator. TK_AND or TK_OR */ u16 wctrlFlags; /* Might include WHERE_AND_ONLY */ int nTerm; /* Number of terms */ int nSlot; /* Number of entries in a[] */ WhereTerm *a; /* Each a[] describes a term of the WHERE cluase */ #if defined(SQLITE_SMALL_STACK) | > | 102167 102168 102169 102170 102171 102172 102173 102174 102175 102176 102177 102178 102179 102180 102181 | ** There are separate WhereClause objects for the whole clause and for ** the subclauses "(b AND c)" and "(d AND e)". The pOuter field of the ** subclauses points to the WhereClause object for the whole clause. */ struct WhereClause { Parse *pParse; /* The parser context */ WhereMaskSet *pMaskSet; /* Mapping of table cursor numbers to bitmasks */ Bitmask vmask; /* Bitmask identifying virtual table cursors */ WhereClause *pOuter; /* Outer conjunction */ u8 op; /* Split operator. TK_AND or TK_OR */ u16 wctrlFlags; /* Might include WHERE_AND_ONLY */ int nTerm; /* Number of terms */ int nSlot; /* Number of entries in a[] */ WhereTerm *a; /* Each a[] describes a term of the WHERE cluase */ #if defined(SQLITE_SMALL_STACK) |
︙ | ︙ | |||
104594 104595 104596 104597 104598 104599 104600 | #define WO_LE (WO_EQ<<(TK_LE-TK_EQ)) #define WO_GT (WO_EQ<<(TK_GT-TK_EQ)) #define WO_GE (WO_EQ<<(TK_GE-TK_EQ)) #define WO_MATCH 0x040 #define WO_ISNULL 0x080 #define WO_OR 0x100 /* Two or more OR-connected terms */ #define WO_AND 0x200 /* Two or more AND-connected terms */ | < | 102254 102255 102256 102257 102258 102259 102260 102261 102262 102263 102264 102265 102266 102267 | #define WO_LE (WO_EQ<<(TK_LE-TK_EQ)) #define WO_GT (WO_EQ<<(TK_GT-TK_EQ)) #define WO_GE (WO_EQ<<(TK_GE-TK_EQ)) #define WO_MATCH 0x040 #define WO_ISNULL 0x080 #define WO_OR 0x100 /* Two or more OR-connected terms */ #define WO_AND 0x200 /* Two or more AND-connected terms */ #define WO_NOOP 0x800 /* This term does not restrict search space */ #define WO_ALL 0xfff /* Mask of all possible WO_* values */ #define WO_SINGLE 0x0ff /* Mask of all non-compound WO_* values */ /* ** Value for wsFlags returned by bestIndex() and stored in |
︙ | ︙ | |||
104621 104622 104623 104624 104625 104626 104627 | #define WHERE_ROWID_RANGE 0x00002000 /* rowid<EXPR and/or rowid>EXPR */ #define WHERE_COLUMN_EQ 0x00010000 /* x=EXPR or x IN (...) or x IS NULL */ #define WHERE_COLUMN_RANGE 0x00020000 /* x<EXPR and/or x>EXPR */ #define WHERE_COLUMN_IN 0x00040000 /* x IN (...) */ #define WHERE_COLUMN_NULL 0x00080000 /* x IS NULL */ #define WHERE_INDEXED 0x000f0000 /* Anything that uses an index */ #define WHERE_NOT_FULLSCAN 0x100f3000 /* Does not do a full table scan */ | | < < | 102280 102281 102282 102283 102284 102285 102286 102287 102288 102289 102290 102291 102292 102293 102294 102295 102296 102297 102298 102299 102300 102301 102302 | #define WHERE_ROWID_RANGE 0x00002000 /* rowid<EXPR and/or rowid>EXPR */ #define WHERE_COLUMN_EQ 0x00010000 /* x=EXPR or x IN (...) or x IS NULL */ #define WHERE_COLUMN_RANGE 0x00020000 /* x<EXPR and/or x>EXPR */ #define WHERE_COLUMN_IN 0x00040000 /* x IN (...) */ #define WHERE_COLUMN_NULL 0x00080000 /* x IS NULL */ #define WHERE_INDEXED 0x000f0000 /* Anything that uses an index */ #define WHERE_NOT_FULLSCAN 0x100f3000 /* Does not do a full table scan */ #define WHERE_IN_ABLE 0x000f1000 /* Able to support an IN operator */ #define WHERE_TOP_LIMIT 0x00100000 /* x<EXPR or x<=EXPR constraint */ #define WHERE_BTM_LIMIT 0x00200000 /* x>EXPR or x>=EXPR constraint */ #define WHERE_BOTH_LIMIT 0x00300000 /* Both x>EXPR and x<EXPR */ #define WHERE_IDX_ONLY 0x00400000 /* Use index only - omit table */ #define WHERE_ORDERED 0x00800000 /* Output will appear in correct order */ #define WHERE_REVERSE 0x01000000 /* Scan in reverse order */ #define WHERE_UNIQUE 0x02000000 /* Selects no more than one row */ #define WHERE_ALL_UNIQUE 0x04000000 /* This and all prior have 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 */ #define WHERE_COVER_SCAN 0x80000000 /* Full scan of a covering index */ /* |
︙ | ︙ | |||
104686 104687 104688 104689 104690 104691 104692 104693 104694 104695 104696 104697 104698 104699 | ){ pWC->pParse = pParse; pWC->pMaskSet = pMaskSet; pWC->pOuter = 0; pWC->nTerm = 0; pWC->nSlot = ArraySize(pWC->aStatic); pWC->a = pWC->aStatic; pWC->wctrlFlags = wctrlFlags; } /* Forward reference */ static void whereClauseClear(WhereClause*); /* | > | 102343 102344 102345 102346 102347 102348 102349 102350 102351 102352 102353 102354 102355 102356 102357 | ){ pWC->pParse = pParse; pWC->pMaskSet = pMaskSet; pWC->pOuter = 0; pWC->nTerm = 0; pWC->nSlot = ArraySize(pWC->aStatic); pWC->a = pWC->aStatic; pWC->vmask = 0; pWC->wctrlFlags = wctrlFlags; } /* Forward reference */ static void whereClauseClear(WhereClause*); /* |
︙ | ︙ | |||
104772 104773 104774 104775 104776 104777 104778 | memcpy(pWC->a, pOld, sizeof(pWC->a[0])*pWC->nTerm); if( pOld!=pWC->aStatic ){ sqlite3DbFree(db, pOld); } pWC->nSlot = sqlite3DbMallocSize(db, pWC->a)/sizeof(pWC->a[0]); } pTerm = &pWC->a[idx = pWC->nTerm++]; | | | 102430 102431 102432 102433 102434 102435 102436 102437 102438 102439 102440 102441 102442 102443 102444 | memcpy(pWC->a, pOld, sizeof(pWC->a[0])*pWC->nTerm); if( pOld!=pWC->aStatic ){ sqlite3DbFree(db, pOld); } pWC->nSlot = sqlite3DbMallocSize(db, pWC->a)/sizeof(pWC->a[0]); } pTerm = &pWC->a[idx = pWC->nTerm++]; pTerm->pExpr = p; pTerm->wtFlags = wtFlags; pTerm->pWC = pWC; pTerm->iParent = -1; return idx; } /* |
︙ | ︙ | |||
104932 104933 104934 104935 104936 104937 104938 | */ #define SWAP(TYPE,A,B) {TYPE t=A; A=B; B=t;} /* ** Commute a comparison operator. Expressions of the form "X op Y" ** are converted into "Y op X". ** | < | | | | | < < < < < | | < > | < | < < | 102590 102591 102592 102593 102594 102595 102596 102597 102598 102599 102600 102601 102602 102603 102604 102605 102606 102607 102608 102609 102610 102611 102612 102613 102614 102615 102616 102617 102618 102619 102620 | */ #define SWAP(TYPE,A,B) {TYPE t=A; A=B; B=t;} /* ** Commute a comparison operator. Expressions of the form "X op Y" ** are converted into "Y op X". ** ** If a collation sequence is associated with either the left or right ** side of the comparison, it remains associated with the same side after ** the commutation. So "Y collate NOCASE op X" becomes ** "X collate NOCASE op Y". This is because any collation sequence on ** the left hand side of a comparison overrides any collation sequence ** attached to the right. For the same reason the EP_ExpCollate flag ** is not commuted. */ static void exprCommute(Parse *pParse, Expr *pExpr){ u16 expRight = (pExpr->pRight->flags & EP_ExpCollate); u16 expLeft = (pExpr->pLeft->flags & EP_ExpCollate); assert( allowedOp(pExpr->op) && pExpr->op!=TK_IN ); pExpr->pRight->pColl = sqlite3ExprCollSeq(pParse, pExpr->pRight); pExpr->pLeft->pColl = sqlite3ExprCollSeq(pParse, pExpr->pLeft); SWAP(CollSeq*,pExpr->pRight->pColl,pExpr->pLeft->pColl); pExpr->pRight->flags = (pExpr->pRight->flags & ~EP_ExpCollate) | expLeft; pExpr->pLeft->flags = (pExpr->pLeft->flags & ~EP_ExpCollate) | expRight; SWAP(Expr*,pExpr->pRight,pExpr->pLeft); if( pExpr->op>=TK_GT ){ assert( TK_LT==TK_GT+2 ); assert( TK_GE==TK_LE+2 ); assert( TK_GT>TK_EQ ); assert( TK_GT<TK_LE ); assert( pExpr->op>=TK_GT && pExpr->op<=TK_GE ); |
︙ | ︙ | |||
104998 104999 105000 105001 105002 105003 105004 | } /* ** Search for a term in the WHERE clause that is of the form "X <op> <expr>" ** where X is a reference to the iColumn of table iCur and <op> is one of ** the WO_xx operator codes specified by the op parameter. ** Return a pointer to the term. Return 0 if not found. | < < < < < < < < < < < < < < < < < | < < < < < < < < < | | < < | | | > | < < | | | > | | | < | > | | < < | | | | | | | | | | | | | < | < < | < < < | | < < < < < < < | < < < < < < < < < < < < < < | | 102647 102648 102649 102650 102651 102652 102653 102654 102655 102656 102657 102658 102659 102660 102661 102662 102663 102664 102665 102666 102667 102668 102669 102670 102671 102672 102673 102674 102675 102676 102677 102678 102679 102680 102681 102682 102683 102684 102685 102686 102687 102688 102689 102690 102691 102692 102693 102694 102695 102696 102697 102698 102699 102700 102701 102702 102703 102704 102705 102706 102707 102708 | } /* ** Search for a term in the WHERE clause that is of the form "X <op> <expr>" ** where X is a reference to the iColumn of table iCur and <op> is one of ** the WO_xx operator codes specified by the op parameter. ** Return a pointer to the term. Return 0 if not found. */ static WhereTerm *findTerm( WhereClause *pWC, /* The WHERE clause to be searched */ int iCur, /* Cursor number of LHS */ int iColumn, /* Column number of LHS */ Bitmask notReady, /* RHS must not overlap with this mask */ u32 op, /* Mask of WO_xx values describing operator */ Index *pIdx /* Must be compatible with this index, if not NULL */ ){ WhereTerm *pTerm; int k; assert( iCur>=0 ); op &= WO_ALL; for(; pWC; pWC=pWC->pOuter){ for(pTerm=pWC->a, k=pWC->nTerm; k; k--, pTerm++){ if( pTerm->leftCursor==iCur && (pTerm->prereqRight & notReady)==0 && pTerm->u.leftColumn==iColumn && (pTerm->eOperator & op)!=0 ){ if( iColumn>=0 && pIdx && pTerm->eOperator!=WO_ISNULL ){ Expr *pX = pTerm->pExpr; CollSeq *pColl; char idxaff; int j; Parse *pParse = pWC->pParse; idxaff = pIdx->pTable->aCol[iColumn].affinity; if( !sqlite3IndexAffinityOk(pX, idxaff) ) continue; /* Figure out the collation sequence required from an index for ** it to be useful for optimising expression pX. Store this ** value in variable pColl. */ assert(pX->pLeft); pColl = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight); assert(pColl || pParse->nErr); for(j=0; pIdx->aiColumn[j]!=iColumn; j++){ if( NEVER(j>=pIdx->nColumn) ) return 0; } if( pColl && sqlite3StrICmp(pColl->zName, pIdx->azColl[j]) ) continue; } return pTerm; } } } return 0; } /* Forward reference */ static void exprAnalyze(SrcList*, WhereClause*, int); /* ** Call exprAnalyze on all terms in a WHERE clause. |
︙ | ︙ | |||
105288 105289 105290 105291 105292 105293 105294 | ** (B) x=expr1 OR expr2=x OR x=expr3 ** (C) t1.x=t2.y OR (t1.x=t2.z AND t1.y=15) ** (D) x=expr1 OR (y>11 AND y<22 AND z LIKE '*hello*') ** (E) (p.a=1 AND q.b=2 AND r.c=3) OR (p.x=4 AND q.y=5 AND r.z=6) ** ** CASE 1: ** | | | 102880 102881 102882 102883 102884 102885 102886 102887 102888 102889 102890 102891 102892 102893 102894 | ** (B) x=expr1 OR expr2=x OR x=expr3 ** (C) t1.x=t2.y OR (t1.x=t2.z AND t1.y=15) ** (D) x=expr1 OR (y>11 AND y<22 AND z LIKE '*hello*') ** (E) (p.a=1 AND q.b=2 AND r.c=3) OR (p.x=4 AND q.y=5 AND r.z=6) ** ** CASE 1: ** ** If all subterms are of the form T.C=expr for some single column of C ** a single table T (as shown in example B above) then create a new virtual ** term that is an equivalent IN expression. In other words, if the term ** being analyzed is: ** ** x = expr1 OR expr2 = x OR x = expr3 ** ** then create a new virtual term like this: |
︙ | ︙ | |||
105376 105377 105378 105379 105380 105381 105382 | if( db->mallocFailed ) return; assert( pOrWc->nTerm>=2 ); /* ** Compute the set of tables that might satisfy cases 1 or 2. */ indexable = ~(Bitmask)0; | | > | 102968 102969 102970 102971 102972 102973 102974 102975 102976 102977 102978 102979 102980 102981 102982 102983 102984 102985 102986 | if( db->mallocFailed ) return; assert( pOrWc->nTerm>=2 ); /* ** Compute the set of tables that might satisfy cases 1 or 2. */ indexable = ~(Bitmask)0; chngToIN = ~(pWC->vmask); for(i=pOrWc->nTerm-1, pOrTerm=pOrWc->a; i>=0 && indexable; i--, pOrTerm++){ if( (pOrTerm->eOperator & WO_SINGLE)==0 ){ WhereAndInfo *pAndInfo; assert( pOrTerm->eOperator==0 ); assert( (pOrTerm->wtFlags & (TERM_ANDINFO|TERM_ORINFO))==0 ); chngToIN = 0; pAndInfo = sqlite3DbMallocRaw(db, sizeof(*pAndInfo)); if( pAndInfo ){ WhereClause *pAndWC; WhereTerm *pAndTerm; int j; |
︙ | ︙ | |||
105418 105419 105420 105421 105422 105423 105424 | Bitmask b; b = getMask(pMaskSet, pOrTerm->leftCursor); if( pOrTerm->wtFlags & TERM_VIRTUAL ){ WhereTerm *pOther = &pOrWc->a[pOrTerm->iParent]; b |= getMask(pMaskSet, pOther->leftCursor); } indexable &= b; | | | 103011 103012 103013 103014 103015 103016 103017 103018 103019 103020 103021 103022 103023 103024 103025 | Bitmask b; b = getMask(pMaskSet, pOrTerm->leftCursor); if( pOrTerm->wtFlags & TERM_VIRTUAL ){ WhereTerm *pOther = &pOrWc->a[pOrTerm->iParent]; b |= getMask(pMaskSet, pOther->leftCursor); } indexable &= b; if( pOrTerm->eOperator!=WO_EQ ){ chngToIN = 0; }else{ chngToIN &= b; } } } |
︙ | ︙ | |||
105469 105470 105471 105472 105473 105474 105475 | ** will be recorded in iCursor and iColumn. There might not be any ** such table and column. Set okToChngToIN if an appropriate table ** and column is found but leave okToChngToIN false if not found. */ for(j=0; j<2 && !okToChngToIN; j++){ pOrTerm = pOrWc->a; for(i=pOrWc->nTerm-1; i>=0; i--, pOrTerm++){ | | | 103062 103063 103064 103065 103066 103067 103068 103069 103070 103071 103072 103073 103074 103075 103076 | ** will be recorded in iCursor and iColumn. There might not be any ** such table and column. Set okToChngToIN if an appropriate table ** and column is found but leave okToChngToIN false if not found. */ for(j=0; j<2 && !okToChngToIN; j++){ pOrTerm = pOrWc->a; for(i=pOrWc->nTerm-1; i>=0; i--, pOrTerm++){ assert( pOrTerm->eOperator==WO_EQ ); pOrTerm->wtFlags &= ~TERM_OR_OK; if( pOrTerm->leftCursor==iCursor ){ /* This is the 2-bit case and we are on the second iteration and ** current term is from the first iteration. So skip this term. */ assert( j==1 ); continue; } |
︙ | ︙ | |||
105495 105496 105497 105498 105499 105500 105501 | iCursor = pOrTerm->leftCursor; break; } if( i<0 ){ /* No candidate table+column was found. This can only occur ** on the second iteration */ assert( j==1 ); | | | | 103088 103089 103090 103091 103092 103093 103094 103095 103096 103097 103098 103099 103100 103101 103102 103103 103104 103105 103106 103107 103108 103109 103110 103111 103112 | iCursor = pOrTerm->leftCursor; break; } if( i<0 ){ /* No candidate table+column was found. This can only occur ** on the second iteration */ assert( j==1 ); assert( (chngToIN&(chngToIN-1))==0 ); assert( chngToIN==getMask(pMaskSet, iCursor) ); break; } testcase( j==1 ); /* We have found a candidate table and column. Check to see if that ** table and column is common to every term in the OR clause */ okToChngToIN = 1; for(; i>=0 && okToChngToIN; i--, pOrTerm++){ assert( pOrTerm->eOperator==WO_EQ ); if( pOrTerm->leftCursor!=iCursor ){ pOrTerm->wtFlags &= ~TERM_OR_OK; }else if( pOrTerm->u.leftColumn!=iColumn ){ okToChngToIN = 0; }else{ int affLeft, affRight; /* If the right-hand side is also a column, then the affinities |
︙ | ︙ | |||
105541 105542 105543 105544 105545 105546 105547 | Expr *pDup; /* A transient duplicate expression */ ExprList *pList = 0; /* The RHS of the IN operator */ Expr *pLeft = 0; /* The LHS of the IN operator */ Expr *pNew; /* The complete IN operator */ for(i=pOrWc->nTerm-1, pOrTerm=pOrWc->a; i>=0; i--, pOrTerm++){ if( (pOrTerm->wtFlags & TERM_OR_OK)==0 ) continue; | | | 103134 103135 103136 103137 103138 103139 103140 103141 103142 103143 103144 103145 103146 103147 103148 | Expr *pDup; /* A transient duplicate expression */ ExprList *pList = 0; /* The RHS of the IN operator */ Expr *pLeft = 0; /* The LHS of the IN operator */ Expr *pNew; /* The complete IN operator */ for(i=pOrWc->nTerm-1, pOrTerm=pOrWc->a; i>=0; i--, pOrTerm++){ if( (pOrTerm->wtFlags & TERM_OR_OK)==0 ) continue; assert( pOrTerm->eOperator==WO_EQ ); assert( pOrTerm->leftCursor==iCursor ); assert( pOrTerm->u.leftColumn==iColumn ); pDup = sqlite3ExprDup(db, pOrTerm->pExpr->pRight, 0); pList = sqlite3ExprListAppend(pWC->pParse, pList, pDup); pLeft = pOrTerm->pExpr->pLeft; } assert( pLeft!=0 ); |
︙ | ︙ | |||
105570 105571 105572 105573 105574 105575 105576 105577 105578 105579 105580 105581 105582 105583 | sqlite3ExprListDelete(db, pList); } pTerm->eOperator = WO_NOOP; /* case 1 trumps case 2 */ } } } #endif /* !SQLITE_OMIT_OR_OPTIMIZATION && !SQLITE_OMIT_SUBQUERY */ /* ** The input to this routine is an WhereTerm structure with only the ** "pExpr" field filled in. The job of this routine is to analyze the ** subexpression and populate all the other fields of the WhereTerm ** structure. ** | > | 103163 103164 103165 103166 103167 103168 103169 103170 103171 103172 103173 103174 103175 103176 103177 | sqlite3ExprListDelete(db, pList); } pTerm->eOperator = WO_NOOP; /* case 1 trumps case 2 */ } } } #endif /* !SQLITE_OMIT_OR_OPTIMIZATION && !SQLITE_OMIT_SUBQUERY */ /* ** The input to this routine is an WhereTerm structure with only the ** "pExpr" field filled in. The job of this routine is to analyze the ** subexpression and populate all the other fields of the WhereTerm ** structure. ** |
︙ | ︙ | |||
105613 105614 105615 105616 105617 105618 105619 | if( db->mallocFailed ){ return; } pTerm = &pWC->a[idxTerm]; pMaskSet = pWC->pMaskSet; pExpr = pTerm->pExpr; | < | 103207 103208 103209 103210 103211 103212 103213 103214 103215 103216 103217 103218 103219 103220 | if( db->mallocFailed ){ return; } pTerm = &pWC->a[idxTerm]; pMaskSet = pWC->pMaskSet; pExpr = pTerm->pExpr; prereqLeft = exprTableUsage(pMaskSet, pExpr->pLeft); op = pExpr->op; if( op==TK_IN ){ assert( pExpr->pRight==0 ); if( ExprHasProperty(pExpr, EP_xIsSelect) ){ pTerm->prereqRight = exprSelectTableUsage(pMaskSet, pExpr->x.pSelect); }else{ |
︙ | ︙ | |||
105639 105640 105641 105642 105643 105644 105645 | extraRight = x-1; /* ON clause terms may not be used with an index ** on left table of a LEFT JOIN. Ticket #3015 */ } pTerm->prereqAll = prereqAll; pTerm->leftCursor = -1; pTerm->iParent = -1; pTerm->eOperator = 0; | | | | < | < < < < < < < < | | | 103232 103233 103234 103235 103236 103237 103238 103239 103240 103241 103242 103243 103244 103245 103246 103247 103248 103249 103250 103251 103252 103253 103254 103255 103256 103257 103258 103259 103260 103261 103262 103263 103264 103265 103266 103267 103268 103269 103270 103271 103272 103273 103274 103275 103276 103277 103278 103279 103280 103281 103282 | extraRight = x-1; /* ON clause terms may not be used with an index ** on left table of a LEFT JOIN. Ticket #3015 */ } pTerm->prereqAll = prereqAll; pTerm->leftCursor = -1; pTerm->iParent = -1; pTerm->eOperator = 0; if( allowedOp(op) && (pTerm->prereqRight & prereqLeft)==0 ){ Expr *pLeft = pExpr->pLeft; Expr *pRight = pExpr->pRight; if( pLeft->op==TK_COLUMN ){ pTerm->leftCursor = pLeft->iTable; pTerm->u.leftColumn = pLeft->iColumn; pTerm->eOperator = operatorMask(op); } if( pRight && pRight->op==TK_COLUMN ){ WhereTerm *pNew; Expr *pDup; if( pTerm->leftCursor>=0 ){ int idxNew; pDup = sqlite3ExprDup(db, pExpr, 0); if( db->mallocFailed ){ sqlite3ExprDelete(db, pDup); return; } idxNew = whereClauseInsert(pWC, pDup, TERM_VIRTUAL|TERM_DYNAMIC); if( idxNew==0 ) return; pNew = &pWC->a[idxNew]; pNew->iParent = idxTerm; pTerm = &pWC->a[idxTerm]; pTerm->nChild = 1; pTerm->wtFlags |= TERM_COPIED; }else{ pDup = pExpr; pNew = pTerm; } exprCommute(pParse, pDup); pLeft = pDup->pLeft; pNew->leftCursor = pLeft->iTable; pNew->u.leftColumn = pLeft->iColumn; testcase( (prereqLeft | extraRight) != prereqLeft ); pNew->prereqRight = prereqLeft | extraRight; pNew->prereqAll = prereqAll; pNew->eOperator = operatorMask(pDup->op); } } #ifndef SQLITE_OMIT_BETWEEN_OPTIMIZATION /* If a term is the BETWEEN operator, create two new virtual terms ** that define the range that the BETWEEN implements. For example: ** |
︙ | ︙ | |||
105757 105758 105759 105760 105761 105762 105763 | ){ Expr *pLeft; /* LHS of LIKE/GLOB operator */ Expr *pStr2; /* Copy of pStr1 - RHS of LIKE/GLOB operator */ Expr *pNewExpr1; Expr *pNewExpr2; int idxNew1; int idxNew2; | | | 103341 103342 103343 103344 103345 103346 103347 103348 103349 103350 103351 103352 103353 103354 103355 | ){ Expr *pLeft; /* LHS of LIKE/GLOB operator */ Expr *pStr2; /* Copy of pStr1 - RHS of LIKE/GLOB operator */ Expr *pNewExpr1; Expr *pNewExpr2; int idxNew1; int idxNew2; CollSeq *pColl; /* Collating sequence to use */ pLeft = pExpr->x.pList->a[1].pExpr; pStr2 = sqlite3ExprDup(db, pStr1, 0); if( !db->mallocFailed ){ u8 c, *pC; /* Last character before the first wildcard */ pC = (u8*)&pStr2->u.zToken[sqlite3Strlen30(pStr2->u.zToken)-1]; c = *pC; |
︙ | ︙ | |||
105779 105780 105781 105782 105783 105784 105785 | if( c=='A'-1 ) isComplete = 0; /* EV: R-64339-08207 */ c = sqlite3UpperToLower[c]; } *pC = c + 1; } | | < < | | < | | | 103363 103364 103365 103366 103367 103368 103369 103370 103371 103372 103373 103374 103375 103376 103377 103378 103379 103380 103381 103382 103383 103384 103385 103386 | if( c=='A'-1 ) isComplete = 0; /* EV: R-64339-08207 */ c = sqlite3UpperToLower[c]; } *pC = c + 1; } pColl = sqlite3FindCollSeq(db, SQLITE_UTF8, noCase ? "NOCASE" : "BINARY",0); pNewExpr1 = sqlite3PExpr(pParse, TK_GE, sqlite3ExprSetColl(sqlite3ExprDup(db,pLeft,0), pColl), pStr1, 0); idxNew1 = whereClauseInsert(pWC, pNewExpr1, TERM_VIRTUAL|TERM_DYNAMIC); testcase( idxNew1==0 ); exprAnalyze(pSrc, pWC, idxNew1); pNewExpr2 = sqlite3PExpr(pParse, TK_LT, sqlite3ExprSetColl(sqlite3ExprDup(db,pLeft,0), pColl), pStr2, 0); idxNew2 = whereClauseInsert(pWC, pNewExpr2, TERM_VIRTUAL|TERM_DYNAMIC); testcase( idxNew2==0 ); exprAnalyze(pSrc, pWC, idxNew2); pTerm = &pWC->a[idxTerm]; if( isComplete ){ pWC->a[idxNew1].iParent = idxTerm; pWC->a[idxNew2].iParent = idxTerm; |
︙ | ︙ | |||
105909 105910 105911 105912 105913 105914 105915 | 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++){ | | | | 103490 103491 103492 103493 103494 103495 103496 103497 103498 103499 103500 103501 103502 103503 103504 103505 103506 103507 103508 103509 | Index *pIdx, /* Index to match column of */ int iCol /* Column of index to match */ ){ int i; const char *zColl = pIdx->azColl[iCol]; for(i=0; i<pList->nExpr; i++){ Expr *p = 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; |
︙ | ︙ | |||
105961 105962 105963 105964 105965 105966 105967 | ** 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; | | | 103542 103543 103544 103545 103546 103547 103548 103549 103550 103551 103552 103553 103554 103555 103556 | ** can be ignored. If it does not, and the column does not belong to the ** same table as index pIdx, return early. Finally, if there is no ** matching "col=X" expression and the column is on the same table as pIdx, ** set the corresponding bit in variable mask. */ for(i=0; i<pDistinct->nExpr; i++){ WhereTerm *pTerm; Expr *p = 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; |
︙ | ︙ | |||
106013 106014 106015 106016 106017 106018 106019 | 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++){ | | | 103594 103595 103596 103597 103598 103599 103600 103601 103602 103603 103604 103605 103606 103607 103608 | pTab = pTabList->a[0].pTab; /* If any of the expressions is an IPK column on table iBase, then return ** true. Note: The (p->iTable==iBase) part of this test may be false if the ** current SELECT is a correlated sub-query. */ for(i=0; i<pDistinct->nExpr; i++){ Expr *p = 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 |
︙ | ︙ | |||
106143 106144 106145 106146 106147 106148 106149 | } if( pWC->wctrlFlags & WHERE_AND_ONLY ){ return; } /* Search the WHERE clause terms for a usable WO_OR term. */ for(pTerm=pWC->a; pTerm<pWCEnd; pTerm++){ | | | | 103724 103725 103726 103727 103728 103729 103730 103731 103732 103733 103734 103735 103736 103737 103738 103739 103740 103741 103742 103743 103744 103745 103746 103747 103748 103749 103750 103751 103752 103753 103754 103755 103756 103757 103758 103759 | } if( pWC->wctrlFlags & WHERE_AND_ONLY ){ return; } /* Search the WHERE clause terms for a usable WO_OR term. */ for(pTerm=pWC->a; pTerm<pWCEnd; pTerm++){ if( pTerm->eOperator==WO_OR && ((pTerm->prereqAll & ~maskSrc) & p->notReady)==0 && (pTerm->u.pOrInfo->indexable & maskSrc)!=0 ){ WhereClause * const pOrWC = &pTerm->u.pOrInfo->wc; WhereTerm * const pOrWCEnd = &pOrWC->a[pOrWC->nTerm]; WhereTerm *pOrTerm; int flags = WHERE_MULTI_OR; double rTotal = 0; double nRow = 0; Bitmask used = 0; WhereBestIdx sBOI; sBOI = *p; sBOI.pOrderBy = 0; sBOI.pDistinct = 0; sBOI.ppIdxInfo = 0; for(pOrTerm=pOrWC->a; pOrTerm<pOrWCEnd; pOrTerm++){ WHERETRACE(("... Multi-index OR testing for term %d of %d....\n", (pOrTerm - pOrWC->a), (pTerm - pWC->a) )); if( pOrTerm->eOperator==WO_AND ){ sBOI.pWC = &pOrTerm->u.pAndInfo->wc; bestIndex(&sBOI); }else if( pOrTerm->leftCursor==iCur ){ WhereClause tempWC; tempWC.pParse = pWC->pParse; tempWC.pMaskSet = pWC->pMaskSet; tempWC.pOuter = pWC; |
︙ | ︙ | |||
106225 106226 106227 106228 106229 106230 106231 | static int termCanDriveIndex( WhereTerm *pTerm, /* WHERE clause term to check */ struct SrcList_item *pSrc, /* Table we are trying to access */ Bitmask notReady /* Tables in outer loops of the join */ ){ char aff; if( pTerm->leftCursor!=pSrc->iCursor ) return 0; | | | 103806 103807 103808 103809 103810 103811 103812 103813 103814 103815 103816 103817 103818 103819 103820 | static int termCanDriveIndex( WhereTerm *pTerm, /* WHERE clause term to check */ struct SrcList_item *pSrc, /* Table we are trying to access */ Bitmask notReady /* Tables in outer loops of the join */ ){ char aff; if( pTerm->leftCursor!=pSrc->iCursor ) return 0; if( pTerm->eOperator!=WO_EQ ) return 0; if( (pTerm->prereqRight & notReady)!=0 ) return 0; aff = pSrc->pTab->aCol[pTerm->u.leftColumn].affinity; if( !sqlite3IndexAffinityOk(pTerm->pExpr, aff) ) return 0; return 1; } #endif |
︙ | ︙ | |||
106261 106262 106263 106264 106265 106266 106267 | /* 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; } | | < < < < < < | 103842 103843 103844 103845 103846 103847 103848 103849 103850 103851 103852 103853 103854 103855 103856 103857 103858 103859 | /* There is no point in building an automatic index for a single scan */ return; } if( (pParse->db->flags & SQLITE_AutoIndex)==0 ){ /* Automatic indices are disabled at run-time */ return; } if( (p->cost.plan.wsFlags & WHERE_NOT_FULLSCAN)!=0 ){ /* 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; |
︙ | ︙ | |||
106487 106488 106489 106490 106491 106492 106493 | WHERETRACE(("Recomputing index info for %s...\n", pSrc->pTab->zName)); /* Count the number of possible WHERE clause constraints referring ** to this virtual table */ for(i=nTerm=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){ if( pTerm->leftCursor != pSrc->iCursor ) continue; | | | | | | 104062 104063 104064 104065 104066 104067 104068 104069 104070 104071 104072 104073 104074 104075 104076 104077 104078 104079 | WHERETRACE(("Recomputing index info for %s...\n", pSrc->pTab->zName)); /* Count the number of possible WHERE clause constraints referring ** to this virtual table */ for(i=nTerm=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){ if( pTerm->leftCursor != pSrc->iCursor ) continue; assert( (pTerm->eOperator&(pTerm->eOperator-1))==0 ); testcase( pTerm->eOperator==WO_IN ); testcase( pTerm->eOperator==WO_ISNULL ); if( pTerm->eOperator & (WO_IN|WO_ISNULL) ) continue; if( pTerm->wtFlags & TERM_VNULL ) continue; nTerm++; } /* If the ORDER BY clause contains only columns in the current ** virtual table then allocate space for the aOrderBy part of ** the sqlite3_index_info structure. |
︙ | ︙ | |||
106538 106539 106540 106541 106542 106543 106544 | *(int*)&pIdxInfo->nOrderBy = nOrderBy; *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint = pIdxCons; *(struct sqlite3_index_orderby**)&pIdxInfo->aOrderBy = pIdxOrderBy; *(struct sqlite3_index_constraint_usage**)&pIdxInfo->aConstraintUsage = pUsage; for(i=j=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){ | < | | | | < < | | | 104113 104114 104115 104116 104117 104118 104119 104120 104121 104122 104123 104124 104125 104126 104127 104128 104129 104130 104131 104132 104133 104134 104135 104136 104137 104138 104139 104140 104141 104142 104143 104144 104145 | *(int*)&pIdxInfo->nOrderBy = nOrderBy; *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint = pIdxCons; *(struct sqlite3_index_orderby**)&pIdxInfo->aOrderBy = pIdxOrderBy; *(struct sqlite3_index_constraint_usage**)&pIdxInfo->aConstraintUsage = pUsage; for(i=j=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){ if( pTerm->leftCursor != pSrc->iCursor ) continue; assert( (pTerm->eOperator&(pTerm->eOperator-1))==0 ); testcase( pTerm->eOperator==WO_IN ); testcase( pTerm->eOperator==WO_ISNULL ); if( pTerm->eOperator & (WO_IN|WO_ISNULL) ) continue; if( pTerm->wtFlags & TERM_VNULL ) continue; pIdxCons[j].iColumn = pTerm->u.leftColumn; pIdxCons[j].iTermOffset = i; pIdxCons[j].op = (u8)pTerm->eOperator; /* The direct assignment in the previous line is possible only because ** the WO_ and SQLITE_INDEX_CONSTRAINT_ codes are identical. The ** following asserts verify this fact. */ assert( WO_EQ==SQLITE_INDEX_CONSTRAINT_EQ ); assert( WO_LT==SQLITE_INDEX_CONSTRAINT_LT ); assert( WO_LE==SQLITE_INDEX_CONSTRAINT_LE ); assert( WO_GT==SQLITE_INDEX_CONSTRAINT_GT ); assert( WO_GE==SQLITE_INDEX_CONSTRAINT_GE ); assert( WO_MATCH==SQLITE_INDEX_CONSTRAINT_MATCH ); assert( pTerm->eOperator & (WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE|WO_MATCH) ); j++; } for(i=0; i<nOrderBy; i++){ Expr *pExpr = pOrderBy->a[i].pExpr; pIdxOrderBy[i].iColumn = pExpr->iColumn; pIdxOrderBy[i].desc = pOrderBy->a[i].sortOrder; } |
︙ | ︙ | |||
106645 106646 106647 106648 106649 106650 106651 | Table *pTab = pSrc->pTab; sqlite3_index_info *pIdxInfo; struct sqlite3_index_constraint *pIdxCons; struct sqlite3_index_constraint_usage *pUsage; WhereTerm *pTerm; int i, j; int nOrderBy; | < | 104217 104218 104219 104220 104221 104222 104223 104224 104225 104226 104227 104228 104229 104230 | Table *pTab = pSrc->pTab; sqlite3_index_info *pIdxInfo; struct sqlite3_index_constraint *pIdxCons; struct sqlite3_index_constraint_usage *pUsage; WhereTerm *pTerm; int i, j; int nOrderBy; double rCost; /* Make sure wsFlags is initialized to some sane value. Otherwise, if the ** malloc in allocateIndexInfo() fails and this function returns leaving ** wsFlags in an uninitialized state, the caller may behave unpredictably. */ memset(&p->cost, 0, sizeof(p->cost)); |
︙ | ︙ | |||
106680 106681 106682 106683 106684 106685 106686 | /* The module name must be defined. Also, by this point there must ** be a pointer to an sqlite3_vtab structure. Otherwise ** sqlite3ViewGetColumnNames() would have picked up the error. */ assert( pTab->azModuleArg && pTab->azModuleArg[0] ); assert( sqlite3GetVTable(pParse->db, pTab) ); | < < < < < < < < < < < | | | | | | | | | | | | | | | | | | | | | | | | | < < < | < < < | | | | | | | | | | | | | | | | | | | | | | | < < | < < < < < < < | < < < < < < | | < < < < < < < < < < < < < < < | 104251 104252 104253 104254 104255 104256 104257 104258 104259 104260 104261 104262 104263 104264 104265 104266 104267 104268 104269 104270 104271 104272 104273 104274 104275 104276 104277 104278 104279 104280 104281 104282 104283 104284 104285 104286 104287 104288 104289 104290 104291 104292 104293 104294 104295 104296 104297 104298 104299 104300 104301 104302 104303 104304 104305 104306 104307 104308 104309 104310 104311 104312 104313 104314 104315 104316 104317 | /* The module name must be defined. Also, by this point there must ** be a pointer to an sqlite3_vtab structure. Otherwise ** sqlite3ViewGetColumnNames() would have picked up the error. */ assert( pTab->azModuleArg && pTab->azModuleArg[0] ); assert( sqlite3GetVTable(pParse->db, pTab) ); /* Set the aConstraint[].usable fields and initialize all ** output variables to zero. ** ** aConstraint[].usable is true for constraints where the right-hand ** side contains only references to tables to the left of the current ** table. In other words, if the constraint is of the form: ** ** column = expr ** ** and we are evaluating a join, then the constraint on column is ** only valid if all tables referenced in expr occur to the left ** of the table containing column. ** ** The aConstraints[] array contains entries for all constraints ** on the current table. That way we only have to compute it once ** even though we might try to pick the best index multiple times. ** For each attempt at picking an index, the order of tables in the ** join might be different so we have to recompute the usable flag ** each time. */ pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint; pUsage = pIdxInfo->aConstraintUsage; for(i=0; i<pIdxInfo->nConstraint; i++, pIdxCons++){ j = pIdxCons->iTermOffset; pTerm = &pWC->a[j]; pIdxCons->usable = (pTerm->prereqRight&p->notReady) ? 0 : 1; } memset(pUsage, 0, sizeof(pUsage[0])*pIdxInfo->nConstraint); if( pIdxInfo->needToFreeIdxStr ){ sqlite3_free(pIdxInfo->idxStr); } pIdxInfo->idxStr = 0; pIdxInfo->idxNum = 0; pIdxInfo->needToFreeIdxStr = 0; pIdxInfo->orderByConsumed = 0; /* ((double)2) In case of SQLITE_OMIT_FLOATING_POINT... */ pIdxInfo->estimatedCost = SQLITE_BIG_DBL / ((double)2); nOrderBy = pIdxInfo->nOrderBy; if( !p->pOrderBy ){ pIdxInfo->nOrderBy = 0; } if( vtabBestIndex(pParse, pTab, pIdxInfo) ){ return; } pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint; for(i=0; i<pIdxInfo->nConstraint; i++){ if( pUsage[i].argvIndex>0 ){ p->cost.used |= pWC->a[pIdxCons[i].iTermOffset].prereqRight; } } /* If there is an ORDER BY clause, and the selected virtual table index ** does not satisfy it, increase the cost of the scan accordingly. This ** matches the processing for non-virtual tables in bestBtreeIndex(). */ rCost = pIdxInfo->estimatedCost; if( p->pOrderBy && pIdxInfo->orderByConsumed==0 ){ rCost += estLog(rCost)*rCost; |
︙ | ︙ | |||
107074 107075 107076 107077 107078 107079 107080 | tRowcnt iUpper = p->aiRowEst[0]; tRowcnt a[2]; u8 aff = p->pTable->aCol[p->aiColumn[0]].affinity; if( pLower ){ Expr *pExpr = pLower->pExpr->pRight; rc = valueFromExpr(pParse, pExpr, aff, &pRangeVal); | | | | | | 104598 104599 104600 104601 104602 104603 104604 104605 104606 104607 104608 104609 104610 104611 104612 104613 104614 104615 104616 104617 104618 104619 104620 104621 104622 104623 104624 104625 104626 104627 104628 104629 | tRowcnt iUpper = p->aiRowEst[0]; tRowcnt a[2]; u8 aff = p->pTable->aCol[p->aiColumn[0]].affinity; if( pLower ){ Expr *pExpr = pLower->pExpr->pRight; rc = valueFromExpr(pParse, pExpr, aff, &pRangeVal); assert( pLower->eOperator==WO_GT || pLower->eOperator==WO_GE ); if( rc==SQLITE_OK && whereKeyStats(pParse, p, pRangeVal, 0, a)==SQLITE_OK ){ iLower = a[0]; if( pLower->eOperator==WO_GT ) iLower += a[1]; } sqlite3ValueFree(pRangeVal); } if( rc==SQLITE_OK && pUpper ){ Expr *pExpr = pUpper->pExpr->pRight; rc = valueFromExpr(pParse, pExpr, aff, &pRangeVal); assert( pUpper->eOperator==WO_LT || pUpper->eOperator==WO_LE ); if( rc==SQLITE_OK && whereKeyStats(pParse, p, pRangeVal, 1, a)==SQLITE_OK ){ iUpper = a[0]; if( pUpper->eOperator==WO_LE ) iUpper += a[1]; } sqlite3ValueFree(pRangeVal); } if( rc==SQLITE_OK ){ if( iUpper<=iLower ){ *pRangeDiv = (double)p->aiRowEst[0]; }else{ |
︙ | ︙ | |||
107281 107282 107283 107284 107285 107286 107287 | ** The *pbRev value is set to 0 order 1 depending on whether or not ** pIdx should be run in the forward order or in reverse order. */ static int isSortingIndex( WhereBestIdx *p, /* Best index search context */ Index *pIdx, /* The index we are testing */ int base, /* Cursor number for the table to be sorted */ | | < < < < < | < < < | 104805 104806 104807 104808 104809 104810 104811 104812 104813 104814 104815 104816 104817 104818 104819 104820 104821 104822 104823 104824 104825 104826 104827 104828 104829 104830 104831 104832 104833 104834 104835 104836 104837 104838 104839 104840 104841 104842 104843 104844 104845 104846 104847 | ** The *pbRev value is set to 0 order 1 depending on whether or not ** pIdx should be run in the forward order or in reverse order. */ static int isSortingIndex( WhereBestIdx *p, /* Best index search context */ Index *pIdx, /* The index we are testing */ int base, /* Cursor number for the table to be sorted */ int *pbRev /* Set to 1 for reverse-order scan of pIdx */ ){ int i; /* Number of pIdx terms used */ int j; /* Number of ORDER BY terms satisfied */ int sortOrder = 2; /* 0: forward. 1: backward. 2: unknown */ int nTerm; /* Number of ORDER BY terms */ struct ExprList_item *pOBItem;/* A term of the ORDER BY clause */ Table *pTab = pIdx->pTable; /* Table that owns index pIdx */ ExprList *pOrderBy; /* The ORDER BY clause */ Parse *pParse = p->pParse; /* Parser context */ sqlite3 *db = pParse->db; /* Database connection */ int nPriorSat; /* ORDER BY terms satisfied by outer loops */ int seenRowid = 0; /* True if an ORDER BY rowid term is seen */ int uniqueNotNull; /* pIdx is UNIQUE with all terms are NOT NULL */ if( p->i==0 ){ nPriorSat = 0; }else{ nPriorSat = p->aLevel[p->i-1].plan.nOBSat; if( (p->aLevel[p->i-1].plan.wsFlags & WHERE_ORDERED)==0 ){ /* This loop cannot be ordered unless the next outer loop is ** also ordered */ return nPriorSat; } if( OptimizationDisabled(db, SQLITE_OrderByIdxJoin) ){ /* Only look at the outer-most loop if the OrderByIdxJoin ** optimization is disabled */ return nPriorSat; } } pOrderBy = p->pOrderBy; assert( pOrderBy!=0 ); if( pIdx->bUnordered ){ /* Hash indices (indicated by the "unordered" tag on sqlite_stat1) cannot ** be used for sorting */ return nPriorSat; |
︙ | ︙ | |||
107358 107359 107360 107361 107362 107363 107364 | int isMatch; /* ORDER BY term matches the index term */ const char *zColl; /* Name of collating sequence for i-th index term */ WhereTerm *pConstraint; /* A constraint in the WHERE clause */ /* If the next term of the ORDER BY clause refers to anything other than ** a column in the "base" table, then this index will not be of any ** further use in handling the ORDER BY. */ | | | 104874 104875 104876 104877 104878 104879 104880 104881 104882 104883 104884 104885 104886 104887 104888 | int isMatch; /* ORDER BY term matches the index term */ const char *zColl; /* Name of collating sequence for i-th index term */ WhereTerm *pConstraint; /* A constraint in the WHERE clause */ /* If the next term of the ORDER BY clause refers to anything other than ** a column in the "base" table, then this index will not be of any ** further use in handling the ORDER BY. */ pOBExpr = pOBItem->pExpr; if( pOBExpr->op!=TK_COLUMN || pOBExpr->iTable!=base ){ break; } /* Find column number and collating sequence for the next entry ** in the index */ if( pIdx->zName && i<pIdx->nColumn ){ |
︙ | ︙ | |||
107384 107385 107386 107387 107388 107389 107390 | } /* Check to see if the column number and collating sequence of the ** index match the column number and collating sequence of the ORDER BY ** clause entry. Set isMatch to 1 if they both match. */ if( pOBExpr->iColumn==iColumn ){ if( zColl ){ | | | 104900 104901 104902 104903 104904 104905 104906 104907 104908 104909 104910 104911 104912 104913 104914 | } /* Check to see if the column number and collating sequence of the ** index match the column number and collating sequence of the ORDER BY ** clause entry. Set isMatch to 1 if they both match. */ if( pOBExpr->iColumn==iColumn ){ if( zColl ){ pColl = sqlite3ExprCollSeq(pParse, pOBExpr); if( !pColl ) pColl = db->pDfltColl; isMatch = sqlite3StrICmp(pColl->zName, zColl)==0; }else{ isMatch = 1; } }else{ isMatch = 0; |
︙ | ︙ | |||
107407 107408 107409 107410 107411 107412 107413 | /* If X is the column in the index and ORDER BY clause, check to see ** if there are any X= or X IS NULL constraints in the WHERE clause. */ pConstraint = findTerm(p->pWC, base, iColumn, p->notReady, WO_EQ|WO_ISNULL|WO_IN, pIdx); if( pConstraint==0 ){ isEq = 0; | | | > > > | | 104923 104924 104925 104926 104927 104928 104929 104930 104931 104932 104933 104934 104935 104936 104937 104938 104939 104940 104941 104942 | /* If X is the column in the index and ORDER BY clause, check to see ** if there are any X= or X IS NULL constraints in the WHERE clause. */ pConstraint = findTerm(p->pWC, base, iColumn, p->notReady, WO_EQ|WO_ISNULL|WO_IN, pIdx); if( pConstraint==0 ){ isEq = 0; }else if( pConstraint->eOperator==WO_IN ){ /* Constraints of the form: "X IN ..." cannot be used with an ORDER BY ** because we do not know in what order the values on the RHS of the IN ** operator will occur. */ break; }else if( pConstraint->eOperator==WO_ISNULL ){ uniqueNotNull = 0; isEq = 1; /* "X IS NULL" means X has only a single value */ }else if( pConstraint->prereqRight==0 ){ isEq = 1; /* Constraint "X=constant" means X has only a single value */ }else{ Expr *pRight = pConstraint->pExpr->pRight; if( pRight->op==TK_COLUMN ){ |
︙ | ︙ | |||
107459 107460 107461 107462 107463 107464 107465 | }else if( pTab->aCol[iColumn].notNull==0 && isEq!=1 ){ testcase( isEq==0 ); testcase( isEq==2 ); testcase( isEq==3 ); uniqueNotNull = 0; } } | < < < < < < < < < < < < < < < | | 104978 104979 104980 104981 104982 104983 104984 104985 104986 104987 104988 104989 104990 104991 104992 104993 104994 104995 104996 104997 104998 104999 105000 105001 105002 105003 105004 | }else if( pTab->aCol[iColumn].notNull==0 && isEq!=1 ){ testcase( isEq==0 ); testcase( isEq==2 ); testcase( isEq==3 ); uniqueNotNull = 0; } } /* If we have not found at least one ORDER BY term that matches the ** index, then show no progress. */ if( pOBItem==&pOrderBy->a[nPriorSat] ) return nPriorSat; /* Return the necessary scan order back to the caller */ *pbRev = sortOrder & 1; /* If there was an "ORDER BY rowid" term that matched, or it is only ** possible for a single row from this table to match, then skip over ** any additional ORDER BY terms dealing with this table. */ if( seenRowid || (uniqueNotNull && i>=pIdx->nColumn) ){ /* Advance j over additional ORDER BY terms associated with base */ WhereMaskSet *pMS = p->pWC->pMaskSet; Bitmask m = ~getMask(pMS, base); while( j<nTerm && (exprTableUsage(pMS, pOrderBy->a[j].pExpr)&m)==0 ){ j++; } } |
︙ | ︙ | |||
107519 107520 107521 107522 107523 107524 107525 | ** ** If there was an INDEXED BY clause (pSrc->pIndex) attached to the table in ** the SQL statement, then this function only considers plans using the ** named index. If no such plan is found, then the returned cost is ** SQLITE_BIG_DBL. If a plan is found that uses the named index, ** then the cost is calculated in the usual way. ** | | < < < < < | 105023 105024 105025 105026 105027 105028 105029 105030 105031 105032 105033 105034 105035 105036 105037 105038 105039 105040 105041 105042 105043 105044 105045 105046 105047 105048 105049 105050 105051 105052 105053 105054 | ** ** If there was an INDEXED BY clause (pSrc->pIndex) attached to the table in ** the SQL statement, then this function only considers plans using the ** named index. If no such plan is found, then the returned cost is ** SQLITE_BIG_DBL. If a plan is found that uses the named index, ** then the cost is calculated in the usual way. ** ** If a NOT INDEXED clause (pSrc->notIndexed!=0) was attached to the table ** in the SELECT statement, then no indexes are considered. However, the ** selected plan may still take advantage of the built-in rowid primary key ** index. */ static void bestBtreeIndex(WhereBestIdx *p){ Parse *pParse = p->pParse; /* The parsing context */ WhereClause *pWC = p->pWC; /* The WHERE clause */ struct SrcList_item *pSrc = p->pSrc; /* The FROM clause term to search */ int iCur = pSrc->iCursor; /* The cursor of the table to be accessed */ Index *pProbe; /* An index we are evaluating */ Index *pIdx; /* Copy of pProbe, or zero for IPK index */ int eqTermMask; /* Current mask of valid equality operators */ int idxEqTermMask; /* Index mask of valid equality operators */ Index sPk; /* A fake index object for the primary key */ tRowcnt aiRowEstPk[2]; /* The aiRowEst[] value for the sPk index */ int aiColumnPk = -1; /* The aColumn[] value for the sPk index */ int wsFlagMask; /* Allowed flags in p->cost.plan.wsFlag */ /* Initialize the cost to a worst-case value */ memset(&p->cost, 0, sizeof(p->cost)); p->cost.rCost = SQLITE_BIG_DBL; /* If the pSrc table is the right table of a LEFT JOIN then we may not ** use an index to satisfy IS NULL constraints on that table. This is |
︙ | ︙ | |||
107591 107592 107593 107594 107595 107596 107597 | wsFlagMask = ~( WHERE_COLUMN_IN|WHERE_COLUMN_EQ|WHERE_COLUMN_NULL|WHERE_COLUMN_RANGE ); eqTermMask = WO_EQ|WO_IN; pIdx = 0; } | < < < < < < < < < < < | 105090 105091 105092 105093 105094 105095 105096 105097 105098 105099 105100 105101 105102 105103 | wsFlagMask = ~( WHERE_COLUMN_IN|WHERE_COLUMN_EQ|WHERE_COLUMN_NULL|WHERE_COLUMN_RANGE ); eqTermMask = WO_EQ|WO_IN; pIdx = 0; } /* Loop over all indices looking for the best one to use */ for(; pProbe; pIdx=pProbe=pProbe->pNext){ const tRowcnt * const aiRowEst = pProbe->aiRowEst; WhereCost pc; /* Cost of using pProbe */ double log10N = (double)1; /* base-10 logarithm of nRow (inexact) */ |
︙ | ︙ | |||
107679 107680 107681 107682 107683 107684 107685 | ** SELECT a, b FROM tbl WHERE a = 1; ** SELECT a, b, c FROM tbl WHERE a = 1; */ int bInEst = 0; /* True if "x IN (SELECT...)" seen */ int nInMul = 1; /* Number of distinct equalities to lookup */ double rangeDiv = (double)1; /* Estimated reduction in search space */ int nBound = 0; /* Number of range constraints seen */ | | | | > > > > > > > > | > > > | 105167 105168 105169 105170 105171 105172 105173 105174 105175 105176 105177 105178 105179 105180 105181 105182 105183 105184 105185 105186 105187 105188 105189 105190 105191 105192 105193 105194 105195 105196 105197 105198 105199 105200 105201 105202 105203 105204 105205 | ** SELECT a, b FROM tbl WHERE a = 1; ** SELECT a, b, c FROM tbl WHERE a = 1; */ int bInEst = 0; /* True if "x IN (SELECT...)" seen */ int nInMul = 1; /* Number of distinct equalities to lookup */ double rangeDiv = (double)1; /* Estimated reduction in search space */ int nBound = 0; /* Number of range constraints seen */ int bSort; /* True if external sort required */ int bDist; /* True if index cannot help with DISTINCT */ int bLookup = 0; /* True if not a covering index */ int nPriorSat; /* ORDER BY terms satisfied by outer loops */ int nOrderBy; /* Number of ORDER BY terms */ WhereTerm *pTerm; /* A single term of the WHERE clause */ #ifdef SQLITE_ENABLE_STAT3 WhereTerm *pFirstTerm = 0; /* First term matching the index */ #endif WHERETRACE(( " %s(%s):\n", pSrc->pTab->zName, (pIdx ? pIdx->zName : "ipk") )); memset(&pc, 0, sizeof(pc)); nOrderBy = p->pOrderBy ? p->pOrderBy->nExpr : 0; if( p->i ){ nPriorSat = pc.plan.nOBSat = p->aLevel[p->i-1].plan.nOBSat; bSort = nPriorSat<nOrderBy; bDist = 0; }else{ nPriorSat = pc.plan.nOBSat = 0; bSort = nOrderBy>0; bDist = p->pDistinct!=0; } /* Determine the values of pc.plan.nEq and nInMul */ for(pc.plan.nEq=0; pc.plan.nEq<pProbe->nColumn; pc.plan.nEq++){ int j = pProbe->aiColumn[pc.plan.nEq]; pTerm = findTerm(pWC, iCur, j, p->notReady, eqTermMask, pIdx); if( pTerm==0 ) break; pc.plan.wsFlags |= (WHERE_COLUMN_EQ|WHERE_ROWID_EQ); |
︙ | ︙ | |||
107727 107728 107729 107730 107731 107732 107733 | /* If the index being considered is UNIQUE, and there is an equality ** constraint for all columns in the index, then this search will find ** at most a single row. In this case set the WHERE_UNIQUE flag to ** indicate this to the caller. ** ** Otherwise, if the search may find more than one row, test to see if | | | | 105226 105227 105228 105229 105230 105231 105232 105233 105234 105235 105236 105237 105238 105239 105240 105241 | /* If the index being considered is UNIQUE, and there is an equality ** constraint for all columns in the index, then this search will find ** at most a single row. In this case set the WHERE_UNIQUE flag to ** indicate this to the caller. ** ** Otherwise, if the search may find more than one row, test to see if ** there is a range constraint on indexed column (pc.plan.nEq+1) that can be ** optimized using the index. */ if( pc.plan.nEq==pProbe->nColumn && pProbe->onError!=OE_None ){ testcase( pc.plan.wsFlags & WHERE_COLUMN_IN ); testcase( pc.plan.wsFlags & WHERE_COLUMN_NULL ); if( (pc.plan.wsFlags & (WHERE_COLUMN_IN|WHERE_COLUMN_NULL))==0 ){ pc.plan.wsFlags |= WHERE_UNIQUE; if( p->i==0 || (p->aLevel[p->i-1].plan.wsFlags & WHERE_ALL_UNIQUE)!=0 ){ |
︙ | ︙ | |||
107770 107771 107772 107773 107774 107775 107776 | /* 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 pc.plan.wsFlags. Otherwise, if there is an ORDER BY clause but ** the index will scan rows in a different order, set the bSort ** variable. */ if( bSort && (pSrc->jointype & JT_LEFT)==0 ){ int bRev = 2; | < | | | | | < | 105269 105270 105271 105272 105273 105274 105275 105276 105277 105278 105279 105280 105281 105282 105283 105284 105285 105286 105287 105288 | /* 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 pc.plan.wsFlags. Otherwise, if there is an ORDER BY clause but ** the index will scan rows in a different order, set the bSort ** variable. */ if( bSort && (pSrc->jointype & JT_LEFT)==0 ){ int bRev = 2; WHERETRACE((" --> before isSortingIndex: nPriorSat=%d\n",nPriorSat)); pc.plan.nOBSat = isSortingIndex(p, pProbe, iCur, &bRev); WHERETRACE((" --> after isSortingIndex: bRev=%d nOBSat=%d\n", bRev, pc.plan.nOBSat)); if( nPriorSat<pc.plan.nOBSat || (pc.plan.wsFlags & WHERE_UNIQUE)!=0 ){ pc.plan.wsFlags |= WHERE_ORDERED; } if( nOrderBy==pc.plan.nOBSat ){ bSort = 0; pc.plan.wsFlags |= WHERE_ROWID_RANGE|WHERE_COLUMN_RANGE; } if( bRev & 1 ) pc.plan.wsFlags |= WHERE_REVERSE; } |
︙ | ︙ | |||
107839 107840 107841 107842 107843 107844 107845 | ** to get a better estimate on the number of rows based on ** VALUE and how common that value is according to the histogram. */ if( pc.plan.nRow>(double)1 && pc.plan.nEq==1 && pFirstTerm!=0 && aiRowEst[1]>1 ){ assert( (pFirstTerm->eOperator & (WO_EQ|WO_ISNULL|WO_IN))!=0 ); if( pFirstTerm->eOperator & (WO_EQ|WO_ISNULL) ){ | | | < | | 105336 105337 105338 105339 105340 105341 105342 105343 105344 105345 105346 105347 105348 105349 105350 105351 105352 105353 105354 105355 | ** to get a better estimate on the number of rows based on ** VALUE and how common that value is according to the histogram. */ if( pc.plan.nRow>(double)1 && pc.plan.nEq==1 && pFirstTerm!=0 && aiRowEst[1]>1 ){ assert( (pFirstTerm->eOperator & (WO_EQ|WO_ISNULL|WO_IN))!=0 ); if( pFirstTerm->eOperator & (WO_EQ|WO_ISNULL) ){ testcase( pFirstTerm->eOperator==WO_EQ ); testcase( pFirstTerm->eOperator==WO_ISNULL ); whereEqualScanEst(pParse, pProbe, pFirstTerm->pExpr->pRight, &pc.plan.nRow); }else if( bInEst==0 ){ assert( pFirstTerm->eOperator==WO_IN ); whereInScanEst(pParse, pProbe, pFirstTerm->pExpr->x.pList, &pc.plan.nRow); } } #endif /* SQLITE_ENABLE_STAT3 */ /* Adjust the number of output rows and downward to reflect rows |
︙ | ︙ | |||
107871 107872 107873 107874 107875 107876 107877 | ** on one page and hence more pages have to be fetched. ** ** The ANALYZE command and the sqlite_stat1 and sqlite_stat3 tables do ** not give us data on the relative sizes of table and index records. ** So this computation assumes table records are about twice as big ** as index records */ | | < | 105367 105368 105369 105370 105371 105372 105373 105374 105375 105376 105377 105378 105379 105380 105381 | ** on one page and hence more pages have to be fetched. ** ** The ANALYZE command and the sqlite_stat1 and sqlite_stat3 tables do ** not give us data on the relative sizes of table and index records. ** So this computation assumes table records are about twice as big ** as index records */ if( (pc.plan.wsFlags&~(WHERE_REVERSE|WHERE_ORDERED))==WHERE_IDX_ONLY && (pWC->wctrlFlags & WHERE_ONEPASS_DESIRED)==0 && sqlite3GlobalConfig.bUseCis && OptimizationEnabled(pParse->db, SQLITE_CoverIdxScan) ){ /* This index is not useful for indexing, but it is a covering index. ** A full-scan of the index might be a little faster than a full-scan ** of the table, so give this case a cost slightly less than a table |
︙ | ︙ | |||
107993 107994 107995 107996 107997 107998 107999 | ** set size by a factor of 3. Indexed range constraints reduce ** the search space by a larger factor: 4. We make indexed range ** more selective intentionally because of the subjective ** observation that indexed range constraints really are more ** selective in practice, on average. */ pc.plan.nRow /= 3; } | | | 105488 105489 105490 105491 105492 105493 105494 105495 105496 105497 105498 105499 105500 105501 105502 | ** set size by a factor of 3. Indexed range constraints reduce ** the search space by a larger factor: 4. We make indexed range ** more selective intentionally because of the subjective ** observation that indexed range constraints really are more ** selective in practice, on average. */ pc.plan.nRow /= 3; } }else if( pTerm->eOperator!=WO_NOOP ){ /* Any other expression lowers the output row count by half */ pc.plan.nRow /= 2; } } if( pc.plan.nRow<2 ) pc.plan.nRow = 2; } |
︙ | ︙ | |||
108032 108033 108034 108035 108036 108037 108038 | wsFlagMask = ~(WHERE_ROWID_EQ|WHERE_ROWID_RANGE); eqTermMask = idxEqTermMask; } /* If there is no ORDER BY clause and the SQLITE_ReverseOrder flag ** is set, then reverse the order that the index will be scanned ** in. This is used for application testing, to help find cases | | | | < | 105527 105528 105529 105530 105531 105532 105533 105534 105535 105536 105537 105538 105539 105540 105541 105542 105543 105544 105545 105546 105547 105548 105549 105550 105551 105552 105553 105554 105555 | wsFlagMask = ~(WHERE_ROWID_EQ|WHERE_ROWID_RANGE); eqTermMask = idxEqTermMask; } /* If there is no ORDER BY clause and the SQLITE_ReverseOrder flag ** is set, then reverse the order that the index will be scanned ** in. This is used for application testing, to help find cases ** where application behaviour depends on the (undefined) order that ** SQLite outputs rows in in the absence of an ORDER BY clause. */ if( !p->pOrderBy && pParse->db->flags & SQLITE_ReverseOrder ){ p->cost.plan.wsFlags |= WHERE_REVERSE; } assert( p->pOrderBy || (p->cost.plan.wsFlags&WHERE_ORDERED)==0 ); assert( p->cost.plan.u.pIdx==0 || (p->cost.plan.wsFlags&WHERE_ROWID_EQ)==0 ); assert( pSrc->pIndex==0 || p->cost.plan.u.pIdx==0 || p->cost.plan.u.pIdx==pSrc->pIndex ); WHERETRACE((" best index is: %s\n", p->cost.plan.u.pIdx ? p->cost.plan.u.pIdx->zName : "ipk")); bestOrClauseIndex(p); bestAutomaticIndex(p); p->cost.plan.wsFlags |= eqTermMask; } /* |
︙ | ︙ | |||
108072 108073 108074 108075 108076 108077 108078 | */ static void bestIndex(WhereBestIdx *p){ #ifndef SQLITE_OMIT_VIRTUALTABLE if( IsVirtual(p->pSrc->pTab) ){ sqlite3_index_info *pIdxInfo = 0; p->ppIdxInfo = &pIdxInfo; bestVirtualIndex(p); | < | | 105566 105567 105568 105569 105570 105571 105572 105573 105574 105575 105576 105577 105578 105579 105580 | */ static void bestIndex(WhereBestIdx *p){ #ifndef SQLITE_OMIT_VIRTUALTABLE if( IsVirtual(p->pSrc->pTab) ){ sqlite3_index_info *pIdxInfo = 0; p->ppIdxInfo = &pIdxInfo; bestVirtualIndex(p); if( pIdxInfo->needToFreeIdxStr ){ sqlite3_free(pIdxInfo->idxStr); } sqlite3DbFree(p->pParse->db, pIdxInfo); }else #endif { bestBtreeIndex(p); |
︙ | ︙ | |||
108179 108180 108181 108182 108183 108184 108185 | ** For a constraint of the form X=expr, the expression is evaluated and its ** result is left on the stack. For constraints of the form X IN (...) ** this routine sets up a loop that will iterate over all values of X. */ static int codeEqualityTerm( Parse *pParse, /* The parsing context */ WhereTerm *pTerm, /* The term of the WHERE clause to be coded */ | | < < < < < < < < < < < < < < < | < | 105672 105673 105674 105675 105676 105677 105678 105679 105680 105681 105682 105683 105684 105685 105686 105687 105688 105689 105690 105691 105692 105693 105694 105695 105696 105697 105698 105699 105700 105701 105702 105703 105704 105705 105706 105707 105708 105709 105710 105711 105712 105713 105714 105715 105716 105717 105718 105719 105720 105721 105722 105723 105724 105725 105726 | ** For a constraint of the form X=expr, the expression is evaluated and its ** result is left on the stack. For constraints of the form X IN (...) ** this routine sets up a loop that will iterate over all values of X. */ static int codeEqualityTerm( Parse *pParse, /* The parsing context */ WhereTerm *pTerm, /* The term of the WHERE clause to be coded */ WhereLevel *pLevel, /* When level of the FROM clause we are working on */ int iTarget /* Attempt to leave results in this register */ ){ Expr *pX = pTerm->pExpr; Vdbe *v = pParse->pVdbe; int iReg; /* Register holding results */ assert( iTarget>0 ); if( pX->op==TK_EQ ){ iReg = sqlite3ExprCodeTarget(pParse, pX->pRight, iTarget); }else if( pX->op==TK_ISNULL ){ iReg = iTarget; sqlite3VdbeAddOp2(v, OP_Null, 0, iReg); #ifndef SQLITE_OMIT_SUBQUERY }else{ int eType; int iTab; struct InLoop *pIn; assert( pX->op==TK_IN ); iReg = iTarget; eType = sqlite3FindInIndex(pParse, pX, 0); iTab = pX->iTable; sqlite3VdbeAddOp2(v, OP_Rewind, iTab, 0); assert( pLevel->plan.wsFlags & WHERE_IN_ABLE ); if( pLevel->u.in.nIn==0 ){ pLevel->addrNxt = sqlite3VdbeMakeLabel(v); } pLevel->u.in.nIn++; pLevel->u.in.aInLoop = sqlite3DbReallocOrFree(pParse->db, pLevel->u.in.aInLoop, sizeof(pLevel->u.in.aInLoop[0])*pLevel->u.in.nIn); pIn = pLevel->u.in.aInLoop; if( pIn ){ pIn += pLevel->u.in.nIn - 1; pIn->iCur = iTab; if( eType==IN_INDEX_ROWID ){ pIn->addrInTop = sqlite3VdbeAddOp2(v, OP_Rowid, iTab, iReg); }else{ pIn->addrInTop = sqlite3VdbeAddOp3(v, OP_Column, iTab, 0, iReg); } sqlite3VdbeAddOp1(v, OP_IsNull, iReg); }else{ pLevel->u.in.nIn = 0; } #endif } disableTerm(pLevel, pTerm); |
︙ | ︙ | |||
108330 108331 108332 108333 108334 108335 108336 | int k = pIdx->aiColumn[j]; pTerm = findTerm(pWC, iCur, k, notReady, pLevel->plan.wsFlags, pIdx); if( pTerm==0 ) break; /* The following true for indices with redundant columns. ** Ex: CREATE INDEX i1 ON t1(a,b,a); SELECT * FROM t1 WHERE a=0 AND b=0; */ testcase( (pTerm->wtFlags & TERM_CODED)!=0 ); testcase( pTerm->wtFlags & TERM_VIRTUAL ); /* EV: R-30575-11662 */ | | | 105807 105808 105809 105810 105811 105812 105813 105814 105815 105816 105817 105818 105819 105820 105821 | int k = pIdx->aiColumn[j]; pTerm = findTerm(pWC, iCur, k, notReady, pLevel->plan.wsFlags, pIdx); if( pTerm==0 ) break; /* The following true for indices with redundant columns. ** Ex: CREATE INDEX i1 ON t1(a,b,a); SELECT * FROM t1 WHERE a=0 AND b=0; */ testcase( (pTerm->wtFlags & TERM_CODED)!=0 ); testcase( pTerm->wtFlags & TERM_VIRTUAL ); /* EV: R-30575-11662 */ r1 = codeEqualityTerm(pParse, pTerm, pLevel, regBase+j); if( r1!=regBase+j ){ if( nReg==1 ){ sqlite3ReleaseTempReg(pParse, regBase); regBase = r1; }else{ sqlite3VdbeAddOp2(v, OP_SCopy, r1, regBase+j); } |
︙ | ︙ | |||
108540 108541 108542 108543 108544 108545 108546 | Parse *pParse; /* Parsing context */ Vdbe *v; /* The prepared stmt under constructions */ struct SrcList_item *pTabItem; /* FROM clause term being coded */ int addrBrk; /* Jump here to break out of the loop */ int addrCont; /* Jump here to continue with next cycle */ int iRowidReg = 0; /* Rowid is stored in this register, if not zero */ int iReleaseReg = 0; /* Temp register to free before returning */ | < < | 106017 106018 106019 106020 106021 106022 106023 106024 106025 106026 106027 106028 106029 106030 106031 106032 106033 106034 106035 106036 106037 106038 106039 106040 | Parse *pParse; /* Parsing context */ Vdbe *v; /* The prepared stmt under constructions */ struct SrcList_item *pTabItem; /* FROM clause term being coded */ int addrBrk; /* Jump here to break out of the loop */ int addrCont; /* Jump here to continue with next cycle */ int iRowidReg = 0; /* Rowid is stored in this register, if not zero */ int iReleaseReg = 0; /* Temp register to free before returning */ pParse = pWInfo->pParse; v = pParse->pVdbe; pWC = pWInfo->pWC; pLevel = &pWInfo->a[iLevel]; pTabItem = &pWInfo->pTabList->a[pLevel->iFrom]; iCur = pTabItem->iCursor; bRev = (pLevel->plan.wsFlags & WHERE_REVERSE)!=0; omitTable = (pLevel->plan.wsFlags & WHERE_IDX_ONLY)!=0 && (wctrlFlags & WHERE_FORCE_TABLE)==0; /* Create labels for the "break" and "continue" instructions ** for the current loop. Jump to addrBrk to break out of a loop. ** Jump to cont to go immediately to the next iteration of the ** loop. ** ** When there is an IN operator, we also have a "addrNxt" label that |
︙ | ︙ | |||
108576 108577 108578 108579 108580 108581 108582 | */ if( pLevel->iFrom>0 && (pTabItem[0].jointype & JT_LEFT)!=0 ){ pLevel->iLeftJoin = ++pParse->nMem; sqlite3VdbeAddOp2(v, OP_Integer, 0, pLevel->iLeftJoin); VdbeComment((v, "init LEFT JOIN no-match flag")); } | < < < < < < < < < < < < < | < < < < | < | | 106051 106052 106053 106054 106055 106056 106057 106058 106059 106060 106061 106062 106063 106064 106065 106066 106067 106068 106069 106070 106071 106072 106073 106074 106075 106076 106077 106078 106079 106080 106081 106082 106083 106084 106085 106086 106087 106088 106089 106090 106091 106092 | */ if( pLevel->iFrom>0 && (pTabItem[0].jointype & JT_LEFT)!=0 ){ pLevel->iLeftJoin = ++pParse->nMem; sqlite3VdbeAddOp2(v, OP_Integer, 0, pLevel->iLeftJoin); VdbeComment((v, "init LEFT JOIN no-match flag")); } #ifndef SQLITE_OMIT_VIRTUALTABLE if( (pLevel->plan.wsFlags & WHERE_VIRTUALTABLE)!=0 ){ /* Case 0: The table is a virtual-table. Use the VFilter and VNext ** to access the data. */ int iReg; /* P3 Value for OP_VFilter */ sqlite3_index_info *pVtabIdx = pLevel->plan.u.pVtabIdx; int nConstraint = pVtabIdx->nConstraint; struct sqlite3_index_constraint_usage *aUsage = pVtabIdx->aConstraintUsage; const struct sqlite3_index_constraint *aConstraint = pVtabIdx->aConstraint; sqlite3ExprCachePush(pParse); iReg = sqlite3GetTempRange(pParse, nConstraint+2); for(j=1; j<=nConstraint; j++){ for(k=0; k<nConstraint; k++){ if( aUsage[k].argvIndex==j ){ int iTerm = aConstraint[k].iTermOffset; sqlite3ExprCode(pParse, pWC->a[iTerm].pExpr->pRight, iReg+j+1); break; } } if( k==nConstraint ) break; } sqlite3VdbeAddOp2(v, OP_Integer, pVtabIdx->idxNum, iReg); sqlite3VdbeAddOp2(v, OP_Integer, j-1, iReg+1); sqlite3VdbeAddOp4(v, OP_VFilter, iCur, addrBrk, iReg, pVtabIdx->idxStr, pVtabIdx->needToFreeIdxStr ? P4_MPRINTF : P4_STATIC); pVtabIdx->needToFreeIdxStr = 0; for(j=0; j<nConstraint; j++){ if( aUsage[j].omit ){ int iTerm = aConstraint[j].iTermOffset; disableTerm(pLevel, &pWC->a[iTerm]); } |
︙ | ︙ | |||
108648 108649 108650 108651 108652 108653 108654 108655 108656 | ** we reference multiple rows using a "rowid IN (...)" ** construct. */ iReleaseReg = sqlite3GetTempReg(pParse); pTerm = findTerm(pWC, iCur, -1, notReady, WO_EQ|WO_IN, 0); assert( pTerm!=0 ); assert( pTerm->pExpr!=0 ); assert( omitTable==0 ); testcase( pTerm->wtFlags & TERM_VIRTUAL ); /* EV: R-30575-11662 */ | > | < | 106105 106106 106107 106108 106109 106110 106111 106112 106113 106114 106115 106116 106117 106118 106119 106120 106121 106122 106123 106124 106125 | ** we reference multiple rows using a "rowid IN (...)" ** construct. */ iReleaseReg = sqlite3GetTempReg(pParse); pTerm = findTerm(pWC, iCur, -1, notReady, WO_EQ|WO_IN, 0); assert( pTerm!=0 ); assert( pTerm->pExpr!=0 ); assert( pTerm->leftCursor==iCur ); assert( omitTable==0 ); testcase( pTerm->wtFlags & TERM_VIRTUAL ); /* EV: R-30575-11662 */ iRowidReg = codeEqualityTerm(pParse, pTerm, pLevel, iReleaseReg); addrNxt = pLevel->addrNxt; sqlite3VdbeAddOp2(v, OP_MustBeInt, iRowidReg, addrNxt); sqlite3VdbeAddOp3(v, OP_NotExists, iCur, addrNxt, iRowidReg); sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg); VdbeComment((v, "pk")); pLevel->op = OP_Noop; }else if( pLevel->plan.wsFlags & WHERE_ROWID_RANGE ){ /* Case 2: We have an inequality comparison against the ROWID field. */ int testOp = OP_Noop; |
︙ | ︙ | |||
109039 109040 109041 109042 109043 109044 109045 | int iRetInit; /* Address of regReturn init */ int untestedTerms = 0; /* Some terms not completely tested */ int ii; /* Loop counter */ Expr *pAndExpr = 0; /* An ".. AND (...)" expression */ pTerm = pLevel->plan.u.pTerm; assert( pTerm!=0 ); | | | 106496 106497 106498 106499 106500 106501 106502 106503 106504 106505 106506 106507 106508 106509 106510 | int iRetInit; /* Address of regReturn init */ int untestedTerms = 0; /* Some terms not completely tested */ int ii; /* Loop counter */ Expr *pAndExpr = 0; /* An ".. AND (...)" expression */ pTerm = pLevel->plan.u.pTerm; assert( pTerm!=0 ); assert( pTerm->eOperator==WO_OR ); assert( (pTerm->wtFlags & TERM_ORINFO)!=0 ); pOrWc = &pTerm->u.pOrInfo->wc; pLevel->op = OP_Return; pLevel->p1 = regReturn; /* Set up a new SrcList in pOrTab containing the table being scanned ** by this loop in the a[0] slot and all notReady tables in a[1..] slots. |
︙ | ︙ | |||
109094 109095 109096 109097 109098 109099 109100 | ** That way, terms in y that are factored into the disjunction will ** be picked up by the recursive calls to sqlite3WhereBegin() below. ** ** Actually, each subexpression is converted to "xN AND w" where w is ** the "interesting" terms of z - terms that did not originate in the ** ON or USING clause of a LEFT JOIN, and terms that are usable as ** indices. | < < < < | | | 106551 106552 106553 106554 106555 106556 106557 106558 106559 106560 106561 106562 106563 106564 106565 106566 106567 106568 106569 106570 106571 106572 106573 106574 106575 106576 106577 106578 106579 106580 106581 106582 106583 106584 106585 106586 | ** That way, terms in y that are factored into the disjunction will ** be picked up by the recursive calls to sqlite3WhereBegin() below. ** ** Actually, each subexpression is converted to "xN AND w" where w is ** the "interesting" terms of z - terms that did not originate in the ** ON or USING clause of a LEFT JOIN, and terms that are usable as ** indices. */ if( pWC->nTerm>1 ){ int iTerm; for(iTerm=0; iTerm<pWC->nTerm; iTerm++){ Expr *pExpr = pWC->a[iTerm].pExpr; if( ExprHasProperty(pExpr, EP_FromJoin) ) continue; if( pWC->a[iTerm].wtFlags & (TERM_VIRTUAL|TERM_ORINFO) ) continue; if( (pWC->a[iTerm].eOperator & WO_ALL)==0 ) continue; pExpr = sqlite3ExprDup(pParse->db, pExpr, 0); pAndExpr = sqlite3ExprAnd(pParse->db, pAndExpr, pExpr); } if( pAndExpr ){ pAndExpr = sqlite3PExpr(pParse, TK_AND, 0, pAndExpr, 0); } } for(ii=0; ii<pOrWc->nTerm; ii++){ WhereTerm *pOrTerm = &pOrWc->a[ii]; if( pOrTerm->leftCursor==iCur || pOrTerm->eOperator==WO_AND ){ WhereInfo *pSubWInfo; /* Info for single OR-term scan */ Expr *pOrExpr = pOrTerm->pExpr; if( pAndExpr ){ pAndExpr->pLeft = pOrExpr; pOrExpr = pAndExpr; } /* Loop through table entries that match term pOrTerm. */ pSubWInfo = sqlite3WhereBegin(pParse, pOrTab, pOrExpr, 0, 0, WHERE_OMIT_OPEN_CLOSE | WHERE_AND_ONLY | WHERE_FORCE_TABLE | WHERE_ONETABLE_ONLY, iCovCur); |
︙ | ︙ | |||
109206 109207 109208 109209 109210 109211 109212 | assert( bRev==0 || bRev==1 ); assert( omitTable==0 ); pLevel->op = aStep[bRev]; pLevel->p1 = iCur; pLevel->p2 = 1 + sqlite3VdbeAddOp2(v, aStart[bRev], iCur, addrBrk); pLevel->p5 = SQLITE_STMTSTATUS_FULLSCAN_STEP; } | | | < < < < < < < < < < < < < < < < < < < < < < < < < < < | | | 106659 106660 106661 106662 106663 106664 106665 106666 106667 106668 106669 106670 106671 106672 106673 106674 106675 106676 106677 106678 106679 106680 106681 106682 106683 106684 106685 106686 106687 106688 106689 106690 106691 106692 106693 106694 106695 106696 106697 106698 106699 106700 106701 106702 106703 106704 106705 106706 106707 106708 106709 106710 106711 106712 106713 106714 106715 106716 106717 106718 106719 106720 106721 106722 106723 106724 106725 | assert( bRev==0 || bRev==1 ); assert( omitTable==0 ); pLevel->op = aStep[bRev]; pLevel->p1 = iCur; pLevel->p2 = 1 + sqlite3VdbeAddOp2(v, aStart[bRev], iCur, addrBrk); pLevel->p5 = SQLITE_STMTSTATUS_FULLSCAN_STEP; } notReady &= ~getMask(pWC->pMaskSet, iCur); /* Insert code to test every subexpression that can be completely ** computed using the current set of tables. ** ** IMPLEMENTATION-OF: R-49525-50935 Terms that cannot be satisfied through ** the use of indices become tests that are evaluated against each row of ** the relevant input tables. */ for(pTerm=pWC->a, j=pWC->nTerm; j>0; j--, pTerm++){ Expr *pE; testcase( pTerm->wtFlags & TERM_VIRTUAL ); /* IMP: R-30575-11662 */ testcase( pTerm->wtFlags & TERM_CODED ); if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue; if( (pTerm->prereqAll & notReady)!=0 ){ testcase( pWInfo->untestedTerms==0 && (pWInfo->wctrlFlags & WHERE_ONETABLE_ONLY)!=0 ); pWInfo->untestedTerms = 1; continue; } pE = pTerm->pExpr; assert( pE!=0 ); if( pLevel->iLeftJoin && !ExprHasProperty(pE, EP_FromJoin) ){ continue; } sqlite3ExprIfFalse(pParse, pE, addrCont, SQLITE_JUMPIFNULL); pTerm->wtFlags |= TERM_CODED; } /* For a LEFT OUTER JOIN, generate code that will record the fact that ** at least one row of the right table has matched the left table. */ if( pLevel->iLeftJoin ){ pLevel->addrFirst = sqlite3VdbeCurrentAddr(v); sqlite3VdbeAddOp2(v, OP_Integer, 1, pLevel->iLeftJoin); VdbeComment((v, "record LEFT JOIN hit")); sqlite3ExprCacheClear(pParse); for(pTerm=pWC->a, j=0; j<pWC->nTerm; j++, pTerm++){ testcase( pTerm->wtFlags & TERM_VIRTUAL ); /* IMP: R-30575-11662 */ testcase( pTerm->wtFlags & TERM_CODED ); if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue; if( (pTerm->prereqAll & notReady)!=0 ){ assert( pWInfo->untestedTerms ); continue; } assert( pTerm->pExpr ); sqlite3ExprIfFalse(pParse, pTerm->pExpr, addrCont, SQLITE_JUMPIFNULL); pTerm->wtFlags |= TERM_CODED; } } sqlite3ReleaseTempReg(pParse, iReleaseReg); return notReady; } #if defined(SQLITE_TEST) /* ** The following variable holds a text description of query plan generated ** by the most recent call to sqlite3WhereBegin(). Each call to WhereBegin ** overwrites the previous. This information is used for testing and |
︙ | ︙ | |||
109520 109521 109522 109523 109524 109525 109526 109527 109528 109529 109530 109531 109532 109533 109534 109535 109536 109537 109538 109539 109540 109541 | ** the case that if X is the bitmask for the N-th FROM clause term then ** the bitmask for all FROM clause terms to the left of the N-th term ** is (X-1). An expression from the ON clause of a LEFT JOIN can use ** its Expr.iRightJoinTable value to find the bitmask of the right table ** of the join. Subtracting one from the right table bitmask gives a ** bitmask for all tables to the left of the join. Knowing the bitmask ** for all tables to the left of a left join is important. Ticket #3015. ** ** Note that bitmasks are created for all pTabList->nSrc tables in ** pTabList, not just the first nTabList tables. nTabList is normally ** equal to pTabList->nSrc but might be shortened to 1 if the ** WHERE_ONETABLE_ONLY flag is set. */ for(ii=0; ii<pTabList->nSrc; ii++){ createMask(pMaskSet, pTabList->a[ii].iCursor); } #ifndef NDEBUG { Bitmask toTheLeft = 0; for(ii=0; ii<pTabList->nSrc; ii++){ Bitmask m = getMask(pMaskSet, pTabList->a[ii].iCursor); assert( (m-1)==toTheLeft ); | > > > > > > > > > > > | 106946 106947 106948 106949 106950 106951 106952 106953 106954 106955 106956 106957 106958 106959 106960 106961 106962 106963 106964 106965 106966 106967 106968 106969 106970 106971 106972 106973 106974 106975 106976 106977 106978 | ** the case that if X is the bitmask for the N-th FROM clause term then ** the bitmask for all FROM clause terms to the left of the N-th term ** is (X-1). An expression from the ON clause of a LEFT JOIN can use ** its Expr.iRightJoinTable value to find the bitmask of the right table ** of the join. Subtracting one from the right table bitmask gives a ** bitmask for all tables to the left of the join. Knowing the bitmask ** for all tables to the left of a left join is important. Ticket #3015. ** ** Configure the WhereClause.vmask variable so that bits that correspond ** to virtual table cursors are set. This is used to selectively disable ** the OR-to-IN transformation in exprAnalyzeOrTerm(). It is not helpful ** with virtual tables. ** ** Note that bitmasks are created for all pTabList->nSrc tables in ** pTabList, not just the first nTabList tables. nTabList is normally ** equal to pTabList->nSrc but might be shortened to 1 if the ** WHERE_ONETABLE_ONLY flag is set. */ assert( sWBI.pWC->vmask==0 && pMaskSet->n==0 ); for(ii=0; ii<pTabList->nSrc; ii++){ createMask(pMaskSet, pTabList->a[ii].iCursor); #ifndef SQLITE_OMIT_VIRTUALTABLE if( ALWAYS(pTabList->a[ii].pTab) && IsVirtual(pTabList->a[ii].pTab) ){ sWBI.pWC->vmask |= ((Bitmask)1 << ii); } #endif } #ifndef NDEBUG { Bitmask toTheLeft = 0; for(ii=0; ii<pTabList->nSrc; ii++){ Bitmask m = getMask(pMaskSet, pTabList->a[ii].iCursor); assert( (m-1)==toTheLeft ); |
︙ | ︙ | |||
109587 109588 109589 109590 109591 109592 109593 | for(sWBI.i=iFrom=0, pLevel=pWInfo->a; sWBI.i<nTabList; sWBI.i++, pLevel++){ WhereCost bestPlan; /* Most efficient plan seen so far */ Index *pIdx; /* Index for FROM table at pTabItem */ int j; /* For looping over FROM tables */ int bestJ = -1; /* The value of j */ Bitmask m; /* Bitmask value for j or bestJ */ int isOptimal; /* Iterator for optimal/non-optimal search */ | < | 107024 107025 107026 107027 107028 107029 107030 107031 107032 107033 107034 107035 107036 107037 | for(sWBI.i=iFrom=0, pLevel=pWInfo->a; sWBI.i<nTabList; sWBI.i++, pLevel++){ WhereCost bestPlan; /* Most efficient plan seen so far */ Index *pIdx; /* Index for FROM table at pTabItem */ int j; /* For looping over FROM tables */ int bestJ = -1; /* The value of j */ Bitmask m; /* Bitmask value for j or bestJ */ int isOptimal; /* Iterator for optimal/non-optimal search */ int nUnconstrained; /* Number tables without INDEXED BY */ Bitmask notIndexed; /* Mask of tables that cannot use an index */ memset(&bestPlan, 0, sizeof(bestPlan)); bestPlan.rCost = SQLITE_BIG_DBL; WHERETRACE(("*** Begin search for loop %d ***\n", sWBI.i)); |
︙ | ︙ | |||
109622 109623 109624 109625 109626 109627 109628 | ** that do not use indices. But this nRow reduction only happens if the ** table really is the innermost join. ** ** The second loop iteration is only performed if no optimal scan ** strategies were found by the first iteration. This second iteration ** is used to search for the lowest cost scan overall. ** | | > > | | < < < < < < > > > > < < < < < < < < < < < < < < < < < < < < < < | 107058 107059 107060 107061 107062 107063 107064 107065 107066 107067 107068 107069 107070 107071 107072 107073 107074 107075 107076 107077 107078 107079 107080 107081 107082 107083 107084 107085 107086 107087 107088 107089 107090 107091 107092 107093 107094 107095 107096 107097 107098 107099 107100 | ** that do not use indices. But this nRow reduction only happens if the ** table really is the innermost join. ** ** The second loop iteration is only performed if no optimal scan ** strategies were found by the first iteration. This second iteration ** is used to search for the lowest cost scan overall. ** ** Previous versions of SQLite performed only the second iteration - ** the next outermost loop was always that with the lowest overall ** cost. However, this meant that SQLite could select the wrong plan ** for scripts such as the following: ** ** CREATE TABLE t1(a, b); ** CREATE TABLE t2(c, d); ** SELECT * FROM t2, t1 WHERE t2.rowid = t1.a; ** ** The best strategy is to iterate through table t1 first. However it ** is not possible to determine this with a simple greedy algorithm. ** Since the cost of a linear scan through table t2 is the same ** as the cost of a linear scan through table t1, a simple greedy ** algorithm may choose to use t2 for the outer loop, which is a much ** costlier approach. */ nUnconstrained = 0; notIndexed = 0; for(isOptimal=(iFrom<nTabList-1); isOptimal>=0 && bestJ<0; isOptimal--){ for(j=iFrom, sWBI.pSrc=&pTabList->a[j]; j<nTabList; j++, sWBI.pSrc++){ int doNotReorder; /* True if this table should not be reordered */ doNotReorder = (sWBI.pSrc->jointype & (JT_LEFT|JT_CROSS))!=0; if( j!=iFrom && doNotReorder ) break; m = getMask(pMaskSet, sWBI.pSrc->iCursor); if( (m & sWBI.notValid)==0 ){ if( j==iFrom ) iFrom++; continue; } sWBI.notReady = (isOptimal ? m : sWBI.notValid); if( sWBI.pSrc->pIndex==0 ) nUnconstrained++; WHERETRACE((" === trying table %d (%s) with isOptimal=%d ===\n", j, sWBI.pSrc->pTab->zName, isOptimal)); assert( sWBI.pSrc->pTab ); #ifndef SQLITE_OMIT_VIRTUALTABLE |
︙ | ︙ | |||
109699 109700 109701 109702 109703 109704 109705 | assert( sWBI.pSrc->pIndex==0 || (sWBI.cost.plan.wsFlags & WHERE_NOT_FULLSCAN)==0 || sWBI.cost.plan.u.pIdx==sWBI.pSrc->pIndex ); if( isOptimal && (sWBI.cost.plan.wsFlags & WHERE_NOT_FULLSCAN)==0 ){ notIndexed |= m; } | < < < < < < < < < < < < < | | > > > | < < < < < < < < | 107113 107114 107115 107116 107117 107118 107119 107120 107121 107122 107123 107124 107125 107126 107127 107128 107129 107130 107131 107132 107133 107134 107135 107136 107137 107138 107139 107140 107141 107142 107143 107144 107145 107146 107147 107148 107149 107150 107151 107152 107153 107154 107155 107156 107157 107158 107159 107160 107161 107162 107163 107164 107165 107166 107167 107168 107169 | assert( sWBI.pSrc->pIndex==0 || (sWBI.cost.plan.wsFlags & WHERE_NOT_FULLSCAN)==0 || sWBI.cost.plan.u.pIdx==sWBI.pSrc->pIndex ); if( isOptimal && (sWBI.cost.plan.wsFlags & WHERE_NOT_FULLSCAN)==0 ){ notIndexed |= m; } /* Conditions under which this table becomes the best so far: ** ** (1) The table must not depend on other tables that have not ** yet run. (In other words, it must not depend on tables ** in inner loops.) ** ** (2) A full-table-scan plan cannot supercede indexed plan unless ** the full-table-scan is an "optimal" plan as defined above. ** ** (3) All tables have an INDEXED BY clause or this table lacks an ** INDEXED BY clause or this table uses the specific ** index specified by its INDEXED BY clause. This rule ensures ** that a best-so-far is always selected even if an impossible ** combination of INDEXED BY clauses are given. The error ** will be detected and relayed back to the application later. ** The NEVER() comes about because rule (2) above prevents ** An indexable full-table-scan from reaching rule (3). ** ** (4) The plan cost must be lower than prior plans, where "cost" ** is defined by the compareCost() function above. */ if( (sWBI.cost.used&sWBI.notValid)==0 /* (1) */ && (bestJ<0 || (notIndexed&m)!=0 /* (2) */ || (bestPlan.plan.wsFlags & WHERE_NOT_FULLSCAN)==0 || (sWBI.cost.plan.wsFlags & WHERE_NOT_FULLSCAN)!=0) && (nUnconstrained==0 || sWBI.pSrc->pIndex==0 /* (3) */ || NEVER((sWBI.cost.plan.wsFlags & WHERE_NOT_FULLSCAN)!=0)) && (bestJ<0 || compareCost(&sWBI.cost, &bestPlan)) /* (4) */ ){ WHERETRACE((" === table %d (%s) is best so far\n" " cost=%.1f, nRow=%.1f, nOBSat=%d, wsFlags=%08x\n", j, sWBI.pSrc->pTab->zName, sWBI.cost.rCost, sWBI.cost.plan.nRow, sWBI.cost.plan.nOBSat, sWBI.cost.plan.wsFlags)); bestPlan = sWBI.cost; bestJ = j; } if( doNotReorder ) break; } } assert( bestJ>=0 ); assert( sWBI.notValid & getMask(pMaskSet, pTabList->a[bestJ].iCursor) ); WHERETRACE(("*** Optimizer selects table %d (%s) for loop %d with:\n" " cost=%.1f, nRow=%.1f, nOBSat=%d, wsFlags=0x%08x\n", bestJ, pTabList->a[bestJ].pTab->zName, pLevel-pWInfo->a, bestPlan.rCost, bestPlan.plan.nRow, bestPlan.plan.nOBSat, bestPlan.plan.wsFlags)); if( (bestPlan.plan.wsFlags & WHERE_DISTINCT)!=0 ){ assert( pWInfo->eDistinct==0 ); |
︙ | ︙ | |||
109862 109863 109864 109865 109866 109867 109868 | /* Do nothing */ }else #ifndef SQLITE_OMIT_VIRTUALTABLE if( (pLevel->plan.wsFlags & WHERE_VIRTUALTABLE)!=0 ){ const char *pVTab = (const char *)sqlite3GetVTable(db, pTab); int iCur = pTabItem->iCursor; sqlite3VdbeAddOp4(v, OP_VOpen, iCur, 0, 0, pVTab, P4_VTAB); | < < | 107258 107259 107260 107261 107262 107263 107264 107265 107266 107267 107268 107269 107270 107271 | /* Do nothing */ }else #ifndef SQLITE_OMIT_VIRTUALTABLE if( (pLevel->plan.wsFlags & WHERE_VIRTUALTABLE)!=0 ){ const char *pVTab = (const char *)sqlite3GetVTable(db, pTab); int iCur = pTabItem->iCursor; sqlite3VdbeAddOp4(v, OP_VOpen, iCur, 0, 0, pVTab, P4_VTAB); }else #endif if( (pLevel->plan.wsFlags & WHERE_IDX_ONLY)==0 && (wctrlFlags & WHERE_OMIT_OPEN_CLOSE)==0 ){ int op = pWInfo->okOnePass ? OP_OpenWrite : OP_OpenRead; sqlite3OpenTable(pParse, pTabItem->iCursor, iDb, pTab, op); testcase( pTab->nCol==BMS-1 ); |
︙ | ︙ | |||
110011 110012 110013 110014 110015 110016 110017 | } if( pLevel->plan.wsFlags & WHERE_IN_ABLE && pLevel->u.in.nIn>0 ){ struct InLoop *pIn; int j; sqlite3VdbeResolveLabel(v, pLevel->addrNxt); for(j=pLevel->u.in.nIn, pIn=&pLevel->u.in.aInLoop[j-1]; j>0; j--, pIn--){ sqlite3VdbeJumpHere(v, pIn->addrInTop+1); | | | 107405 107406 107407 107408 107409 107410 107411 107412 107413 107414 107415 107416 107417 107418 107419 | } if( pLevel->plan.wsFlags & WHERE_IN_ABLE && pLevel->u.in.nIn>0 ){ struct InLoop *pIn; int j; sqlite3VdbeResolveLabel(v, pLevel->addrNxt); for(j=pLevel->u.in.nIn, pIn=&pLevel->u.in.aInLoop[j-1]; j>0; j--, pIn--){ sqlite3VdbeJumpHere(v, pIn->addrInTop+1); sqlite3VdbeAddOp2(v, OP_Next, pIn->iCur, pIn->addrInTop); sqlite3VdbeJumpHere(v, pIn->addrInTop-1); } sqlite3DbFree(db, pLevel->u.in.aInLoop); } sqlite3VdbeResolveLabel(v, pLevel->addrBrk); if( pLevel->iLeftJoin ){ int addr; |
︙ | ︙ | |||
110319 110320 110321 110322 110323 110324 110325 | sqlite3ParserTOKENTYPE yy0; struct LimitVal yy64; Expr* yy122; Select* yy159; IdList* yy180; struct {int value; int mask;} yy207; u8 yy258; | < | 107713 107714 107715 107716 107717 107718 107719 107720 107721 107722 107723 107724 107725 107726 | sqlite3ParserTOKENTYPE yy0; struct LimitVal yy64; Expr* yy122; Select* yy159; IdList* yy180; struct {int value; int mask;} yy207; u8 yy258; struct LikeOp yy318; TriggerStep* yy327; ExprSpan yy342; SrcList* yy347; int yy392; struct TrigEvent yy410; ExprList* yy442; |
︙ | ︙ | |||
112270 112271 112272 112273 112274 112275 112276 112277 112278 112279 112280 112281 112282 112283 112284 112285 112286 112287 112288 112289 112290 112291 112292 | case 31: /* temp ::= */ yytestcase(yyruleno==31); case 69: /* autoinc ::= */ yytestcase(yyruleno==69); case 82: /* defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */ yytestcase(yyruleno==82); case 84: /* init_deferred_pred_opt ::= */ yytestcase(yyruleno==84); case 86: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */ yytestcase(yyruleno==86); case 98: /* defer_subclause_opt ::= */ yytestcase(yyruleno==98); case 109: /* ifexists ::= */ yytestcase(yyruleno==109); case 221: /* between_op ::= BETWEEN */ yytestcase(yyruleno==221); case 224: /* in_op ::= IN */ yytestcase(yyruleno==224); {yygotominor.yy392 = 0;} break; case 29: /* ifnotexists ::= IF NOT EXISTS */ case 30: /* temp ::= TEMP */ yytestcase(yyruleno==30); case 70: /* autoinc ::= AUTOINCR */ yytestcase(yyruleno==70); case 85: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */ yytestcase(yyruleno==85); case 108: /* ifexists ::= IF EXISTS */ yytestcase(yyruleno==108); case 222: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==222); case 225: /* in_op ::= NOT IN */ yytestcase(yyruleno==225); {yygotominor.yy392 = 1;} break; case 32: /* create_table_args ::= LP columnlist conslist_opt RP */ { sqlite3EndTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,0); | > > > | 109663 109664 109665 109666 109667 109668 109669 109670 109671 109672 109673 109674 109675 109676 109677 109678 109679 109680 109681 109682 109683 109684 109685 109686 109687 109688 | case 31: /* temp ::= */ yytestcase(yyruleno==31); case 69: /* autoinc ::= */ yytestcase(yyruleno==69); case 82: /* defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */ yytestcase(yyruleno==82); case 84: /* init_deferred_pred_opt ::= */ yytestcase(yyruleno==84); case 86: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */ yytestcase(yyruleno==86); case 98: /* defer_subclause_opt ::= */ yytestcase(yyruleno==98); case 109: /* ifexists ::= */ yytestcase(yyruleno==109); case 120: /* distinct ::= ALL */ yytestcase(yyruleno==120); case 121: /* distinct ::= */ yytestcase(yyruleno==121); case 221: /* between_op ::= BETWEEN */ yytestcase(yyruleno==221); case 224: /* in_op ::= IN */ yytestcase(yyruleno==224); {yygotominor.yy392 = 0;} break; case 29: /* ifnotexists ::= IF NOT EXISTS */ case 30: /* temp ::= TEMP */ yytestcase(yyruleno==30); case 70: /* autoinc ::= AUTOINCR */ yytestcase(yyruleno==70); case 85: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */ yytestcase(yyruleno==85); case 108: /* ifexists ::= IF EXISTS */ yytestcase(yyruleno==108); case 119: /* distinct ::= DISTINCT */ yytestcase(yyruleno==119); case 222: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==222); case 225: /* in_op ::= NOT IN */ yytestcase(yyruleno==225); {yygotominor.yy392 = 1;} break; case 32: /* create_table_args ::= LP columnlist conslist_opt RP */ { sqlite3EndTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,0); |
︙ | ︙ | |||
112518 112519 112520 112521 112522 112523 112524 | } break; case 116: /* multiselect_op ::= UNION ALL */ {yygotominor.yy392 = TK_ALL;} break; case 118: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */ { | | < < < < < < < | 109914 109915 109916 109917 109918 109919 109920 109921 109922 109923 109924 109925 109926 109927 109928 109929 | } break; case 116: /* multiselect_op ::= UNION ALL */ {yygotominor.yy392 = TK_ALL;} break; case 118: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */ { yygotominor.yy159 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy442,yymsp[-5].minor.yy347,yymsp[-4].minor.yy122,yymsp[-3].minor.yy442,yymsp[-2].minor.yy122,yymsp[-1].minor.yy442,yymsp[-7].minor.yy392,yymsp[0].minor.yy64.pLimit,yymsp[0].minor.yy64.pOffset); } break; case 122: /* sclp ::= selcollist COMMA */ case 246: /* idxlist_opt ::= LP idxlist RP */ yytestcase(yyruleno==246); {yygotominor.yy442 = yymsp[-1].minor.yy442;} break; case 123: /* sclp ::= */ case 151: /* orderby_opt ::= */ yytestcase(yyruleno==151); |
︙ | ︙ | |||
112596 112597 112598 112599 112600 112601 112602 | yygotominor.yy347 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy347,0,0,&yymsp[-2].minor.yy0,yymsp[-4].minor.yy159,yymsp[-1].minor.yy122,yymsp[0].minor.yy180); } break; case 136: /* seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */ { if( yymsp[-6].minor.yy347==0 && yymsp[-2].minor.yy0.n==0 && yymsp[-1].minor.yy122==0 && yymsp[0].minor.yy180==0 ){ yygotominor.yy347 = yymsp[-4].minor.yy347; | < < < < < < < < < < < < | | 109985 109986 109987 109988 109989 109990 109991 109992 109993 109994 109995 109996 109997 109998 109999 110000 110001 110002 | yygotominor.yy347 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy347,0,0,&yymsp[-2].minor.yy0,yymsp[-4].minor.yy159,yymsp[-1].minor.yy122,yymsp[0].minor.yy180); } break; case 136: /* seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */ { if( yymsp[-6].minor.yy347==0 && yymsp[-2].minor.yy0.n==0 && yymsp[-1].minor.yy122==0 && yymsp[0].minor.yy180==0 ){ yygotominor.yy347 = yymsp[-4].minor.yy347; }else{ Select *pSubquery; sqlite3SrcListShiftJoinType(yymsp[-4].minor.yy347); pSubquery = sqlite3SelectNew(pParse,0,yymsp[-4].minor.yy347,0,0,0,0,0,0,0); yygotominor.yy347 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy347,0,0,&yymsp[-2].minor.yy0,pSubquery,yymsp[-1].minor.yy122,yymsp[0].minor.yy180); } } break; case 137: /* dbnm ::= */ case 146: /* indexed_opt ::= */ yytestcase(yyruleno==146); {yygotominor.yy0.z=0; yygotominor.yy0.n=0;} |
︙ | ︙ | |||
112826 112827 112828 112829 112830 112831 112832 | spanExpr(&yygotominor.yy342, pParse, TK_VARIABLE, &yymsp[0].minor.yy0); sqlite3ExprAssignVarNumber(pParse, yygotominor.yy342.pExpr); spanSet(&yygotominor.yy342, &yymsp[0].minor.yy0, &yymsp[0].minor.yy0); } break; case 194: /* expr ::= expr COLLATE ids */ { | | | | 110203 110204 110205 110206 110207 110208 110209 110210 110211 110212 110213 110214 110215 110216 110217 110218 110219 110220 110221 110222 110223 110224 110225 110226 110227 110228 110229 110230 110231 110232 110233 110234 110235 | spanExpr(&yygotominor.yy342, pParse, TK_VARIABLE, &yymsp[0].minor.yy0); sqlite3ExprAssignVarNumber(pParse, yygotominor.yy342.pExpr); spanSet(&yygotominor.yy342, &yymsp[0].minor.yy0, &yymsp[0].minor.yy0); } break; case 194: /* expr ::= expr COLLATE ids */ { yygotominor.yy342.pExpr = sqlite3ExprSetCollByToken(pParse, yymsp[-2].minor.yy342.pExpr, &yymsp[0].minor.yy0); yygotominor.yy342.zStart = yymsp[-2].minor.yy342.zStart; yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; } break; case 195: /* expr ::= CAST LP expr AS typetoken RP */ { yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_CAST, yymsp[-3].minor.yy342.pExpr, 0, &yymsp[-1].minor.yy0); spanSet(&yygotominor.yy342,&yymsp[-5].minor.yy0,&yymsp[0].minor.yy0); } break; case 196: /* expr ::= ID LP distinct exprlist RP */ { if( yymsp[-1].minor.yy442 && yymsp[-1].minor.yy442->nExpr>pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG] ){ sqlite3ErrorMsg(pParse, "too many arguments on function %T", &yymsp[-4].minor.yy0); } yygotominor.yy342.pExpr = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy442, &yymsp[-4].minor.yy0); spanSet(&yygotominor.yy342,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0); if( yymsp[-2].minor.yy392 && yygotominor.yy342.pExpr ){ yygotominor.yy342.pExpr->flags |= EP_Distinct; } } break; case 197: /* expr ::= ID LP STAR RP */ { yygotominor.yy342.pExpr = sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0); |
︙ | ︙ | |||
113085 113086 113087 113088 113089 113090 113091 | {yygotominor.yy392 = OE_Abort;} break; case 244: /* uniqueflag ::= */ {yygotominor.yy392 = OE_None;} break; case 247: /* idxlist ::= idxlist COMMA nm collate sortorder */ { | > | > > > > | > > > | 110462 110463 110464 110465 110466 110467 110468 110469 110470 110471 110472 110473 110474 110475 110476 110477 110478 110479 110480 110481 110482 110483 110484 110485 110486 110487 110488 110489 110490 110491 110492 110493 | {yygotominor.yy392 = OE_Abort;} break; case 244: /* uniqueflag ::= */ {yygotominor.yy392 = OE_None;} break; case 247: /* idxlist ::= idxlist COMMA nm collate sortorder */ { Expr *p = 0; if( yymsp[-1].minor.yy0.n>0 ){ p = sqlite3Expr(pParse->db, TK_COLUMN, 0); sqlite3ExprSetCollByToken(pParse, p, &yymsp[-1].minor.yy0); } yygotominor.yy442 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy442, p); sqlite3ExprListSetName(pParse,yygotominor.yy442,&yymsp[-2].minor.yy0,1); sqlite3ExprListCheckLength(pParse, yygotominor.yy442, "index"); if( yygotominor.yy442 ) yygotominor.yy442->a[yygotominor.yy442->nExpr-1].sortOrder = (u8)yymsp[0].minor.yy392; } break; case 248: /* idxlist ::= nm collate sortorder */ { Expr *p = 0; if( yymsp[-1].minor.yy0.n>0 ){ p = sqlite3PExpr(pParse, TK_COLUMN, 0, 0, 0); sqlite3ExprSetCollByToken(pParse, p, &yymsp[-1].minor.yy0); } yygotominor.yy442 = sqlite3ExprListAppend(pParse,0, p); sqlite3ExprListSetName(pParse, yygotominor.yy442, &yymsp[-2].minor.yy0, 1); sqlite3ExprListCheckLength(pParse, yygotominor.yy442, "index"); if( yygotominor.yy442 ) yygotominor.yy442->a[yygotominor.yy442->nExpr-1].sortOrder = (u8)yymsp[0].minor.yy392; } break; case 249: /* collate ::= */ |
︙ | ︙ | |||
114909 114910 114911 114912 114913 114914 114915 | /* If SQLite is already completely initialized, then this call ** to sqlite3_initialize() should be a no-op. But the initialization ** must be complete. So isInit must not be set until the very end ** of this routine. */ if( sqlite3GlobalConfig.isInit ) return SQLITE_OK; | < < < < < < < | 112294 112295 112296 112297 112298 112299 112300 112301 112302 112303 112304 112305 112306 112307 | /* If SQLite is already completely initialized, then this call ** to sqlite3_initialize() should be a no-op. But the initialization ** must be complete. So isInit must not be set until the very end ** of this routine. */ if( sqlite3GlobalConfig.isInit ) return SQLITE_OK; /* Make sure the mutex subsystem is initialized. If unable to ** initialize the mutex subsystem, return early with the error. ** If the system is so sick that we are unable to allocate a mutex, ** there is not much SQLite is going to be able to do. ** ** The mutex subsystem must take care of serializing its own ** initialization. |
︙ | ︙ | |||
115264 115265 115266 115267 115268 115269 115270 | } case SQLITE_CONFIG_COVERING_INDEX_SCAN: { sqlite3GlobalConfig.bUseCis = va_arg(ap, int); break; } | < < < < < < < < < < < < < < < < < < < < < < | 112642 112643 112644 112645 112646 112647 112648 112649 112650 112651 112652 112653 112654 112655 | } case SQLITE_CONFIG_COVERING_INDEX_SCAN: { sqlite3GlobalConfig.bUseCis = va_arg(ap, int); break; } default: { rc = SQLITE_ERROR; break; } } va_end(ap); return rc; |
︙ | ︙ | |||
115625 115626 115627 115628 115629 115630 115631 | if( !forceZombie && connectionIsBusy(db) ){ sqlite3Error(db, SQLITE_BUSY, "unable to close due to unfinalized " "statements or unfinished backups"); sqlite3_mutex_leave(db->mutex); return SQLITE_BUSY; } | < < < < < < < | 112981 112982 112983 112984 112985 112986 112987 112988 112989 112990 112991 112992 112993 112994 | if( !forceZombie && connectionIsBusy(db) ){ sqlite3Error(db, SQLITE_BUSY, "unable to close due to unfinalized " "statements or unfinished backups"); sqlite3_mutex_leave(db->mutex); return SQLITE_BUSY; } /* Convert the connection into a zombie and then close it. */ db->magic = SQLITE_MAGIC_ZOMBIE; sqlite3LeaveMutexAndCloseZombie(db); return SQLITE_OK; } |
︙ | ︙ | |||
115675 115676 115677 115678 115679 115680 115681 | if( db->magic!=SQLITE_MAGIC_ZOMBIE || connectionIsBusy(db) ){ sqlite3_mutex_leave(db->mutex); return; } /* If we reach this point, it means that the database connection has ** closed all sqlite3_stmt and sqlite3_backup objects and has been | | < < < < < < | 113024 113025 113026 113027 113028 113029 113030 113031 113032 113033 113034 113035 113036 113037 113038 113039 113040 113041 | if( db->magic!=SQLITE_MAGIC_ZOMBIE || connectionIsBusy(db) ){ sqlite3_mutex_leave(db->mutex); return; } /* If we reach this point, it means that the database connection has ** closed all sqlite3_stmt and sqlite3_backup objects and has been ** pased to sqlite3_close (meaning that it is a zombie). Therefore, ** go ahead and free all resources. */ /* Free any outstanding Savepoint structures. */ sqlite3CloseSavepoints(db); /* Close all database connections */ for(j=0; j<db->nDb; j++){ struct Db *pDb = &db->aDb[j]; if( pDb->pBt ){ |
︙ | ︙ | |||
115785 115786 115787 115788 115789 115790 115791 | ** attempts to use that cursor. */ SQLITE_PRIVATE void sqlite3RollbackAll(sqlite3 *db, int tripCode){ int i; int inTrans = 0; assert( sqlite3_mutex_held(db->mutex) ); sqlite3BeginBenignMalloc(); | < < < < < < < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 113128 113129 113130 113131 113132 113133 113134 113135 113136 113137 113138 113139 113140 113141 113142 113143 113144 113145 113146 113147 113148 113149 113150 113151 113152 113153 113154 113155 113156 113157 113158 113159 113160 113161 113162 113163 113164 113165 113166 113167 113168 | ** attempts to use that cursor. */ SQLITE_PRIVATE void sqlite3RollbackAll(sqlite3 *db, int tripCode){ int i; int inTrans = 0; assert( sqlite3_mutex_held(db->mutex) ); sqlite3BeginBenignMalloc(); for(i=0; i<db->nDb; i++){ Btree *p = db->aDb[i].pBt; if( p ){ if( sqlite3BtreeIsInTrans(p) ){ inTrans = 1; } sqlite3BtreeRollback(p, tripCode); db->aDb[i].inTrans = 0; } } sqlite3VtabRollback(db); sqlite3EndBenignMalloc(); if( db->flags&SQLITE_InternChanges ){ sqlite3ExpirePreparedStatements(db); sqlite3ResetAllSchemasOfConnection(db); } /* Any deferred constraint violations have now been resolved. */ db->nDeferredCons = 0; /* If one has been configured, invoke the rollback-hook callback */ if( db->xRollbackCallback && (inTrans || !db->autoCommit) ){ db->xRollbackCallback(db->pRollbackArg); } } /* ** Return a static string that describes the kind of error specified in the ** argument. */ SQLITE_PRIVATE const char *sqlite3ErrStr(int rc){ static const char* const aMsg[] = { /* SQLITE_OK */ "not an error", |
︙ | ︙ | |||
117226 117227 117228 117229 117230 117231 117232 | db->magic = SQLITE_MAGIC_BUSY; db->aDb = db->aDbStatic; assert( sizeof(db->aLimit)==sizeof(aHardLimit) ); memcpy(db->aLimit, aHardLimit, sizeof(db->aLimit)); db->autoCommit = 1; db->nextAutovac = -1; | < | 114455 114456 114457 114458 114459 114460 114461 114462 114463 114464 114465 114466 114467 114468 | db->magic = SQLITE_MAGIC_BUSY; db->aDb = db->aDbStatic; assert( sizeof(db->aLimit)==sizeof(aHardLimit) ); memcpy(db->aLimit, aHardLimit, sizeof(db->aLimit)); db->autoCommit = 1; db->nextAutovac = -1; db->nextPagesize = 0; db->flags |= SQLITE_ShortColNames | SQLITE_AutoIndex | SQLITE_EnableTrigger #if SQLITE_DEFAULT_FILE_FORMAT<4 | SQLITE_LegacyFileFmt #endif #ifdef SQLITE_ENABLE_LOAD_EXTENSION | SQLITE_LoadExtension |
︙ | ︙ | |||
117385 117386 117387 117388 117389 117390 117391 | if( rc==SQLITE_NOMEM ){ sqlite3_close(db); db = 0; }else if( rc!=SQLITE_OK ){ db->magic = SQLITE_MAGIC_SICK; } *ppDb = db; | < < < < < < < | 114613 114614 114615 114616 114617 114618 114619 114620 114621 114622 114623 114624 114625 114626 | if( rc==SQLITE_NOMEM ){ sqlite3_close(db); db = 0; }else if( rc!=SQLITE_OK ){ db->magic = SQLITE_MAGIC_SICK; } *ppDb = db; return sqlite3ApiExit(0, rc); } /* ** Open a new database handle. */ SQLITE_API int sqlite3_open( |
︙ | ︙ | |||
117960 117961 117962 117963 117964 117965 117966 | ** operation N should be 0. The idea is that a test program (like the ** SQL Logic Test or SLT test module) can run the same SQL multiple times ** with various optimizations disabled to verify that the same answer ** is obtained in every case. */ case SQLITE_TESTCTRL_OPTIMIZATIONS: { sqlite3 *db = va_arg(ap, sqlite3*); | | | 115181 115182 115183 115184 115185 115186 115187 115188 115189 115190 115191 115192 115193 115194 115195 | ** operation N should be 0. The idea is that a test program (like the ** SQL Logic Test or SLT test module) can run the same SQL multiple times ** with various optimizations disabled to verify that the same answer ** is obtained in every case. */ case SQLITE_TESTCTRL_OPTIMIZATIONS: { sqlite3 *db = va_arg(ap, sqlite3*); db->dbOptFlags = (u8)(va_arg(ap, int) & 0xff); break; } #ifdef SQLITE_N_KEYWORD /* sqlite3_test_control(SQLITE_TESTCTRL_ISKEYWORD, const char *zWord) ** ** If zWord is a keyword recognized by the parser, then return the |
︙ | ︙ | |||
118848 118849 118850 118851 118852 118853 118854 | ** ** then argc is set to 2, and the argv[] array contains pointers ** to the strings "arg1" and "arg2". ** ** This method should return either SQLITE_OK (0), or an SQLite error ** code. If SQLITE_OK is returned, then *ppTokenizer should be set ** to point at the newly created tokenizer structure. The generic | | | 116069 116070 116071 116072 116073 116074 116075 116076 116077 116078 116079 116080 116081 116082 116083 | ** ** then argc is set to 2, and the argv[] array contains pointers ** to the strings "arg1" and "arg2". ** ** This method should return either SQLITE_OK (0), or an SQLite error ** code. If SQLITE_OK is returned, then *ppTokenizer should be set ** to point at the newly created tokenizer structure. The generic ** sqlite3_tokenizer.pModule variable should not be initialised by ** this callback. The caller will do so. */ int (*xCreate)( int argc, /* Size of argv array */ const char *const*argv, /* Tokenizer argument strings */ sqlite3_tokenizer **ppTokenizer /* OUT: Created tokenizer */ ); |
︙ | ︙ | |||
118953 118954 118955 118956 118957 118958 118959 | ** 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. ** ************************************************************************* | | | 116174 116175 116176 116177 116178 116179 116180 116181 116182 116183 116184 116185 116186 116187 116188 | ** 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 is the header file for the generic hash-table implemenation ** used in SQLite. We've modified it slightly to serve as a standalone ** hash table implementation for the full-text indexing module. ** */ #ifndef _FTS3_HASH_H_ #define _FTS3_HASH_H_ |
︙ | ︙ | |||
119543 119544 119545 119546 119547 119548 119549 | SQLITE_PRIVATE void sqlite3Fts3Snippet(sqlite3_context *, Fts3Cursor *, const char *, const char *, const char *, int, int ); SQLITE_PRIVATE void sqlite3Fts3Matchinfo(sqlite3_context *, Fts3Cursor *, const char *); /* fts3_expr.c */ SQLITE_PRIVATE int sqlite3Fts3ExprParse(sqlite3_tokenizer *, int, | | | 116764 116765 116766 116767 116768 116769 116770 116771 116772 116773 116774 116775 116776 116777 116778 | SQLITE_PRIVATE void sqlite3Fts3Snippet(sqlite3_context *, Fts3Cursor *, const char *, const char *, const char *, int, int ); SQLITE_PRIVATE void sqlite3Fts3Matchinfo(sqlite3_context *, Fts3Cursor *, const char *); /* fts3_expr.c */ SQLITE_PRIVATE int sqlite3Fts3ExprParse(sqlite3_tokenizer *, int, char **, int, int, int, const char *, int, Fts3Expr ** ); SQLITE_PRIVATE void sqlite3Fts3ExprFree(Fts3Expr *); #ifdef SQLITE_TEST SQLITE_PRIVATE int sqlite3Fts3ExprInitTestInterface(sqlite3 *db); SQLITE_PRIVATE int sqlite3Fts3InitTerm(sqlite3 *db); #endif |
︙ | ︙ | |||
119568 119569 119570 119571 119572 119573 119574 | Fts3Table*, Fts3MultiSegReader*, int, const char*, int); SQLITE_PRIVATE int sqlite3Fts3MsrIncrNext( Fts3Table *, Fts3MultiSegReader *, sqlite3_int64 *, char **, int *); SQLITE_PRIVATE int sqlite3Fts3EvalPhrasePoslist(Fts3Cursor *, Fts3Expr *, int iCol, char **); SQLITE_PRIVATE int sqlite3Fts3MsrOvfl(Fts3Cursor *, Fts3MultiSegReader *, int *); SQLITE_PRIVATE int sqlite3Fts3MsrIncrRestart(Fts3MultiSegReader *pCsr); | < < < | 116789 116790 116791 116792 116793 116794 116795 116796 116797 116798 116799 116800 116801 116802 | Fts3Table*, Fts3MultiSegReader*, int, const char*, int); SQLITE_PRIVATE int sqlite3Fts3MsrIncrNext( Fts3Table *, Fts3MultiSegReader *, sqlite3_int64 *, char **, int *); SQLITE_PRIVATE int sqlite3Fts3EvalPhrasePoslist(Fts3Cursor *, Fts3Expr *, int iCol, char **); SQLITE_PRIVATE int sqlite3Fts3MsrOvfl(Fts3Cursor *, Fts3MultiSegReader *, int *); SQLITE_PRIVATE int sqlite3Fts3MsrIncrRestart(Fts3MultiSegReader *pCsr); /* fts3_unicode2.c (functions generated by parsing unicode text files) */ #ifdef SQLITE_ENABLE_FTS4_UNICODE61 SQLITE_PRIVATE int sqlite3FtsUnicodeFold(int, int); SQLITE_PRIVATE int sqlite3FtsUnicodeIsalnum(int); SQLITE_PRIVATE int sqlite3FtsUnicodeIsdiacritic(int); #endif |
︙ | ︙ | |||
120863 120864 120865 120866 120867 120868 120869 | sqlite3_bind_int64(pCsr->pStmt, 1, pCsr->iPrevId); pCsr->isRequireSeek = 0; if( SQLITE_ROW==sqlite3_step(pCsr->pStmt) ){ return SQLITE_OK; }else{ rc = sqlite3_reset(pCsr->pStmt); if( rc==SQLITE_OK && ((Fts3Table *)pCsr->base.pVtab)->zContentTbl==0 ){ | | | 118081 118082 118083 118084 118085 118086 118087 118088 118089 118090 118091 118092 118093 118094 118095 | sqlite3_bind_int64(pCsr->pStmt, 1, pCsr->iPrevId); pCsr->isRequireSeek = 0; if( SQLITE_ROW==sqlite3_step(pCsr->pStmt) ){ return SQLITE_OK; }else{ rc = sqlite3_reset(pCsr->pStmt); if( rc==SQLITE_OK && ((Fts3Table *)pCsr->base.pVtab)->zContentTbl==0 ){ /* If no row was found and no error has occured, then the %_content ** table is missing a row that is present in the full-text index. ** The data structures are corrupt. */ rc = FTS_CORRUPT_VTAB; pCsr->isEof = 1; } } } |
︙ | ︙ | |||
122103 122104 122105 122106 122107 122108 122109 | */ static void fts3SegReaderCursorFree(Fts3MultiSegReader *pSegcsr){ sqlite3Fts3SegReaderFinish(pSegcsr); sqlite3_free(pSegcsr); } /* | | | 119321 119322 119323 119324 119325 119326 119327 119328 119329 119330 119331 119332 119333 119334 119335 | */ 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 */ |
︙ | ︙ | |||
122267 122268 122269 122270 122271 122272 122273 | if( zQuery==0 && sqlite3_value_type(apVal[0])!=SQLITE_NULL ){ return SQLITE_NOMEM; } pCsr->iLangid = 0; if( nVal==2 ) pCsr->iLangid = sqlite3_value_int(apVal[1]); | < | < > > > > | 119485 119486 119487 119488 119489 119490 119491 119492 119493 119494 119495 119496 119497 119498 119499 119500 119501 119502 119503 119504 119505 119506 | if( zQuery==0 && sqlite3_value_type(apVal[0])!=SQLITE_NULL ){ return SQLITE_NOMEM; } pCsr->iLangid = 0; if( nVal==2 ) pCsr->iLangid = sqlite3_value_int(apVal[1]); rc = sqlite3Fts3ExprParse(p->pTokenizer, pCsr->iLangid, p->azColumn, p->bFts4, p->nColumn, iCol, zQuery, -1, &pCsr->pExpr ); if( rc!=SQLITE_OK ){ if( rc==SQLITE_ERROR ){ static const char *zErr = "malformed MATCH expression: [%s]"; p->base.zErrMsg = sqlite3_mprintf(zErr, zQuery); } return rc; } rc = sqlite3Fts3ReadLock(p); if( rc!=SQLITE_OK ) return rc; rc = fts3EvalStart(pCsr); |
︙ | ︙ | |||
122852 122853 122854 122855 122856 122857 122858 | SQLITE_PRIVATE void sqlite3Fts3UnicodeTokenizer(sqlite3_tokenizer_module const**ppModule); #endif #ifdef SQLITE_ENABLE_ICU SQLITE_PRIVATE void sqlite3Fts3IcuTokenizerModule(sqlite3_tokenizer_module const**ppModule); #endif /* | | | 120072 120073 120074 120075 120076 120077 120078 120079 120080 120081 120082 120083 120084 120085 120086 | SQLITE_PRIVATE void sqlite3Fts3UnicodeTokenizer(sqlite3_tokenizer_module const**ppModule); #endif #ifdef SQLITE_ENABLE_ICU SQLITE_PRIVATE void sqlite3Fts3IcuTokenizerModule(sqlite3_tokenizer_module const**ppModule); #endif /* ** Initialise the fts3 extension. If this extension is built as part ** of the sqlite library, then this function is called directly by ** SQLite. If fts3 is built as a dynamically loadable extension, this ** function is called by the sqlite3_extension_init() entry point. */ SQLITE_PRIVATE int sqlite3Fts3Init(sqlite3 *db){ int rc = SQLITE_OK; Fts3Hash *pHash = 0; |
︙ | ︙ | |||
122886 122887 122888 122889 122890 122891 122892 | rc = sqlite3Fts3InitAux(db); if( rc!=SQLITE_OK ) return rc; sqlite3Fts3SimpleTokenizerModule(&pSimple); sqlite3Fts3PorterTokenizerModule(&pPorter); | | | 120106 120107 120108 120109 120110 120111 120112 120113 120114 120115 120116 120117 120118 120119 120120 | rc = sqlite3Fts3InitAux(db); if( rc!=SQLITE_OK ) return rc; sqlite3Fts3SimpleTokenizerModule(&pSimple); sqlite3Fts3PorterTokenizerModule(&pPorter); /* Allocate and initialise the hash-table used to store tokenizers. */ pHash = sqlite3_malloc(sizeof(Fts3Hash)); if( !pHash ){ rc = SQLITE_NOMEM; }else{ sqlite3Fts3HashInit(pHash, FTS3_HASH_STRING, 1); } |
︙ | ︙ | |||
122936 122937 122938 122939 122940 122941 122942 | db, "fts3", &fts3Module, (void *)pHash, hashDestroy ); if( rc==SQLITE_OK ){ rc = sqlite3_create_module_v2( db, "fts4", &fts3Module, (void *)pHash, 0 ); } | < < < < | 120156 120157 120158 120159 120160 120161 120162 120163 120164 120165 120166 120167 120168 120169 120170 120171 | db, "fts3", &fts3Module, (void *)pHash, hashDestroy ); if( rc==SQLITE_OK ){ rc = sqlite3_create_module_v2( db, "fts4", &fts3Module, (void *)pHash, 0 ); } return rc; } /* An error has occurred. Delete the hash table and return the error code. */ assert( rc!=SQLITE_OK ); if( pHash ){ sqlite3Fts3HashClear(pHash); sqlite3_free(pHash); } |
︙ | ︙ | |||
124037 124038 124039 124040 124041 124042 124043 | char *aTmp; /* Temp space for PoslistNearMerge() */ /* Allocate temporary working space. */ for(p=pExpr; p->pLeft; p=p->pLeft){ nTmp += p->pRight->pPhrase->doclist.nList; } nTmp += p->pPhrase->doclist.nList; | < < < | | | | | | | | | | | | | | | | | | | | | | | | | | | < | 121253 121254 121255 121256 121257 121258 121259 121260 121261 121262 121263 121264 121265 121266 121267 121268 121269 121270 121271 121272 121273 121274 121275 121276 121277 121278 121279 121280 121281 121282 121283 121284 121285 121286 121287 121288 121289 121290 121291 121292 121293 121294 121295 | char *aTmp; /* Temp space for PoslistNearMerge() */ /* Allocate temporary working space. */ for(p=pExpr; p->pLeft; p=p->pLeft){ nTmp += p->pRight->pPhrase->doclist.nList; } nTmp += p->pPhrase->doclist.nList; aTmp = sqlite3_malloc(nTmp*2); if( !aTmp ){ *pRc = SQLITE_NOMEM; res = 0; }else{ char *aPoslist = p->pPhrase->doclist.pList; int nToken = p->pPhrase->nToken; for(p=p->pParent;res && p && p->eType==FTSQUERY_NEAR; p=p->pParent){ Fts3Phrase *pPhrase = p->pRight->pPhrase; int nNear = p->nNear; res = fts3EvalNearTrim(nNear, aTmp, &aPoslist, &nToken, pPhrase); } aPoslist = pExpr->pRight->pPhrase->doclist.pList; nToken = pExpr->pRight->pPhrase->nToken; for(p=pExpr->pLeft; p && res; p=p->pLeft){ int nNear; Fts3Phrase *pPhrase; assert( p->pParent && p->pParent->pLeft==p ); nNear = p->pParent->nNear; pPhrase = ( p->eType==FTSQUERY_NEAR ? p->pRight->pPhrase : p->pPhrase ); res = fts3EvalNearTrim(nNear, aTmp, &aPoslist, &nToken, pPhrase); } } sqlite3_free(aTmp); } return res; } /* ** This function is a helper function for fts3EvalTestDeferredAndNear(). |
︙ | ︙ | |||
124489 124490 124491 124492 124493 124494 124495 | ** must be of type FTSQUERY_PHRASE. ** ** The returned value is either NULL or a pointer to a buffer containing ** a position-list indicating the occurrences of the phrase in column iCol ** of the current row. ** ** More specifically, the returned buffer contains 1 varint for each | | | 121701 121702 121703 121704 121705 121706 121707 121708 121709 121710 121711 121712 121713 121714 121715 | ** must be of type FTSQUERY_PHRASE. ** ** The returned value is either NULL or a pointer to a buffer containing ** a position-list indicating the occurrences of the phrase in column iCol ** of the current row. ** ** More specifically, the returned buffer contains 1 varint for each ** occurence of the phrase in the column, stored using the normal (delta+2) ** compression and is terminated by either an 0x01 or 0x00 byte. For example, ** if the requested column contains "a b X c d X X" and the position-list ** for 'X' is requested, the buffer returned may contain: ** ** 0x04 0x05 0x03 0x01 or 0x04 0x05 0x03 0x00 ** ** This function works regardless of whether or not the phrase is deferred, |
︙ | ︙ | |||
124716 124717 124718 124719 124720 124721 124722 | int nFts3; /* Result of strlen(zFts3) */ int nByte; /* Bytes of space to allocate here */ int rc; /* value returned by declare_vtab() */ Fts3auxTable *p; /* Virtual table object to return */ UNUSED_PARAMETER(pUnused); | | < < < < | > > > > | | < < < | | < < < < < | < | 121928 121929 121930 121931 121932 121933 121934 121935 121936 121937 121938 121939 121940 121941 121942 121943 121944 121945 121946 121947 121948 121949 121950 121951 121952 | int nFts3; /* Result of strlen(zFts3) */ int nByte; /* Bytes of space to allocate here */ int rc; /* value returned by declare_vtab() */ Fts3auxTable *p; /* Virtual table object to return */ UNUSED_PARAMETER(pUnused); /* The user should specify a single argument - the name of an fts3 table. */ if( argc!=4 ){ *pzErr = sqlite3_mprintf( "wrong number of arguments to fts4aux constructor" ); return SQLITE_ERROR; } zDb = argv[1]; nDb = (int)strlen(zDb); zFts3 = argv[3]; nFts3 = (int)strlen(zFts3); rc = sqlite3_declare_vtab(db, FTS3_TERMS_SCHEMA); if( rc!=SQLITE_OK ) return rc; nByte = sizeof(Fts3auxTable) + sizeof(Fts3Table) + nDb + nFts3 + 2; p = (Fts3auxTable *)sqlite3_malloc(nByte); |
︙ | ︙ | |||
124758 124759 124760 124761 124762 124763 124764 | memcpy((char *)p->pFts3Tab->zDb, zDb, nDb); memcpy((char *)p->pFts3Tab->zName, zFts3, nFts3); sqlite3Fts3Dequote((char *)p->pFts3Tab->zName); *ppVtab = (sqlite3_vtab *)p; return SQLITE_OK; | < < < < | 121961 121962 121963 121964 121965 121966 121967 121968 121969 121970 121971 121972 121973 121974 | memcpy((char *)p->pFts3Tab->zDb, zDb, nDb); memcpy((char *)p->pFts3Tab->zName, zFts3, nFts3); sqlite3Fts3Dequote((char *)p->pFts3Tab->zName); *ppVtab = (sqlite3_vtab *)p; return SQLITE_OK; } /* ** This function does the work for both the xDisconnect and xDestroy methods. ** These tables have no persistent representation of their own, so xDisconnect ** and xDestroy are identical operations. */ |
︙ | ︙ | |||
125241 125242 125243 125244 125245 125246 125247 | int nNest; /* Number of nested brackets */ }; /* ** This function is equivalent to the standard isspace() function. ** ** The standard isspace() can be awkward to use safely, because although it | | | 122440 122441 122442 122443 122444 122445 122446 122447 122448 122449 122450 122451 122452 122453 122454 | int nNest; /* Number of nested brackets */ }; /* ** This function is equivalent to the standard isspace() function. ** ** The standard isspace() can be awkward to use safely, because although it ** is defined to accept an argument of type int, its behaviour when passed ** an integer that falls outside of the range of the unsigned char type ** is undefined (and sometimes, "undefined" means segfault). This wrapper ** is defined to accept an argument of type char, and always returns 0 for ** any values that fall outside of the range of the unsigned char type (i.e. ** negative values). */ static int fts3isspace(char c){ |
︙ | ︙ | |||
125320 125321 125322 125323 125324 125325 125326 | sqlite3_tokenizer_cursor *pCursor; Fts3Expr *pRet = 0; int nConsumed = 0; rc = sqlite3Fts3OpenTokenizer(pTokenizer, pParse->iLangid, z, n, &pCursor); if( rc==SQLITE_OK ){ const char *zToken; | | | 122519 122520 122521 122522 122523 122524 122525 122526 122527 122528 122529 122530 122531 122532 122533 | sqlite3_tokenizer_cursor *pCursor; Fts3Expr *pRet = 0; int nConsumed = 0; rc = sqlite3Fts3OpenTokenizer(pTokenizer, pParse->iLangid, z, n, &pCursor); if( rc==SQLITE_OK ){ const char *zToken; int nToken, iStart, iEnd, iPosition; int nByte; /* total space to allocate */ rc = pModule->xNext(pCursor, &zToken, &nToken, &iStart, &iEnd, &iPosition); if( rc==SQLITE_OK ){ nByte = sizeof(Fts3Expr) + sizeof(Fts3Phrase) + nToken; pRet = (Fts3Expr *)fts3MallocZero(nByte); if( !pRet ){ |
︙ | ︙ | |||
125435 125436 125437 125438 125439 125440 125441 | */ rc = sqlite3Fts3OpenTokenizer( pTokenizer, pParse->iLangid, zInput, nInput, &pCursor); if( rc==SQLITE_OK ){ int ii; for(ii=0; rc==SQLITE_OK; ii++){ const char *zByte; | | | 122634 122635 122636 122637 122638 122639 122640 122641 122642 122643 122644 122645 122646 122647 122648 | */ rc = sqlite3Fts3OpenTokenizer( pTokenizer, pParse->iLangid, zInput, nInput, &pCursor); if( rc==SQLITE_OK ){ int ii; for(ii=0; rc==SQLITE_OK; ii++){ const char *zByte; int nByte, iBegin, iEnd, iPos; rc = pModule->xNext(pCursor, &zByte, &nByte, &iBegin, &iEnd, &iPos); if( rc==SQLITE_OK ){ Fts3PhraseToken *pToken; p = fts3ReallocOrFree(p, nSpace + ii*sizeof(Fts3PhraseToken)); if( !p ) goto no_mem; |
︙ | ︙ | |||
125775 125776 125777 125778 125779 125780 125781 | if( !pNot ){ sqlite3Fts3ExprFree(p); rc = SQLITE_NOMEM; goto exprparse_out; } pNot->eType = FTSQUERY_NOT; pNot->pRight = p; | < < | 122974 122975 122976 122977 122978 122979 122980 122981 122982 122983 122984 122985 122986 122987 122988 122989 | if( !pNot ){ sqlite3Fts3ExprFree(p); rc = SQLITE_NOMEM; goto exprparse_out; } pNot->eType = FTSQUERY_NOT; pNot->pRight = p; if( pNotBranch ){ pNot->pLeft = pNotBranch; } pNotBranch = pNot; p = pPrev; }else{ int eType = p->eType; isPhrase = (eType==FTSQUERY_PHRASE || p->pLeft); |
︙ | ︙ | |||
125866 125867 125868 125869 125870 125871 125872 | rc = SQLITE_ERROR; }else{ Fts3Expr *pIter = pNotBranch; while( pIter->pLeft ){ pIter = pIter->pLeft; } pIter->pLeft = pRet; | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 123063 123064 123065 123066 123067 123068 123069 123070 123071 123072 123073 123074 123075 123076 123077 123078 123079 123080 123081 123082 123083 123084 123085 123086 123087 123088 123089 | rc = SQLITE_ERROR; }else{ Fts3Expr *pIter = pNotBranch; while( pIter->pLeft ){ pIter = pIter->pLeft; } pIter->pLeft = pRet; pRet = pNotBranch; } } } *pnConsumed = n - nIn; exprparse_out: if( rc!=SQLITE_OK ){ sqlite3Fts3ExprFree(pRet); sqlite3Fts3ExprFree(pNotBranch); pRet = 0; } *ppExpr = pRet; return rc; } /* ** Parameters z and n contain a pointer to and length of a buffer containing ** an fts3 query expression, respectively. This function attempts to parse the ** query expression and create a tree of Fts3Expr structures representing the |
︙ | ︙ | |||
126132 126133 126134 126135 126136 126137 126138 | sqlite3_tokenizer *pTokenizer, /* Tokenizer module */ int iLangid, /* Language id for tokenizer */ char **azCol, /* Array of column names for fts3 table */ int bFts4, /* True to allow FTS4-only syntax */ int nCol, /* Number of entries in azCol[] */ int iDefaultCol, /* Default column to query */ const char *z, int n, /* Text of MATCH query */ | | < | | < < > | > > | | > > > | | | < | > > > > > | < < < < < < < < | | > | > > | | | < < < < < < < < < < < < < < < < < < < < < < < < < < < | 123111 123112 123113 123114 123115 123116 123117 123118 123119 123120 123121 123122 123123 123124 123125 123126 123127 123128 123129 123130 123131 123132 123133 123134 123135 123136 123137 123138 123139 123140 123141 123142 123143 123144 123145 123146 123147 123148 123149 123150 123151 123152 123153 123154 123155 123156 123157 123158 123159 123160 123161 123162 123163 123164 123165 123166 123167 | sqlite3_tokenizer *pTokenizer, /* Tokenizer module */ int iLangid, /* Language id for tokenizer */ char **azCol, /* Array of column names for fts3 table */ int bFts4, /* True to allow FTS4-only syntax */ int nCol, /* Number of entries in azCol[] */ int iDefaultCol, /* Default column to query */ const char *z, int n, /* Text of MATCH query */ Fts3Expr **ppExpr /* OUT: Parsed query structure */ ){ int nParsed; int rc; ParseContext sParse; memset(&sParse, 0, sizeof(ParseContext)); sParse.pTokenizer = pTokenizer; sParse.iLangid = iLangid; sParse.azCol = (const char **)azCol; sParse.nCol = nCol; sParse.iDefaultCol = iDefaultCol; sParse.bFts4 = bFts4; if( z==0 ){ *ppExpr = 0; return SQLITE_OK; } if( n<0 ){ n = (int)strlen(z); } rc = fts3ExprParse(&sParse, z, n, ppExpr, &nParsed); /* Check for mismatched parenthesis */ if( rc==SQLITE_OK && sParse.nNest ){ rc = SQLITE_ERROR; sqlite3Fts3ExprFree(*ppExpr); *ppExpr = 0; } return rc; } /* ** Free a parsed fts3 query expression allocated by sqlite3Fts3ExprParse(). */ SQLITE_PRIVATE void sqlite3Fts3ExprFree(Fts3Expr *p){ if( p ){ assert( p->eType==FTSQUERY_PHRASE || p->pPhrase==0 ); sqlite3Fts3ExprFree(p->pLeft); sqlite3Fts3ExprFree(p->pRight); sqlite3Fts3EvalPhraseCleanup(p->pPhrase); sqlite3_free(p->aMI); sqlite3_free(p); } } /**************************************************************************** ***************************************************************************** ** Everything after this point is just test code. */ |
︙ | ︙ | |||
126251 126252 126253 126254 126255 126256 126257 | ** sqlite3_free() to release the memory. If an OOM condition is encountered, ** NULL is returned. ** ** If the second argument is not NULL, then its contents are prepended to ** the returned expression text and then freed using sqlite3_free(). */ static char *exprToString(Fts3Expr *pExpr, char *zBuf){ | < < < | 123205 123206 123207 123208 123209 123210 123211 123212 123213 123214 123215 123216 123217 123218 | ** sqlite3_free() to release the memory. If an OOM condition is encountered, ** NULL is returned. ** ** If the second argument is not NULL, then its contents are prepended to ** the returned expression text and then freed using sqlite3_free(). */ static char *exprToString(Fts3Expr *pExpr, char *zBuf){ switch( pExpr->eType ){ case FTSQUERY_PHRASE: { Fts3Phrase *pPhrase = pExpr->pPhrase; int i; zBuf = sqlite3_mprintf( "%zPHRASE %d 0", zBuf, pPhrase->iColumn); for(i=0; zBuf && i<pPhrase->nToken; i++){ |
︙ | ︙ | |||
126361 126362 126363 126364 126365 126366 126367 | sqlite3_result_error_nomem(context); goto exprtest_out; } for(ii=0; ii<nCol; ii++){ azCol[ii] = (char *)sqlite3_value_text(argv[ii+2]); } | < < | < < < < < < | | < < < | 123312 123313 123314 123315 123316 123317 123318 123319 123320 123321 123322 123323 123324 123325 123326 123327 123328 123329 | sqlite3_result_error_nomem(context); goto exprtest_out; } for(ii=0; ii<nCol; ii++){ azCol[ii] = (char *)sqlite3_value_text(argv[ii+2]); } rc = sqlite3Fts3ExprParse( pTokenizer, 0, azCol, 0, nCol, nCol, zExpr, nExpr, &pExpr ); if( rc!=SQLITE_OK && rc!=SQLITE_NOMEM ){ sqlite3_result_error(context, "Error parsing expression", -1); }else if( rc==SQLITE_NOMEM || !(zBuf = exprToString(pExpr, 0)) ){ sqlite3_result_error_nomem(context); }else{ sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT); sqlite3_free(zBuf); } |
︙ | ︙ | |||
126398 126399 126400 126401 126402 126403 126404 | } /* ** Register the query expression parser test function fts3_exprtest() ** with database connection db. */ SQLITE_PRIVATE int sqlite3Fts3ExprInitTestInterface(sqlite3* db){ | | < < < < < < | 123338 123339 123340 123341 123342 123343 123344 123345 123346 123347 123348 123349 123350 123351 123352 123353 123354 | } /* ** Register the query expression parser test function fts3_exprtest() ** with database connection db. */ SQLITE_PRIVATE int sqlite3Fts3ExprInitTestInterface(sqlite3* db){ return sqlite3_create_function( db, "fts3_exprtest", -1, SQLITE_UTF8, 0, fts3ExprTest, 0, 0 ); } #endif #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */ /************** End of fts3_expr.c *******************************************/ /************** Begin file fts3_hash.c ***************************************/ |
︙ | ︙ | |||
127697 127698 127699 127700 127701 127702 127703 | int nName; const char *zInput; int nInput; const char *azArg[64]; const char *zToken; | | | | | | 124631 124632 124633 124634 124635 124636 124637 124638 124639 124640 124641 124642 124643 124644 124645 124646 124647 124648 | int nName; const char *zInput; int nInput; const char *azArg[64]; const char *zToken; int nToken; int iStart; int iEnd; int iPos; int i; Tcl_Obj *pRet; if( argc<2 ){ sqlite3_result_error(context, "insufficient arguments", -1); return; |
︙ | ︙ | |||
127874 127875 127876 127877 127878 127879 127880 | } #endif /* ** Set up SQL objects in database db used to access the contents of ** the hash table pointed to by argument pHash. The hash table must | | | 124808 124809 124810 124811 124812 124813 124814 124815 124816 124817 124818 124819 124820 124821 124822 | } #endif /* ** Set up SQL objects in database db used to access the contents of ** the hash table pointed to by argument pHash. The hash table must ** been initialised to use string keys, and to take a private copy ** of the key when a value is inserted. i.e. by a call similar to: ** ** sqlite3Fts3HashInit(pHash, FTS3_HASH_STRING, 1); ** ** This function adds a scalar function (see header comment above ** scalarFunc() in this file for details) and, if ENABLE_TABLE is ** defined at compilation time, a temporary virtual table (see header |
︙ | ︙ | |||
128169 128170 128171 128172 128173 128174 128175 | ){ *ppModule = &simpleTokenizerModule; } #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */ /************** End of fts3_tokenizer1.c *************************************/ | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 125103 125104 125105 125106 125107 125108 125109 125110 125111 125112 125113 125114 125115 125116 | ){ *ppModule = &simpleTokenizerModule; } #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */ /************** End of fts3_tokenizer1.c *************************************/ /************** Begin file fts3_write.c **************************************/ /* ** 2009 Oct 23 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** |
︙ | ︙ | |||
129403 129404 129405 129406 129407 129408 129409 | ** If successful, SQLITE_OK is returned. Otherwise, an SQLite error code. */ static int fts3PendingTermsAdd( Fts3Table *p, /* Table into which text will be inserted */ int iLangid, /* Language id to use */ const char *zText, /* Text of document to be inserted */ int iCol, /* Column into which text is being inserted */ | | | | | | | 125881 125882 125883 125884 125885 125886 125887 125888 125889 125890 125891 125892 125893 125894 125895 125896 125897 125898 125899 125900 125901 125902 125903 125904 | ** If successful, SQLITE_OK is returned. Otherwise, an SQLite error code. */ static int fts3PendingTermsAdd( Fts3Table *p, /* Table into which text will be inserted */ int iLangid, /* Language id to use */ const char *zText, /* Text of document to be inserted */ int iCol, /* Column into which text is being inserted */ u32 *pnWord /* OUT: Number of tokens inserted */ ){ int rc; int iStart; int iEnd; int iPos; int nWord = 0; char const *zToken; int nToken; sqlite3_tokenizer *pTokenizer = p->pTokenizer; sqlite3_tokenizer_module const *pModule = pTokenizer->pModule; sqlite3_tokenizer_cursor *pCsr; int (*xNext)(sqlite3_tokenizer_cursor *pCursor, const char**,int*,int*,int*,int*); |
︙ | ︙ | |||
129467 129468 129469 129470 129471 129472 129473 | rc = fts3PendingTermsAddOne( p, iCol, iPos, &pIndex->hPending, zToken, pIndex->nPrefix ); } } pModule->xClose(pCsr); | | | 125945 125946 125947 125948 125949 125950 125951 125952 125953 125954 125955 125956 125957 125958 125959 | rc = fts3PendingTermsAddOne( p, iCol, iPos, &pIndex->hPending, zToken, pIndex->nPrefix ); } } pModule->xClose(pCsr); *pnWord = nWord; return (rc==SQLITE_DONE ? SQLITE_OK : rc); } /* ** Calling this function indicates that subsequent calls to ** fts3PendingTermsAdd() are to add term/position-list pairs for the ** contents of the document with docid iDocid. |
︙ | ︙ | |||
129671 129672 129673 129674 129675 129676 129677 | ** (an integer) of a row about to be deleted. Remove all terms from the ** full-text index. */ static void fts3DeleteTerms( int *pRC, /* Result code */ Fts3Table *p, /* The FTS table to delete from */ sqlite3_value *pRowid, /* The docid to be deleted */ | | < < < | 126149 126150 126151 126152 126153 126154 126155 126156 126157 126158 126159 126160 126161 126162 126163 126164 126165 126166 126167 126168 126169 126170 126171 126172 126173 126174 126175 126176 126177 126178 126179 126180 126181 126182 126183 126184 | ** (an integer) of a row about to be deleted. Remove all terms from the ** full-text index. */ static void fts3DeleteTerms( int *pRC, /* Result code */ Fts3Table *p, /* The FTS table to delete from */ sqlite3_value *pRowid, /* The docid to be deleted */ u32 *aSz /* Sizes of deleted document written here */ ){ int rc; sqlite3_stmt *pSelect; if( *pRC ) return; rc = fts3SqlStmt(p, SQL_SELECT_CONTENT_BY_ROWID, &pSelect, &pRowid); if( rc==SQLITE_OK ){ if( SQLITE_ROW==sqlite3_step(pSelect) ){ int i; int iLangid = langidFromSelect(p, pSelect); rc = fts3PendingTermsDocid(p, iLangid, sqlite3_column_int64(pSelect, 0)); for(i=1; rc==SQLITE_OK && i<=p->nColumn; i++){ const char *zText = (const char *)sqlite3_column_text(pSelect, i); rc = fts3PendingTermsAdd(p, iLangid, zText, -1, &aSz[i-1]); aSz[p->nColumn] += sqlite3_column_bytes(pSelect, i); } if( rc!=SQLITE_OK ){ sqlite3_reset(pSelect); *pRC = rc; return; } } rc = sqlite3_reset(pSelect); }else{ sqlite3_reset(pSelect); } *pRC = rc; } |
︙ | ︙ | |||
130109 130110 130111 130112 130113 130114 130115 | ** size of the previous offset-list. */ if( ppOffsetList ){ *ppOffsetList = pReader->pOffsetList; *pnOffsetList = (int)(p - pReader->pOffsetList - 1); } | < | 126584 126585 126586 126587 126588 126589 126590 126591 126592 126593 126594 126595 126596 126597 | ** size of the previous offset-list. */ if( ppOffsetList ){ *ppOffsetList = pReader->pOffsetList; *pnOffsetList = (int)(p - pReader->pOffsetList - 1); } while( p<pEnd && *p==0 ) p++; /* If there are no more entries in the doclist, set pOffsetList to ** NULL. Otherwise, set Fts3SegReader.iDocid to the next docid and ** Fts3SegReader.pOffsetList to point to the next offset list before ** returning. */ |
︙ | ︙ | |||
131125 131126 131127 131128 131129 131130 131131 | ** When this function is called, buffer *ppList (size *pnList bytes) contains ** a position list that may (or may not) feature multiple columns. This ** function adjusts the pointer *ppList and the length *pnList so that they ** identify the subset of the position list that corresponds to column iCol. ** ** If there are no entries in the input position list for column iCol, then ** *pnList is set to zero before returning. | < < < < | 127599 127600 127601 127602 127603 127604 127605 127606 127607 127608 127609 127610 127611 127612 127613 127614 127615 | ** When this function is called, buffer *ppList (size *pnList bytes) contains ** a position list that may (or may not) feature multiple columns. This ** function adjusts the pointer *ppList and the length *pnList so that they ** identify the subset of the position list that corresponds to column iCol. ** ** If there are no entries in the input position list for column iCol, then ** *pnList is set to zero before returning. */ static void fts3ColumnFilter( int iCol, /* Column to filter on */ char **ppList, /* IN/OUT: Pointer to position list */ int *pnList /* IN/OUT: Size of buffer *ppList in bytes */ ){ char *pList = *ppList; int nList = *pnList; char *pEnd = &pList[nList]; int iCurrent = 0; |
︙ | ︙ | |||
131160 131161 131162 131163 131164 131165 131166 | if( nList==0 ){ break; } p = &pList[1]; p += sqlite3Fts3GetVarint32(p, &iCurrent); } | < < < | 127630 127631 127632 127633 127634 127635 127636 127637 127638 127639 127640 127641 127642 127643 | if( nList==0 ){ break; } p = &pList[1]; p += sqlite3Fts3GetVarint32(p, &iCurrent); } *ppList = pList; *pnList = nList; } /* ** Cache data in the Fts3MultiSegReader.aBuffer[] buffer (overwriting any ** existing data). Grow the buffer if required. |
︙ | ︙ | |||
131236 131237 131238 131239 131240 131241 131242 | ){ rc = fts3SegReaderNextDocid(p, apSegment[j], 0, 0); j++; } if( rc!=SQLITE_OK ) return rc; fts3SegReaderSort(pMsr->apSegment, nMerge, j, xCmp); | < < < < < < < | > > > > > > | > | 127703 127704 127705 127706 127707 127708 127709 127710 127711 127712 127713 127714 127715 127716 127717 127718 127719 127720 127721 127722 127723 127724 127725 127726 127727 127728 127729 | ){ rc = fts3SegReaderNextDocid(p, apSegment[j], 0, 0); j++; } if( rc!=SQLITE_OK ) return rc; fts3SegReaderSort(pMsr->apSegment, nMerge, j, xCmp); if( pMsr->iColFilter>=0 ){ fts3ColumnFilter(pMsr->iColFilter, &pList, &nList); } if( nList>0 ){ if( fts3SegReaderIsPending(apSegment[0]) ){ rc = fts3MsrBufferData(pMsr, pList, nList+1); if( rc!=SQLITE_OK ) return rc; *paPoslist = pMsr->aBuffer; assert( (pMsr->aBuffer[nList] & 0xFE)==0x00 ); }else{ *paPoslist = pList; } *piDocid = iDocid; *pnPoslist = nList; break; } } } |
︙ | ︙ | |||
131491 131492 131493 131494 131495 131496 131497 | && apSegment[j]->iDocid==iDocid ){ fts3SegReaderNextDocid(p, apSegment[j], 0, 0); j++; } if( isColFilter ){ | | | 127958 127959 127960 127961 127962 127963 127964 127965 127966 127967 127968 127969 127970 127971 127972 | && apSegment[j]->iDocid==iDocid ){ fts3SegReaderNextDocid(p, apSegment[j], 0, 0); j++; } if( isColFilter ){ fts3ColumnFilter(pFilter->iCol, &pList, &nList); } if( !isIgnoreEmpty || nList>0 ){ /* Calculate the 'docid' delta value to write into the merged ** doclist. */ sqlite3_int64 iDelta; |
︙ | ︙ | |||
131928 131929 131930 131931 131932 131933 131934 | } } while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){ int iCol; int iLangid = langidFromSelect(p, pStmt); rc = fts3PendingTermsDocid(p, iLangid, sqlite3_column_int64(pStmt, 0)); | | | 128395 128396 128397 128398 128399 128400 128401 128402 128403 128404 128405 128406 128407 128408 128409 | } } while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){ int iCol; int iLangid = langidFromSelect(p, pStmt); rc = fts3PendingTermsDocid(p, iLangid, sqlite3_column_int64(pStmt, 0)); aSz[p->nColumn] = 0; for(iCol=0; rc==SQLITE_OK && iCol<p->nColumn; iCol++){ const char *z = (const char *) sqlite3_column_text(pStmt, iCol+1); rc = fts3PendingTermsAdd(p, iLangid, z, iCol, &aSz[iCol]); aSz[p->nColumn] += sqlite3_column_bytes(pStmt, iCol+1); } if( p->bHasDocsize ){ fts3InsertDocsize(&rc, p, aSz); |
︙ | ︙ | |||
133572 133573 133574 133575 133576 133577 133578 | const char *zText = (const char *)sqlite3_column_text(pStmt, iCol+1); int nText = sqlite3_column_bytes(pStmt, iCol+1); sqlite3_tokenizer_cursor *pT = 0; rc = sqlite3Fts3OpenTokenizer(p->pTokenizer, iLang, zText, nText, &pT); while( rc==SQLITE_OK ){ char const *zToken; /* Buffer containing token */ | | | | | 130039 130040 130041 130042 130043 130044 130045 130046 130047 130048 130049 130050 130051 130052 130053 130054 130055 | const char *zText = (const char *)sqlite3_column_text(pStmt, iCol+1); int nText = sqlite3_column_bytes(pStmt, iCol+1); sqlite3_tokenizer_cursor *pT = 0; rc = sqlite3Fts3OpenTokenizer(p->pTokenizer, iLang, zText, nText, &pT); while( rc==SQLITE_OK ){ char const *zToken; /* Buffer containing token */ int nToken; /* Number of bytes in token */ int iDum1, iDum2; /* Dummy variables */ int iPos; /* Position of token in zText */ rc = pModule->xNext(pT, &zToken, &nToken, &iDum1, &iDum2, &iPos); if( rc==SQLITE_OK ){ int i; cksum2 = cksum2 ^ fts3ChecksumEntry( zToken, nToken, iLang, 0, iDocid, iCol, iPos ); |
︙ | ︙ | |||
133741 133742 133743 133744 133745 133746 133747 | for(i=0; i<p->nColumn && rc==SQLITE_OK; i++){ const char *zText = (const char *)sqlite3_column_text(pCsr->pStmt, i+1); sqlite3_tokenizer_cursor *pTC = 0; rc = sqlite3Fts3OpenTokenizer(pT, pCsr->iLangid, zText, -1, &pTC); while( rc==SQLITE_OK ){ char const *zToken; /* Buffer containing token */ | | | | | 130208 130209 130210 130211 130212 130213 130214 130215 130216 130217 130218 130219 130220 130221 130222 130223 130224 | for(i=0; i<p->nColumn && rc==SQLITE_OK; i++){ const char *zText = (const char *)sqlite3_column_text(pCsr->pStmt, i+1); sqlite3_tokenizer_cursor *pTC = 0; rc = sqlite3Fts3OpenTokenizer(pT, pCsr->iLangid, zText, -1, &pTC); while( rc==SQLITE_OK ){ char const *zToken; /* Buffer containing token */ int nToken; /* Number of bytes in token */ int iDum1, iDum2; /* Dummy variables */ int iPos; /* Position of token in zText */ rc = pModule->xNext(pTC, &zToken, &nToken, &iDum1, &iDum2, &iPos); for(pDef=pCsr->pDeferred; pDef && rc==SQLITE_OK; pDef=pDef->pNext){ Fts3PhraseToken *pPT = pDef->pToken; if( (pDef->iCol>=p->nColumn || pDef->iCol==i) && (pPT->bFirst==0 || iPos==0) && (pPT->n==nToken || (pPT->isPrefix && pPT->n<nToken)) |
︙ | ︙ | |||
133832 133833 133834 133835 133836 133837 133838 | ** SQLite value pRowid contains the rowid of a row that may or may not be ** present in the FTS3 table. If it is, delete it and adjust the contents ** of subsiduary data structures accordingly. */ static int fts3DeleteByRowid( Fts3Table *p, sqlite3_value *pRowid, | | < < < < < | | | | | | | | | < | < > | | > > > | | | < | 130299 130300 130301 130302 130303 130304 130305 130306 130307 130308 130309 130310 130311 130312 130313 130314 130315 130316 130317 130318 130319 130320 130321 130322 130323 130324 130325 130326 130327 130328 130329 130330 130331 130332 130333 130334 | ** SQLite value pRowid contains the rowid of a row that may or may not be ** present in the FTS3 table. If it is, delete it and adjust the contents ** of subsiduary data structures accordingly. */ static int fts3DeleteByRowid( Fts3Table *p, sqlite3_value *pRowid, int *pnDoc, u32 *aSzDel ){ int isEmpty = 0; int rc = fts3IsEmpty(p, pRowid, &isEmpty); if( rc==SQLITE_OK ){ if( isEmpty ){ /* Deleting this row means the whole table is empty. In this case ** delete the contents of all three tables and throw away any ** data in the pendingTerms hash table. */ rc = fts3DeleteAll(p, 1); *pnDoc = *pnDoc - 1; }else{ fts3DeleteTerms(&rc, p, pRowid, aSzDel); if( p->zContentTbl==0 ){ fts3SqlExec(&rc, p, SQL_DELETE_CONTENT, &pRowid); if( sqlite3_changes(p->db) ) *pnDoc = *pnDoc - 1; }else{ *pnDoc = *pnDoc - 1; } if( p->bHasDocsize ){ fts3SqlExec(&rc, p, SQL_DELETE_DOCSIZE, &pRowid); } } } return rc; } |
︙ | ︙ | |||
133888 133889 133890 133891 133892 133893 133894 | sqlite3_value **apVal, /* Array of arguments */ sqlite_int64 *pRowid /* OUT: The affected (or effected) rowid */ ){ Fts3Table *p = (Fts3Table *)pVtab; int rc = SQLITE_OK; /* Return Code */ int isRemove = 0; /* True for an UPDATE or DELETE */ u32 *aSzIns = 0; /* Sizes of inserted documents */ | | | 130351 130352 130353 130354 130355 130356 130357 130358 130359 130360 130361 130362 130363 130364 130365 | sqlite3_value **apVal, /* Array of arguments */ sqlite_int64 *pRowid /* OUT: The affected (or effected) rowid */ ){ Fts3Table *p = (Fts3Table *)pVtab; int rc = SQLITE_OK; /* Return Code */ int isRemove = 0; /* True for an UPDATE or DELETE */ u32 *aSzIns = 0; /* Sizes of inserted documents */ u32 *aSzDel; /* Sizes of deleted documents */ int nChng = 0; /* Net change in number of documents */ int bInsertDone = 0; assert( p->pSegments==0 ); assert( nArg==1 /* DELETE operations */ || nArg==(2 + p->nColumn + 3) /* INSERT or UPDATE operations */ |
︙ | ︙ | |||
133916 133917 133918 133919 133920 133921 133922 | if( nArg>1 && sqlite3_value_int(apVal[2 + p->nColumn + 2])<0 ){ rc = SQLITE_CONSTRAINT; goto update_out; } /* Allocate space to hold the change in document sizes */ | | | | | | 130379 130380 130381 130382 130383 130384 130385 130386 130387 130388 130389 130390 130391 130392 130393 130394 130395 130396 130397 130398 130399 | if( nArg>1 && sqlite3_value_int(apVal[2 + p->nColumn + 2])<0 ){ rc = SQLITE_CONSTRAINT; goto update_out; } /* Allocate space to hold the change in document sizes */ aSzIns = sqlite3_malloc( sizeof(aSzIns[0])*(p->nColumn+1)*2 ); if( aSzIns==0 ){ rc = SQLITE_NOMEM; goto update_out; } aSzDel = &aSzIns[p->nColumn+1]; memset(aSzIns, 0, sizeof(aSzIns[0])*(p->nColumn+1)*2); /* If this is an INSERT operation, or an UPDATE that modifies the rowid ** value, then this operation requires constraint handling. ** ** If the on-conflict mode is REPLACE, this means that the existing row ** should be deleted from the database before inserting the new row. Or, ** if the on-conflict mode is other than REPLACE, then this method must |
︙ | ︙ | |||
134007 134008 134009 134010 134011 134012 134013 | } if( p->bFts4 ){ fts3UpdateDocTotals(&rc, p, aSzIns, aSzDel, nChng); } update_out: | | | 130470 130471 130472 130473 130474 130475 130476 130477 130478 130479 130480 130481 130482 130483 130484 | } if( p->bFts4 ){ fts3UpdateDocTotals(&rc, p, aSzIns, aSzDel, nChng); } update_out: sqlite3_free(aSzIns); sqlite3Fts3SegmentsClose(p); return rc; } /* ** Flush any data in the pending-terms hash table to disk. If successful, ** merge all segments in the database (including the new segment, if |
︙ | ︙ | |||
134428 134429 134430 134431 134432 134433 134434 | /* ** Select the fragment of text consisting of nFragment contiguous tokens ** from column iCol that represent the "best" snippet. The best snippet ** is the snippet with the highest score, where scores are calculated ** by adding: ** | | | | 130891 130892 130893 130894 130895 130896 130897 130898 130899 130900 130901 130902 130903 130904 130905 130906 130907 | /* ** Select the fragment of text consisting of nFragment contiguous tokens ** from column iCol that represent the "best" snippet. The best snippet ** is the snippet with the highest score, where scores are calculated ** by adding: ** ** (a) +1 point for each occurence of a matchable phrase in the snippet. ** ** (b) +1000 points for the first occurence of each matchable phrase in ** the snippet for which the corresponding mCovered bit is not set. ** ** The selected snippet parameters are stored in structure *pFragment before ** returning. The score of the selected snippet is stored in *piScore ** before returning. */ static int fts3BestSnippet( |
︙ | ︙ | |||
134615 134616 134617 134618 134619 134620 134621 | ** or more tokens in zDoc/nDoc. */ rc = sqlite3Fts3OpenTokenizer(pTab->pTokenizer, iLangid, zDoc, nDoc, &pC); if( rc!=SQLITE_OK ){ return rc; } while( rc==SQLITE_OK && iCurrent<(nSnippet+nDesired) ){ | | | 131078 131079 131080 131081 131082 131083 131084 131085 131086 131087 131088 131089 131090 131091 131092 | ** or more tokens in zDoc/nDoc. */ rc = sqlite3Fts3OpenTokenizer(pTab->pTokenizer, iLangid, zDoc, nDoc, &pC); if( rc!=SQLITE_OK ){ return rc; } while( rc==SQLITE_OK && iCurrent<(nSnippet+nDesired) ){ const char *ZDUMMY; int DUMMY1, DUMMY2, DUMMY3; rc = pMod->xNext(pC, &ZDUMMY, &DUMMY1, &DUMMY2, &DUMMY3, &iCurrent); } pMod->xClose(pC); if( rc!=SQLITE_OK && rc!=SQLITE_DONE ){ return rc; } nShift = (rc==SQLITE_DONE)+iCurrent-nSnippet; assert( nShift<=nDesired ); |
︙ | ︙ | |||
134659 134660 134661 134662 134663 134664 134665 134666 134667 134668 134669 134670 134671 134672 134673 134674 134675 134676 134677 134678 134679 134680 134681 134682 134683 | int iEnd = 0; /* Byte offset of end of current token */ int isShiftDone = 0; /* True after snippet is shifted */ int iPos = pFragment->iPos; /* First token of snippet */ u64 hlmask = pFragment->hlmask; /* Highlight-mask for snippet */ int iCol = pFragment->iCol+1; /* Query column to extract text from */ sqlite3_tokenizer_module *pMod; /* Tokenizer module methods object */ sqlite3_tokenizer_cursor *pC; /* Tokenizer cursor open on zDoc/nDoc */ zDoc = (const char *)sqlite3_column_text(pCsr->pStmt, iCol); if( zDoc==0 ){ if( sqlite3_column_type(pCsr->pStmt, iCol)!=SQLITE_NULL ){ return SQLITE_NOMEM; } return SQLITE_OK; } nDoc = sqlite3_column_bytes(pCsr->pStmt, iCol); /* Open a token cursor on the document. */ pMod = (sqlite3_tokenizer_module *)pTab->pTokenizer->pModule; rc = sqlite3Fts3OpenTokenizer(pTab->pTokenizer, pCsr->iLangid, zDoc,nDoc,&pC); if( rc!=SQLITE_OK ){ return rc; } while( rc==SQLITE_OK ){ | > > < < | | | < < < < < < < < < < < | 131122 131123 131124 131125 131126 131127 131128 131129 131130 131131 131132 131133 131134 131135 131136 131137 131138 131139 131140 131141 131142 131143 131144 131145 131146 131147 131148 131149 131150 131151 131152 131153 131154 131155 131156 131157 131158 131159 | int iEnd = 0; /* Byte offset of end of current token */ int isShiftDone = 0; /* True after snippet is shifted */ int iPos = pFragment->iPos; /* First token of snippet */ u64 hlmask = pFragment->hlmask; /* Highlight-mask for snippet */ int iCol = pFragment->iCol+1; /* Query column to extract text from */ sqlite3_tokenizer_module *pMod; /* Tokenizer module methods object */ sqlite3_tokenizer_cursor *pC; /* Tokenizer cursor open on zDoc/nDoc */ const char *ZDUMMY; /* Dummy argument used with tokenizer */ int DUMMY1; /* Dummy argument used with tokenizer */ zDoc = (const char *)sqlite3_column_text(pCsr->pStmt, iCol); if( zDoc==0 ){ if( sqlite3_column_type(pCsr->pStmt, iCol)!=SQLITE_NULL ){ return SQLITE_NOMEM; } return SQLITE_OK; } nDoc = sqlite3_column_bytes(pCsr->pStmt, iCol); /* Open a token cursor on the document. */ pMod = (sqlite3_tokenizer_module *)pTab->pTokenizer->pModule; rc = sqlite3Fts3OpenTokenizer(pTab->pTokenizer, pCsr->iLangid, zDoc,nDoc,&pC); if( rc!=SQLITE_OK ){ return rc; } while( rc==SQLITE_OK ){ int iBegin; /* Offset in zDoc of start of token */ int iFin; /* Offset in zDoc of end of token */ int isHighlight; /* True for highlighted terms */ rc = pMod->xNext(pC, &ZDUMMY, &DUMMY1, &iBegin, &iFin, &iCurrent); if( rc!=SQLITE_OK ){ if( rc==SQLITE_DONE ){ /* Special case - the last token of the snippet is also the last token ** of the column. Append any punctuation that occurred between the end ** of the previous token and the end of the document to the output. ** Then break out of the loop. */ |
︙ | ︙ | |||
135383 135384 135385 135386 135387 135388 135389 135390 135391 135392 135393 135394 135395 135396 | */ SQLITE_PRIVATE void sqlite3Fts3Offsets( sqlite3_context *pCtx, /* SQLite function call context */ Fts3Cursor *pCsr /* Cursor object */ ){ Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; sqlite3_tokenizer_module const *pMod = pTab->pTokenizer->pModule; int rc; /* Return Code */ int nToken; /* Number of tokens in query */ int iCol; /* Column currently being processed */ StrBuffer res = {0, 0, 0}; /* Result string */ TermOffsetCtx sCtx; /* Context for fts3ExprTermOffsetInit() */ if( !pCsr->pExpr ){ | > > | 131835 131836 131837 131838 131839 131840 131841 131842 131843 131844 131845 131846 131847 131848 131849 131850 | */ SQLITE_PRIVATE void sqlite3Fts3Offsets( sqlite3_context *pCtx, /* SQLite function call context */ Fts3Cursor *pCsr /* Cursor object */ ){ Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; sqlite3_tokenizer_module const *pMod = pTab->pTokenizer->pModule; const char *ZDUMMY; /* Dummy argument used with xNext() */ int NDUMMY; /* Dummy argument used with xNext() */ int rc; /* Return Code */ int nToken; /* Number of tokens in query */ int iCol; /* Column currently being processed */ StrBuffer res = {0, 0, 0}; /* Result string */ TermOffsetCtx sCtx; /* Context for fts3ExprTermOffsetInit() */ if( !pCsr->pExpr ){ |
︙ | ︙ | |||
135415 135416 135417 135418 135419 135420 135421 | sCtx.pCsr = pCsr; /* Loop through the table columns, appending offset information to ** string-buffer res for each column. */ for(iCol=0; iCol<pTab->nColumn; iCol++){ sqlite3_tokenizer_cursor *pC; /* Tokenizer cursor */ | < < | | | | 131869 131870 131871 131872 131873 131874 131875 131876 131877 131878 131879 131880 131881 131882 131883 131884 131885 | sCtx.pCsr = pCsr; /* Loop through the table columns, appending offset information to ** string-buffer res for each column. */ for(iCol=0; iCol<pTab->nColumn; iCol++){ sqlite3_tokenizer_cursor *pC; /* Tokenizer cursor */ int iStart; int iEnd; int iCurrent; const char *zDoc; int nDoc; /* Initialize the contents of sCtx.aTerm[] for column iCol. There is ** no way that this operation can fail, so the return code from ** fts3ExprIterate() can be discarded. */ |
︙ | ︙ | |||
135685 135686 135687 135688 135689 135690 135691 | ** If so, no action is taken. Otherwise, the codepoint is added to the ** unicode_tokenizer.aiException[] array. For the purposes of tokenization, ** the return value of sqlite3FtsUnicodeIsalnum() is inverted for all ** codepoints in the aiException[] array. ** ** If a standalone diacritic mark (one that sqlite3FtsUnicodeIsdiacritic() ** identifies as a diacritic) occurs in the zIn/nIn string it is ignored. | | | 132137 132138 132139 132140 132141 132142 132143 132144 132145 132146 132147 132148 132149 132150 132151 | ** If so, no action is taken. Otherwise, the codepoint is added to the ** unicode_tokenizer.aiException[] array. For the purposes of tokenization, ** the return value of sqlite3FtsUnicodeIsalnum() is inverted for all ** codepoints in the aiException[] array. ** ** If a standalone diacritic mark (one that sqlite3FtsUnicodeIsdiacritic() ** identifies as a diacritic) occurs in the zIn/nIn string it is ignored. ** It is not possible to change the behaviour of the tokenizer with respect ** to these codepoints. */ static int unicodeAddExceptions( unicode_tokenizer *p, /* Tokenizer to add exceptions to */ int bAlnum, /* Replace Isalnum() return value with this */ const char *zIn, /* Array of characters to make exceptions */ int nIn /* Length of z in bytes */ |
︙ | ︙ | |||
138988 138989 138990 138991 138992 138993 138994 | static int rtreeDeleteRowid(Rtree *pRtree, sqlite3_int64 iDelete){ int rc; /* Return code */ RtreeNode *pLeaf = 0; /* Leaf node containing record iDelete */ int iCell; /* Index of iDelete cell in pLeaf */ RtreeNode *pRoot; /* Root node of rtree structure */ | | | 135440 135441 135442 135443 135444 135445 135446 135447 135448 135449 135450 135451 135452 135453 135454 | static int rtreeDeleteRowid(Rtree *pRtree, sqlite3_int64 iDelete){ int rc; /* Return code */ RtreeNode *pLeaf = 0; /* Leaf node containing record iDelete */ int iCell; /* Index of iDelete cell in pLeaf */ RtreeNode *pRoot; /* Root node of rtree structure */ /* Obtain a reference to the root node to initialise Rtree.iDepth */ rc = nodeAcquire(pRtree, 1, 0, &pRoot); /* Obtain a reference to the leaf node that contains the entry ** about to be deleted. */ if( rc==SQLITE_OK ){ rc = findLeafNode(pRtree, iDelete, &pLeaf); |
︙ | ︙ | |||
139372 139373 139374 139375 139376 139377 139378 | ** This ensures that each node is stored on a single database page. If the ** database page-size is so large that more than RTREE_MAXCELLS entries ** would fit in a single node, use a smaller node-size. */ static int getNodeSize( sqlite3 *db, /* Database handle */ Rtree *pRtree, /* Rtree handle */ | | < < < < < < | 135824 135825 135826 135827 135828 135829 135830 135831 135832 135833 135834 135835 135836 135837 135838 135839 135840 135841 135842 135843 135844 135845 135846 135847 135848 135849 135850 135851 135852 135853 135854 135855 135856 135857 | ** This ensures that each node is stored on a single database page. If the ** database page-size is so large that more than RTREE_MAXCELLS entries ** would fit in a single node, use a smaller node-size. */ static int getNodeSize( sqlite3 *db, /* Database handle */ Rtree *pRtree, /* Rtree handle */ int isCreate /* True for xCreate, false for xConnect */ ){ int rc; char *zSql; if( isCreate ){ int iPageSize = 0; zSql = sqlite3_mprintf("PRAGMA %Q.page_size", pRtree->zDb); rc = getIntFromStmt(db, zSql, &iPageSize); if( rc==SQLITE_OK ){ pRtree->iNodeSize = iPageSize-64; if( (4+pRtree->nBytesPerCell*RTREE_MAXCELLS)<pRtree->iNodeSize ){ pRtree->iNodeSize = 4+pRtree->nBytesPerCell*RTREE_MAXCELLS; } } }else{ zSql = sqlite3_mprintf( "SELECT length(data) FROM '%q'.'%q_node' WHERE nodeno = 1", pRtree->zDb, pRtree->zName ); rc = getIntFromStmt(db, zSql, &pRtree->iNodeSize); } sqlite3_free(zSql); return rc; } /* |
︙ | ︙ | |||
139461 139462 139463 139464 139465 139466 139467 | pRtree->nDim = (argc-4)/2; pRtree->nBytesPerCell = 8 + pRtree->nDim*4*2; pRtree->eCoordType = eCoordType; memcpy(pRtree->zDb, argv[1], nDb); memcpy(pRtree->zName, argv[2], nName); /* Figure out the node size to use. */ | | | 135907 135908 135909 135910 135911 135912 135913 135914 135915 135916 135917 135918 135919 135920 135921 | pRtree->nDim = (argc-4)/2; pRtree->nBytesPerCell = 8 + pRtree->nDim*4*2; pRtree->eCoordType = eCoordType; memcpy(pRtree->zDb, argv[1], nDb); memcpy(pRtree->zName, argv[2], nName); /* Figure out the node size to use. */ rc = getNodeSize(db, pRtree, isCreate); /* Create/Connect to the underlying relational database schema. If ** that is successful, call sqlite3_declare_vtab() to configure ** the r-tree table schema. */ if( rc==SQLITE_OK ){ if( (rc = rtreeSqlInit(pRtree, db, argv[1], argv[2], isCreate)) ){ |
︙ | ︙ | |||
140308 140309 140310 140311 140312 140313 140314 | zInput = ""; }else if( nInput<0 ){ nInput = strlen(zInput); } nChar = nInput+1; pCsr = (IcuCursor *)sqlite3_malloc( sizeof(IcuCursor) + /* IcuCursor */ | | | | 136754 136755 136756 136757 136758 136759 136760 136761 136762 136763 136764 136765 136766 136767 136768 136769 136770 136771 136772 136773 136774 136775 136776 | zInput = ""; }else if( nInput<0 ){ nInput = strlen(zInput); } nChar = nInput+1; pCsr = (IcuCursor *)sqlite3_malloc( sizeof(IcuCursor) + /* IcuCursor */ nChar * sizeof(UChar) + /* IcuCursor.aChar[] */ (nChar+1) * sizeof(int) /* IcuCursor.aOffset[] */ ); if( !pCsr ){ return SQLITE_NOMEM; } memset(pCsr, 0, sizeof(IcuCursor)); pCsr->aChar = (UChar *)&pCsr[1]; pCsr->aOffset = (int *)&pCsr->aChar[nChar]; pCsr->aOffset[iOut] = iInput; U8_NEXT(zInput, iInput, nInput, c); while( c>0 ){ int isError = 0; c = u_foldCase(c, opt); U16_APPEND(pCsr->aChar, iOut, nChar, c, isError); |
︙ | ︙ |
Changes to SQLite.Interop/src/core/sqlite3.h.
︙ | ︙ | |||
103 104 105 106 107 108 109 | ** 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()]. */ | | | | | 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 | ** string contains the date and time of the check-in (UTC) and an SHA1 ** hash of the entire source tree. ** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ #define SQLITE_VERSION "3.7.15" #define SQLITE_VERSION_NUMBER 3007015 #define SQLITE_SOURCE_ID "2012-10-12 18:06:07 de784399ed1f0e27fc875e32719643d19819c8fb" /* ** CAPI3REF: Run-Time Library Version Numbers ** KEYWORDS: sqlite3_version, sqlite3_sourceid ** ** These interfaces provide the same information as the [SQLITE_VERSION], ** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros |
︙ | ︙ | |||
284 285 286 287 288 289 290 | ** host languages that are garbage collected, and where the order in which ** destructors are called is arbitrary. ** ** Applications should [sqlite3_finalize | finalize] all [prepared statements], ** [sqlite3_blob_close | close] all [BLOB handles], and ** [sqlite3_backup_finish | finish] all [sqlite3_backup] objects associated ** with the [sqlite3] object prior to attempting to close the object. ^If | | | 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 | ** host languages that are garbage collected, and where the order in which ** destructors are called is arbitrary. ** ** Applications should [sqlite3_finalize | finalize] all [prepared statements], ** [sqlite3_blob_close | close] all [BLOB handles], and ** [sqlite3_backup_finish | finish] all [sqlite3_backup] objects associated ** with the [sqlite3] object prior to attempting to close the object. ^If ** sqlite3_close() is called on a [database connection] that still has ** outstanding [prepared statements], [BLOB handles], and/or ** [sqlite3_backup] objects then it returns SQLITE_OK but the deallocation ** of resources is deferred until all [prepared statements], [BLOB handles], ** and [sqlite3_backup] objects are also destroyed. ** ** ^If an [sqlite3] object is destroyed while a transaction is open, ** the transaction is automatically rolled back. |
︙ | ︙ | |||
421 422 423 424 425 426 427 | #define SQLITE_MISMATCH 20 /* Data type mismatch */ #define SQLITE_MISUSE 21 /* Library used incorrectly */ #define SQLITE_NOLFS 22 /* Uses OS features not supported on host */ #define SQLITE_AUTH 23 /* Authorization denied */ #define SQLITE_FORMAT 24 /* Auxiliary database format error */ #define SQLITE_RANGE 25 /* 2nd parameter to sqlite3_bind out of range */ #define SQLITE_NOTADB 26 /* File opened that is not a database file */ | < < | 421 422 423 424 425 426 427 428 429 430 431 432 433 434 | #define SQLITE_MISMATCH 20 /* Data type mismatch */ #define SQLITE_MISUSE 21 /* Library used incorrectly */ #define SQLITE_NOLFS 22 /* Uses OS features not supported on host */ #define SQLITE_AUTH 23 /* Authorization denied */ #define SQLITE_FORMAT 24 /* Auxiliary database format error */ #define SQLITE_RANGE 25 /* 2nd parameter to sqlite3_bind out of range */ #define SQLITE_NOTADB 26 /* File opened that is not a database file */ #define SQLITE_ROW 100 /* sqlite3_step() has another row ready */ #define SQLITE_DONE 101 /* sqlite3_step() has finished executing */ /* end-of-error-codes */ /* ** CAPI3REF: Extended Result Codes ** KEYWORDS: {extended error code} {extended error codes} |
︙ | ︙ | |||
472 473 474 475 476 477 478 | #define SQLITE_IOERR_CLOSE (SQLITE_IOERR | (16<<8)) #define SQLITE_IOERR_DIR_CLOSE (SQLITE_IOERR | (17<<8)) #define SQLITE_IOERR_SHMOPEN (SQLITE_IOERR | (18<<8)) #define SQLITE_IOERR_SHMSIZE (SQLITE_IOERR | (19<<8)) #define SQLITE_IOERR_SHMLOCK (SQLITE_IOERR | (20<<8)) #define SQLITE_IOERR_SHMMAP (SQLITE_IOERR | (21<<8)) #define SQLITE_IOERR_SEEK (SQLITE_IOERR | (22<<8)) | < < < < < < < < < < < < < < | 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 | #define SQLITE_IOERR_CLOSE (SQLITE_IOERR | (16<<8)) #define SQLITE_IOERR_DIR_CLOSE (SQLITE_IOERR | (17<<8)) #define SQLITE_IOERR_SHMOPEN (SQLITE_IOERR | (18<<8)) #define SQLITE_IOERR_SHMSIZE (SQLITE_IOERR | (19<<8)) #define SQLITE_IOERR_SHMLOCK (SQLITE_IOERR | (20<<8)) #define SQLITE_IOERR_SHMMAP (SQLITE_IOERR | (21<<8)) #define SQLITE_IOERR_SEEK (SQLITE_IOERR | (22<<8)) #define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8)) #define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8)) #define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8)) #define SQLITE_CANTOPEN_ISDIR (SQLITE_CANTOPEN | (2<<8)) #define SQLITE_CANTOPEN_FULLPATH (SQLITE_CANTOPEN | (3<<8)) #define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8)) #define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8)) #define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8)) #define SQLITE_ABORT_ROLLBACK (SQLITE_ABORT | (2<<8)) /* ** CAPI3REF: Flags For File Open Operations ** ** These bit values are intended for use in the ** 3rd parameter to the [sqlite3_open_v2()] interface and ** in the 4th parameter to the [sqlite3_vfs.xOpen] method. |
︙ | ︙ | |||
734 735 736 737 738 739 740 | int (*xDeviceCharacteristics)(sqlite3_file*); /* Methods above are valid for version 1 */ int (*xShmMap)(sqlite3_file*, int iPg, int pgsz, int, void volatile**); int (*xShmLock)(sqlite3_file*, int offset, int n, int flags); void (*xShmBarrier)(sqlite3_file*); int (*xShmUnmap)(sqlite3_file*, int deleteFlag); /* Methods above are valid for version 2 */ | < < < | 718 719 720 721 722 723 724 725 726 727 728 729 730 731 | int (*xDeviceCharacteristics)(sqlite3_file*); /* Methods above are valid for version 1 */ int (*xShmMap)(sqlite3_file*, int iPg, int pgsz, int, void volatile**); int (*xShmLock)(sqlite3_file*, int offset, int n, int flags); void (*xShmBarrier)(sqlite3_file*); int (*xShmUnmap)(sqlite3_file*, int deleteFlag); /* Methods above are valid for version 2 */ /* Additional methods may be added in future releases */ }; /* ** CAPI3REF: Standard File Control Opcodes ** ** These integer constants are opcodes for the xFileControl method |
︙ | ︙ | |||
871 872 873 874 875 876 877 878 879 | ** VFS has handled the PRAGMA itself and the parser generates a no-op ** prepared statement. ^If the [SQLITE_FCNTL_PRAGMA] file control returns ** any result code other than [SQLITE_OK] or [SQLITE_NOTFOUND], that means ** that the VFS encountered an error while handling the [PRAGMA] and the ** compilation of the PRAGMA fails with an error. ^The [SQLITE_FCNTL_PRAGMA] ** file control occurs at the beginning of pragma statement analysis and so ** it is able to override built-in [PRAGMA] statements. ** ** <li>[[SQLITE_FCNTL_BUSYHANDLER]] | > < | < < < < < < < < < < < < < < < < < < < < < < < | 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 | ** VFS has handled the PRAGMA itself and the parser generates a no-op ** prepared statement. ^If the [SQLITE_FCNTL_PRAGMA] file control returns ** any result code other than [SQLITE_OK] or [SQLITE_NOTFOUND], that means ** that the VFS encountered an error while handling the [PRAGMA] and the ** compilation of the PRAGMA fails with an error. ^The [SQLITE_FCNTL_PRAGMA] ** file control occurs at the beginning of pragma statement analysis and so ** it is able to override built-in [PRAGMA] statements. ** </ul> ** ** <li>[[SQLITE_FCNTL_BUSYHANDLER]] ** ^This file-control may be invoked by SQLite on the database file handle ** shortly after it is opened in order to provide a custom VFS with access ** to the connections busy-handler callback. The argument is of type (void **) ** - an array of two (void *) values. The first (void *) actually points ** to a function of type (int (*)(void *)). In order to invoke the connections ** busy-handler, this function should be invoked with the second (void *) in ** the array as the only argument. If it returns non-zero, then the operation ** should be retried. If it returns zero, the custom VFS should abandon the ** current operation. */ #define SQLITE_FCNTL_LOCKSTATE 1 #define SQLITE_GET_LOCKPROXYFILE 2 #define SQLITE_SET_LOCKPROXYFILE 3 #define SQLITE_LAST_ERRNO 4 #define SQLITE_FCNTL_SIZE_HINT 5 #define SQLITE_FCNTL_CHUNK_SIZE 6 #define SQLITE_FCNTL_FILE_POINTER 7 #define SQLITE_FCNTL_SYNC_OMITTED 8 #define SQLITE_FCNTL_WIN32_AV_RETRY 9 #define SQLITE_FCNTL_PERSIST_WAL 10 #define SQLITE_FCNTL_OVERWRITE 11 #define SQLITE_FCNTL_VFSNAME 12 #define SQLITE_FCNTL_POWERSAFE_OVERWRITE 13 #define SQLITE_FCNTL_PRAGMA 14 #define SQLITE_FCNTL_BUSYHANDLER 15 /* ** CAPI3REF: Mutex Handle ** ** The mutex module within SQLite defines [sqlite3_mutex] to be an ** abstract type for a mutex object. The SQLite core never looks ** at the internal representation of an [sqlite3_mutex]. It only |
︙ | ︙ | |||
1588 1589 1590 1591 1592 1593 1594 | ** ** [[SQLITE_CONFIG_GETPCACHE2]] <dt>SQLITE_CONFIG_GETPCACHE2</dt> ** <dd> ^(This option takes a single argument which is a pointer to an ** [sqlite3_pcache_methods2] object. SQLite copies of the current ** page cache implementation into that object.)^ </dd> ** ** [[SQLITE_CONFIG_LOG]] <dt>SQLITE_CONFIG_LOG</dt> | < < | | 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 | ** ** [[SQLITE_CONFIG_GETPCACHE2]] <dt>SQLITE_CONFIG_GETPCACHE2</dt> ** <dd> ^(This option takes a single argument which is a pointer to an ** [sqlite3_pcache_methods2] object. SQLite copies of the current ** page cache implementation into that object.)^ </dd> ** ** [[SQLITE_CONFIG_LOG]] <dt>SQLITE_CONFIG_LOG</dt> ** <dd> ^The SQLITE_CONFIG_LOG option takes two arguments: a pointer to a ** function with a call signature of void(*)(void*,int,const char*), ** and a pointer to void. ^If the function pointer is not NULL, it is ** invoked by [sqlite3_log()] to process each logging event. ^If the ** function pointer is NULL, the [sqlite3_log()] interface becomes a no-op. ** ^The void pointer that is the second argument to SQLITE_CONFIG_LOG is ** passed through as the first parameter to the application-defined logger ** function whenever that function is invoked. ^The second parameter to |
︙ | ︙ | |||
1621 1622 1623 1624 1625 1626 1627 | ** connection is opened. If it is globally disabled, filenames are ** only interpreted as URIs if the SQLITE_OPEN_URI flag is set when the ** database connection is opened. By default, URI handling is globally ** disabled. The default value may be changed by compiling with the ** [SQLITE_USE_URI] symbol defined. ** ** [[SQLITE_CONFIG_COVERING_INDEX_SCAN]] <dt>SQLITE_CONFIG_COVERING_INDEX_SCAN | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 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 | ** connection is opened. If it is globally disabled, filenames are ** only interpreted as URIs if the SQLITE_OPEN_URI flag is set when the ** database connection is opened. By default, URI handling is globally ** disabled. The default value may be changed by compiling with the ** [SQLITE_USE_URI] symbol defined. ** ** [[SQLITE_CONFIG_COVERING_INDEX_SCAN]] <dt>SQLITE_CONFIG_COVERING_INDEX_SCAN ** <dd> This option taks a single integer argument which is interpreted as ** a boolean in order to enable or disable the use of covering indices for ** full table scans in the query optimizer. The default setting is determined ** by the [SQLITE_ALLOW_COVERING_INDEX_SCAN] compile-time option, or is "on" ** if that compile-time option is omitted. ** The ability to disable the use of covering indices for full table scans ** is because some incorrectly coded legacy applications might malfunction ** malfunction when the optimization is enabled. Providing the ability to ** disable the optimization allows the older, buggy application code to work ** without change even with newer versions of SQLite. ** ** [[SQLITE_CONFIG_PCACHE]] [[SQLITE_CONFIG_GETPCACHE]] ** <dt>SQLITE_CONFIG_PCACHE and SQLITE_CONFIG_GETPCACHE ** <dd> These options are obsolete and should not be used by new code. ** They are retained for backwards compatibility but are now no-ops. ** </dl> */ #define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */ #define SQLITE_CONFIG_MULTITHREAD 2 /* nil */ #define SQLITE_CONFIG_SERIALIZED 3 /* nil */ #define SQLITE_CONFIG_MALLOC 4 /* sqlite3_mem_methods* */ #define SQLITE_CONFIG_GETMALLOC 5 /* sqlite3_mem_methods* */ |
︙ | ︙ | |||
1690 1691 1692 1693 1694 1695 1696 | #define SQLITE_CONFIG_PCACHE 14 /* no-op */ #define SQLITE_CONFIG_GETPCACHE 15 /* no-op */ #define SQLITE_CONFIG_LOG 16 /* xFunc, void* */ #define SQLITE_CONFIG_URI 17 /* int */ #define SQLITE_CONFIG_PCACHE2 18 /* sqlite3_pcache_methods2* */ #define SQLITE_CONFIG_GETPCACHE2 19 /* sqlite3_pcache_methods2* */ #define SQLITE_CONFIG_COVERING_INDEX_SCAN 20 /* int */ | < < | 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 | #define SQLITE_CONFIG_PCACHE 14 /* no-op */ #define SQLITE_CONFIG_GETPCACHE 15 /* no-op */ #define SQLITE_CONFIG_LOG 16 /* xFunc, void* */ #define SQLITE_CONFIG_URI 17 /* int */ #define SQLITE_CONFIG_PCACHE2 18 /* sqlite3_pcache_methods2* */ #define SQLITE_CONFIG_GETPCACHE2 19 /* sqlite3_pcache_methods2* */ #define SQLITE_CONFIG_COVERING_INDEX_SCAN 20 /* int */ /* ** CAPI3REF: Database Connection Configuration Options ** ** These constants are the available integer configuration options that ** can be passed as the second argument to the [sqlite3_db_config()] interface. ** |
︙ | ︙ | |||
2525 2526 2527 2528 2529 2530 2531 | ** various times when an SQL statement is being run by [sqlite3_step()]. ** ^The sqlite3_trace() callback is invoked with a UTF-8 rendering of the ** SQL statement text as the statement first begins executing. ** ^(Additional sqlite3_trace() callbacks might occur ** as each triggered subprogram is entered. The callbacks for triggers ** contain a UTF-8 SQL comment that identifies the trigger.)^ ** | < < < | 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 | ** various times when an SQL statement is being run by [sqlite3_step()]. ** ^The sqlite3_trace() callback is invoked with a UTF-8 rendering of the ** SQL statement text as the statement first begins executing. ** ^(Additional sqlite3_trace() callbacks might occur ** as each triggered subprogram is entered. The callbacks for triggers ** contain a UTF-8 SQL comment that identifies the trigger.)^ ** ** ^The callback function registered by sqlite3_profile() is invoked ** as each SQL statement finishes. ^The profile callback contains ** the original statement text and an estimate of wall-clock time ** of how long that statement took to run. ^The profile callback ** time is in units of nanoseconds, however the current implementation ** is only capable of millisecond resolution so the six least significant ** digits in the time are meaningless. Future versions of SQLite |
︙ | ︙ | |||
2719 2720 2721 2722 2723 2724 2725 | ** ** <li> <b>cache</b>: ^The cache parameter may be set to either "shared" or ** "private". ^Setting it to "shared" is equivalent to setting the ** SQLITE_OPEN_SHAREDCACHE bit in the flags argument passed to ** sqlite3_open_v2(). ^Setting the cache parameter to "private" is ** equivalent to setting the SQLITE_OPEN_PRIVATECACHE bit. ** ^If sqlite3_open_v2() is used and the "cache" parameter is present in | | | 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 | ** ** <li> <b>cache</b>: ^The cache parameter may be set to either "shared" or ** "private". ^Setting it to "shared" is equivalent to setting the ** SQLITE_OPEN_SHAREDCACHE bit in the flags argument passed to ** sqlite3_open_v2(). ^Setting the cache parameter to "private" is ** equivalent to setting the SQLITE_OPEN_PRIVATECACHE bit. ** ^If sqlite3_open_v2() is used and the "cache" parameter is present in ** a URI filename, its value overrides any behaviour requested by setting ** SQLITE_OPEN_PRIVATECACHE or SQLITE_OPEN_SHAREDCACHE flag. ** </ul> ** ** ^Specifying an unknown parameter in the query component of a URI is not an ** error. Future versions of SQLite might understand additional query ** parameters. See "[query parameters with special meaning to SQLite]" for ** additional information. |
︙ | ︙ | |||
3066 3067 3068 3069 3070 3071 3072 | ** original SQL text. This causes the [sqlite3_step()] interface to ** behave differently in three ways: ** ** <ol> ** <li> ** ^If the database schema changes, instead of returning [SQLITE_SCHEMA] as it ** always used to do, [sqlite3_step()] will automatically recompile the SQL | | < | 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 | ** original SQL text. This causes the [sqlite3_step()] interface to ** behave differently in three ways: ** ** <ol> ** <li> ** ^If the database schema changes, instead of returning [SQLITE_SCHEMA] as it ** always used to do, [sqlite3_step()] will automatically recompile the SQL ** statement and try to run it again. ** </li> ** ** <li> ** ^When an error occurs, [sqlite3_step()] will return one of the detailed ** [error codes] or [extended error codes]. ^The legacy behavior was that ** [sqlite3_step()] would only return a generic [SQLITE_ERROR] result code ** and the application would have to make a second call to [sqlite3_reset()] |
︙ | ︙ | |||
3271 3272 3273 3274 3275 3276 3277 | ** ^The index for named parameters can be looked up using the ** [sqlite3_bind_parameter_index()] API if desired. ^The index ** for "?NNN" parameters is the value of NNN. ** ^The NNN value must be between 1 and the [sqlite3_limit()] ** parameter [SQLITE_LIMIT_VARIABLE_NUMBER] (default value: 999). ** ** ^The third argument is the value to bind to the parameter. | < < < | 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 | ** ^The index for named parameters can be looked up using the ** [sqlite3_bind_parameter_index()] API if desired. ^The index ** for "?NNN" parameters is the value of NNN. ** ^The NNN value must be between 1 and the [sqlite3_limit()] ** parameter [SQLITE_LIMIT_VARIABLE_NUMBER] (default value: 999). ** ** ^The third argument is the value to bind to the parameter. ** ** ^(In those routines that have a fourth argument, its value is the ** number of bytes in the parameter. To be clear: the value is the ** number of <u>bytes</u> in the value, not the number of characters.)^ ** ^If the fourth parameter to sqlite3_bind_text() or sqlite3_bind_text16() ** is negative, then the length of the string is ** the number of bytes up to the first zero terminator. |
︙ | ︙ | |||
4041 4042 4043 4044 4045 4046 4047 | */ #ifndef SQLITE_OMIT_DEPRECATED SQLITE_API SQLITE_DEPRECATED int sqlite3_aggregate_count(sqlite3_context*); SQLITE_API SQLITE_DEPRECATED int sqlite3_expired(sqlite3_stmt*); SQLITE_API SQLITE_DEPRECATED int sqlite3_transfer_bindings(sqlite3_stmt*, sqlite3_stmt*); SQLITE_API SQLITE_DEPRECATED int sqlite3_global_recover(void); SQLITE_API SQLITE_DEPRECATED void sqlite3_thread_cleanup(void); | | < | 3956 3957 3958 3959 3960 3961 3962 3963 3964 3965 3966 3967 3968 3969 3970 | */ #ifndef SQLITE_OMIT_DEPRECATED SQLITE_API SQLITE_DEPRECATED int sqlite3_aggregate_count(sqlite3_context*); SQLITE_API SQLITE_DEPRECATED int sqlite3_expired(sqlite3_stmt*); SQLITE_API SQLITE_DEPRECATED int sqlite3_transfer_bindings(sqlite3_stmt*, sqlite3_stmt*); SQLITE_API SQLITE_DEPRECATED int sqlite3_global_recover(void); SQLITE_API SQLITE_DEPRECATED void sqlite3_thread_cleanup(void); SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int),void*,sqlite3_int64); #endif /* ** CAPI3REF: Obtaining SQL Function Parameter Values ** ** The C-language implementation of SQL functions and aggregates uses ** this set of interface routines to access the parameter values on |
︙ | ︙ | |||
4122 4123 4124 4125 4126 4127 4128 | ** called once for each invocation of the xStep callback and then one ** last time when the xFinal callback is invoked. ^(When no rows match ** an aggregate query, the xStep() callback of the aggregate function ** implementation is never called and xFinal() is called exactly once. ** In those cases, sqlite3_aggregate_context() might be called for the ** first time from within xFinal().)^ ** | | | < | < < | 4036 4037 4038 4039 4040 4041 4042 4043 4044 4045 4046 4047 4048 4049 4050 4051 4052 4053 4054 4055 4056 4057 | ** called once for each invocation of the xStep callback and then one ** last time when the xFinal callback is invoked. ^(When no rows match ** an aggregate query, the xStep() callback of the aggregate function ** implementation is never called and xFinal() is called exactly once. ** In those cases, sqlite3_aggregate_context() might be called for the ** first time from within xFinal().)^ ** ** ^The sqlite3_aggregate_context(C,N) routine returns a NULL pointer if N is ** less than or equal to zero or if a memory allocate error occurs. ** ** ^(The amount of space allocated by sqlite3_aggregate_context(C,N) is ** determined by the N parameter on first successful call. Changing the ** value of N in subsequent call to sqlite3_aggregate_context() within ** the same aggregate function instance will not resize the memory ** allocation.)^ ** ** ^SQLite automatically frees the memory allocated by ** sqlite3_aggregate_context() when the aggregate query concludes. ** ** The first parameter must be a copy of the ** [sqlite3_context | SQL function context] that is the first parameter ** to the xStep or xFinal callback routine that implements the aggregate |
︙ | ︙ | |||
4230 4231 4232 4233 4234 4235 4236 | ** argument is SQLITE_STATIC, it means that the content pointer is constant ** and will never change. It does not need to be destroyed. ^The ** SQLITE_TRANSIENT value means that the content will likely change in ** the near future and that SQLite should make its own private copy of ** the content before returning. ** ** The typedef is necessary to work around problems in certain | | | 4141 4142 4143 4144 4145 4146 4147 4148 4149 4150 4151 4152 4153 4154 4155 | ** argument is SQLITE_STATIC, it means that the content pointer is constant ** and will never change. It does not need to be destroyed. ^The ** SQLITE_TRANSIENT value means that the content will likely change in ** the near future and that SQLite should make its own private copy of ** the content before returning. ** ** The typedef is necessary to work around problems in certain ** C++ compilers. See ticket #2191. */ typedef void (*sqlite3_destructor_type)(void*); #define SQLITE_STATIC ((sqlite3_destructor_type)0) #define SQLITE_TRANSIENT ((sqlite3_destructor_type)-1) /* ** CAPI3REF: Setting The Result Of An SQL Function |
︙ | ︙ | |||
5029 5030 5031 5032 5033 5034 5035 | /* ** CAPI3REF: Load An Extension ** ** ^This interface loads an SQLite extension library from the named file. ** ** ^The sqlite3_load_extension() interface attempts to load an | | < < < < < | | < < < < | 4940 4941 4942 4943 4944 4945 4946 4947 4948 4949 4950 4951 4952 4953 4954 4955 4956 4957 4958 | /* ** CAPI3REF: Load An Extension ** ** ^This interface loads an SQLite extension library from the named file. ** ** ^The sqlite3_load_extension() interface attempts to load an ** SQLite extension library contained in the file zFile. ** ** ^The entry point is zProc. ** ^zProc may be 0, in which case the name of the entry point ** defaults to "sqlite3_extension_init". ** ^The sqlite3_load_extension() interface returns ** [SQLITE_OK] on success and [SQLITE_ERROR] if something goes wrong. ** ^If an error occurs and pzErrMsg is not 0, then the ** [sqlite3_load_extension()] interface shall attempt to ** fill *pzErrMsg with error message text stored in memory ** obtained from [sqlite3_malloc()]. The calling function ** should free this memory by calling [sqlite3_free()]. |
︙ | ︙ | |||
5068 5069 5070 5071 5072 5073 5074 | char **pzErrMsg /* Put error message here if not 0 */ ); /* ** CAPI3REF: Enable Or Disable Extension Loading ** ** ^So as not to open security holes in older applications that are | | | | | | 4970 4971 4972 4973 4974 4975 4976 4977 4978 4979 4980 4981 4982 4983 4984 4985 4986 4987 4988 4989 4990 4991 4992 4993 4994 4995 4996 4997 4998 4999 5000 | char **pzErrMsg /* Put error message here if not 0 */ ); /* ** CAPI3REF: Enable Or Disable Extension Loading ** ** ^So as not to open security holes in older applications that are ** unprepared to deal with extension loading, and as a means of disabling ** extension loading while evaluating user-entered SQL, the following API ** is provided to turn the [sqlite3_load_extension()] mechanism on and off. ** ** ^Extension loading is off by default. See ticket #1863. ** ^Call the sqlite3_enable_load_extension() routine with onoff==1 ** to turn extension loading on and call it with onoff==0 to turn ** it back off again. */ SQLITE_API int sqlite3_enable_load_extension(sqlite3 *db, int onoff); /* ** CAPI3REF: Automatically Load Statically Linked Extensions ** ** ^This interface causes the xEntryPoint() function to be invoked for ** each new [database connection] that is created. The idea here is that ** xEntryPoint() is the entry point for a statically linked SQLite extension ** that is to be automatically loaded into all new database connections. ** ** ^(Even though the function prototype shows that xEntryPoint() takes ** no arguments and returns void, SQLite invokes xEntryPoint() with three ** arguments and expects and integer result as if the signature of the ** entry point where as follows: ** |
︙ | ︙ | |||
6435 6436 6437 6438 6439 6440 6441 | ** If the requested page is already in the page cache, then the page cache ** implementation must return a pointer to the page buffer with its content ** intact. If the requested page is not already in the cache, then the ** cache implementation should use the value of the createFlag ** parameter to help it determined what action to take: ** ** <table border=1 width=85% align=center> | | | 6337 6338 6339 6340 6341 6342 6343 6344 6345 6346 6347 6348 6349 6350 6351 | ** If the requested page is already in the page cache, then the page cache ** implementation must return a pointer to the page buffer with its content ** intact. If the requested page is not already in the cache, then the ** cache implementation should use the value of the createFlag ** parameter to help it determined what action to take: ** ** <table border=1 width=85% align=center> ** <tr><th> createFlag <th> Behaviour when page is not already in cache ** <tr><td> 0 <td> Do not allocate a new page. Return NULL. ** <tr><td> 1 <td> Allocate a new page if it easy and convenient to do so. ** Otherwise return NULL. ** <tr><td> 2 <td> Make every effort to allocate a new page. Only return ** NULL if allocating a new page is effectively impossible. ** </table> ** |
︙ | ︙ | |||
6864 6865 6866 6867 6868 6869 6870 | ** and extensions to compare the contents of two buffers containing UTF-8 ** strings in a case-independent fashion, using the same definition of "case ** independence" that SQLite uses internally when comparing identifiers. */ SQLITE_API int sqlite3_stricmp(const char *, const char *); SQLITE_API int sqlite3_strnicmp(const char *, const char *, int); | < < < < < < < < < < < < < < < | | 6766 6767 6768 6769 6770 6771 6772 6773 6774 6775 6776 6777 6778 6779 6780 6781 6782 6783 | ** and extensions to compare the contents of two buffers containing UTF-8 ** strings in a case-independent fashion, using the same definition of "case ** independence" that SQLite uses internally when comparing identifiers. */ SQLITE_API int sqlite3_stricmp(const char *, const char *); SQLITE_API int sqlite3_strnicmp(const char *, const char *, int); /* ** CAPI3REF: Error Logging Interface ** ** ^The [sqlite3_log()] interface writes a message into the error log ** established by the [SQLITE_CONFIG_LOG] option to [sqlite3_config()]. ** ^If logging is enabled, the zFormat string and subsequent arguments are ** used with [sqlite3_snprintf()] to generate the final output string. ** ** The sqlite3_log() interface is intended for use by extensions such as ** virtual tables, collating functions, and SQL functions. While there is ** nothing to prevent an application from calling sqlite3_log(), doing so |
︙ | ︙ |
Changes to SQLite.Interop/src/core/sqlite3ext.h.
︙ | ︙ | |||
232 233 234 235 236 237 238 | 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*); | < < < < < < < < < < < < < < | 232 233 234 235 236 237 238 239 240 241 242 243 244 245 | int (*unlock_notify)(sqlite3*,void(*)(void**,int),void*); int (*wal_autocheckpoint)(sqlite3*,int); int (*wal_checkpoint)(sqlite3*,const char*); void *(*wal_hook)(sqlite3*,int(*)(void*,sqlite3*,const char*,int),void*); int (*blob_reopen)(sqlite3_blob*,sqlite3_int64); int (*vtab_config)(sqlite3*,int op,...); int (*vtab_on_conflict)(sqlite3*); }; /* ** The following macros redefine the API routines so that they are ** redirected throught the global sqlite3_api structure. ** ** This header file is also used by the loadext.c source file |
︙ | ︙ | |||
449 450 451 452 453 454 455 | #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 | < < < < < < < < < < < < < < < < < | | < < < < < < | 435 436 437 438 439 440 441 442 443 444 445 446 447 | #define sqlite3_unlock_notify sqlite3_api->unlock_notify #define sqlite3_wal_autocheckpoint sqlite3_api->wal_autocheckpoint #define sqlite3_wal_checkpoint sqlite3_api->wal_checkpoint #define sqlite3_wal_hook sqlite3_api->wal_hook #define sqlite3_blob_reopen sqlite3_api->blob_reopen #define sqlite3_vtab_config sqlite3_api->vtab_config #define sqlite3_vtab_on_conflict sqlite3_api->vtab_on_conflict #endif /* SQLITE_CORE */ #define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api = 0; #define SQLITE_EXTENSION_INIT2(v) sqlite3_api = v; #endif /* _SQLITE3EXT_H_ */ |
Changes to SQLite.Interop/src/win/AssemblyInfo.cpp.
︙ | ︙ | |||
8 9 10 11 12 13 14 | using namespace System::Reflection; using namespace System::Resources; using namespace System::Runtime::InteropServices; #include "interop.h" [assembly:AssemblyTitleAttribute("SQLite.Interop")]; | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | using namespace System::Reflection; using namespace System::Resources; using namespace System::Runtime::InteropServices; #include "interop.h" [assembly:AssemblyTitleAttribute("SQLite.Interop")]; [assembly:AssemblyCompanyAttribute("Robert Simpson, et al.")]; [assembly:AssemblyDescriptionAttribute("System.Data.SQLite Interop Assembly")]; [assembly:AssemblyProductAttribute("System.Data.SQLite")]; [assembly:AssemblyCopyrightAttribute("Public Domain")]; [assembly:AssemblyVersionAttribute(INTEROP_VERSION)]; [assembly:AssemblyFileVersionAttribute(INTEROP_VERSION)]; #if DEBUG |
︙ | ︙ |
Changes to SQLite.Interop/src/win/crypt.c.
︙ | ︙ | |||
39 40 41 42 43 44 45 | } /* Create a cryptographic context. Use the enhanced provider because it is available on ** most platforms */ static BOOL InitializeProvider() { | < < < | < < < < < < < | 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | } /* Create a cryptographic context. Use the enhanced provider because it is available on ** most platforms */ static BOOL InitializeProvider() { if (g_hProvider) return TRUE; if (!CryptAcquireContext(&g_hProvider, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { return FALSE; } return TRUE; } /* Create or update a cryptographic context for a pager. ** This function will automatically determine if the encryption algorithm requires ** extra padding, and if it does, will create a temp buffer big enough to provide ** space to hold it. |
︙ | ︙ | |||
234 235 236 237 238 239 240 | if (!pKey || !nKeyLen) return 0; if (!InitializeProvider()) { return MAXDWORD; } | < < < < | | | | | | | | < < < < | 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 | if (!pKey || !nKeyLen) return 0; if (!InitializeProvider()) { return MAXDWORD; } if (CryptCreateHash(g_hProvider, CALG_SHA1, 0, 0, &hHash)) { if (CryptHashData(hHash, (LPBYTE)pKey, nKeyLen, 0)) { CryptDeriveKey(g_hProvider, CALG_RC4, hHash, 0, &hKey); } CryptDestroyHash(hHash); } return hKey; } /* Called by sqlite and sqlite3_key_interop to attach a key to a database. */ int sqlite3CodecAttach(sqlite3 *db, int nDb, const void *pKey, int nKeyLen) { int rc = SQLITE_ERROR; |
︙ | ︙ |
Changes to SQLite.Interop/src/win/interop.c.
︙ | ︙ | |||
37 38 39 40 41 42 43 | #else #define sqlite3InteropBreak(a) #endif typedef void (*SQLITEUSERFUNC)(sqlite3_context *, int, sqlite3_value **); typedef void (*SQLITEFUNCFINAL)(sqlite3_context *); | | | 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | #else #define sqlite3InteropBreak(a) #endif typedef void (*SQLITEUSERFUNC)(sqlite3_context *, int, sqlite3_value **); typedef void (*SQLITEFUNCFINAL)(sqlite3_context *); #if defined(INTEROP_DEBUG) SQLITE_PRIVATE void sqlite3InteropDebug(const char *zFormat, ...){ va_list ap; /* Vararg list */ StrAccum acc; /* String accumulator */ char zMsg[SQLITE_PRINT_BUF_SIZE*3]; /* Complete log message */ va_start(ap, zFormat); sqlite3StrAccumInit(&acc, zMsg, sizeof(zMsg), 0); acc.useMalloc = 0; |
︙ | ︙ | |||
65 66 67 68 69 70 71 | } #else fprintf(stderr, "%s", sqlite3StrAccumFinish(&acc)); #endif } #endif | < < < < < < < < | | 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 | } #else fprintf(stderr, "%s", sqlite3StrAccumFinish(&acc)); #endif } #endif #if SQLITE_VERSION_NUMBER < 3007014 SQLITE_PRIVATE void * sqlite3DbMallocZero_interop(sqlite3 *db, int n) { void *p; if (db) { sqlite3_mutex_enter(db->mutex); } p = sqlite3DbMallocZero(db,n); |
︙ | ︙ | |||
118 119 120 121 122 123 124 | 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; | | | 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 | that memory was deallocated. BAD. So, what we need to do is make a copy of each statement, and call finalize() on the copy -- so that the original statement's memory is preserved, and marked as BAD, but we can still manage to finalize everything and forcibly close the database. Later when the GC gets around to calling finalize_interop() on the "bad" statement, we detect that and finish deallocating the pointer. */ SQLITE_API int WINAPI sqlite3_close_interop(sqlite3 *db) { int ret; #if SQLITE_VERSION_NUMBER >= 3007014 #if defined(INTEROP_DEBUG) && (INTEROP_DEBUG & INTEROP_DEBUG_CLOSE) sqlite3InteropDebug("sqlite3_close_interop(): calling sqlite3_close_v2(%p)...\n", db); #endif ret = sqlite3_close_v2(db); |
︙ | ︙ | |||
187 188 189 190 191 192 193 | sqlite3_mutex_leave(db->mutex); ret = sqlite3_close(db); } return ret; #endif } | < < < < < < < < < < < < < < < < < < | | 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 | sqlite3_mutex_leave(db->mutex); ret = sqlite3_close(db); } return ret; #endif } SQLITE_API int WINAPI sqlite3_open_interop(const char*filename, int flags, sqlite3 **ppdb) { int ret; #if defined(INTEROP_DEBUG) && (INTEROP_DEBUG & INTEROP_DEBUG_OPEN) sqlite3InteropDebug("sqlite3_open_interop(): calling sqlite3_open_v2(\"%s\", %d, %p)...\n", filename, flags, ppdb); #endif |
︙ | ︙ | |||
265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 | #if defined(INTEROP_DEBUG) && (INTEROP_DEBUG & INTEROP_DEBUG_CHANGES) sqlite3InteropDebug("sqlite3_changes_interop(): calling sqlite3_changes(%p)...\n", db); #endif #ifndef NDEBUG if (!db) sqlite3InteropBreak("null database handle for sqlite3_changes()"); #endif result = sqlite3_changes(db); #if defined(INTEROP_DEBUG) && (INTEROP_DEBUG & INTEROP_DEBUG_CHANGES) sqlite3InteropDebug("sqlite3_changes_interop(): sqlite3_changes(%p) returned %d.\n", db, result); #endif return result; } SQLITE_API int WINAPI sqlite3_prepare_interop(sqlite3 *db, const char *sql, int nbytes, sqlite3_stmt **ppstmt, const char **pztail, int *plen) { int n; #if defined(INTEROP_DEBUG) && (INTEROP_DEBUG & INTEROP_DEBUG_PREPARE) sqlite3InteropDebug("sqlite3_prepare_interop(): calling sqlite3_prepare(%p, \"%s\", %d, %p)...\n", db, sql, nbytes, ppstmt); #endif | > > > < < < < < < < < | 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 | #if defined(INTEROP_DEBUG) && (INTEROP_DEBUG & INTEROP_DEBUG_CHANGES) sqlite3InteropDebug("sqlite3_changes_interop(): calling sqlite3_changes(%p)...\n", db); #endif #ifndef NDEBUG if (!db) sqlite3InteropBreak("null database handle for sqlite3_changes()"); if (!sqlite3SafetyCheckOk(db)) sqlite3InteropBreak("bad database handle for sqlite3_changes()"); #endif result = sqlite3_changes(db); #if defined(INTEROP_DEBUG) && (INTEROP_DEBUG & INTEROP_DEBUG_CHANGES) sqlite3InteropDebug("sqlite3_changes_interop(): sqlite3_changes(%p) returned %d.\n", db, result); #endif return result; } SQLITE_API int WINAPI sqlite3_prepare_interop(sqlite3 *db, const char *sql, int nbytes, sqlite3_stmt **ppstmt, const char **pztail, int *plen) { int n; #if defined(INTEROP_DEBUG) && (INTEROP_DEBUG & INTEROP_DEBUG_PREPARE) sqlite3InteropDebug("sqlite3_prepare_interop(): calling sqlite3_prepare(%p, \"%s\", %d, %p)...\n", db, sql, nbytes, ppstmt); #endif n = sqlite3_prepare(db, sql, nbytes, ppstmt, pztail); #if defined(INTEROP_DEBUG) && (INTEROP_DEBUG & INTEROP_DEBUG_PREPARE) sqlite3InteropDebug("sqlite3_prepare_interop(): sqlite3_prepare(%p, \"%s\", %d, %p) returned %d.\n", db, sql, nbytes, ppstmt, n); #endif *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; #if defined(INTEROP_DEBUG) && (INTEROP_DEBUG & INTEROP_DEBUG_PREPARE16) sqlite3InteropDebug("sqlite3_prepare_interop(): calling sqlite3_prepare16(%p, \"%s\", %d, %p)...\n", db, sql, nchars, ppstmt); #endif n = sqlite3_prepare16(db, sql, nchars * sizeof(wchar_t), ppstmt, pztail); #if defined(INTEROP_DEBUG) && (INTEROP_DEBUG & INTEROP_DEBUG_PREPARE16) sqlite3InteropDebug("sqlite3_prepare_interop(): sqlite3_prepare16(%p, \"%s\", %d, %p) returned %d.\n", db, sql, nchars, ppstmt, n); #endif *plen = (*pztail != 0) ? wcslen((wchar_t *)*pztail) * sizeof(wchar_t) : 0; |
︙ | ︙ | |||
395 396 397 398 399 400 401 | { *nBytes = sqlite3_memory_highwater(resetFlag); } 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); | | | | | | 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 | { *nBytes = sqlite3_memory_highwater(resetFlag); } 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) { int ret; #if SQLITE_VERSION_NUMBER >= 3007014 #if defined(INTEROP_DEBUG) && (INTEROP_DEBUG & INTEROP_DEBUG_FINALIZE) Vdbe *p = (Vdbe *)stmt; sqlite3 *db = p->db; sqlite3InteropDebug("sqlite3_finalize_interop(): calling sqlite3_finalize(%p, %p)...\n", db, stmt); #endif ret = sqlite3_finalize(stmt); #if defined(INTEROP_DEBUG) && (INTEROP_DEBUG & INTEROP_DEBUG_FINALIZE) sqlite3InteropDebug("sqlite3_finalize_interop(): sqlite3_finalize(%p, %p) returned %d.\n", db, stmt, ret); #endif return ret; #else Vdbe *p; int ret = SQLITE_OK; p = (Vdbe *)stmt; if (p) { sqlite3 *db = p->db; if (db != NULL) |
︙ | ︙ | |||
475 476 477 478 479 480 481 | return ret; } SQLITE_API int WINAPI sqlite3_reset_interop(sqlite3_stmt *stmt) { int ret; | | | 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 | return ret; } SQLITE_API int WINAPI sqlite3_reset_interop(sqlite3_stmt *stmt) { int ret; #if SQLITE_VERSION_NUMBER >= 3007014 #if defined(INTEROP_DEBUG) && (INTEROP_DEBUG & INTEROP_DEBUG_RESET) sqlite3InteropDebug("sqlite3_reset_interop(): calling sqlite3_reset(%p)...\n", stmt); #endif ret = sqlite3_reset(stmt); |
︙ | ︙ | |||
531 532 533 534 535 536 537 | { *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); | | | | 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 | { *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); } |
︙ | ︙ | |||
764 765 766 767 768 769 770 | #include "../core/sqlite3ext.h" SQLITE_EXTENSION_INIT1 /* ** The interopTest() SQL function returns its first argument or raises an ** error if there are not enough arguments. */ | | < < < < < < < < < < < < < < < < < < < < < < < < | < < < | < < | 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 | #include "../core/sqlite3ext.h" SQLITE_EXTENSION_INIT1 /* ** The interopTest() SQL function returns its first argument or raises an ** error if there are not enough arguments. */ static void interopTestFunc( sqlite3_context *context, int argc, sqlite3_value **argv ){ const unsigned char *z; if( argc!=1 ){ sqlite3_result_error(context, "need exactly one argument", -1); return; } z = sqlite3_value_text(argv[0]); if( z ){ sqlite3_result_text(context, (char*)z, -1, SQLITE_STATIC); }else{ sqlite3_result_null(context); } } /* SQLite invokes this routine once when it loads the extension. ** Create new functions, collating sequences, and virtual table ** modules here. This is usually the only exported symbol in ** the shared library. */ SQLITE_API int interop_test_extension_init( sqlite3 *db, char **pzErrMsg, const sqlite3_api_routines *pApi ){ SQLITE_EXTENSION_INIT2(pApi) return sqlite3_create_function(db, "interopTest", -1, SQLITE_ANY, 0, interopTestFunc, 0, 0); } #endif |
Changes to SQLite.Interop/src/win/interop.h.
1 2 3 4 5 6 7 8 | /* * interop.h - * * Written by Joe Mistachkin. * Released to the public domain, use at your own risk! */ #ifndef INTEROP_VERSION | | | 1 2 3 4 5 6 7 8 9 10 | /* * interop.h - * * Written by Joe Mistachkin. * Released to the public domain, use at your own risk! */ #ifndef INTEROP_VERSION #define INTEROP_VERSION "1.0.83.0" #endif |
Changes to SQLite.MSIL.nuspec.
1 2 3 4 5 6 7 8 9 10 11 12 | <?xml version="1.0" encoding="utf-8"?> <!-- * * SQLite.MSIL.nuspec - * * Written by Joe Mistachkin. * Released to the public domain, use at your own risk! * --> <package> <metadata> <id>System.Data.SQLite.MSIL</id> | | < < | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | <?xml version="1.0" encoding="utf-8"?> <!-- * * SQLite.MSIL.nuspec - * * Written by Joe Mistachkin. * Released to the public domain, use at your own risk! * --> <package> <metadata> <id>System.Data.SQLite.MSIL</id> <version>1.0.83.0</version> <authors>SQLite Development Team</authors> <description>An ADO.NET provider for SQLite (managed-only).</description> <language>en-US</language> <projectUrl>http://system.data.sqlite.org/</projectUrl> <iconUrl>http://system.data.sqlite.org/images/sqlite32.png</iconUrl> <licenseUrl>http://www.sqlite.org/copyright.html</licenseUrl> <tags>sqlite database ado.net provider interop</tags> <copyright>Public Domain</copyright> </metadata> <files> <file src="bin\2008\Release\bin\System.Data.SQLite.dll" target="lib\net20" /> <file src="bin\2010\Release\bin\System.Data.SQLite.dll" target="lib\net40" /> <file src="bin\2008\Release\bin\System.Data.SQLite.Linq.dll" target="lib\net20" /> <file src="bin\2010\Release\bin\System.Data.SQLite.Linq.dll" target="lib\net40" /> </files> </package> |
Changes to SQLite.NET.2005.MSBuild.sln.
1 2 3 4 5 6 7 8 | Microsoft Visual Studio Solution File, Format Version 9.00 # Visual Studio 2005 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{39A3B743-1EBD-4CC0-8E37-ACE3DD38B1C0}" ProjectSection(SolutionItems) = preProject exclude_bin.txt = exclude_bin.txt exclude_src.txt = exclude_src.txt install.ps1 = install.ps1 readme.htm = readme.htm | < < < | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | Microsoft Visual Studio Solution File, Format Version 9.00 # Visual Studio 2005 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{39A3B743-1EBD-4CC0-8E37-ACE3DD38B1C0}" ProjectSection(SolutionItems) = preProject exclude_bin.txt = exclude_bin.txt exclude_src.txt = exclude_src.txt install.ps1 = install.ps1 readme.htm = readme.htm SQLite.MSIL.nuspec = SQLite.MSIL.nuspec SQLite.NET.Settings.targets = SQLite.NET.Settings.targets SQLite.nuspec = SQLite.nuspec SQLite.x64.nuspec = SQLite.x64.nuspec SQLite.x86.nuspec = SQLite.x86.nuspec System.Data.SQLite\System.Data.SQLite.CF.snk = System.Data.SQLite\System.Data.SQLite.CF.snk System.Data.SQLite\System.Data.SQLite.Files.targets = System.Data.SQLite\System.Data.SQLite.Files.targets System.Data.SQLite\System.Data.SQLite.Properties.targets = System.Data.SQLite\System.Data.SQLite.Properties.targets System.Data.SQLite\System.Data.SQLite.References.targets = System.Data.SQLite\System.Data.SQLite.References.targets |
︙ | ︙ |
Changes to SQLite.NET.2005.sln.
1 2 3 4 5 6 7 8 | Microsoft Visual Studio Solution File, Format Version 9.00 # Visual Studio 2005 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{39A3B743-1EBD-4CC0-8E37-ACE3DD38B1C0}" ProjectSection(SolutionItems) = preProject exclude_bin.txt = exclude_bin.txt exclude_src.txt = exclude_src.txt install.ps1 = install.ps1 readme.htm = readme.htm | < < < | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | Microsoft Visual Studio Solution File, Format Version 9.00 # Visual Studio 2005 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{39A3B743-1EBD-4CC0-8E37-ACE3DD38B1C0}" ProjectSection(SolutionItems) = preProject exclude_bin.txt = exclude_bin.txt exclude_src.txt = exclude_src.txt install.ps1 = install.ps1 readme.htm = readme.htm SQLite.MSIL.nuspec = SQLite.MSIL.nuspec SQLite.NET.Settings.targets = SQLite.NET.Settings.targets SQLite.nuspec = SQLite.nuspec SQLite.x64.nuspec = SQLite.x64.nuspec SQLite.x86.nuspec = SQLite.x86.nuspec System.Data.SQLite\System.Data.SQLite.CF.snk = System.Data.SQLite\System.Data.SQLite.CF.snk System.Data.SQLite\System.Data.SQLite.Files.targets = System.Data.SQLite\System.Data.SQLite.Files.targets System.Data.SQLite\System.Data.SQLite.Properties.targets = System.Data.SQLite\System.Data.SQLite.Properties.targets System.Data.SQLite\System.Data.SQLite.References.targets = System.Data.SQLite\System.Data.SQLite.References.targets |
︙ | ︙ |
Changes to SQLite.NET.2008.MSBuild.sln.
1 2 3 4 5 6 7 8 | Microsoft Visual Studio Solution File, Format Version 10.00 # Visual Studio 2008 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{39A3B743-1EBD-4CC0-8E37-ACE3DD38B1C0}" ProjectSection(SolutionItems) = preProject exclude_bin.txt = exclude_bin.txt exclude_src.txt = exclude_src.txt install.ps1 = install.ps1 readme.htm = readme.htm | < < < | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | Microsoft Visual Studio Solution File, Format Version 10.00 # Visual Studio 2008 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{39A3B743-1EBD-4CC0-8E37-ACE3DD38B1C0}" ProjectSection(SolutionItems) = preProject exclude_bin.txt = exclude_bin.txt exclude_src.txt = exclude_src.txt install.ps1 = install.ps1 readme.htm = readme.htm SQLite.MSIL.nuspec = SQLite.MSIL.nuspec SQLite.NET.Settings.targets = SQLite.NET.Settings.targets SQLite.nuspec = SQLite.nuspec SQLite.x64.nuspec = SQLite.x64.nuspec SQLite.x86.nuspec = SQLite.x86.nuspec System.Data.SQLite\System.Data.SQLite.CF.snk = System.Data.SQLite\System.Data.SQLite.CF.snk System.Data.SQLite\System.Data.SQLite.Files.targets = System.Data.SQLite\System.Data.SQLite.Files.targets System.Data.SQLite\System.Data.SQLite.Properties.targets = System.Data.SQLite\System.Data.SQLite.Properties.targets System.Data.SQLite\System.Data.SQLite.References.targets = System.Data.SQLite\System.Data.SQLite.References.targets |
︙ | ︙ |
Changes to SQLite.NET.2008.sln.
1 2 3 4 5 6 7 8 | Microsoft Visual Studio Solution File, Format Version 10.00 # Visual Studio 2008 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{39A3B743-1EBD-4CC0-8E37-ACE3DD38B1C0}" ProjectSection(SolutionItems) = preProject exclude_bin.txt = exclude_bin.txt exclude_src.txt = exclude_src.txt install.ps1 = install.ps1 readme.htm = readme.htm | < < < | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | Microsoft Visual Studio Solution File, Format Version 10.00 # Visual Studio 2008 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{39A3B743-1EBD-4CC0-8E37-ACE3DD38B1C0}" ProjectSection(SolutionItems) = preProject exclude_bin.txt = exclude_bin.txt exclude_src.txt = exclude_src.txt install.ps1 = install.ps1 readme.htm = readme.htm SQLite.MSIL.nuspec = SQLite.MSIL.nuspec SQLite.NET.Settings.targets = SQLite.NET.Settings.targets SQLite.nuspec = SQLite.nuspec SQLite.x64.nuspec = SQLite.x64.nuspec SQLite.x86.nuspec = SQLite.x86.nuspec System.Data.SQLite\System.Data.SQLite.CF.snk = System.Data.SQLite\System.Data.SQLite.CF.snk System.Data.SQLite\System.Data.SQLite.Files.targets = System.Data.SQLite\System.Data.SQLite.Files.targets System.Data.SQLite\System.Data.SQLite.Properties.targets = System.Data.SQLite\System.Data.SQLite.Properties.targets System.Data.SQLite\System.Data.SQLite.References.targets = System.Data.SQLite\System.Data.SQLite.References.targets |
︙ | ︙ |
Changes to SQLite.NET.2010.MSBuild.sln.
1 2 3 4 5 6 7 8 | Microsoft Visual Studio Solution File, Format Version 11.00 # Visual Studio 2010 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{39A3B743-1EBD-4CC0-8E37-ACE3DD38B1C0}" ProjectSection(SolutionItems) = preProject exclude_bin.txt = exclude_bin.txt exclude_src.txt = exclude_src.txt install.ps1 = install.ps1 readme.htm = readme.htm | < < < | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | Microsoft Visual Studio Solution File, Format Version 11.00 # Visual Studio 2010 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{39A3B743-1EBD-4CC0-8E37-ACE3DD38B1C0}" ProjectSection(SolutionItems) = preProject exclude_bin.txt = exclude_bin.txt exclude_src.txt = exclude_src.txt install.ps1 = install.ps1 readme.htm = readme.htm SQLite.MSIL.nuspec = SQLite.MSIL.nuspec SQLite.NET.Settings.targets = SQLite.NET.Settings.targets SQLite.nuspec = SQLite.nuspec SQLite.x64.nuspec = SQLite.x64.nuspec SQLite.x86.nuspec = SQLite.x86.nuspec System.Data.SQLite\System.Data.SQLite.CF.snk = System.Data.SQLite\System.Data.SQLite.CF.snk System.Data.SQLite\System.Data.SQLite.Files.targets = System.Data.SQLite\System.Data.SQLite.Files.targets System.Data.SQLite\System.Data.SQLite.Properties.targets = System.Data.SQLite\System.Data.SQLite.Properties.targets System.Data.SQLite\System.Data.SQLite.References.targets = System.Data.SQLite\System.Data.SQLite.References.targets |
︙ | ︙ |
Changes to SQLite.NET.2010.sln.
1 2 3 4 5 6 7 8 | Microsoft Visual Studio Solution File, Format Version 11.00 # Visual Studio 2010 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{39A3B743-1EBD-4CC0-8E37-ACE3DD38B1C0}" ProjectSection(SolutionItems) = preProject exclude_bin.txt = exclude_bin.txt exclude_src.txt = exclude_src.txt install.ps1 = install.ps1 readme.htm = readme.htm | < < < | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | Microsoft Visual Studio Solution File, Format Version 11.00 # Visual Studio 2010 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{39A3B743-1EBD-4CC0-8E37-ACE3DD38B1C0}" ProjectSection(SolutionItems) = preProject exclude_bin.txt = exclude_bin.txt exclude_src.txt = exclude_src.txt install.ps1 = install.ps1 readme.htm = readme.htm SQLite.MSIL.nuspec = SQLite.MSIL.nuspec SQLite.NET.Settings.targets = SQLite.NET.Settings.targets SQLite.nuspec = SQLite.nuspec SQLite.x64.nuspec = SQLite.x64.nuspec SQLite.x86.nuspec = SQLite.x86.nuspec System.Data.SQLite\System.Data.SQLite.CF.snk = System.Data.SQLite\System.Data.SQLite.CF.snk System.Data.SQLite\System.Data.SQLite.Files.targets = System.Data.SQLite\System.Data.SQLite.Files.targets System.Data.SQLite\System.Data.SQLite.Properties.targets = System.Data.SQLite\System.Data.SQLite.Properties.targets System.Data.SQLite\System.Data.SQLite.References.targets = System.Data.SQLite\System.Data.SQLite.References.targets |
︙ | ︙ |
Changes to SQLite.NET.2012.MSBuild.sln.
1 2 3 4 5 6 7 8 | Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 2012 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{39A3B743-1EBD-4CC0-8E37-ACE3DD38B1C0}" ProjectSection(SolutionItems) = preProject exclude_bin.txt = exclude_bin.txt exclude_src.txt = exclude_src.txt install.ps1 = install.ps1 readme.htm = readme.htm | < < < | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 2012 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{39A3B743-1EBD-4CC0-8E37-ACE3DD38B1C0}" ProjectSection(SolutionItems) = preProject exclude_bin.txt = exclude_bin.txt exclude_src.txt = exclude_src.txt install.ps1 = install.ps1 readme.htm = readme.htm SQLite.MSIL.nuspec = SQLite.MSIL.nuspec SQLite.NET.Settings.targets = SQLite.NET.Settings.targets SQLite.nuspec = SQLite.nuspec SQLite.x64.nuspec = SQLite.x64.nuspec SQLite.x86.nuspec = SQLite.x86.nuspec System.Data.SQLite\System.Data.SQLite.CF.snk = System.Data.SQLite\System.Data.SQLite.CF.snk System.Data.SQLite\System.Data.SQLite.Files.targets = System.Data.SQLite\System.Data.SQLite.Files.targets System.Data.SQLite\System.Data.SQLite.Properties.targets = System.Data.SQLite\System.Data.SQLite.Properties.targets System.Data.SQLite\System.Data.SQLite.References.targets = System.Data.SQLite\System.Data.SQLite.References.targets |
︙ | ︙ |
Changes to SQLite.NET.2012.sln.
1 2 3 4 5 6 7 8 | Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 2012 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{39A3B743-1EBD-4CC0-8E37-ACE3DD38B1C0}" ProjectSection(SolutionItems) = preProject exclude_bin.txt = exclude_bin.txt exclude_src.txt = exclude_src.txt install.ps1 = install.ps1 readme.htm = readme.htm | < < < | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 2012 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{39A3B743-1EBD-4CC0-8E37-ACE3DD38B1C0}" ProjectSection(SolutionItems) = preProject exclude_bin.txt = exclude_bin.txt exclude_src.txt = exclude_src.txt install.ps1 = install.ps1 readme.htm = readme.htm SQLite.MSIL.nuspec = SQLite.MSIL.nuspec SQLite.NET.Settings.targets = SQLite.NET.Settings.targets SQLite.nuspec = SQLite.nuspec SQLite.x64.nuspec = SQLite.x64.nuspec SQLite.x86.nuspec = SQLite.x86.nuspec System.Data.SQLite\System.Data.SQLite.CF.snk = System.Data.SQLite\System.Data.SQLite.CF.snk System.Data.SQLite\System.Data.SQLite.Files.targets = System.Data.SQLite\System.Data.SQLite.Files.targets System.Data.SQLite\System.Data.SQLite.Properties.targets = System.Data.SQLite\System.Data.SQLite.Properties.targets System.Data.SQLite\System.Data.SQLite.References.targets = System.Data.SQLite\System.Data.SQLite.References.targets |
︙ | ︙ |
Changes to SQLite.NET.Settings.targets.
︙ | ︙ | |||
16 17 18 19 20 21 22 | <!-- NOTE: If the per-user settings file exists, import it now. The contained settings, if any, will override the default ones provided below. --> <Import Project="$(SQLiteNetDir)\SQLite.NET.Settings.targets.user" Condition="Exists('$(SQLiteNetDir)\SQLite.NET.Settings.targets.user')" /> | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | <!-- NOTE: If the per-user settings file exists, import it now. The contained settings, if any, will override the default ones provided below. --> <Import Project="$(SQLiteNetDir)\SQLite.NET.Settings.targets.user" Condition="Exists('$(SQLiteNetDir)\SQLite.NET.Settings.targets.user')" /> <!-- ****************************************************************************** ** [Fairly] Generic Properties ** ****************************************************************************** --> <PropertyGroup> |
︙ | ︙ | |||
125 126 127 128 129 130 131 | NOTE: Only use functionality available in the .NET Framework 4.5? By default, this is disabled. This must be enabled to successfully build the project using Visual Studio 2012 and/or the .NET Framework 4.5 (if necessary, it will typically be enabled from within the project file itself). --> <NetFx45 Condition="'$(NetFx45)' == ''">false</NetFx45> | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 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 | NOTE: Only use functionality available in the .NET Framework 4.5? By default, this is disabled. This must be enabled to successfully build the project using Visual Studio 2012 and/or the .NET Framework 4.5 (if necessary, it will typically be enabled from within the project file itself). --> <NetFx45 Condition="'$(NetFx45)' == ''">false</NetFx45> </PropertyGroup> <!-- ****************************************************************************** ** Feature Properties ** ****************************************************************************** --> <PropertyGroup> <!-- NOTE: Enable extra internal state checking for the public members of several key classes that use a connection. By default, this is disabled. --> <CheckState Condition="'$(CheckState)' == ''">false</CheckState> <!-- NOTE: For interaction with the native SQLite implementation, use the custom built interop DLL (i.e. "SQLite.Interop.dll")? By default, this is enabled. This property is mutually exclusive with the "UseSqliteStandard" one, below. This should always be disabled in the project file that builds the NetModule target. --> <UseInteropDll Condition="'$(UseInteropDll)' == ''">true</UseInteropDll> <!-- NOTE: For interaction with the native SQLite implementation, use the standard DLL (i.e. "sqlite3.dll")? By default, this is disabled. This property is mutually exclusive with the "UseInteropDll" one, above. This should always be disabled in the project file that builds the NetModule target. --> |
︙ | ︙ | |||
328 329 330 331 332 333 334 | INTEROP_DEBUG_RESET (0x0080) INTEROP_DEBUG_CHANGES (0x0100) INTEROP_DEBUG_BREAK (0x0200) --> <InteropDebug Condition="'$(InteropDebug)' == '' And '$(Configuration)' == 'Debug'">true</InteropDebug> <InteropDebug Condition="'$(InteropDebug)' == '' And '$(Configuration)' != 'Debug'">false</InteropDebug> | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 236 237 238 239 240 241 242 243 244 245 246 247 248 249 | INTEROP_DEBUG_RESET (0x0080) INTEROP_DEBUG_CHANGES (0x0100) INTEROP_DEBUG_BREAK (0x0200) --> <InteropDebug Condition="'$(InteropDebug)' == '' And '$(Configuration)' == 'Debug'">true</InteropDebug> <InteropDebug Condition="'$(InteropDebug)' == '' And '$(Configuration)' != 'Debug'">false</InteropDebug> <!-- NOTE: Enable the use of native Windows APIs, when available? By default, this is enabled. If this is disabled, all features that require the use of native Windows APIs will be unavailable. --> <UseWindows Condition="'$(UseWindows)' == ''">true</UseWindows> </PropertyGroup> |
︙ | ︙ |
Deleted SQLite.NET.Settings.targets.netFx35.
|
| < < < < < < < < < < < < < < < < < < < < < < |
Changes to SQLite.nuspec.
1 2 3 4 5 6 7 8 9 10 11 12 13 | <?xml version="1.0" encoding="utf-8"?> <!-- * * SQLite.nuspec - * * Written by Joe Mistachkin. * Released to the public domain, use at your own risk! * --> <package> <metadata> <id>System.Data.SQLite</id> <title>System.Data.SQLite (x86/x64)</title> | | < < < < | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | <?xml version="1.0" encoding="utf-8"?> <!-- * * SQLite.nuspec - * * Written by Joe Mistachkin. * Released to the public domain, use at your own risk! * --> <package> <metadata> <id>System.Data.SQLite</id> <title>System.Data.SQLite (x86/x64)</title> <version>1.0.83.0</version> <authors>SQLite Development Team</authors> <description>The official SQLite database engine for both x86 and x64 along with the ADO.NET provider.</description> <language>en-US</language> <projectUrl>http://system.data.sqlite.org/</projectUrl> <iconUrl>http://system.data.sqlite.org/images/sqlite32.png</iconUrl> <licenseUrl>http://www.sqlite.org/copyright.html</licenseUrl> <tags>sqlite database ado.net provider interop</tags> <copyright>Public Domain</copyright> </metadata> <files> <file src="bin\2008\Release\bin\System.Data.SQLite.dll" target="lib\net20" /> <file src="bin\2010\Release\bin\System.Data.SQLite.dll" target="lib\net40" /> <file src="bin\2008\Release\bin\System.Data.SQLite.Linq.dll" target="lib\net20" /> <file src="bin\2010\Release\bin\System.Data.SQLite.Linq.dll" target="lib\net40" /> <file src="bin\2008\Win32\ReleaseNativeOnlyStatic\SQLite.Interop.dll" target="content\net20\x86" /> <file src="bin\2008\x64\ReleaseNativeOnlyStatic\SQLite.Interop.dll" target="content\net20\x64" /> <file src="bin\2010\Win32\ReleaseNativeOnlyStatic\SQLite.Interop.dll" target="content\net40\x86" /> <file src="bin\2010\x64\ReleaseNativeOnlyStatic\SQLite.Interop.dll" target="content\net40\x64" /> <file src="install.ps1" target="tools\install.ps1" /> </files> </package> |
Changes to SQLite.x64.nuspec.
1 2 3 4 5 6 7 8 9 10 11 12 | <?xml version="1.0" encoding="utf-8"?> <!-- * * SQLite.x64.nuspec - * * Written by Joe Mistachkin. * Released to the public domain, use at your own risk! * --> <package> <metadata> <id>System.Data.SQLite.x64</id> | | < < | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | <?xml version="1.0" encoding="utf-8"?> <!-- * * SQLite.x64.nuspec - * * Written by Joe Mistachkin. * Released to the public domain, use at your own risk! * --> <package> <metadata> <id>System.Data.SQLite.x64</id> <version>1.0.83.0</version> <authors>SQLite Development Team</authors> <description>The official SQLite database engine combined with a complete ADO.NET provider all rolled into a single mixed-mode assembly for x64.</description> <language>en-US</language> <projectUrl>http://system.data.sqlite.org/</projectUrl> <iconUrl>http://system.data.sqlite.org/images/sqlite32.png</iconUrl> <licenseUrl>http://www.sqlite.org/copyright.html</licenseUrl> <tags>sqlite database ado.net provider interop</tags> <copyright>Public Domain</copyright> </metadata> <files> <file src="bin\2008\x64\ReleaseStatic\System.Data.SQLite.dll" target="lib\net20" /> <file src="bin\2010\x64\ReleaseStatic\System.Data.SQLite.dll" target="lib\net40" /> <file src="bin\2008\Release\bin\System.Data.SQLite.Linq.dll" target="lib\net20" /> <file src="bin\2010\Release\bin\System.Data.SQLite.Linq.dll" target="lib\net40" /> </files> </package> |
Changes to SQLite.x86.nuspec.
1 2 3 4 5 6 7 8 9 10 11 12 | <?xml version="1.0" encoding="utf-8"?> <!-- * * SQLite.x86.nuspec - * * Written by Joe Mistachkin. * Released to the public domain, use at your own risk! * --> <package> <metadata> <id>System.Data.SQLite.x86</id> | | < < | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | <?xml version="1.0" encoding="utf-8"?> <!-- * * SQLite.x86.nuspec - * * Written by Joe Mistachkin. * Released to the public domain, use at your own risk! * --> <package> <metadata> <id>System.Data.SQLite.x86</id> <version>1.0.83.0</version> <authors>SQLite Development Team</authors> <description>The official SQLite database engine combined with a complete ADO.NET provider all rolled into a single mixed-mode assembly for x86.</description> <language>en-US</language> <projectUrl>http://system.data.sqlite.org/</projectUrl> <iconUrl>http://system.data.sqlite.org/images/sqlite32.png</iconUrl> <licenseUrl>http://www.sqlite.org/copyright.html</licenseUrl> <tags>sqlite database ado.net provider interop</tags> <copyright>Public Domain</copyright> </metadata> <files> <file src="bin\2008\Win32\ReleaseStatic\System.Data.SQLite.dll" target="lib\net20" /> <file src="bin\2010\Win32\ReleaseStatic\System.Data.SQLite.dll" target="lib\net40" /> <file src="bin\2008\Release\bin\System.Data.SQLite.Linq.dll" target="lib\net20" /> <file src="bin\2010\Release\bin\System.Data.SQLite.Linq.dll" target="lib\net40" /> </files> </package> |
Changes to Setup/CheckForNetFx.pas.
︙ | ︙ | |||
29 30 31 32 33 34 35 | NetFx4SetupVersion: String; NetFx4HasServicePack: String; NetFx4ServicePack: Integer; NetFx4ErrorMessage: String; VcRuntimeRedistributable: String; | < < < < < < < < < < < < < < < < < | 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | NetFx4SetupVersion: String; NetFx4HasServicePack: String; NetFx4ServicePack: Integer; NetFx4ErrorMessage: String; VcRuntimeRedistributable: String; function CheckForNetFx2(const NeedServicePack: Integer): Boolean; var SubKeyName: String; IsInstalled: Cardinal; HasServicePack: Cardinal; begin Result := False; |
︙ | ︙ | |||
136 137 138 139 140 141 142 | InstallRoot: String; begin Result := ''; if RegQueryStringValue(HKEY_LOCAL_MACHINE, NetFxSubKeyName, NetFxInstallRoot, InstallRoot) then begin | < < | | | | < < < | | | | < | 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 | InstallRoot: String; begin Result := ''; if RegQueryStringValue(HKEY_LOCAL_MACHINE, NetFxSubKeyName, NetFxInstallRoot, InstallRoot) then begin Result := InstallRoot + '\' + NetFx2Version; if FileName <> '' then begin Result := Result + '\' + FileName; end; end; end; function GetNetFx4InstallRoot(const FileName: String): String; var InstallRoot: String; begin Result := ''; if RegQueryStringValue(HKEY_LOCAL_MACHINE, NetFxSubKeyName, NetFxInstallRoot, InstallRoot) then begin Result := InstallRoot + '\' + NetFx4Version; if FileName <> '' then begin Result := Result + '\' + FileName; end; end; end; function CheckIsNetFx2Setup(): Boolean; begin Result := IsNetFx2Setup; |
︙ | ︙ |
Changes to Setup/SQLite.iss.
︙ | ︙ | |||
79 80 81 82 83 84 85 | #if Year == "2005" Components: Application\Core\MSIL; Name: gac; Description: Install the assemblies into the global assembly cache.; Flags: unchecked; Check: CheckIsNetFx2Setup() or CheckIsNetFx4Setup() #else Components: Application\Core\MSIL Or Application\LINQ; Name: gac; Description: Install the assemblies into the global assembly cache.; Flags: unchecked; Check: CheckIsNetFx2Setup() or CheckIsNetFx4Setup() #endif #if AppProcessor == "x86" | | | 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | #if Year == "2005" Components: Application\Core\MSIL; Name: gac; Description: Install the assemblies into the global assembly cache.; Flags: unchecked; Check: CheckIsNetFx2Setup() or CheckIsNetFx4Setup() #else Components: Application\Core\MSIL Or Application\LINQ; Name: gac; Description: Install the assemblies into the global assembly cache.; Flags: unchecked; Check: CheckIsNetFx2Setup() or CheckIsNetFx4Setup() #endif #if AppProcessor == "x86" #if Year == "2005" || Year == "2008" Components: {#InstallerCondition}; Name: gac\vs2005; Description: Install the designer components for Visual Studio 2005.; Flags: unchecked; Check: CheckIsNetFx2Setup() #endif #if Year == "2008" Components: {#InstallerCondition}; Name: gac\vs2008; Description: Install the designer components for Visual Studio 2008.; Flags: unchecked; Check: CheckIsNetFx2Setup() #endif #if Year == "2010" Components: {#InstallerCondition}; Name: gac\vs2010; Description: Install the designer components for Visual Studio 2010.; Flags: unchecked; Check: CheckIsNetFx4Setup() |
︙ | ︙ | |||
104 105 106 107 108 109 110 | #if Year != "2005" Components: Application\LINQ; Tasks: ngen; Filename: {code:GetNetFx2InstallRoot|Ngen.exe}; Parameters: "install ""{app}\bin\System.Data.SQLite.Linq.dll"" /nologo"; Flags: skipifdoesntexist; Check: CheckIsNetFx2Setup() and CheckForNetFx35(1) Components: Application\LINQ; Tasks: ngen; Filename: {code:GetNetFx4InstallRoot|Ngen.exe}; Parameters: "install ""{app}\bin\System.Data.SQLite.Linq.dll"" /nologo"; Flags: skipifdoesntexist; Check: CheckIsNetFx4Setup() #endif #if Pos("NativeOnly", AppConfiguration) == 0 && AppProcessor == "x86" | | | | | | 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 | #if Year != "2005" Components: Application\LINQ; Tasks: ngen; Filename: {code:GetNetFx2InstallRoot|Ngen.exe}; Parameters: "install ""{app}\bin\System.Data.SQLite.Linq.dll"" /nologo"; Flags: skipifdoesntexist; Check: CheckIsNetFx2Setup() and CheckForNetFx35(1) Components: Application\LINQ; Tasks: ngen; Filename: {code:GetNetFx4InstallRoot|Ngen.exe}; Parameters: "install ""{app}\bin\System.Data.SQLite.Linq.dll"" /nologo"; Flags: skipifdoesntexist; Check: CheckIsNetFx4Setup() #endif #if Pos("NativeOnly", AppConfiguration) == 0 && AppProcessor == "x86" #if Year == "2005" || Year == "2008" Components: {#InstallerCondition}; Tasks: gac\vs2005; Filename: {app}\bin\Installer.exe; Parameters: "-install true -wow64 true -installFlags AllExceptGlobalAssemblyCache -tracePriority Lowest -verbose true -noCompact true -noNetFx35 true -noNetFx40 true -noNetFx45 true -noVs2008 true -noVs2010 true -noVs2012 true -whatIf false -confirm true"; Flags: skipifdoesntexist; Check: CheckIsNetFx2Setup() #endif #if Year == "2008" Components: {#InstallerCondition}; Tasks: gac\vs2008; Filename: {app}\bin\Installer.exe; Parameters: "-install true -wow64 true -installFlags AllExceptGlobalAssemblyCache -tracePriority Lowest -verbose true -noCompact true -noNetFx40 true -noNetFx45 true -noVs2005 true -noVs2010 true -noVs2012 true -whatIf false -confirm true"; Flags: skipifdoesntexist; Check: CheckIsNetFx2Setup() #endif #if Year == "2010" Components: {#InstallerCondition}; Tasks: gac\vs2010; Filename: {app}\bin\Installer.exe; Parameters: "-install true -wow64 true -installFlags AllExceptGlobalAssemblyCache -tracePriority Lowest -verbose true -noCompact true -noNetFx20 true -noNetFx45 true -noVs2005 true -noVs2008 true -noVs2012 true -whatIf false -confirm true"; Flags: skipifdoesntexist; Check: CheckIsNetFx4Setup() #endif #if Year == "2012" Components: {#InstallerCondition}; Tasks: gac\vs2012; Filename: {app}\bin\Installer.exe; Parameters: "-install true -wow64 true -installFlags AllExceptGlobalAssemblyCache -tracePriority Lowest -verbose true -noCompact true -noNetFx20 true -noNetFx40 true -noVs2005 true -noVs2008 true -noVs2010 true -configVersion 4.0.30319 -whatIf false -confirm true"; Flags: skipifdoesntexist; Check: CheckIsNetFx4Setup() Components: {#InstallerCondition}; Tasks: gac\vs2012; Filename: {app}\bin\Installer.exe; Parameters: "-perUser true -install true -wow64 true -installFlags AllExceptGlobalAssemblyCache -tracePriority Lowest -verbose true -noCompact true -noNetFx20 true -noNetFx40 true -noVs2005 true -noVs2008 true -noVs2010 true -configVersion 4.0.30319 -vsVersionSuffix _Config -whatIf false -confirm true"; Flags: skipifdoesntexist; Check: CheckIsNetFx4Setup() #endif #endif [UninstallRun] #if Pos("NativeOnly", AppConfiguration) == 0 && AppProcessor == "x86" #if Year == "2012" Components: {#InstallerCondition}; Tasks: gac\vs2012; Filename: {app}\bin\Installer.exe; Parameters: "-perUser true -install false -wow64 true -installFlags AllExceptGlobalAssemblyCache -tracePriority Lowest -verbose true -noCompact true -noNetFx20 true -noNetFx40 true -noVs2005 true -noVs2008 true -noVs2010 true -configVersion 4.0.30319 -vsVersionSuffix _Config -whatIf false -confirm true"; Flags: skipifdoesntexist; Check: CheckIsNetFx4Setup() Components: {#InstallerCondition}; Tasks: gac\vs2012; Filename: {app}\bin\Installer.exe; Parameters: "-install false -wow64 true -installFlags AllExceptGlobalAssemblyCache -tracePriority Lowest -verbose true -noCompact true -noNetFx20 true -noNetFx40 true -noVs2005 true -noVs2008 true -noVs2010 true -configVersion 4.0.30319 -whatIf false -confirm true"; Flags: skipifdoesntexist; Check: CheckIsNetFx4Setup() #endif #if Year == "2010" Components: {#InstallerCondition}; Tasks: gac\vs2010; Filename: {app}\bin\Installer.exe; Parameters: "-install false -wow64 true -installFlags AllExceptGlobalAssemblyCache -tracePriority Lowest -verbose true -noCompact true -noNetFx20 true -noNetFx45 true -noVs2005 true -noVs2008 true -noVs2012 true -whatIf false -confirm true"; Flags: skipifdoesntexist; Check: CheckIsNetFx4Setup() #endif #if Year == "2008" Components: {#InstallerCondition}; Tasks: gac\vs2008; Filename: {app}\bin\Installer.exe; Parameters: "-install false -wow64 true -installFlags AllExceptGlobalAssemblyCache -tracePriority Lowest -verbose true -noCompact true -noNetFx40 true -noNetFx45 true -noVs2005 true -noVs2010 true -noVs2012 true -whatIf false -confirm true"; Flags: skipifdoesntexist; Check: CheckIsNetFx2Setup() #endif #if Year == "2005" || Year == "2008" Components: {#InstallerCondition}; Tasks: gac\vs2005; Filename: {app}\bin\Installer.exe; Parameters: "-install false -wow64 true -installFlags AllExceptGlobalAssemblyCache -tracePriority Lowest -verbose true -noCompact true -noNetFx35 true -noNetFx40 true -noNetFx45 true -noVs2008 true -noVs2010 true -noVs2012 true -whatIf false -confirm true"; Flags: skipifdoesntexist; Check: CheckIsNetFx2Setup() #endif #endif #if Year != "2005" Components: Application\LINQ; Tasks: ngen; Filename: {code:GetNetFx4InstallRoot|Ngen.exe}; Parameters: "uninstall ""{app}\bin\System.Data.SQLite.Linq.dll"" /nologo"; Flags: skipifdoesntexist; Check: CheckIsNetFx4Setup() Components: Application\LINQ; Tasks: ngen; Filename: {code:GetNetFx2InstallRoot|Ngen.exe}; Parameters: "uninstall ""{app}\bin\System.Data.SQLite.Linq.dll"" /nologo"; Flags: skipifdoesntexist; Check: CheckIsNetFx2Setup() and CheckForNetFx35(1) |
︙ | ︙ |
Changes to Setup/build_ce.bat.
︙ | ︙ | |||
26 27 28 29 30 31 32 | ) SET TOOLS=%~dp0 SET TOOLS=%TOOLS:~0,-1% %_VECHO% Tools = '%TOOLS%' | | | | | 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | ) 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 %__ECHO3% CALL "%TOOLS%\build_all.bat" IF ERRORLEVEL 1 ( ECHO Failed to build PocketPC binaries. |
︙ | ︙ |
Changes to Setup/clean.bat.
︙ | ︙ | |||
72 73 74 75 76 77 78 | ) ) ELSE ( %_AECHO% Directory "%SOURCE%\%%D" does not exist. %_AECHO%. ) ) | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 72 73 74 75 76 77 78 79 80 81 82 83 84 85 | ) ) 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 |
︙ | ︙ |
Changes to Setup/deployAndTestCe.eagle.
︙ | ︙ | |||
25 26 27 28 29 30 31 | # # NOTE: This procedure will output a diagnostic message, typically to the # standard output channel, using the [puts] command unless the global # variable "quiet" is non-zero. # proc qputs { args } { | | | 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | # # NOTE: This procedure will output a diagnostic message, typically to the # standard output channel, using the [puts] command unless the global # variable "quiet" is non-zero. # proc qputs { args } { if {!$::quiet} then { eval puts $args; flush stdout } } # # NOTE: This procedure looks up and returns the target device based on the # locale, platform Id, and device Id. |
︙ | ︙ | |||
114 115 116 117 118 119 120 | set name [lindex $names $index]; set value "" if {$argc > $index} then { set value [string trim [lindex $argv $index]] } if {[string length $value] > 0} then { | | | < < < < | | | < < < < < < < < < < < < < < < < < < < < < < < < < < < | | | | < < | < | | | 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 | set name [lindex $names $index]; set value "" if {$argc > $index} then { set value [string trim [lindex $argv $index]] } if {[string length $value] > 0} then { set $name $value } else { set $name $default($name) } } # # NOTE: Grab the culture instance based on the configured culture name. # set cultureInfo [object invoke -alias System.Globalization.CultureInfo \ GetCultureInfo $culture] # # NOTE: Build the list of .NET Compact Framework packages that need to be # deployed to the target device. # if {![info exists packages]} then { # # NOTE: The two letter ISO language name is needed when building the # default list of .NET Compact Framework packages because one of # them is a localized resource package. # set language [string toupper [$cultureInfo TwoLetterISOLanguageName]] # # NOTE: The default list of .NET Compact Framework packages contains the # .NET Compact Framework 3.5 installation CAB file for ARMV4 on the # Pocket PC and its associated resource installation CAB file. # set packages [list abd785f0-cda7-41c5-8375-2451a7cbff37 \ \\windows\\NETCFv35.ppc.armv4.cab c0ccf48e-4bfb-4d84-827c-981a595e40c5 \ [appendArgs \\windows\\NETCFv35.Messages. $language .cab]] } # # NOTE: Save the path where this script is running from. # set path [file dirname [info script]] |
︙ | ︙ | |||
232 233 234 235 236 237 238 | # itself, the System.Data.SQLite managed assembly, the SQLite interop # assembly, and the test application configuration file. # set fileNames [list [file join $managed_directory testce.exe] [file \ join $managed_directory System.Data.SQLite.dll] [file join \ $native_directory [appendArgs SQLite.Interop. [format %03d \ [$assemblyName Version.Build]] .dll]] [file join $managed_directory \ | | | 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 | # itself, the System.Data.SQLite managed assembly, the SQLite interop # assembly, and the test application configuration file. # set fileNames [list [file join $managed_directory testce.exe] [file \ join $managed_directory System.Data.SQLite.dll] [file join \ $native_directory [appendArgs SQLite.Interop. [format %03d \ [$assemblyName Version.Build]] .dll]] [file join $managed_directory \ test.cfg]] } # # NOTE: Setup the directory on the target device where the application files # should be deployed to. # if {![info exists device_directory]} then { |
︙ | ︙ | |||
271 272 273 274 275 276 277 | # # NOTE: Grab the file deployer instance for the target device. This will # be used to download packages and send files to the target device. # set fileDeployer [$device -alias GetFileDeployer] # | < < < < < | | | | | | | | | | | | | | < | 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 | # # NOTE: Grab the file deployer instance for the target device. This will # be used to download packages and send files to the target device. # set fileDeployer [$device -alias GetFileDeployer] # # NOTE: Process each entry in the list of packages to be downloaded to the # target device. The package list must contain the package Id and the # file name (relative to the target device), in that order, for each # package to be downloaded to the target device. # foreach {packageId packageFileName} $packages { qputs stdout [appendArgs \ "downloading package \"" $packageId "\" to device..."] $fileDeployer DownloadPackage [object create \ Microsoft.SmartDevice.Connectivity.ObjectId $packageId] qputs stdout [appendArgs \ "installing package file \"" $packageFileName "\" on device..."] startRemoteProcess $device wceload.exe [appendArgs "/noui " \ $packageFileName] } # # NOTE: Process each application file to be sent to the target device. # foreach fileName $fileNames { qputs stdout [appendArgs \ |
︙ | ︙ |
Changes to Setup/release_ce.bat.
︙ | ︙ | |||
31 32 33 34 35 36 37 | %_VECHO% Tools = '%TOOLS%' SET RELEASE_CONFIGURATIONS=Release SET BASE_CONFIGURATIONSUFFIX=Compact SET PLATFORMS="Pocket PC 2003 (ARMV4)" SET PROCESSORS=arm SET YEARS=2008 | | | 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | %_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 %__ECHO3% CALL "%TOOLS%\release_all.bat" IF ERRORLEVEL 1 ( |
︙ | ︙ |
Changes to Setup/set_common.bat.
︙ | ︙ | |||
16 17 18 19 20 21 22 | ) IF NOT DEFINED PUBLICKEY ( SET PUBLICKEY=db937bc2d44ff139 ) IF NOT DEFINED BUILD_CONFIGURATIONS ( | | | | 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | ) IF NOT DEFINED PUBLICKEY ( SET PUBLICKEY=db937bc2d44ff139 ) IF NOT DEFINED BUILD_CONFIGURATIONS ( SET BUILD_CONFIGURATIONS=Release ReleaseNativeOnly ) IF NOT DEFINED TEST_CONFIGURATIONS ( SET TEST_CONFIGURATIONS=Release ) IF NOT DEFINED BAKE_CONFIGURATIONS ( SET BAKE_CONFIGURATIONS=Release ReleaseNativeOnly ) IF NOT DEFINED RELEASE_CONFIGURATIONS ( |
︙ | ︙ |
Changes to Setup/set_netFx20.bat.
︙ | ︙ | |||
8 9 10 11 12 13 14 | :: IF NOT DEFINED ISNETFX2 ( SET ISNETFX2=True ) IF NOT DEFINED VCRUNTIME ( | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | :: IF NOT DEFINED ISNETFX2 ( SET ISNETFX2=True ) IF NOT DEFINED VCRUNTIME ( SET VCRUNTIME=2005_SP1 ) IF NOT DEFINED CONFIGURATION ( SET CONFIGURATION=Release ) IF NOT DEFINED PLATFORM ( |
︙ | ︙ |
Changes to Setup/set_netFx35.bat.
︙ | ︙ | |||
8 9 10 11 12 13 14 | :: IF NOT DEFINED ISNETFX2 ( SET ISNETFX2=True ) IF NOT DEFINED VCRUNTIME ( | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | :: IF NOT DEFINED ISNETFX2 ( SET ISNETFX2=True ) IF NOT DEFINED VCRUNTIME ( SET VCRUNTIME=2008_SP1 ) IF NOT DEFINED CONFIGURATION ( SET CONFIGURATION=Release ) IF NOT DEFINED PLATFORM ( |
︙ | ︙ |
Changes to Setup/set_netFx40.bat.
︙ | ︙ | |||
8 9 10 11 12 13 14 | :: IF NOT DEFINED ISNETFX2 ( SET ISNETFX2=False ) IF NOT DEFINED VCRUNTIME ( | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | :: IF NOT DEFINED ISNETFX2 ( SET ISNETFX2=False ) IF NOT DEFINED VCRUNTIME ( SET VCRUNTIME=2010_SP1 ) IF NOT DEFINED CONFIGURATION ( SET CONFIGURATION=Release ) IF NOT DEFINED PLATFORM ( |
︙ | ︙ |
Changes to Setup/set_netFx45.bat.
︙ | ︙ | |||
8 9 10 11 12 13 14 | :: IF NOT DEFINED ISNETFX2 ( SET ISNETFX2=False ) IF NOT DEFINED VCRUNTIME ( | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | :: IF NOT DEFINED ISNETFX2 ( SET ISNETFX2=False ) IF NOT DEFINED VCRUNTIME ( SET VCRUNTIME=2012_RTM ) IF NOT DEFINED CONFIGURATION ( SET CONFIGURATION=Release ) IF NOT DEFINED PLATFORM ( |
︙ | ︙ |
Changes to Setup/set_user_mistachkin_Debug.bat.
︙ | ︙ | |||
9 10 11 12 13 14 15 | :: Released to the public domain, use at your own risk! :: REM REM NOTE: Enables the extra debug code helpful in troubleshooting issues. REM SET MSBUILD_ARGS=/p:CheckState=true | < | 9 10 11 12 13 14 15 16 17 18 | :: Released to the public domain, use at your own risk! :: REM REM NOTE: Enables the extra debug code helpful in troubleshooting issues. REM SET MSBUILD_ARGS=/p:CheckState=true SET MSBUILD_ARGS=%MSBUILD_ARGS% /p:TraceConnection=true SET MSBUILD_ARGS=%MSBUILD_ARGS% /p:TraceHandle=true SET MSBUILD_ARGS=%MSBUILD_ARGS% /p:TraceStatement=true |
Changes to Setup/set_x64_2005.bat.
1 2 3 4 5 6 7 8 9 10 | @ECHO OFF :: :: set_x64_2005.bat -- :: :: Written by Joe Mistachkin. :: Released to the public domain, use at your own risk! :: SET ISNETFX2=True | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 | @ECHO OFF :: :: set_x64_2005.bat -- :: :: Written by Joe Mistachkin. :: Released to the public domain, use at your own risk! :: SET ISNETFX2=True SET VCRUNTIME=2005_SP1 SET PLATFORM=x64 SET PROCESSOR=x64 SET YEAR=2005 |
Changes to Setup/set_x64_2008.bat.
1 2 3 4 5 6 7 8 9 10 | @ECHO OFF :: :: set_x64_2008.bat -- :: :: Written by Joe Mistachkin. :: Released to the public domain, use at your own risk! :: SET ISNETFX2=True | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 | @ECHO OFF :: :: set_x64_2008.bat -- :: :: Written by Joe Mistachkin. :: Released to the public domain, use at your own risk! :: SET ISNETFX2=True SET VCRUNTIME=2008_SP1 SET PLATFORM=x64 SET PROCESSOR=x64 SET YEAR=2008 |
Changes to Setup/set_x64_2010.bat.
1 2 3 4 5 6 7 8 9 10 | @ECHO OFF :: :: set_x64_2010.bat -- :: :: Written by Joe Mistachkin. :: Released to the public domain, use at your own risk! :: SET ISNETFX2=False | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 | @ECHO OFF :: :: set_x64_2010.bat -- :: :: Written by Joe Mistachkin. :: Released to the public domain, use at your own risk! :: SET ISNETFX2=False SET VCRUNTIME=2010_SP1 SET PLATFORM=x64 SET PROCESSOR=x64 SET YEAR=2010 |
Changes to Setup/set_x64_2012.bat.
1 2 3 4 5 6 7 8 9 10 | @ECHO OFF :: :: set_x64_2012.bat -- :: :: Written by Joe Mistachkin. :: Released to the public domain, use at your own risk! :: SET ISNETFX2=False | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 | @ECHO OFF :: :: set_x64_2012.bat -- :: :: Written by Joe Mistachkin. :: Released to the public domain, use at your own risk! :: SET ISNETFX2=False SET VCRUNTIME=2012_RTM SET PLATFORM=x64 SET PROCESSOR=x64 SET YEAR=2012 |
Changes to Setup/set_x86_2005.bat.
1 2 3 4 5 6 7 8 9 10 | @ECHO OFF :: :: set_x86_2005.bat -- :: :: Written by Joe Mistachkin. :: Released to the public domain, use at your own risk! :: SET ISNETFX2=True | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 | @ECHO OFF :: :: set_x86_2005.bat -- :: :: Written by Joe Mistachkin. :: Released to the public domain, use at your own risk! :: SET ISNETFX2=True SET VCRUNTIME=2005_SP1 SET PLATFORM=Win32 SET PROCESSOR=x86 SET YEAR=2005 |
Changes to Setup/set_x86_2008.bat.
1 2 3 4 5 6 7 8 9 10 | @ECHO OFF :: :: set_x86_2008.bat -- :: :: Written by Joe Mistachkin. :: Released to the public domain, use at your own risk! :: SET ISNETFX2=True | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 | @ECHO OFF :: :: set_x86_2008.bat -- :: :: Written by Joe Mistachkin. :: Released to the public domain, use at your own risk! :: SET ISNETFX2=True SET VCRUNTIME=2008_SP1 SET PLATFORM=Win32 SET PROCESSOR=x86 SET YEAR=2008 |
Changes to Setup/set_x86_2010.bat.
1 2 3 4 5 6 7 8 9 10 | @ECHO OFF :: :: set_x86_2010.bat -- :: :: Written by Joe Mistachkin. :: Released to the public domain, use at your own risk! :: SET ISNETFX2=False | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 | @ECHO OFF :: :: set_x86_2010.bat -- :: :: Written by Joe Mistachkin. :: Released to the public domain, use at your own risk! :: SET ISNETFX2=False SET VCRUNTIME=2010_SP1 SET PLATFORM=Win32 SET PROCESSOR=x86 SET YEAR=2010 |
Changes to Setup/set_x86_2012.bat.
1 2 3 4 5 6 7 8 9 10 | @ECHO OFF :: :: set_x86_2012.bat -- :: :: Written by Joe Mistachkin. :: Released to the public domain, use at your own risk! :: SET ISNETFX2=False | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 | @ECHO OFF :: :: set_x86_2012.bat -- :: :: Written by Joe Mistachkin. :: Released to the public domain, use at your own risk! :: SET ISNETFX2=False SET VCRUNTIME=2012_RTM SET PLATFORM=Win32 SET PROCESSOR=x86 SET YEAR=2012 |
Changes to Setup/test_all.bat.
︙ | ︙ | |||
96 97 98 99 100 101 102 | %__ECHO2% PUSHD "%ROOT%" IF ERRORLEVEL 1 ( ECHO Could not change directory to "%ROOT%". GOTO errors ) | < < < < < < | 96 97 98 99 100 101 102 103 104 105 106 107 108 109 | %__ECHO2% PUSHD "%ROOT%" IF ERRORLEVEL 1 ( ECHO Could not change directory to "%ROOT%". GOTO errors ) FOR %%C IN (%TEST_CONFIGURATIONS%) DO ( FOR %%Y IN (%YEARS%) DO ( IF NOT DEFINED NOMANAGEDONLY ( %__ECHO% Externals\Eagle\bin\EagleShell.exe -preInitialize "set test_year {%%Y}; set test_configuration {%%C}" -file "%TEST_FILE%" IF ERRORLEVEL 1 ( ECHO Testing of "%%Y/%%C" managed-only assembly failed. |
︙ | ︙ |
Changes to Setup/verify.lst.
︙ | ︙ | |||
78 79 80 81 82 83 84 | Setup/bake.bat Setup/bake_all.bat Setup/build.bat Setup/build_all.bat Setup/build_ce.bat Setup/CheckForNetFx.pas Setup/clean.bat | < | 78 79 80 81 82 83 84 85 86 87 88 89 90 91 | Setup/bake.bat Setup/bake_all.bat Setup/build.bat Setup/build_all.bat Setup/build_ce.bat Setup/CheckForNetFx.pas Setup/clean.bat Setup/InitializeSetup.pas Setup/release.bat Setup/release_all.bat Setup/release_ce.bat Setup/release_static.bat Setup/set_2005.bat Setup/set_2008.bat |
︙ | ︙ | |||
127 128 129 130 131 132 133 | Setup/set_x64_2012.bat Setup/set_x86_2005.bat Setup/set_x86_2008.bat Setup/set_x86_2010.bat Setup/set_x86_2012.bat Setup/SQLite.iss Setup/test_all.bat | < < | 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 | Setup/set_x64_2012.bat Setup/set_x86_2005.bat Setup/set_x86_2008.bat Setup/set_x86_2010.bat Setup/set_x86_2012.bat Setup/SQLite.iss Setup/test_all.bat Setup/updateFileInfo.tcl Setup/verify.eagle Setup/verify.lst Setup/vsSp.bat SQLite.Designer/ SQLite.Designer/AssemblyInfo.cs SQLite.Designer/ChangePasswordDialog.cs SQLite.Designer/ChangePasswordDialog.Designer.cs SQLite.Designer/ChangePasswordDialog.resx SQLite.Designer/ChangeScriptDialog.cs SQLite.Designer/ChangeScriptDialog.Designer.cs |
︙ | ︙ | |||
246 247 248 249 250 251 252 | SQLite.NET.2008.MSBuild.sln SQLite.NET.2008.sln SQLite.NET.2010.MSBuild.sln SQLite.NET.2010.sln SQLite.NET.2012.MSBuild.sln SQLite.NET.2012.sln SQLite.NET.Settings.targets | < | 243 244 245 246 247 248 249 250 251 252 253 254 255 256 | SQLite.NET.2008.MSBuild.sln SQLite.NET.2008.sln SQLite.NET.2010.MSBuild.sln SQLite.NET.2010.sln SQLite.NET.2012.MSBuild.sln SQLite.NET.2012.sln SQLite.NET.Settings.targets SQLite.NET.targets SQLite.nuspec SQLite.x64.nuspec SQLite.x86.nuspec System.Data.SQLite/ System.Data.SQLite/AssemblyInfo.cs System.Data.SQLite/DataTypes.xml |
︙ | ︙ | |||
394 395 396 397 398 399 400 | testlinq/testlinq.2010.csproj testlinq/testlinq.2012.csproj Tests/ Tests/all.eagle Tests/backup.eagle Tests/basic.eagle Tests/common.eagle | < < < < < < < < < < < | 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 | testlinq/testlinq.2010.csproj testlinq/testlinq.2012.csproj Tests/ Tests/all.eagle Tests/backup.eagle Tests/basic.eagle Tests/common.eagle Tests/installer.eagle Tests/Installer_Test_Vs2005.log Tests/Installer_Test_Vs2008.log Tests/Installer_Test_Vs2010.log Tests/Installer_Test_Vs2012.log Tests/nonWal.db Tests/pkgIndex.eagle Tests/stress.eagle Tests/testlinq.out Tests/tkt-00f86f9739.eagle Tests/tkt-0d5b1ef362.eagle Tests/tkt-17045010df.eagle Tests/tkt-201128cc88.eagle Tests/tkt-2c630bffa7.eagle Tests/tkt-2ce0870fad.eagle Tests/tkt-343d392b51.eagle Tests/tkt-3aa50d8413.eagle Tests/tkt-448d663d11.eagle Tests/tkt-544dba0a2f.eagle Tests/tkt-59edc1018b.eagle Tests/tkt-72905c9a77.eagle Tests/tkt-7e3fa93744.eagle Tests/tkt-84718e79fa.eagle Tests/tkt-8554170e09.eagle Tests/tkt-8b7d179c3c.eagle Tests/tkt-8c3bee31c8.eagle Tests/tkt-996d13cd87.eagle Tests/tkt-ac47dd230a.eagle Tests/tkt-b4a7ddc83f.eagle Tests/tkt-bb4b04d457.eagle Tests/tkt-ccfa69fc32.eagle Tests/tkt-e1b2e0f769.eagle Tests/tkt-e30b820248.eagle Tests/Uninstaller_Test_Vs2005.log Tests/Uninstaller_Test_Vs2008.log Tests/Uninstaller_Test_Vs2010.log Tests/Uninstaller_Test_Vs2012.log Tests/version.eagle |
︙ | ︙ | |||
608 609 610 611 612 613 614 | ############################################################################### # # NOTE: This is the list of files that should be present in all setup archives # supporting the .NET Framework 2.0 for x86. # set sds_manifests(setupX86Vs2005) { | | | | | | | | | | 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 | ############################################################################### # # NOTE: This is the list of files that should be present in all setup archives # supporting the .NET Framework 2.0 for x86. # set sds_manifests(setupX86Vs2005) { {{tmp}\vcredist_x86_2005_SP1.exe} } ############################################################################### # # NOTE: This is the list of files that should be present in all setup archives # supporting the .NET Framework 2.0 for x64. # set sds_manifests(setupX64Vs2005) { {{tmp}\vcredist_x64_2005_SP1.exe} } ############################################################################### # # NOTE: This is the list of files that should be present in all setup archives # supporting the .NET Framework 3.5 for x86. # set sds_manifests(setupX86Vs2008) { {{tmp}\vcredist_x86_2008_SP1.exe} } ############################################################################### # # NOTE: This is the list of files that should be present in all setup archives # supporting the .NET Framework 3.5 for x64. # set sds_manifests(setupX64Vs2008) { {{tmp}\vcredist_x64_2008_SP1.exe} } ############################################################################### # # NOTE: This is the list of files that should be present in all setup archives # supporting the .NET Framework 4.0 for x86. # set sds_manifests(setupX86Vs2010) { {{tmp}\vcredist_x86_2010_SP1.exe} } ############################################################################### # # NOTE: This is the list of files that should be present in all setup archives # supporting the .NET Framework 4.0 for x64. # set sds_manifests(setupX64Vs2010) { {{tmp}\vcredist_x64_2010_SP1.exe} } ############################################################################### # # NOTE: This is the list of files that should be present in all setup archives # supporting the .NET Framework 4.5 for x86. # set sds_manifests(setupX86Vs2012) { {{tmp}\vcredist_x86_2012_RTM.exe} } ############################################################################### # # NOTE: This is the list of files that should be present in all setup archives # supporting the .NET Framework 4.5 for x64. # set sds_manifests(setupX64Vs2012) { {{tmp}\vcredist_x64_2012_RTM.exe} } ############################################################################### # # NOTE: These are the master archive manifest groups, based on file name. The # first element in each list is the array variable name prefix used to # locate another array containing the named elements referenced by the |
︙ | ︙ | |||
833 834 835 836 837 838 839 | set manifests(sqlite-netFx35-setup-bundle-x64-2008-.exe) [list sds \ setupCore setupLinqCore setupBundle setupLinqBundle setupX64Vs2008] ############################################################################### ################# Visual Studio 2008 / .NET Compact Framework ################# ############################################################################### | | | | 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 | set manifests(sqlite-netFx35-setup-bundle-x64-2008-.exe) [list sds \ setupCore setupLinqCore setupBundle setupLinqBundle setupX64Vs2008] ############################################################################### ################# Visual Studio 2008 / .NET Compact Framework ################# ############################################################################### set manifests(sqlite-netFx35-binary-PocketPC-2008-.zip) [list sds \ binaryCore binaryCompact] set manifests(sqlite-netFx35-binary-PocketPC-2008-.zip,subst) ""; # dynamic ############################################################################### ################### Visual Studio 2010 / .NET Framework 4.0 ################### ############################################################################### set manifests(sqlite-netFx40-binary-Win32-2010-.zip) [list sds \ binaryCore binaryLinq binaryExtra binaryInterop] |
︙ | ︙ |
Changes to System.Data.SQLite.Linq/AssemblyInfo.cs.
︙ | ︙ | |||
27 28 29 30 31 32 33 | #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)] | < < < < | | | 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | #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.83.0")] [assembly: AssemblyFileVersion("1.0.83.0")] |
Changes to System.Data.SQLite.Linq/SQLiteProviderServices.cs.
︙ | ︙ | |||
98 99 100 101 102 103 104 | } protected override string GetDbProviderManifestToken(DbConnection connection) { if (String.IsNullOrEmpty(connection.ConnectionString)) throw new ArgumentNullException("ConnectionString"); | < < < < < < < | < | 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 | } protected override string GetDbProviderManifestToken(DbConnection connection) { if (String.IsNullOrEmpty(connection.ConnectionString)) throw new ArgumentNullException("ConnectionString"); SortedList<string, string> opts = SQLiteConnection.ParseConnectionString(connection.ConnectionString); return SQLiteConnection.FindKey(opts, "DateTimeFormat", "ISO8601"); } protected override DbProviderManifest GetDbProviderManifest(string versionHint) { return new SQLiteProviderManifest(versionHint); } |
︙ | ︙ |
Changes to System.Data.SQLite/AssemblyInfo.cs.
︙ | ︙ | |||
40 41 42 43 44 45 46 | // COM, set the ComVisible attribute to true on that type. [assembly: ComVisible(false)] [assembly: CLSCompliant(true)] [assembly: InternalsVisibleTo("System.Data.SQLite.Linq, PublicKey=" + System.Data.SQLite.SQLite3.PublicKey)] [assembly: NeutralResourcesLanguage("en")] #if !PLATFORM_COMPACTFRAMEWORK | < < < | | | 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 | // COM, set the ComVisible attribute to true on that type. [assembly: ComVisible(false)] [assembly: CLSCompliant(true)] [assembly: InternalsVisibleTo("System.Data.SQLite.Linq, PublicKey=" + System.Data.SQLite.SQLite3.PublicKey)] [assembly: NeutralResourcesLanguage("en")] #if !PLATFORM_COMPACTFRAMEWORK [assembly: AllowPartiallyTrustedCallers] [assembly: ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] #if NET_40 || NET_45 // // NOTE: This attribute is only available in .NET Framework 4.0 or higher. // [assembly: SecurityRules(System.Security.SecurityRuleSet.Level1)] #endif #endif // 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.83.0")] #if !PLATFORM_COMPACTFRAMEWORK [assembly: AssemblyFileVersion("1.0.83.0")] #endif |
Changes to System.Data.SQLite/LINQ/SQLiteFactory_Linq.cs.
︙ | ︙ | |||
22 23 24 25 26 27 28 | static SQLiteFactory() { #if (SQLITE_STANDARD || USE_INTEROP_DLL || PLATFORM_COMPACTFRAMEWORK) && PRELOAD_NATIVE_LIBRARY UnsafeNativeMethods.Initialize(); #endif | | < < < < < < | 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | static SQLiteFactory() { #if (SQLITE_STANDARD || USE_INTEROP_DLL || PLATFORM_COMPACTFRAMEWORK) && PRELOAD_NATIVE_LIBRARY UnsafeNativeMethods.Initialize(); #endif #if !PLATFORM_COMPACTFRAMEWORK SQLiteLog.Initialize(); #endif string version = #if NET_40 || NET_45 "4.0.0.0"; #else |
︙ | ︙ |
Changes to System.Data.SQLite/SQLite3.cs.
︙ | ︙ | |||
53 54 55 56 57 58 59 | internal const string PublicKey = "002400000480000094000000060200000024000052534131000400000100010005a288de5687c4e1" + "b621ddff5d844727418956997f475eb829429e411aff3e93f97b70de698b972640925bdd44280df0" + "a25a843266973704137cbb0e7441c1fe7cae4e2440ae91ab8cde3933febcb1ac48dd33b40e13c421" + "d8215c18a4349a436dd499e3c385cc683015f886f6c10bd90115eb2bd61b67750839e3a19941dc9c"; #if !PLATFORM_COMPACTFRAMEWORK | | | 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | internal const string PublicKey = "002400000480000094000000060200000024000052534131000400000100010005a288de5687c4e1" + "b621ddff5d844727418956997f475eb829429e411aff3e93f97b70de698b972640925bdd44280df0" + "a25a843266973704137cbb0e7441c1fe7cae4e2440ae91ab8cde3933febcb1ac48dd33b40e13c421" + "d8215c18a4349a436dd499e3c385cc683015f886f6c10bd90115eb2bd61b67750839e3a19941dc9c"; #if !PLATFORM_COMPACTFRAMEWORK internal const string DesignerVersion = "1.0.83.0"; #endif /// <summary> /// The opaque pointer returned to us by the sqlite provider /// </summary> protected internal SQLiteConnectionHandle _sql; protected string _fileName; |
︙ | ︙ | |||
171 172 173 174 175 176 177 | { get { return SQLite3.SQLiteVersion; } } | < < < < < < < < | 171 172 173 174 175 176 177 178 179 180 181 182 183 184 | { get { return SQLite3.SQLiteVersion; } } internal static string DefineConstants { get { StringBuilder result = new StringBuilder(); IList<string> list = SQLiteDefineConstants.OptionList; |
︙ | ︙ | |||
212 213 214 215 216 217 218 | { get { return UTF8ToString(UnsafeNativeMethods.sqlite3_libversion(), -1); } } | < < < < < < < < | 204 205 206 207 208 209 210 211 212 213 214 215 216 217 | { get { return UTF8ToString(UnsafeNativeMethods.sqlite3_libversion(), -1); } } internal static string SQLiteSourceId { get { return UTF8ToString(UnsafeNativeMethods.sqlite3_sourceid(), -1); } } |
︙ | ︙ | |||
514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 | "{0}.", baseSchemaName), String.Empty); } } SQLiteConnectionFlags flags = (cnn != null) ? cnn.Flags : SQLiteConnectionFlags.Default; if ((flags & SQLiteConnectionFlags.LogPrepare) == SQLiteConnectionFlags.LogPrepare) { if ((strSql == null) || (strSql.Length == 0) || (strSql.Trim().Length == 0)) SQLiteLog.LogMessage("Preparing {<nothing>}..."); else SQLiteLog.LogMessage(String.Format( CultureInfo.CurrentCulture, "Preparing {{{0}}}...", strSql)); } IntPtr stmt = IntPtr.Zero; IntPtr ptr = IntPtr.Zero; int len = 0; SQLiteErrorCode n = SQLiteErrorCode.Schema; int retries = 0; byte[] b = ToUTF8(strSql); | > > | 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 | "{0}.", baseSchemaName), String.Empty); } } SQLiteConnectionFlags flags = (cnn != null) ? cnn.Flags : SQLiteConnectionFlags.Default; #if !PLATFORM_COMPACTFRAMEWORK if ((flags & SQLiteConnectionFlags.LogPrepare) == SQLiteConnectionFlags.LogPrepare) { if ((strSql == null) || (strSql.Length == 0) || (strSql.Trim().Length == 0)) SQLiteLog.LogMessage("Preparing {<nothing>}..."); else SQLiteLog.LogMessage(String.Format( CultureInfo.CurrentCulture, "Preparing {{{0}}}...", strSql)); } #endif IntPtr stmt = IntPtr.Zero; IntPtr ptr = IntPtr.Zero; int len = 0; SQLiteErrorCode n = SQLiteErrorCode.Schema; int retries = 0; byte[] b = ToUTF8(strSql); |
︙ | ︙ | |||
550 551 552 553 554 555 556 | // do nothing. } finally /* NOTE: Thread.Abort() protection. */ { #if !SQLITE_STANDARD n = UnsafeNativeMethods.sqlite3_prepare_interop(_sql, psql, b.Length - 1, out stmt, out ptr, out len); #else | < < < < | 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 | // do nothing. } finally /* NOTE: Thread.Abort() protection. */ { #if !SQLITE_STANDARD n = UnsafeNativeMethods.sqlite3_prepare_interop(_sql, psql, b.Length - 1, out stmt, out ptr, out len); #else n = UnsafeNativeMethods.sqlite3_prepare(_sql, psql, b.Length - 1, out stmt, out ptr); len = -1; #endif #if !NET_COMPACT_20 && TRACE_STATEMENT Trace.WriteLine(String.Format("Prepare ({0}): {1}", n, stmt)); #endif |
︙ | ︙ | |||
651 652 653 654 655 656 657 658 659 660 661 662 663 664 | } finally { handle.Free(); } } protected static void LogBind(SQLiteStatementHandle handle, int index) { IntPtr handleIntPtr = handle; SQLiteLog.LogMessage(String.Format( "Binding statement {0} paramter #{1} as NULL...", handleIntPtr, index)); | > | 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 | } finally { handle.Free(); } } #if !PLATFORM_COMPACTFRAMEWORK protected static void LogBind(SQLiteStatementHandle handle, int index) { IntPtr handleIntPtr = handle; SQLiteLog.LogMessage(String.Format( "Binding statement {0} paramter #{1} as NULL...", handleIntPtr, index)); |
︙ | ︙ | |||
725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 | { IntPtr handleIntPtr = handle; SQLiteLog.LogMessage(String.Format( "Binding statement {0} paramter #{1} as type {2} with value {{{3}}}...", handleIntPtr, index, typeof(Byte[]), (value != null) ? ToHexadecimalString(value) : "<null>")); } internal override void Bind_Double(SQLiteStatement stmt, SQLiteConnectionFlags flags, int index, double value) { SQLiteStatementHandle handle = stmt._sqlite_stmt; if ((flags & SQLiteConnectionFlags.LogBind) == SQLiteConnectionFlags.LogBind) { LogBind(handle, index, value); } | > > < > > < < < < < < < < < < < < < < | < | 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 | { IntPtr handleIntPtr = handle; SQLiteLog.LogMessage(String.Format( "Binding statement {0} paramter #{1} as type {2} with value {{{3}}}...", handleIntPtr, index, typeof(Byte[]), (value != null) ? ToHexadecimalString(value) : "<null>")); } #endif internal override void Bind_Double(SQLiteStatement stmt, SQLiteConnectionFlags flags, int index, double value) { SQLiteStatementHandle handle = stmt._sqlite_stmt; #if !PLATFORM_COMPACTFRAMEWORK if ((flags & SQLiteConnectionFlags.LogBind) == SQLiteConnectionFlags.LogBind) { LogBind(handle, index, value); } SQLiteErrorCode n = UnsafeNativeMethods.sqlite3_bind_double(handle, index, value); #else SQLiteErrorCode n = UnsafeNativeMethods.sqlite3_bind_double_interop(handle, index, ref value); #endif if (n != SQLiteErrorCode.Ok) throw new SQLiteException(n, GetLastError()); } internal override void Bind_Int32(SQLiteStatement stmt, SQLiteConnectionFlags flags, int index, int value) { SQLiteStatementHandle handle = stmt._sqlite_stmt; #if !PLATFORM_COMPACTFRAMEWORK if ((flags & SQLiteConnectionFlags.LogBind) == SQLiteConnectionFlags.LogBind) { LogBind(handle, index, value); } #endif SQLiteErrorCode n = UnsafeNativeMethods.sqlite3_bind_int(handle, index, value); if (n != SQLiteErrorCode.Ok) throw new SQLiteException(n, GetLastError()); } internal override void Bind_UInt32(SQLiteStatement stmt, SQLiteConnectionFlags flags, int index, uint value) { SQLiteStatementHandle handle = stmt._sqlite_stmt; #if !PLATFORM_COMPACTFRAMEWORK if ((flags & SQLiteConnectionFlags.LogBind) == SQLiteConnectionFlags.LogBind) { LogBind(handle, index, value); } #endif SQLiteErrorCode n = UnsafeNativeMethods.sqlite3_bind_uint(handle, index, value); if (n != SQLiteErrorCode.Ok) throw new SQLiteException(n, GetLastError()); } internal override void Bind_Int64(SQLiteStatement stmt, SQLiteConnectionFlags flags, int index, long value) { SQLiteStatementHandle handle = stmt._sqlite_stmt; |
︙ | ︙ | |||
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 | } internal override int Bind_ParamCount(SQLiteStatement stmt, SQLiteConnectionFlags flags) { SQLiteStatementHandle handle = stmt._sqlite_stmt; int value = UnsafeNativeMethods.sqlite3_bind_parameter_count(handle); if ((flags & SQLiteConnectionFlags.LogBind) == SQLiteConnectionFlags.LogBind) { IntPtr handleIntPtr = handle; SQLiteLog.LogMessage(String.Format( "Statement {0} paramter count is {1}.", handleIntPtr, value)); } return value; } internal override string Bind_ParamName(SQLiteStatement stmt, SQLiteConnectionFlags flags, int index) { SQLiteStatementHandle handle = stmt._sqlite_stmt; string name; #if !SQLITE_STANDARD int len; name = UTF8ToString(UnsafeNativeMethods.sqlite3_bind_parameter_name_interop(handle, index, out len), len); #else name = UTF8ToString(UnsafeNativeMethods.sqlite3_bind_parameter_name(handle, index), -1); #endif if ((flags & SQLiteConnectionFlags.LogBind) == SQLiteConnectionFlags.LogBind) { IntPtr handleIntPtr = handle; SQLiteLog.LogMessage(String.Format( "Statement {0} paramter #{1} name is {{{2}}}.", handleIntPtr, index, name)); } return name; } internal override int Bind_ParamIndex(SQLiteStatement stmt, SQLiteConnectionFlags flags, string paramName) { SQLiteStatementHandle handle = stmt._sqlite_stmt; int index = UnsafeNativeMethods.sqlite3_bind_parameter_index(handle, ToUTF8(paramName)); if ((flags & SQLiteConnectionFlags.LogBind) == SQLiteConnectionFlags.LogBind) { IntPtr handleIntPtr = handle; SQLiteLog.LogMessage(String.Format( "Statement {0} paramter index of name {{{1}}} is #{2}.", handleIntPtr, paramName, index)); } return index; } internal override int ColumnCount(SQLiteStatement stmt) { return UnsafeNativeMethods.sqlite3_column_count(stmt._sqlite_stmt); | > > > > > > | 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 | } internal override int Bind_ParamCount(SQLiteStatement stmt, SQLiteConnectionFlags flags) { SQLiteStatementHandle handle = stmt._sqlite_stmt; int value = UnsafeNativeMethods.sqlite3_bind_parameter_count(handle); #if !PLATFORM_COMPACTFRAMEWORK if ((flags & SQLiteConnectionFlags.LogBind) == SQLiteConnectionFlags.LogBind) { IntPtr handleIntPtr = handle; SQLiteLog.LogMessage(String.Format( "Statement {0} paramter count is {1}.", handleIntPtr, value)); } #endif return value; } internal override string Bind_ParamName(SQLiteStatement stmt, SQLiteConnectionFlags flags, int index) { SQLiteStatementHandle handle = stmt._sqlite_stmt; string name; #if !SQLITE_STANDARD int len; name = UTF8ToString(UnsafeNativeMethods.sqlite3_bind_parameter_name_interop(handle, index, out len), len); #else name = UTF8ToString(UnsafeNativeMethods.sqlite3_bind_parameter_name(handle, index), -1); #endif #if !PLATFORM_COMPACTFRAMEWORK if ((flags & SQLiteConnectionFlags.LogBind) == SQLiteConnectionFlags.LogBind) { IntPtr handleIntPtr = handle; SQLiteLog.LogMessage(String.Format( "Statement {0} paramter #{1} name is {{{2}}}.", handleIntPtr, index, name)); } #endif return name; } internal override int Bind_ParamIndex(SQLiteStatement stmt, SQLiteConnectionFlags flags, string paramName) { SQLiteStatementHandle handle = stmt._sqlite_stmt; int index = UnsafeNativeMethods.sqlite3_bind_parameter_index(handle, ToUTF8(paramName)); #if !PLATFORM_COMPACTFRAMEWORK if ((flags & SQLiteConnectionFlags.LogBind) == SQLiteConnectionFlags.LogBind) { IntPtr handleIntPtr = handle; SQLiteLog.LogMessage(String.Format( "Statement {0} paramter index of name {{{1}}} is #{2}.", handleIntPtr, paramName, index)); } #endif return index; } internal override int ColumnCount(SQLiteStatement stmt) { return UnsafeNativeMethods.sqlite3_column_count(stmt._sqlite_stmt); |
︙ | ︙ | |||
1152 1153 1154 1155 1156 1157 1158 | value = UnsafeNativeMethods.sqlite3_column_double(stmt._sqlite_stmt, index); #else UnsafeNativeMethods.sqlite3_column_double_interop(stmt._sqlite_stmt, index, out value); #endif return value; } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < | < | 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 | value = UnsafeNativeMethods.sqlite3_column_double(stmt._sqlite_stmt, index); #else UnsafeNativeMethods.sqlite3_column_double_interop(stmt._sqlite_stmt, index, out value); #endif return value; } internal override int GetInt32(SQLiteStatement stmt, int index) { return UnsafeNativeMethods.sqlite3_column_int(stmt._sqlite_stmt, index); } internal override long GetInt64(SQLiteStatement stmt, int index) { long value; #if !PLATFORM_COMPACTFRAMEWORK value = UnsafeNativeMethods.sqlite3_column_int64(stmt._sqlite_stmt, index); #else UnsafeNativeMethods.sqlite3_column_int64_interop(stmt._sqlite_stmt, index, out value); #endif return value; } internal override string GetText(SQLiteStatement stmt, int index) { #if !SQLITE_STANDARD int len; return UTF8ToString(UnsafeNativeMethods.sqlite3_column_text_interop(stmt._sqlite_stmt, index, out len), len); #else return UTF8ToString(UnsafeNativeMethods.sqlite3_column_text(stmt._sqlite_stmt, index), -1); #endif } internal override DateTime GetDateTime(SQLiteStatement stmt, int index) { #if !SQLITE_STANDARD int len; return ToDateTime(UnsafeNativeMethods.sqlite3_column_text_interop(stmt._sqlite_stmt, index, out len), len); #else return ToDateTime(UnsafeNativeMethods.sqlite3_column_text(stmt._sqlite_stmt, index), -1); #endif } internal override long GetBytes(SQLiteStatement stmt, int index, int nDataOffset, byte[] bDest, int nStart, int nLength) { int nlen = UnsafeNativeMethods.sqlite3_column_bytes(stmt._sqlite_stmt, index); |
︙ | ︙ | |||
1434 1435 1436 1437 1438 1439 1440 | internal override string GetParamValueText(IntPtr ptr) { #if !SQLITE_STANDARD int len; return UTF8ToString(UnsafeNativeMethods.sqlite3_value_text_interop(ptr, out len), len); #else | | < | 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 | internal override string GetParamValueText(IntPtr ptr) { #if !SQLITE_STANDARD int len; return UTF8ToString(UnsafeNativeMethods.sqlite3_value_text_interop(ptr, out len), len); #else return UTF8ToString(UnsafeNativeMethods.sqlite3_value_text(ptr), -1); #endif } internal override TypeAffinity GetParamValueType(IntPtr ptr) { return UnsafeNativeMethods.sqlite3_value_type(ptr); } |
︙ | ︙ | |||
1840 1841 1842 1843 1844 1845 1846 | IntPtr handlePtr = handle; if (handlePtr == IntPtr.Zero) throw new InvalidOperationException( "Backup object has an invalid handle pointer."); | < < < < < < < < | 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 | IntPtr handlePtr = handle; if (handlePtr == IntPtr.Zero) throw new InvalidOperationException( "Backup object has an invalid handle pointer."); SQLiteErrorCode n = UnsafeNativeMethods.sqlite3_backup_finish(handlePtr); handle.SetHandleAsInvalid(); if ((n != SQLiteErrorCode.Ok) && (n != backup._stepResult)) throw new SQLiteException(n, GetLastError()); } /////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> |
︙ | ︙ | |||
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 | { // // BUGFIX: Prevent races with other threads for this entire block, due // to the try/finally semantics. See ticket [72905c9a77]. // lock (syncRoot) { // // NOTE: Save the state of the logging class and then restore it // after we are done to avoid logging too many false errors. // bool savedEnabled = SQLiteLog.Enabled; SQLiteLog.Enabled = false; try { // // NOTE: This method [ab]uses the fact that SQLite will always // return SQLITE_ERROR for any unknown configuration option // *unless* the SQLite library has already been initialized. // In that case it will always return SQLITE_MISUSE. // SQLiteErrorCode rc = UnsafeNativeMethods.sqlite3_config_none( SQLiteConfigOpsEnum.SQLITE_CONFIG_NONE); return (rc == SQLiteErrorCode.Misuse); } finally { SQLiteLog.Enabled = savedEnabled; } } } /// <summary> /// Helper function to retrieve a column of data from an active statement. /// </summary> /// <param name="stmt">The statement being step()'d through</param> | > > > > < | < < < > | < | < < < < < | | 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 | { // // BUGFIX: Prevent races with other threads for this entire block, due // to the try/finally semantics. See ticket [72905c9a77]. // lock (syncRoot) { #if !PLATFORM_COMPACTFRAMEWORK // // NOTE: Save the state of the logging class and then restore it // after we are done to avoid logging too many false errors. // bool savedEnabled = SQLiteLog.Enabled; SQLiteLog.Enabled = false; try { #endif // // NOTE: This method [ab]uses the fact that SQLite will always // return SQLITE_ERROR for any unknown configuration option // *unless* the SQLite library has already been initialized. // In that case it will always return SQLITE_MISUSE. // SQLiteErrorCode rc = UnsafeNativeMethods.sqlite3_config_none( SQLiteConfigOpsEnum.SQLITE_CONFIG_NONE); return (rc == SQLiteErrorCode.Misuse); #if !PLATFORM_COMPACTFRAMEWORK } finally { SQLiteLog.Enabled = savedEnabled; } #endif } } /// <summary> /// Helper function to retrieve a column of data from an active statement. /// </summary> /// <param name="stmt">The statement being step()'d through</param> /// <param name="index">The column index to retrieve</param> /// <param name="typ">The type of data contained in the column. If Uninitialized, this function will retrieve the datatype information.</param> /// <returns>Returns the data in the column</returns> internal override object GetValue(SQLiteStatement stmt, int index, SQLiteType typ) { if (IsNull(stmt, index)) return DBNull.Value; TypeAffinity aff = typ.Affinity; Type t = null; if (typ.Type != DbType.Object) { t = SQLiteConvert.SQLiteTypeToType(typ); aff = TypeToAffinity(t); } switch (aff) { case TypeAffinity.Blob: if (typ.Type == DbType.Guid && typ.Affinity == TypeAffinity.Text) return new Guid(GetText(stmt, index)); int n = (int)GetBytes(stmt, index, 0, null, 0, 0); byte[] b = new byte[n]; GetBytes(stmt, index, 0, b, 0, n); if (typ.Type == DbType.Guid && n == 16) return new Guid(b); return b; case TypeAffinity.DateTime: return GetDateTime(stmt, index); case TypeAffinity.Double: if (t == null) return GetDouble(stmt, index); else return Convert.ChangeType(GetDouble(stmt, index), t, null); case TypeAffinity.Int64: if (t == null) return GetInt64(stmt, index); else return Convert.ChangeType(GetInt64(stmt, index), t, null); default: return GetText(stmt, index); } } internal override int GetCursorForTable(SQLiteStatement stmt, int db, int rootPage) { |
︙ | ︙ |
Changes to System.Data.SQLite/SQLite3_UTF16.cs.
︙ | ︙ | |||
213 214 215 216 217 218 219 | internal override string GetText(SQLiteStatement stmt, int index) { #if !SQLITE_STANDARD int len; return UTF16ToString(UnsafeNativeMethods.sqlite3_column_text16_interop(stmt._sqlite_stmt, index, out len), len); #else | | < | 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 | internal override string GetText(SQLiteStatement stmt, int index) { #if !SQLITE_STANDARD int len; return UTF16ToString(UnsafeNativeMethods.sqlite3_column_text16_interop(stmt._sqlite_stmt, index, out len), len); #else return UTF16ToString(UnsafeNativeMethods.sqlite3_column_text16(stmt._sqlite_stmt, index), -1); #endif } internal override string ColumnOriginalName(SQLiteStatement stmt, int index) { #if !SQLITE_STANDARD int len; |
︙ | ︙ | |||
254 255 256 257 258 259 260 | internal override string GetParamValueText(IntPtr ptr) { #if !SQLITE_STANDARD int len; return UTF16ToString(UnsafeNativeMethods.sqlite3_value_text16_interop(ptr, out len), len); #else | | < | 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 | internal override string GetParamValueText(IntPtr ptr) { #if !SQLITE_STANDARD int len; return UTF16ToString(UnsafeNativeMethods.sqlite3_value_text16_interop(ptr, out len), len); #else return UTF16ToString(UnsafeNativeMethods.sqlite3_value_text16(ptr), -1); #endif } internal override void ReturnError(IntPtr context, string value) { UnsafeNativeMethods.sqlite3_result_error16(context, value, value.Length * 2); } |
︙ | ︙ |
Changes to System.Data.SQLite/SQLiteBase.cs.
︙ | ︙ | |||
23 24 25 26 27 28 29 | : base(fmt, kind) { } /// <summary> /// Returns a string representing the active version of SQLite /// </summary> internal abstract string Version { get; } /// <summary> | < < < < | 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | : base(fmt, kind) { } /// <summary> /// Returns a string representing the active version of SQLite /// </summary> internal abstract string Version { get; } /// <summary> /// Returns 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; } |
︙ | ︙ | |||
159 160 161 162 163 164 165 | internal abstract string ColumnOriginalName(SQLiteStatement stmt, int index); internal abstract string ColumnDatabaseName(SQLiteStatement stmt, int index); internal abstract string ColumnTableName(SQLiteStatement stmt, int index); internal abstract void ColumnMetaData(string dataBase, string table, string column, out string dataType, out string collateSequence, out bool notNull, out bool primaryKey, out bool autoIncrement); internal abstract void GetIndexColumnExtendedInfo(string database, string index, string column, out int sortMode, out int onError, out string collationSequence); internal abstract double GetDouble(SQLiteStatement stmt, int index); | < < < < < < | 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 | internal abstract string ColumnOriginalName(SQLiteStatement stmt, int index); internal abstract string ColumnDatabaseName(SQLiteStatement stmt, int index); internal abstract string ColumnTableName(SQLiteStatement stmt, int index); internal abstract void ColumnMetaData(string dataBase, string table, string column, out string dataType, out string collateSequence, out bool notNull, out bool primaryKey, out bool autoIncrement); internal abstract void GetIndexColumnExtendedInfo(string database, string index, string column, out int sortMode, out int onError, out string collationSequence); internal abstract double GetDouble(SQLiteStatement stmt, int index); internal abstract Int32 GetInt32(SQLiteStatement stmt, int index); internal abstract Int64 GetInt64(SQLiteStatement stmt, int index); internal abstract string GetText(SQLiteStatement stmt, int index); internal abstract long GetBytes(SQLiteStatement stmt, int index, int nDataoffset, byte[] bDest, int nStart, int nLength); internal abstract long GetChars(SQLiteStatement stmt, int index, int nDataoffset, char[] bDest, int nStart, int nLength); internal abstract DateTime GetDateTime(SQLiteStatement stmt, int index); internal abstract bool IsNull(SQLiteStatement stmt, int index); internal abstract void CreateCollation(string strCollation, SQLiteCollation func, SQLiteCollation func16); |
︙ | ︙ | |||
267 268 269 270 271 272 273 | /// zero otherwise. /// </returns> internal abstract bool IsInitialized(); internal abstract int GetCursorForTable(SQLiteStatement stmt, int database, int rootPage); internal abstract long GetRowIdForCursor(SQLiteStatement stmt, int cursor); | | | 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 | /// zero otherwise. /// </returns> internal abstract bool IsInitialized(); internal abstract int GetCursorForTable(SQLiteStatement stmt, int database, int rootPage); internal abstract long GetRowIdForCursor(SQLiteStatement stmt, int cursor); internal abstract object GetValue(SQLiteStatement stmt, int index, SQLiteType typ); internal abstract bool AutoCommit { get; } internal abstract SQLiteErrorCode FileControl(string zDbName, int op, IntPtr pArg); |
︙ | ︙ | |||
583 584 585 586 587 588 589 | #else lock (hdl) #endif { #if !SQLITE_STANDARD SQLiteErrorCode n = UnsafeNativeMethods.sqlite3_close_interop(db); #else | | | < < | < < < < < < < < | | < > | < < < < < < | | < | < < | < < | 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 | #else lock (hdl) #endif { #if !SQLITE_STANDARD SQLiteErrorCode n = UnsafeNativeMethods.sqlite3_close_interop(db); #else ResetConnection(hdl, db); SQLiteErrorCode n; try { n = UnsafeNativeMethods.sqlite3_close_v2(db); } catch (EntryPointNotFoundException) { n = UnsafeNativeMethods.sqlite3_close(db); } #endif if (n != SQLiteErrorCode.Ok) throw new SQLiteException(n, GetLastError(hdl, db)); } } } internal static bool ResetConnection(SQLiteConnectionHandle hdl, IntPtr db, bool canThrow) { if ((hdl == null) || (db == IntPtr.Zero)) return false; bool result = false; |
︙ | ︙ | |||
780 781 782 783 784 785 786 | /// <summary> /// Skip adding the extension functions provided by the native /// interop assembly. /// </summary> NoExtensionFunctions = 0x20, | < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 749 750 751 752 753 754 755 756 757 758 759 760 761 762 | /// <summary> /// Skip adding the extension functions provided by the native /// interop assembly. /// </summary> NoExtensionFunctions = 0x20, /// <summary> /// Enable all logging. /// </summary> LogAll = LogPrepare | LogPreBind | LogBind | LogCallbackException | LogBackup, /// <summary> |
︙ | ︙ |
Changes to System.Data.SQLite/SQLiteCommand.cs.
︙ | ︙ | |||
18 19 20 21 22 23 24 | /// 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 { | < < < < < < < | 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | /// SQLite implementation of DbCommand. /// </summary> #if !PLATFORM_COMPACTFRAMEWORK [Designer("SQLite.Designer.SQLiteCommandDesigner, SQLite.Designer, Version=" + SQLite3.DesignerVersion + ", Culture=neutral, PublicKeyToken=db937bc2d44ff139"), ToolboxItem(true)] #endif public sealed class SQLiteCommand : DbCommand, ICloneable { /// <summary> /// The command text this command is based on /// </summary> private string _commandText; /// <summary> /// The connection the command is associated with /// </summary> |
︙ | ︙ | |||
231 232 233 234 235 236 237 | finally { base.Dispose(disposing); } } #endregion | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 224 225 226 227 228 229 230 231 232 233 234 235 236 237 | finally { base.Dispose(disposing); } } #endregion /////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// Clears and destroys all statements currently prepared /// </summary> internal void ClearCommands() { |
︙ | ︙ | |||
634 635 636 637 638 639 640 | /// <param name="behavior">The behavior the data reader should adopt</param> /// <returns>Returns a SQLiteDataReader object</returns> protected override DbDataReader ExecuteDbDataReader(CommandBehavior behavior) { return ExecuteReader(behavior); } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 592 593 594 595 596 597 598 599 600 601 602 603 604 605 | /// <param name="behavior">The behavior the data reader should adopt</param> /// <returns>Returns a SQLiteDataReader object</returns> protected override DbDataReader ExecuteDbDataReader(CommandBehavior behavior) { return ExecuteReader(behavior); } /// <summary> /// Overrides the default behavior to return a SQLiteDataReader specialization class /// </summary> /// <param name="behavior">The flags to be associated with the reader</param> /// <returns>A SQLiteDataReader</returns> public new SQLiteDataReader ExecuteReader(CommandBehavior behavior) { |
︙ | ︙ |
Changes to System.Data.SQLite/SQLiteConnection.cs.
︙ | ︙ | |||
12 13 14 15 16 17 18 | using System.Data.Common; using System.Diagnostics; using System.Collections.Generic; using System.Globalization; using System.ComponentModel; using System.Runtime.InteropServices; using System.IO; | < | 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | using System.Data.Common; using System.Diagnostics; using System.Collections.Generic; using System.Globalization; using System.ComponentModel; using System.Runtime.InteropServices; using System.IO; ///////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// Event data for connection event handlers. /// </summary> public class ConnectionEventArgs : EventArgs |
︙ | ︙ | |||
179 180 181 182 183 184 185 | /// <item> /// <description>Password</description> /// <description>{password} - Using this parameter requires that the CryptoAPI based codec be enabled at compile-time for both the native interop assembly and the core managed assemblies; otherwise, using this parameter may result in an exception being thrown when attempting to open the connection.</description> /// <description>N</description> /// <description></description> /// </item> /// <item> | < < < < < < < < | < < < < < | 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 | /// <item> /// <description>Password</description> /// <description>{password} - Using this parameter requires that the CryptoAPI based codec be enabled at compile-time for both the native interop assembly and the core managed assemblies; otherwise, using this parameter may result in an exception being thrown when attempting to open the connection.</description> /// <description>N</description> /// <description></description> /// </item> /// <item> /// <description>Enlist</description> /// <description><b>Y</b> - Automatically enlist in distributed transactions<br/><b>N</b> - No automatic enlistment</description> /// <description>N</description> /// <description>Y</description> /// </item> /// <item> /// <description>Pooling</description> /// <description><b>True</b> - Use connection pooling<br/><b>False</b> - Do not use connection pooling</description> /// <description>N</description> /// <description>False</description> /// </item> /// <item> /// <description>FailIfMissing</description> /// <description><b>True</b> - Don't create the database if it does not exist, throw an error instead<br/><b>False</b> - Automatically create the database if it does not exist</description> /// <description>N</description> |
︙ | ︙ | |||
306 307 308 309 310 311 312 | private const SQLiteJournalModeEnum DefaultJournalMode = SQLiteJournalModeEnum.Default; private const IsolationLevel DefaultIsolationLevel = IsolationLevel.Serializable; private const SQLiteDateFormats DefaultDateTimeFormat = SQLiteDateFormats.ISO8601; private const DateTimeKind DefaultDateTimeKind = DateTimeKind.Unspecified; private const string DefaultDataSource = null; private const string DefaultUri = null; private const string DefaultFullUri = null; | < | 292 293 294 295 296 297 298 299 300 301 302 303 304 305 | private const SQLiteJournalModeEnum DefaultJournalMode = SQLiteJournalModeEnum.Default; private const IsolationLevel DefaultIsolationLevel = IsolationLevel.Serializable; private const SQLiteDateFormats DefaultDateTimeFormat = SQLiteDateFormats.ISO8601; private const DateTimeKind DefaultDateTimeKind = DateTimeKind.Unspecified; private const string DefaultDataSource = null; private const string DefaultUri = null; private const string DefaultFullUri = null; private const string DefaultPassword = null; private const int DefaultVersion = 3; private const int DefaultPageSize = 1024; private const int DefaultMaxPageCount = 0; private const int DefaultCacheSize = 2000; private const int DefaultMaxPoolSize = 100; private const int DefaultConnectionTimeout = 30; |
︙ | ︙ | |||
345 346 347 348 349 350 351 | /// </summary> private static object _syncRoot = new object(); /// <summary> /// Static variable to store the connection event handlers to call. /// </summary> private static event SQLiteConnectionEventHandler _handlers; | < < < < < < < | 330 331 332 333 334 335 336 337 338 339 340 341 342 343 | /// </summary> private static object _syncRoot = new object(); /// <summary> /// Static variable to store the connection event handlers to call. /// </summary> private static event SQLiteConnectionEventHandler _handlers; #endregion /////////////////////////////////////////////////////////////////////////////////////////////// #region Private Data /// <summary> /// State of the current connection |
︙ | ︙ | |||
420 421 422 423 424 425 426 | private SQLiteConnectionFlags _flags; /// <summary> /// Default command timeout /// </summary> private int _defaultTimeout = 30; | < < < < < < | 398 399 400 401 402 403 404 405 406 407 408 409 410 411 | private SQLiteConnectionFlags _flags; /// <summary> /// Default command timeout /// </summary> private int _defaultTimeout = 30; internal bool _binaryGuid; internal long _version; private event SQLiteUpdateEventHandler _updateHandler; private event SQLiteCommitHandler _commitHandler; private event SQLiteTraceEventHandler _traceHandler; |
︙ | ︙ | |||
462 463 464 465 466 467 468 | /// </summary> public SQLiteConnection() : this("") { } /// <summary> | | | < < < < < < < < < < < < < < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 | /// </summary> public SQLiteConnection() : this("") { } /// <summary> /// Initializes the connection with the specified connection string /// </summary> /// <param name="connectionString">The connection string to use on the connection</param> public SQLiteConnection(string connectionString) { #if (SQLITE_STANDARD || USE_INTEROP_DLL || PLATFORM_COMPACTFRAMEWORK) && PRELOAD_NATIVE_LIBRARY UnsafeNativeMethods.Initialize(); #endif #if !PLATFORM_COMPACTFRAMEWORK SQLiteLog.Initialize(); #endif _flags = SQLiteConnectionFlags.Default; _connectionState = ConnectionState.Closed; _connectionString = ""; //_commandList = new List<WeakReference>(); if (connectionString != null) ConnectionString = connectionString; } /// <summary> /// Clones the settings and connection string from an existing connection. If the existing connection is already open, this /// function will open its own connection, enumerate any attached databases of the original connection, and automatically /// attach to them. /// </summary> /// <param name="connection"></param> public SQLiteConnection(SQLiteConnection connection) : this(connection.ConnectionString) { string str; if (connection.State == ConnectionState.Open) { |
︙ | ︙ | |||
635 636 637 638 639 640 641 | lock (_syncRoot) { _handlers -= value; } } } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 558 559 560 561 562 563 564 565 566 567 568 569 570 571 | lock (_syncRoot) { _handlers -= value; } } } /////////////////////////////////////////////////////////////////////////////////////////////// #region Backup API Members /// <summary> /// Backs up the database, using the specified database connection as the /// destination. /// </summary> |
︙ | ︙ | |||
770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 | // NOTE: There is no point in calling the native API to copy // zero pages as it does nothing; therefore, stop now. // if (pages == 0) break; } } catch (Exception e) { if ((_flags & SQLiteConnectionFlags.LogBackup) == SQLiteConnectionFlags.LogBackup) { SQLiteLog.LogMessage(String.Format( CultureInfo.CurrentCulture, "Caught exception while backing up database: {0}", e)); } throw; } finally { if (backup != null) sqliteBase.FinishBackup(backup); /* throw */ } } #endregion | > > | 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 | // NOTE: There is no point in calling the native API to copy // zero pages as it does nothing; therefore, stop now. // if (pages == 0) break; } } #if !PLATFORM_COMPACTFRAMEWORK catch (Exception e) { if ((_flags & SQLiteConnectionFlags.LogBackup) == SQLiteConnectionFlags.LogBackup) { SQLiteLog.LogMessage(String.Format( CultureInfo.CurrentCulture, "Caught exception while backing up database: {0}", e)); } throw; } #endif finally { if (backup != null) sqliteBase.FinishBackup(backup); /* throw */ } } #endregion |
︙ | ︙ | |||
1195 1196 1197 1198 1199 1200 1201 | /// <item> /// <description>Password</description> /// <description>{password} - Using this parameter requires that the CryptoAPI based codec be enabled at compile-time for both the native interop assembly and the core managed assemblies; otherwise, using this parameter may result in an exception being thrown when attempting to open the connection.</description> /// <description>N</description> /// <description></description> /// </item> /// <item> | < < < < < < < < | < < < < < | 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 | /// <item> /// <description>Password</description> /// <description>{password} - Using this parameter requires that the CryptoAPI based codec be enabled at compile-time for both the native interop assembly and the core managed assemblies; otherwise, using this parameter may result in an exception being thrown when attempting to open the connection.</description> /// <description>N</description> /// <description></description> /// </item> /// <item> /// <description>Enlist</description> /// <description><b>Y</b> - Automatically enlist in distributed transactions<br/><b>N</b> - No automatic enlistment</description> /// <description>N</description> /// <description>Y</description> /// </item> /// <item> /// <description>Pooling</description> /// <description><b>True</b> - Use connection pooling<br/><b>False</b> - Do not use connection pooling</description> /// <description>N</description> /// <description>False</description> /// </item> /// <item> /// <description>FailIfMissing</description> /// <description><b>True</b> - Don't create the database if it does not exist, throw an error instead<br/><b>False</b> - Automatically create the database if it does not exist</description> /// <description>N</description> |
︙ | ︙ | |||
1386 1387 1388 1389 1390 1391 1392 | else if (path.StartsWith ("/", StringComparison.OrdinalIgnoreCase)) return path; else throw new InvalidOperationException ("Invalid connection string: invalid URI"); } /// <summary> | | < | > | < < < < < < < < | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 | else if (path.StartsWith ("/", StringComparison.OrdinalIgnoreCase)) return path; else throw new InvalidOperationException ("Invalid connection string: invalid URI"); } /// <summary> /// Parses the connection string into component parts /// </summary> /// <param name="connectionString">The connection string to parse</param> /// <returns>An array of key-value pairs representing each parameter of the connection string</returns> internal static SortedList<string, string> ParseConnectionString(string connectionString) { string s = connectionString; int n; SortedList<string, string> ls = new SortedList<string, string>(StringComparer.OrdinalIgnoreCase); // First split into semi-colon delimited values. The Split() function of SQLiteBase accounts for and properly // skips semi-colons in quoted strings string[] arParts = SQLiteConvert.Split(s, ';'); int x = arParts.Length; // For each semi-colon piece, split into key and value pairs by the presence of the = sign for (n = 0; n < x; n++) { int indexOf = arParts[n].IndexOf('='); if (indexOf != -1) ls.Add(arParts[n].Substring(0, indexOf), arParts[n].Substring(indexOf + 1)); else throw new ArgumentException(String.Format(CultureInfo.CurrentCulture, "Invalid ConnectionString format for part \"{0}\"", arParts[n])); } return ls; } #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) { |
︙ | ︙ | |||
1553 1554 1555 1556 1557 1558 1559 | { // do nothing. } return null; } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 | { // do nothing. } return null; } /// <summary> /// Enables or disabled extension loading. /// </summary> /// <param name="enable"> /// True to enable loading of extensions, false to disable. /// </param> public void EnableExtensions( |
︙ | ︙ | |||
1650 1651 1652 1653 1654 1655 1656 | if (_sql == null) throw new InvalidOperationException( "Database connection not valid for loading extensions."); _sql.LoadExtension(fileName, procName); } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < < < < > | 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 | if (_sql == null) throw new InvalidOperationException( "Database connection not valid for loading extensions."); _sql.LoadExtension(fileName, procName); } /// <summary> /// Opens the connection using the parameters found in the <see cref="ConnectionString" />. /// </summary> public override void Open() { CheckDisposed(); OnChanged(this, new ConnectionEventArgs( SQLiteConnectionEventType.Opening, null, null, null, null, null)); if (_connectionState != ConnectionState.Closed) throw new InvalidOperationException(); Close(); SortedList<string, string> opts = ParseConnectionString(_connectionString); object enumValue; enumValue = TryParseEnum(typeof(SQLiteConnectionFlags), FindKey(opts, "Flags", DefaultFlags.ToString()), true); _flags = (enumValue is SQLiteConnectionFlags) ? (SQLiteConnectionFlags)enumValue : DefaultFlags; bool fullUri = false; string fileName; if (Convert.ToInt32(FindKey(opts, "Version", DefaultVersion.ToString()), CultureInfo.InvariantCulture) != DefaultVersion) throw new NotSupportedException(String.Format(CultureInfo.CurrentCulture, "Only SQLite Version {0} is supported at this time", DefaultVersion)); fileName = FindKey(opts, "Data Source", DefaultDataSource); fileName = UnwrapFileName(fileName); if (String.IsNullOrEmpty(fileName)) { fileName = FindKey(opts, "Uri", DefaultUri); if (String.IsNullOrEmpty(fileName)) { fileName = FindKey(opts, "FullUri", DefaultFullUri); |
︙ | ︙ | |||
1891 1892 1893 1894 1895 1896 1897 | flags |= SQLiteOpenFlagsEnum.Uri; _sql.Open(fileName, _flags, flags, maxPoolSize, usePooling); _binaryGuid = SQLiteConvert.ToBoolean(FindKey(opts, "BinaryGUID", DefaultBinaryGUID.ToString())); #if INTEROP_CODEC | < < < < < < < < < < < < < < < < < < | | | | | | | 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 | flags |= SQLiteOpenFlagsEnum.Uri; _sql.Open(fileName, _flags, flags, maxPoolSize, usePooling); _binaryGuid = SQLiteConvert.ToBoolean(FindKey(opts, "BinaryGUID", DefaultBinaryGUID.ToString())); #if INTEROP_CODEC string password = FindKey(opts, "Password", DefaultPassword); if (!String.IsNullOrEmpty(password)) _sql.SetPassword(System.Text.UTF8Encoding.UTF8.GetBytes(password)); else if (_password != null) _sql.SetPassword(_password); _password = null; #endif if (!fullUri) _dataSource = Path.GetFileNameWithoutExtension(fileName); else _dataSource = fileName; |
︙ | ︙ | |||
2064 2065 2066 2067 2068 2069 2070 | /// </summary> public int DefaultTimeout { get { CheckDisposed(); return _defaultTimeout; } set { CheckDisposed(); _defaultTimeout = value; } } | < < < < < < < < < < | 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 | /// </summary> public int DefaultTimeout { get { CheckDisposed(); return _defaultTimeout; } set { CheckDisposed(); _defaultTimeout = value; } } /// <summary> /// Gets/sets the extra behavioral flags for this connection. See the /// <see cref="SQLiteConnectionFlags" /> enumeration for a list of /// possible values. /// </summary> public SQLiteConnectionFlags Flags { |
︙ | ︙ | |||
2123 2124 2125 2126 2127 2128 2129 | if (_sql == null) throw new InvalidOperationException("Database connection not valid for getting last insert rowid."); return _sql.LastInsertRowId; } } | < < < < < < < < < < < < < < < < < < < | 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 | if (_sql == null) throw new InvalidOperationException("Database connection not valid for getting last insert rowid."); return _sql.LastInsertRowId; } } /// <summary> /// 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 |
︙ | ︙ | |||
2263 2264 2265 2266 2267 2268 2269 | public SQLiteErrorCode Shutdown() { CheckDisposed(); // make sure we have an instance of the base class if (_sql == null) { | | < < < | 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 | public SQLiteErrorCode Shutdown() { CheckDisposed(); // make sure we have an instance of the base class if (_sql == null) { SortedList<string, string> opts = ParseConnectionString(_connectionString); object enumValue; enumValue = TryParseEnum(typeof(SQLiteDateFormats), FindKey(opts, "DateTimeFormat", DefaultDateTimeFormat.ToString()), true); SQLiteDateFormats dateFormat = (enumValue is SQLiteDateFormats) ? (SQLiteDateFormats)enumValue : DefaultDateTimeFormat; |
︙ | ︙ | |||
2360 2361 2362 2363 2364 2365 2366 | /// and if it already was password protected, the existing password must already have been supplied. /// </remarks> /// <param name="newPassword">The new password to assign to the database</param> public void ChangePassword(string newPassword) { CheckDisposed(); | | | 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 | /// and if it already was password protected, the existing password must already have been supplied. /// </remarks> /// <param name="newPassword">The new password to assign to the database</param> public void ChangePassword(string newPassword) { CheckDisposed(); ChangePassword(String.IsNullOrEmpty(newPassword) ? null : System.Text.UTF8Encoding.UTF8.GetBytes(newPassword)); } /// <summary> /// Change the password (or assign a password) to an open database. /// </summary> /// <remarks> /// No readers or writers may be active for this process. The database must already be open |
︙ | ︙ | |||
2390 2391 2392 2393 2394 2395 2396 | /// unusable for any operation until the password has been set. /// </summary> /// <param name="databasePassword">The password for the database</param> public void SetPassword(string databasePassword) { CheckDisposed(); | | | 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 | /// unusable for any operation until the password has been set. /// </summary> /// <param name="databasePassword">The password for the database</param> public void SetPassword(string databasePassword) { CheckDisposed(); SetPassword(String.IsNullOrEmpty(databasePassword) ? null : System.Text.UTF8Encoding.UTF8.GetBytes(databasePassword)); } /// <summary> /// Sets the password for a password-protected database. A password-protected database is /// unusable for any operation until the password has been set. /// </summary> /// <param name="databasePassword">The password for the database</param> |
︙ | ︙ | |||
2459 2460 2461 2462 2463 2464 2465 | Marshal.FreeHGlobal(pArg); } return rc; } /// <summary> | | | | | | < < < | | | | | | | | | 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 | Marshal.FreeHGlobal(pArg); } return rc; } /// <summary> /// Removes one set of surrounding single -OR- double quotes from the file /// name and returns the resulting file name. If the string is null, empty, /// or contains quotes that are not balanced, nothing is done and the original /// string will be returned. /// </summary> /// <param name="sourceFile">The database file name to process.</param> /// <returns>The modified database file name.</returns> private string UnwrapFileName(string sourceFile) { if (String.IsNullOrEmpty(sourceFile)) { // // NOTE: The string is null or empty, return it verbatim. // return sourceFile; } int length = sourceFile.Length; if (((sourceFile[0] == '\'') && (sourceFile[length - 1] == '\'')) || ((sourceFile[0] == '"') && (sourceFile[length - 1] == '"'))) { // // NOTE: Remove the first and last character. // return sourceFile.Substring(1, length - 2); } // // NOTE: No match, return the input string verbatim. // return sourceFile; } /// <summary> /// Expand the filename of the data source, resolving the |DataDirectory| /// macro as appropriate. /// </summary> /// <param name="sourceFile">The database filename to expand</param> |
︙ | ︙ |
Changes to System.Data.SQLite/SQLiteConnectionPool.cs.
1 2 3 4 5 6 7 8 9 | /******************************************************** * 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 { | | | < < < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < < < < < < | < < < < < | < < < < < < < < < | > | < < | < < < < < < < < < < < < < < < < < | < < | > | | < < < < < | | < < < | < | < < < < < < < < < < < < < < < < < < < | < | < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < | < < < < < < < < | < < < | | | | < < | | | | | < < | | | | | < < < < | | | < | < | < < < | < < | < < | < | | | | | | | | < < < < | < < < < < < | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < < < < | < < < < < < < < < < < < < < < < < < < < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | < < | < < < | < < < | < < < | < < < < < < < < < < < < < | | | | | | < | | | | | | < | | | | < | < | < | < | < | < | | | | | | < | < < | | < < < < | < | < | | | | | | < | | | | | | | | | | < | | < < | | | | | < | | | | | | | | | < | | | < | | | | | < | | | | | | < | | | | | | | > > > > > > > > > > > > > > > | | | | | | < < < < < < < < < < < < < < < < | < | | | | | | < | | | | | | | | | | | | | | | | | | | | | | | | | > > > > > > | | < > | > | | | | < < < | < < | > > > | < > > | > > > > | < > > > > > | > > | < < > > | | < < < | > | > > > > > | > > > > | > > > | < > > | | > > | > > > > > > > > > > > > > > > > | > > > > > > > > > > > > > > > > | | | | | < < < | | < | < < < | | | | | | | | < | < | < > | < | | | | | < | < | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 | /******************************************************** * ADO.NET 2.0 Data Provider for SQLite Version 3.X * Written by Robert Simpson (robert@blackcastlesoft.com) * * Released to the public domain, use at your own risk! ********************************************************/ namespace System.Data.SQLite { using System; using System.Collections.Generic; using System.Threading; internal static class SQLiteConnectionPool { /// <summary> /// Keeps track of connections made on a specified file. The PoolVersion dictates whether old objects get /// returned to the pool or discarded when no longer in use. /// </summary> internal class Pool { internal readonly Queue<WeakReference> Queue = new Queue<WeakReference>(); internal int PoolVersion; internal int MaxPoolSize; internal Pool(int version, int maxSize) { PoolVersion = version; MaxPoolSize = maxSize; } } /// <summary> /// The connection pool object /// </summary> private static SortedList<string, Pool> _connections = new SortedList<string, Pool>(StringComparer.OrdinalIgnoreCase); /// <summary> /// The default version number new pools will get /// </summary> private static int _poolVersion = 1; /// <summary> /// The number of connections successfully opened from any pool. /// This value is incremented by the Remove method. /// </summary> private static int _poolOpened = 0; /// <summary> /// The number of connections successfully closed from any pool. /// This value is incremented by the Add method. /// </summary> private static int _poolClosed = 0; /// <summary> /// Counts the number of pool entries matching the specified file name. /// </summary> /// <param name="fileName">The file name to match or null to match all files.</param> /// <param name="counts">The pool entry counts for each matching file.</param> /// <param name="openCount">The total number of connections successfully opened from any pool.</param> /// <param name="closeCount">The total number of connections successfully closed from any pool.</param> /// <param name="totalCount">The total number of pool entries for all matching files.</param> internal static void GetCounts( string fileName, ref Dictionary<string, int> counts, ref int openCount, ref int closeCount, ref int totalCount ) { lock (_connections) { openCount = _poolOpened; closeCount = _poolClosed; if (counts == null) { counts = new Dictionary<string, int>( StringComparer.OrdinalIgnoreCase); } if (fileName != null) { Pool queue; if (_connections.TryGetValue(fileName, out queue)) { Queue<WeakReference> poolQueue = queue.Queue; int count = (poolQueue != null) ? poolQueue.Count : 0; counts.Add(fileName, count); totalCount += count; } } else { foreach (KeyValuePair<string, Pool> pair in _connections) { if (pair.Value == null) continue; Queue<WeakReference> poolQueue = pair.Value.Queue; int count = (poolQueue != null) ? poolQueue.Count : 0; counts.Add(pair.Key, count); totalCount += count; } } } } /// <summary> /// Attempt to pull a pooled connection out of the queue for active duty /// </summary> /// <param name="fileName">The filename for a desired connection</param> /// <param name="maxPoolSize">The maximum size the connection pool for the filename can be</param> /// <param name="version">The pool version the returned connection will belong to</param> /// <returns>Returns NULL if no connections were available. Even if none are, the poolversion will still be a valid pool version</returns> internal static SQLiteConnectionHandle Remove(string fileName, int maxPoolSize, out int version) { int localVersion; Queue<WeakReference> poolQueue; // // NOTE: This lock cannot be held while checking the queue for available // connections because other methods of this class are called from // the GC finalizer thread and we use the WaitForPendingFinalizers // method (below). Holding this lock while calling that method // would therefore result in a deadlock. Instead, this lock is // held only while a temporary copy of the queue is created, and // if necessary, when committing changes back to that original // queue prior to returning from this method. // lock (_connections) { Pool queue; // Default to the highest pool version version = _poolVersion; // If we didn't find a pool for this file, create one even though it will be empty. // We have to do this here because otherwise calling ClearPool() on the file will not work for active connections // that have never seen the pool yet. if (_connections.TryGetValue(fileName, out queue) == false) { queue = new Pool(_poolVersion, maxPoolSize); _connections.Add(fileName, queue); return null; } // We found a pool for this file, so use its version number version = localVersion = queue.PoolVersion; queue.MaxPoolSize = maxPoolSize; ResizePool(queue, false); // Try and get a pooled connection from the queue poolQueue = queue.Queue; if (poolQueue == null) return null; // // NOTE: Temporarily tranfer the queue for this file into a local // variable. The queue for this file will be modified and // then committed back to the real pool list (below) prior // to returning from this method. // _connections.Remove(fileName); poolQueue = new Queue<WeakReference>(poolQueue); } try { while (poolQueue.Count > 0) { WeakReference cnn = poolQueue.Dequeue(); if (cnn == null) continue; SQLiteConnectionHandle hdl = cnn.Target as SQLiteConnectionHandle; if (hdl == null) continue; // // BUGFIX: For ticket [996d13cd87], step #1. After this point, // make sure that the finalizer for the connection // handle just obtained from the queue cannot START // running (i.e. it may still be pending but it will no // longer start after this point). // GC.SuppressFinalize(hdl); try { // // BUGFIX: For ticket [996d13cd87], step #2. Now, we must wait // for all pending finalizers which have STARTED running // and have not yet COMPLETED. This must be done just // in case the finalizer for the connection handle just // obtained from the queue has STARTED running at some // point before SuppressFinalize was called on it. // // After this point, checking properties of the // connection handle (e.g. IsClosed) should work // reliably without having to worry that they will // (due to the finalizer) change out from under us. // GC.WaitForPendingFinalizers(); // // BUGFIX: For ticket [996d13cd87], step #3. Next, verify that // the connection handle is actually valid and [still?] // not closed prior to actually returning it to our // caller. // if (!hdl.IsInvalid && !hdl.IsClosed) { Interlocked.Increment(ref _poolOpened); return hdl; } } finally { // // BUGFIX: For ticket [996d13cd87], step #4. Next, we must // re-register the connection handle for finalization // now that we have a strong reference to it (i.e. the // finalizer will not run at least until the connection // is subsequently closed). // GC.ReRegisterForFinalize(hdl); } GC.KeepAlive(hdl); } } finally { // // BUGFIX: For ticket [996d13cd87], step #5. Finally, commit any // changes to the pool/queue for this database file. // lock (_connections) { // // NOTE: We must check [again] if a pool exists for this file // because one may have been added while the search for // an available connection was in progress (above). // Pool queue; Queue<WeakReference> newPoolQueue; bool addPool; if (_connections.TryGetValue(fileName, out queue)) { addPool = false; } else { addPool = true; queue = new Pool(localVersion, maxPoolSize); } newPoolQueue = queue.Queue; while (poolQueue.Count > 0) newPoolQueue.Enqueue(poolQueue.Dequeue()); ResizePool(queue, false); if (addPool) _connections.Add(fileName, queue); } } return null; } /// <summary> /// Clears out all pooled connections and rev's up the default pool version to force all old active objects /// not in the pool to get discarded rather than returned to their pools. /// </summary> internal static void ClearAllPools() { lock (_connections) { foreach (KeyValuePair<string, Pool> pair in _connections) { if (pair.Value == null) continue; Queue<WeakReference> poolQueue = pair.Value.Queue; while (poolQueue.Count > 0) { WeakReference cnn = poolQueue.Dequeue(); if (cnn == null) continue; SQLiteConnectionHandle hdl = cnn.Target as SQLiteConnectionHandle; if (hdl != null) { hdl.Dispose(); } GC.KeepAlive(hdl); } // Keep track of the highest revision so we can go one higher when we're finished if (_poolVersion <= pair.Value.PoolVersion) _poolVersion = pair.Value.PoolVersion + 1; } // All pools are cleared and we have a new highest version number to force all old version active items to get discarded // instead of going back to the queue when they are closed. // We can get away with this because we've pumped up the _poolVersion out of range of all active connections, so they // will all get discarded when they try to put themselves back in their pool. _connections.Clear(); } } /// <summary> /// Clear a given pool for a given filename. Discards anything in the pool for the given file, and revs the pool /// version so current active objects on the old version of the pool will get discarded rather than be returned to the pool. /// </summary> /// <param name="fileName">The filename of the pool to clear</param> internal static void ClearPool(string fileName) { lock (_connections) { Pool queue; if (_connections.TryGetValue(fileName, out queue) == true) { queue.PoolVersion++; Queue<WeakReference> poolQueue = queue.Queue; if (poolQueue == null) return; while (poolQueue.Count > 0) { WeakReference cnn = poolQueue.Dequeue(); if (cnn == null) continue; SQLiteConnectionHandle hdl = cnn.Target as SQLiteConnectionHandle; if (hdl != null) { hdl.Dispose(); } GC.KeepAlive(hdl); } } } } /// <summary> /// Return a connection to the pool for someone else to use. /// </summary> /// <param name="fileName">The filename of the pool to use</param> /// <param name="hdl">The connection handle to pool</param> /// <param name="version">The pool version the handle was created under</param> /// <remarks> /// If the version numbers don't match between the connection and the pool, then the handle is discarded. /// </remarks> internal static void Add(string fileName, SQLiteConnectionHandle hdl, int version) { lock (_connections) { // If the queue doesn't exist in the pool, then it must've been cleared sometime after the connection was created. Pool queue; if (_connections.TryGetValue(fileName, out queue) == true && version == queue.PoolVersion) { ResizePool(queue, true); Queue<WeakReference> poolQueue = queue.Queue; if (poolQueue == null) return; poolQueue.Enqueue(new WeakReference(hdl, false)); Interlocked.Increment(ref _poolClosed); } else { hdl.Close(); } GC.KeepAlive(hdl); } } /// <summary> /// We don't have to thread-lock anything in this function, because it's only called by other functions above /// which already have a thread-safe lock. /// </summary> /// <param name="queue">The queue to resize</param> /// <param name="forAdding">If a function intends to add to the pool, this is true, which forces the resize /// to take one more than it needs from the pool</param> private static void ResizePool(Pool queue, bool forAdding) { int target = queue.MaxPoolSize; if (forAdding && target > 0) target--; Queue<WeakReference> poolQueue = queue.Queue; if (poolQueue == null) return; while (poolQueue.Count > target) { WeakReference cnn = poolQueue.Dequeue(); if (cnn == null) continue; SQLiteConnectionHandle hdl = cnn.Target as SQLiteConnectionHandle; if (hdl != null) { hdl.Dispose(); } GC.KeepAlive(hdl); } } } } |
Changes to System.Data.SQLite/SQLiteConnectionStringBuilder.cs.
︙ | ︙ | |||
343 344 345 346 347 348 349 | } set { this["password"] = value; } } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 343 344 345 346 347 348 349 350 351 352 353 354 355 356 | } set { this["password"] = value; } } /// <summary> /// Gets/Sets the page size for the connection. /// </summary> [DisplayName("Page Size")] [Browsable(true)] [DefaultValue(1024)] public int PageSize |
︙ | ︙ | |||
671 672 673 674 675 676 677 | if (pd == null) return b; // Attempt to coerce the value into something more solid if (b) { if (pd.PropertyType == typeof(Boolean)) value = SQLiteConvert.ToBoolean(value); | | | 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 | if (pd == null) return b; // Attempt to coerce the value into something more solid if (b) { if (pd.PropertyType == typeof(Boolean)) value = SQLiteConvert.ToBoolean(value); else value = TypeDescriptor.GetConverter(pd.PropertyType).ConvertFrom(value); } else { DefaultValueAttribute att = pd.Attributes[typeof(DefaultValueAttribute)] as DefaultValueAttribute; if (att != null) { |
︙ | ︙ |
Changes to System.Data.SQLite/SQLiteConvert.cs.
1 2 3 | /******************************************************** * ADO.NET 2.0 Data Provider for SQLite Version 3.X * Written by Robert Simpson (robert@blackcastlesoft.com) | | | 1 2 3 4 5 6 7 8 9 10 11 | /******************************************************** * ADO.NET 2.0 Data Provider for SQLite Version 3.X * Written by Robert Simpson (robert@blackcastlesoft.com) * * Released to the public domain, use at your own risk! ********************************************************/ namespace System.Data.SQLite { using System; |
︙ | ︙ | |||
158 159 160 161 162 163 164 | /// Converts a UTF-8 encoded IntPtr of the specified length into a .NET string /// </summary> /// <param name="nativestring">The pointer to the memory where the UTF-8 string is encoded</param> /// <param name="nativestringlen">The number of bytes to decode</param> /// <returns>A string containing the translated character(s)</returns> public static string UTF8ToString(IntPtr nativestring, int nativestringlen) { | | | < > | < | < | | 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 | /// Converts a UTF-8 encoded IntPtr of the specified length into a .NET string /// </summary> /// <param name="nativestring">The pointer to the memory where the UTF-8 string is encoded</param> /// <param name="nativestringlen">The number of bytes to decode</param> /// <returns>A string containing the translated character(s)</returns> public static string UTF8ToString(IntPtr nativestring, int nativestringlen) { if (nativestringlen == 0 || nativestring == IntPtr.Zero) return ""; if (nativestringlen == -1) { do { nativestringlen++; } while (Marshal.ReadByte(nativestring, nativestringlen) != 0); } byte[] byteArray = new byte[nativestringlen]; Marshal.Copy(nativestring, byteArray, 0, nativestringlen); return _utf8.GetString(byteArray, 0, nativestringlen); } #endregion |
︙ | ︙ | |||
503 504 505 506 507 508 509 | string[] ar = new string[ls.Count]; ls.CopyTo(ar, 0); return ar; } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 501 502 503 504 505 506 507 508 509 510 511 512 513 514 | string[] ar = new string[ls.Count]; ls.CopyTo(ar, 0); return ar; } /// <summary> /// Convert a value to true or false. /// </summary> /// <param name="source">A string or number representing true or false</param> /// <returns></returns> public static bool ToBoolean(object source) { |
︙ | ︙ | |||
693 694 695 696 697 698 699 | if (t.Type == DbType.Object) return _affinitytotype[(int)t.Affinity]; else return SQLiteConvert.DbTypeToType(t.Type); } private static Type[] _affinitytotype = { | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < | | | | | | | | | | | | | | | | | | | | | | | | | < | | | | 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 | if (t.Type == DbType.Object) return _affinitytotype[(int)t.Affinity]; else return SQLiteConvert.DbTypeToType(t.Type); } private static Type[] _affinitytotype = { typeof(object), typeof(Int64), typeof(Double), typeof(string), typeof(byte[]), typeof(object), typeof(DateTime), typeof(object) }; /// <summary> /// For a given intrinsic type, return a DbType /// </summary> /// <param name="typ">The native type to convert</param> /// <returns>The corresponding (closest match) DbType</returns> internal static DbType TypeToDbType(Type typ) { TypeCode tc = Type.GetTypeCode(typ); if (tc == TypeCode.Object) { if (typ == typeof(byte[])) return DbType.Binary; if (typ == typeof(Guid)) return DbType.Guid; return DbType.String; } return _typetodbtype[(int)tc]; } private static DbType[] _typetodbtype = { DbType.Object, DbType.Binary, DbType.Object, DbType.Boolean, DbType.SByte, DbType.SByte, DbType.Byte, DbType.Int16, // 7 DbType.UInt16, DbType.Int32, DbType.UInt32, DbType.Int64, // 11 DbType.UInt64, DbType.Single, DbType.Double, DbType.Decimal, DbType.DateTime, DbType.Object, DbType.String, }; /// <summary> /// Returns the ColumnSize for the given DbType /// </summary> /// <param name="typ">The DbType to get the size of</param> /// <returns></returns> internal static int DbTypeToColumnSize(DbType typ) { return _dbtypetocolumnsize[(int)typ]; } private static int[] _dbtypetocolumnsize = { 2147483647, // 0 2147483647, // 1 1, // 2 1, // 3 8, // 4 8, // 5 8, // 6 8, // 7 8, // 8 16, // 9 2, 4, 8, 2147483647, 1, 4, 2147483647, 8, 2, 4, 8, 8, 2147483647, 2147483647, 2147483647, 2147483647, // 25 (Xml) }; internal static object DbTypeToNumericPrecision(DbType typ) { return _dbtypetonumericprecision[(int)typ]; } private static object[] _dbtypetonumericprecision = { DBNull.Value, // 0 DBNull.Value, // 1 3, DBNull.Value, 19, DBNull.Value, // 5 DBNull.Value, // 6 53, 53, DBNull.Value, 5, 10, 19, DBNull.Value, 3, 24, DBNull.Value, DBNull.Value, 5, 10, 19, 53, DBNull.Value, DBNull.Value, DBNull.Value }; internal static object DbTypeToNumericScale(DbType typ) { return _dbtypetonumericscale[(int)typ]; } private static object[] _dbtypetonumericscale = { DBNull.Value, // 0 DBNull.Value, // 1 0, DBNull.Value, 4, DBNull.Value, // 5 DBNull.Value, // 6 DBNull.Value, DBNull.Value, DBNull.Value, 0, 0, 0, DBNull.Value, 0, DBNull.Value, DBNull.Value, DBNull.Value, 0, 0, 0, 0, DBNull.Value, DBNull.Value, DBNull.Value }; internal static string DbTypeToTypeName(DbType typ) { for (int n = 0; n < _dbtypeNames.Length; n++) { if (_dbtypeNames[n].dataType == typ) |
︙ | ︙ | |||
868 869 870 871 872 873 874 | "WARNING: Type mapping failed, returning default name \"{0}\" for type {1}.", defaultTypeName, typ)); #endif return defaultTypeName; } | | | > > > > > > > > > > > > > > > | | | | | | | | | | | | | | | | | | | | | | | | | | | 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 | "WARNING: Type mapping failed, returning default name \"{0}\" for type {1}.", defaultTypeName, typ)); #endif return defaultTypeName; } private static SQLiteTypeNames[] _dbtypeNames = { new SQLiteTypeNames("INTEGER", DbType.Int64), new SQLiteTypeNames("TINYINT", DbType.Byte), new SQLiteTypeNames("INT", DbType.Int32), new SQLiteTypeNames("VARCHAR", DbType.AnsiString), new SQLiteTypeNames("NVARCHAR", DbType.String), new SQLiteTypeNames("CHAR", DbType.AnsiStringFixedLength), new SQLiteTypeNames("NCHAR", DbType.StringFixedLength), new SQLiteTypeNames("FLOAT", DbType.Double), new SQLiteTypeNames("REAL", DbType.Double), new SQLiteTypeNames("BIT", DbType.Boolean), new SQLiteTypeNames("DECIMAL", DbType.Decimal), new SQLiteTypeNames("DATETIME", DbType.DateTime), new SQLiteTypeNames("BLOB", DbType.Binary), new SQLiteTypeNames("UNIQUEIDENTIFIER", DbType.Guid), new SQLiteTypeNames("SMALLINT", DbType.Int16), }; /// <summary> /// Convert a DbType to a Type /// </summary> /// <param name="typ">The DbType to convert from</param> /// <returns>The closest-match .NET type</returns> internal static Type DbTypeToType(DbType typ) { return _dbtypeToType[(int)typ]; } private static Type[] _dbtypeToType = { typeof(string), // 0 typeof(byte[]), // 1 typeof(byte), // 2 typeof(bool), // 3 typeof(decimal), // 4 typeof(DateTime), // 5 typeof(DateTime), // 6 typeof(decimal), // 7 typeof(double), // 8 typeof(Guid), // 9 typeof(Int16), typeof(Int32), typeof(Int64), typeof(object), typeof(sbyte), typeof(float), typeof(string), typeof(DateTime), typeof(UInt16), typeof(UInt32), typeof(UInt64), typeof(double), typeof(string), typeof(string), typeof(string), typeof(string), // 25 (Xml) }; /// <summary> /// For a given type, return the closest-match SQLite TypeAffinity, which only understands a very limited subset of types. /// </summary> /// <param name="typ">The type to evaluate</param> /// <returns>The SQLite type affinity for that type.</returns> |
︙ | ︙ | |||
928 929 930 931 932 933 934 | else return TypeAffinity.Text; } return _typecodeAffinities[(int)tc]; } private static TypeAffinity[] _typecodeAffinities = { | | | | | | | | | < < | < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | < < < < < | < < < | < < | < < < < | < < < < < | < | < | < < < < < < < < < < < < < < | < | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 | else return TypeAffinity.Text; } return _typecodeAffinities[(int)tc]; } private static TypeAffinity[] _typecodeAffinities = { TypeAffinity.Null, TypeAffinity.Blob, TypeAffinity.Null, TypeAffinity.Int64, TypeAffinity.Int64, TypeAffinity.Int64, TypeAffinity.Int64, TypeAffinity.Int64, // 7 TypeAffinity.Int64, TypeAffinity.Int64, TypeAffinity.Int64, TypeAffinity.Int64, // 11 TypeAffinity.Int64, TypeAffinity.Double, TypeAffinity.Double, TypeAffinity.Double, TypeAffinity.DateTime, TypeAffinity.Null, TypeAffinity.Text, }; /// <summary> /// For a given type name, return a closest-match .NET type /// </summary> /// <param name="Name">The name of the type to match</param> /// <returns>The .NET DBType the text evaluates to.</returns> internal static DbType TypeNameToDbType(string Name) { lock (_syncRoot) { if (_typeNames == null) { _typeNames = new Dictionary<string, SQLiteTypeNames>( new TypeNameStringComparer()); foreach (SQLiteTypeNames typeName in new SQLiteTypeNames[] { new SQLiteTypeNames("COUNTER", DbType.Int64), new SQLiteTypeNames("AUTOINCREMENT", DbType.Int64), new SQLiteTypeNames("IDENTITY", DbType.Int64), new SQLiteTypeNames("LONGTEXT", DbType.String), new SQLiteTypeNames("LONGCHAR", DbType.String), new SQLiteTypeNames("LONGVARCHAR", DbType.String), new SQLiteTypeNames("LONG", DbType.Int64), new SQLiteTypeNames("TINYINT", DbType.Byte), new SQLiteTypeNames("INTEGER", DbType.Int64), new SQLiteTypeNames("INT", DbType.Int32), new SQLiteTypeNames("VARCHAR", DbType.String), new SQLiteTypeNames("NVARCHAR", DbType.String), new SQLiteTypeNames("CHAR", DbType.String), new SQLiteTypeNames("NCHAR", DbType.String), new SQLiteTypeNames("TEXT", DbType.String), new SQLiteTypeNames("NTEXT", DbType.String), new SQLiteTypeNames("STRING", DbType.String), new SQLiteTypeNames("DOUBLE", DbType.Double), new SQLiteTypeNames("FLOAT", DbType.Double), new SQLiteTypeNames("REAL", DbType.Double), new SQLiteTypeNames("BIT", DbType.Boolean), new SQLiteTypeNames("YESNO", DbType.Boolean), new SQLiteTypeNames("LOGICAL", DbType.Boolean), new SQLiteTypeNames("BOOL", DbType.Boolean), new SQLiteTypeNames("BOOLEAN", DbType.Boolean), new SQLiteTypeNames("NUMERIC", DbType.Decimal), new SQLiteTypeNames("DECIMAL", DbType.Decimal), new SQLiteTypeNames("MONEY", DbType.Decimal), new SQLiteTypeNames("CURRENCY", DbType.Decimal), new SQLiteTypeNames("TIME", DbType.DateTime), new SQLiteTypeNames("DATE", DbType.DateTime), new SQLiteTypeNames("DATETIME", DbType.DateTime), new SQLiteTypeNames("SMALLDATE", DbType.DateTime), new SQLiteTypeNames("TIMESTAMP", DbType.DateTime), new SQLiteTypeNames("BLOB", DbType.Binary), new SQLiteTypeNames("BINARY", DbType.Binary), new SQLiteTypeNames("VARBINARY", DbType.Binary), new SQLiteTypeNames("IMAGE", DbType.Binary), new SQLiteTypeNames("GENERAL", DbType.Binary), new SQLiteTypeNames("OLEOBJECT", DbType.Binary), new SQLiteTypeNames("GUID", DbType.Guid), new SQLiteTypeNames("UNIQUEIDENTIFIER", DbType.Guid), new SQLiteTypeNames("MEMO", DbType.String), new SQLiteTypeNames("NOTE", DbType.String), new SQLiteTypeNames("SMALLINT", DbType.Int16), new SQLiteTypeNames("BIGINT", DbType.Int64) }) { _typeNames.Add(typeName.typeName, typeName); } } } if (String.IsNullOrEmpty(Name)) return DbType.Object; SQLiteTypeNames value; |
︙ | ︙ | |||
1147 1148 1149 1150 1151 1152 1153 | Unknown = 0, /// <summary> /// The connection is being opened. /// </summary> Opening = 1, | < < < < < | | | | | | | | | | 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 | Unknown = 0, /// <summary> /// The connection is being opened. /// </summary> Opening = 1, /// <summary> /// The connection was opened. /// </summary> Opened = 2, /// <summary> /// The <see cref="ChangeDatabase" /> method was called on the /// connection. /// </summary> ChangeDatabase = 3, /// <summary> /// A transaction was created using the connection. /// </summary> NewTransaction = 4, /// <summary> /// The connection was enlisted into a transaction. /// </summary> EnlistTransaction = 5, /// <summary> /// A command was created using the connection. /// </summary> NewCommand = 6, /// <summary> /// The connection is being closed. /// </summary> Closing = 7, /// <summary> /// The connection was closed. /// </summary> Closed = 8 } /// <summary> /// This implementation of SQLite for ADO.NET can process date/time fields in databases in only one of three formats. Ticks, ISO8601 /// and JulianDay. /// </summary> /// <remarks> /// ISO8601 is more compatible, readable, fully-processable, but less accurate as it doesn't provide time down to fractions of a second. /// JulianDay is the numeric format the SQLite uses internally and is arguably the most compatible with 3rd party tools. It is /// not readable as text without post-processing. /// Ticks less compatible with 3rd party tools that query the database, and renders the DateTime field unreadable as text without post-processing. /// /// The preferred order of choosing a datetime format is JulianDay, ISO8601, and then Ticks. Ticks is mainly present for legacy /// code support. /// </remarks> public enum SQLiteDateFormats { /// <summary> /// Use the value of DateTime.Ticks. This value is not recommended and is not well supported with LINQ. /// </summary> |
︙ | ︙ | |||
1242 1243 1244 1245 1246 1247 1248 | /// <summary> /// This enum determines how SQLite treats its journal file. /// </summary> /// <remarks> /// By default SQLite will create and delete the journal file when needed during a transaction. /// However, for some computers running certain filesystem monitoring tools, the rapid /// creation and deletion of the journal file can cause those programs to fail, or to interfere with SQLite. | | | 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 | /// <summary> /// This enum determines how SQLite treats its journal file. /// </summary> /// <remarks> /// By default SQLite will create and delete the journal file when needed during a transaction. /// However, for some computers running certain filesystem monitoring tools, the rapid /// creation and deletion of the journal file can cause those programs to fail, or to interfere with SQLite. /// /// If a program or virus scanner is interfering with SQLite's journal file, you may receive errors like "unable to open database file" /// when starting a transaction. If this is happening, you may want to change the default journal mode to Persist. /// </remarks> public enum SQLiteJournalModeEnum { /// <summary> /// The default mode, this causes SQLite to use the existing journaling mode for the database. |
︙ | ︙ | |||
1323 1324 1325 1326 1327 1328 1329 | /// This ensures that an operating system crash or power failure will not /// corrupt the database. FULL synchronous is very safe, but it is also /// slower. /// </summary> Full = 2 } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 | /// This ensures that an operating system crash or power failure will not /// corrupt the database. FULL synchronous is very safe, but it is also /// slower. /// </summary> Full = 2 } /// <summary> /// Struct used internally to determine the datatype of a column in a resultset /// </summary> internal class SQLiteType { /// <summary> /// The DbType of the column, or DbType.Object if it cannot be determined |
︙ | ︙ | |||
1407 1408 1409 1410 1411 1412 1413 | public int GetHashCode( string value ) { // // NOTE: The only thing that we must guarantee here, according | | | | 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 | public int GetHashCode( string value ) { // // NOTE: The only thing that we must guarantee here, according // to the MSDN documentation for IEqualityComparer, is // that for two given strings, if Equals return true then // the two strings must hash to the same value. // if (value != null) #if !PLATFORM_COMPACTFRAMEWORK return value.ToLowerInvariant().GetHashCode(); #else return value.ToLower().GetHashCode(); |
︙ | ︙ |
Changes to System.Data.SQLite/SQLiteDataAdapter.cs.
︙ | ︙ | |||
17 18 19 20 21 22 23 | #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 { | < < < < < < < | < < < < | < < < < | < < | < | < < < < | < < | < < | < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < < | 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 | #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(); /// <overloads> /// This class is just a shell around the DbDataAdapter. Nothing from DbDataAdapter is overridden here, just a few constructors are defined. /// </overloads> /// <summary> /// Default constructor. /// </summary> public SQLiteDataAdapter() { } /// <summary> /// Constructs a data adapter using the specified select command. /// </summary> /// <param name="cmd">The select command to associate with the adapter.</param> public SQLiteDataAdapter(SQLiteCommand cmd) { SelectCommand = cmd; } /// <summary> /// Constructs a data adapter with the supplied select command text and associated with the specified connection. /// </summary> /// <param name="commandText">The select command text to associate with the data adapter.</param> /// <param name="connection">The connection to associate with the select command.</param> public SQLiteDataAdapter(string commandText, SQLiteConnection connection) { SelectCommand = new SQLiteCommand(commandText, connection); } /// <summary> /// Constructs a data adapter with the specified select command text, and using the specified database connection string. /// </summary> /// <param name="commandText">The select command text to use to construct a select command.</param> /// <param name="connectionString">A connection string suitable for passing to a new SQLiteConnection, which is associated with the select command.</param> public SQLiteDataAdapter(string commandText, string connectionString) { SQLiteConnection cnn = new SQLiteConnection(connectionString); SelectCommand = new SQLiteCommand(commandText, cnn); } /////////////////////////////////////////////////////////////////////////////////////////////// #region IDisposable "Pattern" Members private bool disposed; private void CheckDisposed() /* throw */ { |
︙ | ︙ | |||
141 142 143 144 145 146 147 | protected override void Dispose(bool disposing) { try { if (!disposed) { | | < | > | < | < < < < < | < < < < < < < < < < < < < < < < < < | 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 | protected override void Dispose(bool disposing) { try { if (!disposed) { //if (disposing) //{ // //////////////////////////////////// // // dispose managed resources here... // //////////////////////////////////// //} ////////////////////////////////////// // release unmanaged resources here... ////////////////////////////////////// disposed = true; } |
︙ | ︙ |
Changes to System.Data.SQLite/SQLiteDataReader.cs.
︙ | ︙ | |||
642 643 644 645 646 647 648 | /// </summary> /// <param name="name">The name of the column to retrieve</param> /// <returns>The int i of the column</returns> public override int GetOrdinal(string name) { CheckDisposed(); CheckClosed(); | | | 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 | /// </summary> /// <param name="name">The name of the column to retrieve</param> /// <returns>The int i of the column</returns> public override int GetOrdinal(string name) { CheckDisposed(); CheckClosed(); SQLiteCommand.Check(_command); // // NOTE: First, check if the column name cache has been initialized yet. // If not, do it now. // if (_fieldIndexes == null) _fieldIndexes = new Dictionary<string, int>(new ColumnNameComparer()); |
︙ | ︙ | |||
850 851 852 853 854 855 856 | columnToParent.Add(n, value); } } internal DataTable GetSchemaTable(bool wantUniqueInfo, bool wantDefaultValue) { CheckClosed(); | | | 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 | columnToParent.Add(n, value); } } internal DataTable GetSchemaTable(bool wantUniqueInfo, bool wantDefaultValue) { CheckClosed(); SQLiteCommand.Check(_command); // // BUGFIX: We need to quickly scan all the fields in the current // "result set" to see how many distinct tables are actually // involved. This information is necessary so that some // intelligent decisions can be made when constructing the // metadata below. For example, we need to be very careful |
︙ | ︙ | |||
1113 1114 1115 1116 1117 1118 1119 | /// Retrieves the column as an object corresponding to the underlying datatype of the column /// </summary> /// <param name="i">The index of the column to retrieve</param> /// <returns>object</returns> public override object GetValue(int i) { CheckDisposed(); | < | < | 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 | /// Retrieves the column as an object corresponding to the underlying datatype of the column /// </summary> /// <param name="i">The index of the column to retrieve</param> /// <returns>object</returns> public override object GetValue(int i) { CheckDisposed(); if (i >= VisibleFieldCount && _keyInfo != null) return _keyInfo.GetValue(i - VisibleFieldCount); SQLiteType typ = GetSQLiteType(i); return _activeStatement._sql.GetValue(_activeStatement, i, typ); } /// <summary> /// Retreives the values of multiple columns, up to the size of the supplied array /// </summary> /// <param name="values">The array to fill with values from the columns in the current resultset</param> /// <returns>The number of columns retrieved</returns> |
︙ | ︙ | |||
1219 1220 1221 1222 1223 1224 1225 | /// Moves to the next resultset in multiple row-returning SQL command. /// </summary> /// <returns>True if the command was successful and a new resultset is available, False otherwise.</returns> public override bool NextResult() { CheckDisposed(); CheckClosed(); | | | 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 | /// Moves to the next resultset in multiple row-returning SQL command. /// </summary> /// <returns>True if the command was successful and a new resultset is available, False otherwise.</returns> public override bool NextResult() { CheckDisposed(); CheckClosed(); SQLiteCommand.Check(_command); SQLiteStatement stmt = null; int fieldCount; while (true) { if (stmt == null && _activeStatement != null && _activeStatement._sql != null && _activeStatement._sql.IsOpen()) |
︙ | ︙ | |||
1345 1346 1347 1348 1349 1350 1351 | /// Reads the next row from the resultset /// </summary> /// <returns>True if a new row was successfully loaded and is ready for processing</returns> public override bool Read() { CheckDisposed(); CheckClosed(); | | | 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 | /// Reads the next row from the resultset /// </summary> /// <returns>True if a new row was successfully loaded and is ready for processing</returns> public override bool Read() { CheckDisposed(); CheckClosed(); SQLiteCommand.Check(_command); if (_readingState == -1) // First step was already done at the NextResult() level, so don't step again, just return true. { _readingState = 0; return true; } else if (_readingState == 0) // Actively reading rows |
︙ | ︙ |
Changes to System.Data.SQLite/SQLiteDefineConstants.cs.
︙ | ︙ | |||
12 13 14 15 16 17 18 | internal static class SQLiteDefineConstants { public static readonly IList<string> OptionList = new List<string>(new string[] { #if CHECK_STATE "CHECK_STATE", #endif | < < < < < < < < < < < < | 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | internal static class SQLiteDefineConstants { public static readonly IList<string> OptionList = new List<string>(new string[] { #if CHECK_STATE "CHECK_STATE", #endif #if DEBUG "DEBUG", #endif #if INTEROP_CODEC "INTEROP_CODEC", #endif #if INTEROP_DEBUG "INTEROP_DEBUG", #endif #if INTEROP_EXTENSION_FUNCTIONS "INTEROP_EXTENSION_FUNCTIONS", #endif #if INTEROP_TEST_EXTENSION "INTEROP_TEST_EXTENSION", #endif #if NET_20 "NET_20", #endif |
︙ | ︙ | |||
112 113 114 115 116 117 118 | "TRACE_WARNING", #endif #if USE_INTEROP_DLL "USE_INTEROP_DLL", #endif | < < < < < < < < | 100 101 102 103 104 105 106 107 108 109 110 | "TRACE_WARNING", #endif #if USE_INTEROP_DLL "USE_INTEROP_DLL", #endif null }); } } |
Changes to System.Data.SQLite/SQLiteException.cs.
1 2 3 | /******************************************************** * ADO.NET 2.0 Data Provider for SQLite Version 3.X * Written by Robert Simpson (robert@blackcastlesoft.com) | | | 1 2 3 4 5 6 7 8 9 10 11 | /******************************************************** * ADO.NET 2.0 Data Provider for SQLite Version 3.X * Written by Robert Simpson (robert@blackcastlesoft.com) * * Released to the public domain, use at your own risk! ********************************************************/ namespace System.Data.SQLite { using System; using System.Data.Common; |
︙ | ︙ | |||
180 181 182 183 184 185 186 | private static string GetStockErrorMessage( SQLiteErrorCode errorCode, string message ) { return String.Format("{0}{1}{2}", GetErrorString(errorCode), | < < < < | 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 | private static string GetStockErrorMessage( SQLiteErrorCode errorCode, string message ) { return String.Format("{0}{1}{2}", GetErrorString(errorCode), Environment.NewLine, message).Trim(); } } /// <summary> /// SQLite error codes. Actually, this enumeration represents a return code, /// which may also indicate success in one of several ways (e.g. SQLITE_OK, /// SQLITE_ROW, and SQLITE_DONE). Therefore, the name of this enumeration is |
︙ | ︙ | |||
305 306 307 308 309 310 311 | /// </summary> Range /* 25 */, /// <summary> /// File opened that is not a database file /// </summary> NotADb /* 26 */, /// <summary> | < < < < < < < < | 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 | /// </summary> Range /* 25 */, /// <summary> /// File opened that is not a database file /// </summary> NotADb /* 26 */, /// <summary> /// sqlite3_step() has another row ready /// </summary> Row = 100, /// <summary> /// sqlite3_step() has finished executing /// </summary> Done /* 101 */ } } |
Changes to System.Data.SQLite/SQLiteFunction.cs.
1 2 3 | /******************************************************** * ADO.NET 2.0 Data Provider for SQLite Version 3.X * Written by Robert Simpson (robert@blackcastlesoft.com) | | | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | /******************************************************** * ADO.NET 2.0 Data Provider for SQLite Version 3.X * Written by Robert Simpson (robert@blackcastlesoft.com) * * Released to the public domain, use at your own risk! ********************************************************/ namespace System.Data.SQLite { using System; using System.Collections.Generic; using System.Runtime.InteropServices; using System.Globalization; /// <summary> /// This abstract class is designed to handle user-defined functions easily. An instance of the derived class is made for each /// connection to the database. /// </summary> /// <remarks> /// Although there is one instance of a class derived from SQLiteFunction per database connection, the derived class has no access /// to the underlying connection. This is necessary to deter implementers from thinking it would be a good idea to make database /// calls during processing. /// /// It is important to distinguish between a per-connection instance, and a per-SQL statement context. One instance of this class /// services all SQL statements being stepped through on that connection, and there can be many. One should never store per-statement /// information in member variables of user-defined function classes. /// /// For aggregate functions, always create and store your per-statement data in the contextData object on the 1st step. This data will /// be automatically freed for you (and Dispose() called if the item supports IDisposable) when the statement completes. /// </remarks> public abstract class SQLiteFunction : IDisposable { private class AggregateData { |
︙ | ︙ | |||
379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 | { try { _context = context; SetReturnValue(context, Invoke(ConvertParams(nArgs, argsptr))); /* throw */ } catch (Exception e) /* NOTE: Must catch ALL. */ { try { if ((_flags & SQLiteConnectionFlags.LogCallbackException) == SQLiteConnectionFlags.LogCallbackException) { SQLiteLog.LogMessage(COR_E_EXCEPTION, String.Format( CultureInfo.CurrentCulture, "Caught exception in \"Invoke\" method: {0}", e)); /* throw */ } } catch { // do nothing. } } } /// <summary> /// Internal collation sequence function, which wraps up the raw string pointers and executes the Compare() virtual function. /// WARNING: Must not throw exceptions. /// </summary> /// <param name="ptr">Not used</param> /// <param name="len1">Length of the string pv1</param> /// <param name="ptr1">Pointer to the first string to compare</param> /// <param name="len2">Length of the string pv2</param> /// <param name="ptr2">Pointer to the second string to compare</param> /// <returns>Returns -1 if the first string is less than the second. 0 if they are equal, or 1 if the first string is greater /// than the second. Returns 0 if an exception is caught.</returns> internal int CompareCallback(IntPtr ptr, int len1, IntPtr ptr1, int len2, IntPtr ptr2) { try { return Compare(SQLiteConvert.UTF8ToString(ptr1, len1), SQLiteConvert.UTF8ToString(ptr2, len2)); /* throw */ } catch (Exception e) /* NOTE: Must catch ALL. */ { try { if ((_flags & SQLiteConnectionFlags.LogCallbackException) == SQLiteConnectionFlags.LogCallbackException) { SQLiteLog.LogMessage(COR_E_EXCEPTION, String.Format( CultureInfo.CurrentCulture, "Caught exception in \"Compare\" (UTF8) method: {0}", e)); /* throw */ } } catch { // do nothing. } } // // NOTE: This must be done to prevent the core SQLite library from // using our (invalid) result. // if (_base != null) _base.Cancel(); | > > > > > > > > > > > > > > | 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 | { try { _context = context; SetReturnValue(context, Invoke(ConvertParams(nArgs, argsptr))); /* throw */ } #if !PLATFORM_COMPACTFRAMEWORK catch (Exception e) /* NOTE: Must catch ALL. */ { try { if ((_flags & SQLiteConnectionFlags.LogCallbackException) == SQLiteConnectionFlags.LogCallbackException) { SQLiteLog.LogMessage(COR_E_EXCEPTION, String.Format( CultureInfo.CurrentCulture, "Caught exception in \"Invoke\" method: {0}", e)); /* throw */ } } catch { // do nothing. } } #else catch /* NOTE: Must catch ALL. */ { // do nothing (Windows CE). } #endif } /// <summary> /// Internal collation sequence function, which wraps up the raw string pointers and executes the Compare() virtual function. /// WARNING: Must not throw exceptions. /// </summary> /// <param name="ptr">Not used</param> /// <param name="len1">Length of the string pv1</param> /// <param name="ptr1">Pointer to the first string to compare</param> /// <param name="len2">Length of the string pv2</param> /// <param name="ptr2">Pointer to the second string to compare</param> /// <returns>Returns -1 if the first string is less than the second. 0 if they are equal, or 1 if the first string is greater /// than the second. Returns 0 if an exception is caught.</returns> internal int CompareCallback(IntPtr ptr, int len1, IntPtr ptr1, int len2, IntPtr ptr2) { try { return Compare(SQLiteConvert.UTF8ToString(ptr1, len1), SQLiteConvert.UTF8ToString(ptr2, len2)); /* throw */ } #if !PLATFORM_COMPACTFRAMEWORK catch (Exception e) /* NOTE: Must catch ALL. */ { try { if ((_flags & SQLiteConnectionFlags.LogCallbackException) == SQLiteConnectionFlags.LogCallbackException) { SQLiteLog.LogMessage(COR_E_EXCEPTION, String.Format( CultureInfo.CurrentCulture, "Caught exception in \"Compare\" (UTF8) method: {0}", e)); /* throw */ } } catch { // do nothing. } } #else catch /* NOTE: Must catch ALL. */ { // do nothing (Windows CE). } #endif // // NOTE: This must be done to prevent the core SQLite library from // using our (invalid) result. // if (_base != null) _base.Cancel(); |
︙ | ︙ | |||
464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 | internal int CompareCallback16(IntPtr ptr, int len1, IntPtr ptr1, int len2, IntPtr ptr2) { try { return Compare(SQLite3_UTF16.UTF16ToString(ptr1, len1), SQLite3_UTF16.UTF16ToString(ptr2, len2)); /* throw */ } catch (Exception e) /* NOTE: Must catch ALL. */ { try { if ((_flags & SQLiteConnectionFlags.LogCallbackException) == SQLiteConnectionFlags.LogCallbackException) { SQLiteLog.LogMessage(COR_E_EXCEPTION, String.Format( CultureInfo.CurrentCulture, "Caught exception in \"Compare\" (UTF16) method: {0}", e)); /* throw */ } } catch { // do nothing. } } // // NOTE: This must be done to prevent the core SQLite library from // using our (invalid) result. // if (_base != null) _base.Cancel(); | > > > > > > > | 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 | internal int CompareCallback16(IntPtr ptr, int len1, IntPtr ptr1, int len2, IntPtr ptr2) { try { return Compare(SQLite3_UTF16.UTF16ToString(ptr1, len1), SQLite3_UTF16.UTF16ToString(ptr2, len2)); /* throw */ } #if !PLATFORM_COMPACTFRAMEWORK catch (Exception e) /* NOTE: Must catch ALL. */ { try { if ((_flags & SQLiteConnectionFlags.LogCallbackException) == SQLiteConnectionFlags.LogCallbackException) { SQLiteLog.LogMessage(COR_E_EXCEPTION, String.Format( CultureInfo.CurrentCulture, "Caught exception in \"Compare\" (UTF16) method: {0}", e)); /* throw */ } } catch { // do nothing. } } #else catch /* NOTE: Must catch ALL. */ { // do nothing (Windows CE). } #endif // // NOTE: This must be done to prevent the core SQLite library from // using our (invalid) result. // if (_base != null) _base.Cancel(); |
︙ | ︙ | |||
537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 | data._count, ref data._data); /* throw */ } finally { data._count++; } } catch (Exception e) /* NOTE: Must catch ALL. */ { try { if ((_flags & SQLiteConnectionFlags.LogCallbackException) == SQLiteConnectionFlags.LogCallbackException) { SQLiteLog.LogMessage(COR_E_EXCEPTION, String.Format( CultureInfo.CurrentCulture, "Caught exception in \"Step\" method: {1}", e)); /* throw */ } } catch { // do nothing. } } } /// <summary> /// An internal aggregate Final function callback, which wraps the context pointer and calls the virtual Final() method. /// WARNING: Must not throw exceptions. /// </summary> /// <param name="context">A raw context pointer</param> | > > > > > > > | 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 | data._count, ref data._data); /* throw */ } finally { data._count++; } } #if !PLATFORM_COMPACTFRAMEWORK catch (Exception e) /* NOTE: Must catch ALL. */ { try { if ((_flags & SQLiteConnectionFlags.LogCallbackException) == SQLiteConnectionFlags.LogCallbackException) { SQLiteLog.LogMessage(COR_E_EXCEPTION, String.Format( CultureInfo.CurrentCulture, "Caught exception in \"Step\" method: {1}", e)); /* throw */ } } catch { // do nothing. } } #else catch /* NOTE: Must catch ALL. */ { // do nothing (Windows CE). } #endif } /// <summary> /// An internal aggregate Final function callback, which wraps the context pointer and calls the virtual Final() method. /// WARNING: Must not throw exceptions. /// </summary> /// <param name="context">A raw context pointer</param> |
︙ | ︙ | |||
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 | } finally { IDisposable disp = obj as IDisposable; if (disp != null) disp.Dispose(); /* throw */ } } catch (Exception e) /* NOTE: Must catch ALL. */ { try { if ((_flags & SQLiteConnectionFlags.LogCallbackException) == SQLiteConnectionFlags.LogCallbackException) { SQLiteLog.LogMessage(COR_E_EXCEPTION, String.Format( CultureInfo.CurrentCulture, "Caught exception in \"Final\" method: {1}", e)); /* throw */ } } catch { // do nothing. } } } /// <summary> /// Using reflection, enumerate all assemblies in the current appdomain looking for classes that /// have a SQLiteFunctionAttribute attribute, and registering them accordingly. /// </summary> #if !PLATFORM_COMPACTFRAMEWORK [Security.Permissions.FileIOPermission(Security.Permissions.SecurityAction.Assert, AllFiles = Security.Permissions.FileIOPermissionAccess.PathDiscovery)] #endif static SQLiteFunction() { _registeredFunctions = new List<SQLiteFunctionAttribute>(); try { #if !PLATFORM_COMPACTFRAMEWORK | > > > > > > > < < < < < < < | 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 | } finally { IDisposable disp = obj as IDisposable; if (disp != null) disp.Dispose(); /* throw */ } } #if !PLATFORM_COMPACTFRAMEWORK catch (Exception e) /* NOTE: Must catch ALL. */ { try { if ((_flags & SQLiteConnectionFlags.LogCallbackException) == SQLiteConnectionFlags.LogCallbackException) { SQLiteLog.LogMessage(COR_E_EXCEPTION, String.Format( CultureInfo.CurrentCulture, "Caught exception in \"Final\" method: {1}", e)); /* throw */ } } catch { // do nothing. } } #else catch /* NOTE: Must catch ALL. */ { // do nothing (Windows CE). } #endif } /// <summary> /// Using reflection, enumerate all assemblies in the current appdomain looking for classes that /// have a SQLiteFunctionAttribute attribute, and registering them accordingly. /// </summary> #if !PLATFORM_COMPACTFRAMEWORK [Security.Permissions.FileIOPermission(Security.Permissions.SecurityAction.Assert, AllFiles = Security.Permissions.FileIOPermissionAccess.PathDiscovery)] #endif static SQLiteFunction() { _registeredFunctions = new List<SQLiteFunctionAttribute>(); try { #if !PLATFORM_COMPACTFRAMEWORK SQLiteFunctionAttribute at; System.Reflection.Assembly[] arAssemblies = System.AppDomain.CurrentDomain.GetAssemblies(); int w = arAssemblies.Length; System.Reflection.AssemblyName sqlite = System.Reflection.Assembly.GetCallingAssembly().GetName(); for (int n = 0; n < w; n++) { |
︙ | ︙ |
Changes to System.Data.SQLite/SQLiteLog.cs.
︙ | ︙ | |||
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 | /// </summary> /// <param name="sender">The current connection</param> /// <param name="e">Event arguments of the trace</param> public delegate void SQLiteLogEventHandler(object sender, LogEventArgs e); /////////////////////////////////////////////////////////////////////////// /// <summary> /// Manages the SQLite custom logging functionality and the associated /// callback for the whole process. /// </summary> public static class SQLiteLog { /// <summary> /// Object used to synchronize access to the static instance data /// for this class. /// </summary> private static object syncRoot = new object(); | > < < < < < < < < < < < < < < < < < < < < < | 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 | /// </summary> /// <param name="sender">The current connection</param> /// <param name="e">Event arguments of the trace</param> public delegate void SQLiteLogEventHandler(object sender, LogEventArgs e); /////////////////////////////////////////////////////////////////////////// #if !PLATFORM_COMPACTFRAMEWORK /// <summary> /// Manages the SQLite custom logging functionality and the associated /// callback for the whole process. /// </summary> public static class SQLiteLog { /// <summary> /// Object used to synchronize access to the static instance data /// for this class. /// </summary> private static object syncRoot = new object(); /// <summary> /// Member variable to store the AppDomain.DomainUnload event handler. /// </summary> private static EventHandler _domainUnload; /// <summary> /// Member variable to store the application log handler to call. /// </summary> private static event SQLiteLogEventHandler _handlers; /// <summary> /// The default log event handler. /// </summary> private static SQLiteLogEventHandler _defaultHandler; /// <summary> /// The log callback passed to native SQLite engine. This must live /// as long as the SQLite library has a pointer to it. /// </summary> private static SQLiteLogCallback _callback; /// <summary> /// The base SQLite object to interop with. /// </summary> private static SQLiteBase _sql; /// <summary> /// This will be non-zero if logging is currently enabled. /// </summary> private static bool _enabled; /// <summary> /// Initializes the SQLite logging facilities. /// </summary> public static void Initialize() { // // BUFXIX: We cannot initialize the logging interface if the SQLite // core library has already been initialized anywhere in // the process (see ticket [2ce0870fad]). // if (SQLite3.StaticIsInitialized()) return; // // BUGFIX: To avoid nasty situations where multiple AppDomains are // attempting to initialize and/or shutdown what is really // a shared native resource (i.e. the SQLite core library // is loaded per-process and has only one logging callback, // not one per-AppDomain, which it knows nothing about), // prevent all non-default AppDomains from registering a // log handler unless the "Force_SQLiteLog" environment // variable is used to manually override this safety check. // if (!AppDomain.CurrentDomain.IsDefaultAppDomain() && Environment.GetEnvironmentVariable("Force_SQLiteLog") == null) { return; } lock (syncRoot) { // // NOTE: Add an event handler for the DomainUnload event so // that we can unhook our logging managed function // pointer from the native SQLite code prior to it // being invalidated. // // BUGFIX: Make sure this event handler is only added one // time (per-AppDomain). // if (_domainUnload == null) { _domainUnload = new EventHandler(DomainUnload); AppDomain.CurrentDomain.DomainUnload += _domainUnload; } // // NOTE: Create an instance of the SQLite wrapper class. // if (_sql == null) _sql = new SQLite3(SQLiteDateFormats.Default, DateTimeKind.Unspecified); |
︙ | ︙ | |||
208 209 210 211 212 213 214 | // // NOTE: For now, always setup the default log event handler. // AddDefaultHandler(); } } | < < < | 188 189 190 191 192 193 194 195 196 197 198 199 200 201 | // // NOTE: For now, always setup the default log event handler. // AddDefaultHandler(); } } /// <summary> /// Handles the AppDomain being unloaded. /// </summary> /// <param name="sender">Should be null.</param> /// <param name="e">The data associated with this event.</param> private static void DomainUnload( object sender, |
︙ | ︙ | |||
277 278 279 280 281 282 283 | if (_domainUnload != null) { AppDomain.CurrentDomain.DomainUnload -= _domainUnload; _domainUnload = null; } } } | < < < | 254 255 256 257 258 259 260 261 262 263 264 265 266 267 | if (_domainUnload != null) { AppDomain.CurrentDomain.DomainUnload -= _domainUnload; _domainUnload = null; } } } /// <summary> /// This event is raised whenever SQLite raises a logging event. /// Note that this should be set as one of the first things in the /// application. /// </summary> public static event SQLiteLogEventHandler Log |
︙ | ︙ | |||
310 311 312 313 314 315 316 | lock (syncRoot) { _handlers -= value; } } } | < < < < < < < < < < < < < < | < < < < < < < < | 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 | lock (syncRoot) { _handlers -= value; } } } /// <summary> /// If this property is true, logging is enabled; otherwise, logging is /// disabled. When logging is disabled, no logging events will fire. /// </summary> public static bool Enabled { get { lock (syncRoot) { return _enabled; } } set { lock (syncRoot) { _enabled = value; } } } /// <summary> /// Log a message to all the registered log event handlers without going /// through the SQLite library. /// </summary> /// <param name="message">The message to be logged.</param> public static void LogMessage( string message ) { LogMessage(null, message); } /// <summary> /// Log a message to all the registered log event handlers without going /// through the SQLite library. /// </summary> /// <param name="errorCode">The SQLite error code.</param> /// <param name="message">The message to be logged.</param> public static void LogMessage( SQLiteErrorCode errorCode, string message ) { LogMessage((object)errorCode, message); } /// <summary> /// Log a message to all the registered log event handlers without going /// through the SQLite library. /// </summary> /// <param name="errorCode">The integer error code.</param> /// <param name="message">The message to be logged.</param> public static void LogMessage( int errorCode, string message ) { LogMessage((object)errorCode, message); } /// <summary> /// Log a message to all the registered log event handlers without going /// through the SQLite library. /// </summary> /// <param name="errorCode"> /// The error code. The type of this object value should be /// System.Int32 or SQLiteErrorCode. /// </param> /// <param name="message">The message to be logged.</param> private static void LogMessage( object errorCode, string message ) { bool enabled; SQLiteLogEventHandler handlers; lock (syncRoot) { enabled = _enabled; handlers = _handlers; } if (enabled && (handlers != null)) handlers(null, new LogEventArgs( IntPtr.Zero, errorCode, message, null)); } /// <summary> /// Creates and initializes the default log event handler. /// </summary> private static void InitializeDefaultHandler() { lock (syncRoot) { if (_defaultHandler == null) _defaultHandler = new SQLiteLogEventHandler(LogEventHandler); } } /// <summary> /// Adds the default log event handler to the list of handlers. /// </summary> public static void AddDefaultHandler() { InitializeDefaultHandler(); Log += _defaultHandler; } /// <summary> /// Removes the default log event handler from the list of handlers. /// </summary> public static void RemoveDefaultHandler() { InitializeDefaultHandler(); Log -= _defaultHandler; } /// <summary> /// Internal proxy function that calls any registered application log /// event handlers. /// /// WARNING: This method is used more-or-less directly by native code, /// do not modify its type signature. /// </summary> |
︙ | ︙ | |||
480 481 482 483 484 485 486 | } if (enabled && (handlers != null)) handlers(null, new LogEventArgs(pUserData, errorCode, SQLiteBase.UTF8ToString(pMessage, -1), null)); } | < < < | 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 | } 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) { |
︙ | ︙ | |||
521 522 523 524 525 526 527 | if (errorCode is SQLiteErrorCode) success = ((SQLiteErrorCode)errorCode == SQLiteErrorCode.Ok); else if (errorCode is int) success = ((int)errorCode == 0); Trace.WriteLine(String.Format("SQLite {0} ({1}): {2}", success ? "message" : "error", errorCode, message)); | < > | 470 471 472 473 474 475 476 477 478 479 480 | if (errorCode is SQLiteErrorCode) success = ((SQLiteErrorCode)errorCode == SQLiteErrorCode.Ok); else if (errorCode is int) success = ((int)errorCode == 0); Trace.WriteLine(String.Format("SQLite {0} ({1}): {2}", success ? "message" : "error", errorCode, message)); } } #endif } |
Changes to System.Data.SQLite/SQLiteStatement.cs.
︙ | ︙ | |||
296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 | object obj = param.Value; DbType objType = param.DbType; if ((obj != null) && (objType == DbType.Object)) objType = SQLiteConvert.TypeToDbType(obj.GetType()); if ((_flags & SQLiteConnectionFlags.LogPreBind) == SQLiteConnectionFlags.LogPreBind) { IntPtr handle = _sqlite_stmt; SQLiteLog.LogMessage(String.Format( "Binding statement {0} paramter #{1} with database type {2} and raw value {{{3}}}...", handle, index, objType, obj)); } if ((obj == null) || Convert.IsDBNull(obj)) { _sql.Bind_Null(this, _flags, index); return; } | > > < < < < < < | 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 | object obj = param.Value; DbType objType = param.DbType; if ((obj != null) && (objType == DbType.Object)) objType = SQLiteConvert.TypeToDbType(obj.GetType()); #if !PLATFORM_COMPACTFRAMEWORK if ((_flags & SQLiteConnectionFlags.LogPreBind) == SQLiteConnectionFlags.LogPreBind) { IntPtr handle = _sqlite_stmt; SQLiteLog.LogMessage(String.Format( "Binding statement {0} paramter #{1} with database type {2} and raw value {{{3}}}...", handle, index, objType, obj)); } #endif if ((obj == null) || Convert.IsDBNull(obj)) { _sql.Bind_Null(this, _flags, index); return; } switch (objType) { case DbType.Date: case DbType.Time: case DbType.DateTime: // // NOTE: The old method (commented below) does not honor the selected date format |
︙ | ︙ |
Changes to System.Data.SQLite/System.Data.SQLite.Properties.targets.
︙ | ︙ | |||
66 67 68 69 70 71 72 | <!-- NOTE: Enable extra internal state checking? --> <PropertyGroup Condition="'$(CheckState)' != 'false'"> <DefineConstants>$(DefineConstants);CHECK_STATE</DefineConstants> </PropertyGroup> | < < < < < < < < < < < < < < < | 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 | <!-- NOTE: Enable extra internal state checking? --> <PropertyGroup Condition="'$(CheckState)' != 'false'"> <DefineConstants>$(DefineConstants);CHECK_STATE</DefineConstants> </PropertyGroup> <!-- NOTE: For interaction with the native SQLite implementation, use the custom build interop DLL (i.e. "SQLite.Interop.DLL")? --> <PropertyGroup Condition="'$(UseInteropDll)' != 'false'"> <DefineConstants>$(DefineConstants);USE_INTEROP_DLL</DefineConstants> </PropertyGroup> <!-- NOTE: For interaction with the native SQLite implementation, use the standard DLL (i.e. "sqlite3.dll")? --> <PropertyGroup Condition="'$(UseSqliteStandard)' != 'false'"> <DefineConstants>$(DefineConstants);SQLITE_STANDARD</DefineConstants> </PropertyGroup> |
︙ | ︙ | |||
157 158 159 160 161 162 163 | NOTE: Enable extra diagnostics from the custom built interop DLL (see the "SQLite.NET.Settings.targets" file for more information)? --> <PropertyGroup Condition="'$(InteropDebug)' != 'false'"> <DefineConstants>$(DefineConstants);INTEROP_DEBUG</DefineConstants> </PropertyGroup> | < < < < < < < < < < < < < < < < | 142 143 144 145 146 147 148 149 150 151 152 153 154 155 | NOTE: Enable extra diagnostics from the custom built interop DLL (see the "SQLite.NET.Settings.targets" file for more information)? --> <PropertyGroup Condition="'$(InteropDebug)' != 'false'"> <DefineConstants>$(DefineConstants);INTEROP_DEBUG</DefineConstants> </PropertyGroup> <!-- NOTE: Enable various Trace.WriteLine statements included in the code, based on several criteria (see the "SQLite.NET.Settings.targets" file for more information)? --> <PropertyGroup Condition="'$(TraceConnection)' != 'false'"> <DefineConstants>$(DefineConstants);TRACE_CONNECTION</DefineConstants> |
︙ | ︙ |
Changes to System.Data.SQLite/UnsafeNativeMethods.cs.
1 2 3 | /******************************************************** * ADO.NET 2.0 Data Provider for SQLite Version 3.X * Written by Robert Simpson (robert@blackcastlesoft.com) | | | 1 2 3 4 5 6 7 8 9 10 11 | /******************************************************** * ADO.NET 2.0 Data Provider for SQLite Version 3.X * Written by Robert Simpson (robert@blackcastlesoft.com) * * Released to the public domain, use at your own risk! ********************************************************/ namespace System.Data.SQLite { using System; using System.Globalization; |
︙ | ︙ | |||
22 23 24 25 26 27 28 | #if !PLATFORM_COMPACTFRAMEWORK && !DEBUG using System.Security; #endif using System.Runtime.InteropServices; | | < < < < < < < < < < < < < < < < < < < | 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | #if !PLATFORM_COMPACTFRAMEWORK && !DEBUG using System.Security; #endif using System.Runtime.InteropServices; #if !PLATFORM_COMPACTFRAMEWORK using System.Threading; #endif #if !PLATFORM_COMPACTFRAMEWORK && !DEBUG [SuppressUnmanagedCodeSecurity] #endif internal static class UnsafeNativeMethods { #region Optional Native SQLite Library Pre-Loading Code // // NOTE: If we are looking for the standard SQLite DLL ("sqlite3.dll"), // the interop DLL ("SQLite.Interop.dll"), or we are running on the // .NET Compact Framework, we should include this code (only if the // feature has actually been enabled). This code would be totally // redundant if this module has been bundled into the mixed-mode |
︙ | ︙ | |||
91 92 93 94 95 96 97 | /// </summary> /// <param name="fileName"> /// The name of the executable library. /// </param> /// <returns> /// The native module handle upon success -OR- IntPtr.Zero on failure. /// </returns> | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | /// </summary> /// <param name="fileName"> /// The name of the executable library. /// </param> /// <returns> /// The native module handle upon success -OR- IntPtr.Zero on failure. /// </returns> [DllImport("kernel32", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Auto, #if !PLATFORM_COMPACTFRAMEWORK BestFitMapping = false, ThrowOnUnmappableChar = true, #endif SetLastError = true)] private static extern IntPtr LoadLibrary(string fileName); /// <summary> /// This lock is used to protect the static _SQLiteModule and /// processorArchitecturePlatforms fields, below. /// </summary> private static readonly object staticSyncRoot = new object(); ///////////////////////////////////////////////////////////////////////// |
︙ | ︙ | |||
199 200 201 202 203 204 205 | /// Attempts to initialize this class by pre-loading the native SQLite /// library for the processor architecture of the current process. /// </summary> internal static void Initialize() { #if !PLATFORM_COMPACTFRAMEWORK // | | | | 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 | /// Attempts to initialize this class by pre-loading the native SQLite /// library for the processor architecture of the current process. /// </summary> internal static void Initialize() { #if !PLATFORM_COMPACTFRAMEWORK // // NOTE: If the "NoPreLoadSQLite" environment variable is set, skip // all our special code and simply return. // if (Environment.GetEnvironmentVariable("No_PreLoadSQLite") != null) return; #endif lock (staticSyncRoot) { |
︙ | ︙ | |||
231 232 233 234 235 236 237 | // // NOTE: Setup the list of platform names associated with // the supported processor architectures. // processorArchitecturePlatforms.Add("x86", "Win32"); processorArchitecturePlatforms.Add("AMD64", "x64"); processorArchitecturePlatforms.Add("IA64", "Itanium"); | < | 150 151 152 153 154 155 156 157 158 159 160 161 162 163 | // // NOTE: Setup the list of platform names associated with // the supported processor architectures. // processorArchitecturePlatforms.Add("x86", "Win32"); processorArchitecturePlatforms.Add("AMD64", "x64"); processorArchitecturePlatforms.Add("IA64", "Itanium"); } // // BUGBUG: What about other application domains? // if (_SQLiteModule == IntPtr.Zero) _SQLiteModule = PreLoadSQLiteDll(null, null); |
︙ | ︙ | |||
264 265 266 267 268 269 270 | // string directory = Environment.GetEnvironmentVariable( "PreLoadSQLite_BaseDirectory"); if (directory != null) return directory; | < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 182 183 184 185 186 187 188 189 190 191 192 193 194 195 | // string directory = Environment.GetEnvironmentVariable( "PreLoadSQLite_BaseDirectory"); if (directory != null) return directory; // // NOTE: Otherwise, fallback on using the base directory of the // current application domain. // return AppDomain.CurrentDomain.BaseDirectory; #else Assembly assembly = Assembly.GetExecutingAssembly(); |
︙ | ︙ | |||
364 365 366 367 368 369 370 | ///////////////////////////////////////////////////////////////////////// /// <summary> /// Queries and returns the processor architecture of the current /// process. /// </summary> /// <returns> /// The processor architecture of the current process -OR- null if it | | > | 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 | ///////////////////////////////////////////////////////////////////////// /// <summary> /// Queries and returns the processor architecture of the current /// process. /// </summary> /// <returns> /// The processor architecture of the current process -OR- null if it /// cannot be determined. Always returns an empty string when running on /// the .NET Compact Framework. /// </returns> private static string GetProcessorArchitecture() { #if !PLATFORM_COMPACTFRAMEWORK // // NOTE: If the "PreLoadSQLite_ProcessorArchitecture" environment // variable is set, use it verbatim for the current processor |
︙ | ︙ | |||
386 387 388 389 390 391 392 | // // BUGBUG: Will this always be reliable? // return Environment.GetEnvironmentVariable(PROCESSOR_ARCHITECTURE); #else // | < < < < < < < < < < < < | < < < < < | < < < < < < < < < < < < | 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 | // // BUGBUG: Will this always be reliable? // return Environment.GetEnvironmentVariable(PROCESSOR_ARCHITECTURE); #else // // BUGBUG: No way to determine this value on the .NET Compact // Framework (running on Windows CE, etc). // return String.Empty; #endif } ///////////////////////////////////////////////////////////////////////// /// <summary> |
︙ | ︙ | |||
623 624 625 626 627 628 629 | // // NOTE: On the .NET Compact Framework, the native interop assembly must // be used because it provides several workarounds to .NET Compact // Framework limitations important for proper operation of the core // System.Data.SQLite functionality (e.g. being able to bind // parameters and handle column values of types Int64 and Double). // | | | | | 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 | // // NOTE: On the .NET Compact Framework, the native interop assembly must // be used because it provides several workarounds to .NET Compact // Framework limitations important for proper operation of the core // System.Data.SQLite functionality (e.g. being able to bind // parameters and handle column values of types Int64 and Double). // internal const string SQLITE_DLL = "SQLite.Interop.083.dll"; #elif SQLITE_STANDARD // // NOTE: Otherwise, if the standard SQLite library is enabled, use it. // private const string SQLITE_DLL = "sqlite3"; #elif USE_INTEROP_DLL // // NOTE: Otherwise, if the native SQLite interop assembly is enabled, // use it. // private const string SQLITE_DLL = "SQLite.Interop.dll"; #else // // NOTE: Finally, assume that the mixed-mode assembly is being used. // private const string SQLITE_DLL = "System.Data.SQLite.dll"; #endif // This section uses interop calls that also fetch text length to optimize conversion. // When using the standard dll, we can replace these calls with normal sqlite calls and // do unoptimized conversions instead afterwards #region interop added textlength calls #if !SQLITE_STANDARD [DllImport(SQLITE_DLL)] internal static extern IntPtr sqlite3_bind_parameter_name_interop(IntPtr stmt, int index, out int len); |
︙ | ︙ | |||
703 704 705 706 707 708 709 | [DllImport(SQLITE_DLL)] internal static extern IntPtr sqlite3_value_text_interop(IntPtr p, out int len); [DllImport(SQLITE_DLL)] internal static extern IntPtr sqlite3_value_text16_interop(IntPtr p, out int len); | < < < < | 565 566 567 568 569 570 571 572 573 574 575 576 577 578 | [DllImport(SQLITE_DLL)] internal static extern IntPtr sqlite3_value_text_interop(IntPtr p, out int len); [DllImport(SQLITE_DLL)] internal static extern IntPtr sqlite3_value_text16_interop(IntPtr p, out int len); #endif // !SQLITE_STANDARD #endregion // These functions add existing functionality on top of SQLite and require a little effort to // get working when using the standard SQLite library. |
︙ | ︙ | |||
758 759 760 761 762 763 764 | #if !PLATFORM_COMPACTFRAMEWORK [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)] #else [DllImport(SQLITE_DLL)] #endif internal static extern SQLiteErrorCode sqlite3_close(IntPtr db); | < < < < < < < < < | 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 | #if !PLATFORM_COMPACTFRAMEWORK [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)] #else [DllImport(SQLITE_DLL)] #endif internal static extern SQLiteErrorCode sqlite3_close(IntPtr db); #if !PLATFORM_COMPACTFRAMEWORK [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)] #else [DllImport(SQLITE_DLL)] #endif internal static extern SQLiteErrorCode sqlite3_close_v2(IntPtr db); /* 3.7.14+ */ #if !PLATFORM_COMPACTFRAMEWORK [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)] #else [DllImport(SQLITE_DLL)] #endif internal static extern SQLiteErrorCode sqlite3_create_function(IntPtr db, byte[] strName, int nArgs, int nType, IntPtr pvUser, SQLiteCallback func, SQLiteCallback fstep, SQLiteFinalCallback ffinal); #if !PLATFORM_COMPACTFRAMEWORK [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)] #else [DllImport(SQLITE_DLL)] #endif internal static extern SQLiteErrorCode sqlite3_finalize(IntPtr stmt); #if !PLATFORM_COMPACTFRAMEWORK [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)] #else [DllImport(SQLITE_DLL)] #endif internal static extern SQLiteErrorCode sqlite3_reset(IntPtr stmt); |
︙ | ︙ | |||
900 901 902 903 904 905 906 | #if !PLATFORM_COMPACTFRAMEWORK [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)] #else [DllImport(SQLITE_DLL)] #endif internal static extern SQLiteErrorCode sqlite3_prepare(IntPtr db, IntPtr pSql, int nBytes, out IntPtr stmt, out IntPtr ptrRemain); | < < < < < < < < < | 749 750 751 752 753 754 755 756 757 758 759 760 761 762 | #if !PLATFORM_COMPACTFRAMEWORK [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)] #else [DllImport(SQLITE_DLL)] #endif internal static extern SQLiteErrorCode sqlite3_prepare(IntPtr db, IntPtr pSql, int nBytes, out IntPtr stmt, out IntPtr ptrRemain); #if !PLATFORM_COMPACTFRAMEWORK [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)] #else [DllImport(SQLITE_DLL)] #endif internal static extern SQLiteErrorCode sqlite3_table_column_metadata(IntPtr db, byte[] dbName, byte[] tblName, byte[] colName, out IntPtr ptrDataType, out IntPtr ptrCollSeq, out int notNull, out int primaryKey, out int autoInc); |
︙ | ︙ | |||
931 932 933 934 935 936 937 | [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)] #else [DllImport(SQLITE_DLL)] #endif internal static extern IntPtr sqlite3_value_text16(IntPtr p); #endif | | | 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 | [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)] #else [DllImport(SQLITE_DLL)] #endif internal static extern IntPtr sqlite3_value_text16(IntPtr p); #endif // SQLITE_STANDARD #endregion // These functions are custom and have no equivalent standard library method. // All of them are "nice to haves" and not necessarily "need to haves". #region no equivalent standard method |
︙ | ︙ | |||
997 998 999 1000 1001 1002 1003 | #if !PLATFORM_COMPACTFRAMEWORK [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)] #else [DllImport(SQLITE_DLL)] #endif internal static extern IntPtr sqlite3_libversion(); | < < < < < < < | 837 838 839 840 841 842 843 844 845 846 847 848 849 850 | #if !PLATFORM_COMPACTFRAMEWORK [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)] #else [DllImport(SQLITE_DLL)] #endif internal static extern IntPtr sqlite3_libversion(); #if !PLATFORM_COMPACTFRAMEWORK [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)] #else [DllImport(SQLITE_DLL)] #endif internal static extern IntPtr sqlite3_sourceid(); |
︙ | ︙ | |||
1233 1234 1235 1236 1237 1238 1239 | [DllImport(SQLITE_DLL)] #endif internal static extern int sqlite3_column_bytes(IntPtr stmt, int index); #if !PLATFORM_COMPACTFRAMEWORK [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)] #else | < < < < < < < | 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 | [DllImport(SQLITE_DLL)] #endif internal static extern int sqlite3_column_bytes(IntPtr stmt, int index); #if !PLATFORM_COMPACTFRAMEWORK [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)] #else [DllImport(SQLITE_DLL)] #endif internal static extern TypeAffinity sqlite3_column_type(IntPtr stmt, int index); #if !PLATFORM_COMPACTFRAMEWORK [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)] #else |
︙ | ︙ | |||
1272 1273 1274 1275 1276 1277 1278 | #if !PLATFORM_COMPACTFRAMEWORK [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)] #else [DllImport(SQLITE_DLL)] #endif internal static extern int sqlite3_value_bytes(IntPtr p); | < < < < < < < | 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 | #if !PLATFORM_COMPACTFRAMEWORK [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)] #else [DllImport(SQLITE_DLL)] #endif internal static extern int sqlite3_value_bytes(IntPtr p); #if !PLATFORM_COMPACTFRAMEWORK [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)] internal static extern double sqlite3_value_double(IntPtr p); #else [DllImport(SQLITE_DLL)] internal static extern void sqlite3_value_double_interop(IntPtr p, out double value); #endif |
︙ | ︙ | |||
1512 1513 1514 1515 1516 1517 1518 | [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)] #else [DllImport(SQLITE_DLL)] #endif internal static extern IntPtr sqlite3_errstr(SQLiteErrorCode rc); /* 3.7.15+ */ // Since sqlite3_log() takes a variable argument list, we have to overload declarations | | | 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 | [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)] #else [DllImport(SQLITE_DLL)] #endif internal static extern IntPtr sqlite3_errstr(SQLiteErrorCode rc); /* 3.7.15+ */ // Since sqlite3_log() takes a variable argument list, we have to overload declarations // for all possible calls. For now, we are only exposing a single string, and // depend on the caller to format the string. #if !PLATFORM_COMPACTFRAMEWORK [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)] #else [DllImport(SQLITE_DLL)] #endif internal static extern void sqlite3_log(SQLiteErrorCode iErrCode, byte[] zFormat); |
︙ | ︙ | |||
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 | [DllImport(SQLITE_DLL)] #endif internal static extern SQLiteErrorCode sqlite3_backup_step(IntPtr backup, int nPage); #if !PLATFORM_COMPACTFRAMEWORK [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)] #else [DllImport(SQLITE_DLL)] #endif internal static extern int sqlite3_backup_remaining(IntPtr backup); #if !PLATFORM_COMPACTFRAMEWORK [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)] #else [DllImport(SQLITE_DLL)] #endif internal static extern int sqlite3_backup_pagecount(IntPtr backup); #endregion } #if PLATFORM_COMPACTFRAMEWORK internal abstract class CriticalHandle : IDisposable { private bool _isClosed; protected IntPtr handle; | > > > > > > > | | 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 | [DllImport(SQLITE_DLL)] #endif internal static extern SQLiteErrorCode sqlite3_backup_step(IntPtr backup, int nPage); #if !PLATFORM_COMPACTFRAMEWORK [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)] #else [DllImport(SQLITE_DLL)] #endif internal static extern SQLiteErrorCode sqlite3_backup_finish(IntPtr backup); #if !PLATFORM_COMPACTFRAMEWORK [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)] #else [DllImport(SQLITE_DLL)] #endif internal static extern int sqlite3_backup_remaining(IntPtr backup); #if !PLATFORM_COMPACTFRAMEWORK [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)] #else [DllImport(SQLITE_DLL)] #endif internal static extern int sqlite3_backup_pagecount(IntPtr backup); #endregion } #if PLATFORM_COMPACTFRAMEWORK internal abstract class CriticalHandle : IDisposable { private bool _isClosed; protected IntPtr handle; protected CriticalHandle(IntPtr invalidHandleValue) { handle = invalidHandleValue; _isClosed = false; } ~CriticalHandle() |
︙ | ︙ | |||
1635 1636 1637 1638 1639 1640 1641 | #endif /////////////////////////////////////////////////////////////////////////// #region SQLiteConnectionHandle Class // Handles the unmanaged database pointer, and provides finalization // support for it. | | < < < < < < < < < < | 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 | #endif /////////////////////////////////////////////////////////////////////////// #region SQLiteConnectionHandle Class // Handles the unmanaged database pointer, and provides finalization // support for it. internal class SQLiteConnectionHandle : CriticalHandle { #if PLATFORM_COMPACTFRAMEWORK internal readonly object syncRoot = new object(); #endif /////////////////////////////////////////////////////////////////////// public static implicit operator IntPtr(SQLiteConnectionHandle db) |
︙ | ︙ | |||
1685 1686 1687 1688 1689 1690 1691 | } /////////////////////////////////////////////////////////////////////// private SQLiteConnectionHandle() : base(IntPtr.Zero) { | < < < < < < < < < | 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 | } /////////////////////////////////////////////////////////////////////// private SQLiteConnectionHandle() : base(IntPtr.Zero) { } /////////////////////////////////////////////////////////////////////// protected override bool ReleaseHandle() { try { #if !PLATFORM_COMPACTFRAMEWORK IntPtr localHandle = Interlocked.Exchange( ref handle, IntPtr.Zero); if (localHandle != IntPtr.Zero) SQLiteBase.CloseConnection(this, localHandle); #if !NET_COMPACT_20 && TRACE_HANDLE try { Trace.WriteLine(String.Format( "CloseConnection: {0}", localHandle)); } |
︙ | ︙ | |||
1729 1730 1731 1732 1733 1734 1735 | if (handle != IntPtr.Zero) { SQLiteBase.CloseConnection(this, handle); SetHandle(IntPtr.Zero); } } #endif | < < < < | 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 | if (handle != IntPtr.Zero) { SQLiteBase.CloseConnection(this, handle); SetHandle(IntPtr.Zero); } } #endif #if DEBUG return true; #endif } #if !NET_COMPACT_20 && TRACE_HANDLE catch (SQLiteException e) #else |
︙ | ︙ | |||
1773 1774 1775 1776 1777 1778 1779 | #else return true; #endif } /////////////////////////////////////////////////////////////////////// | < < < < < < < < < < | 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 | #else return true; #endif } /////////////////////////////////////////////////////////////////////// public override bool IsInvalid { get { #if PLATFORM_COMPACTFRAMEWORK lock (syncRoot) #endif |
︙ | ︙ | |||
1816 1817 1818 1819 1820 1821 1822 | } #endregion /////////////////////////////////////////////////////////////////////////// #region SQLiteStatementHandle Class // Provides finalization support for unmanaged SQLite statements. | | | 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 | } #endregion /////////////////////////////////////////////////////////////////////////// #region SQLiteStatementHandle Class // Provides finalization support for unmanaged SQLite statements. internal class SQLiteStatementHandle : CriticalHandle { #if PLATFORM_COMPACTFRAMEWORK internal readonly object syncRoot = new object(); #endif /////////////////////////////////////////////////////////////////////// |
︙ | ︙ | |||
1861 1862 1863 1864 1865 1866 1867 | } /////////////////////////////////////////////////////////////////////// private SQLiteStatementHandle() : base(IntPtr.Zero) { | < < < < | 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 | } /////////////////////////////////////////////////////////////////////// private SQLiteStatementHandle() : base(IntPtr.Zero) { } /////////////////////////////////////////////////////////////////////// protected override bool ReleaseHandle() { try |
︙ | ︙ | |||
1900 1901 1902 1903 1904 1905 1906 | if (handle != IntPtr.Zero) { SQLiteBase.FinalizeStatement(cnn, handle); SetHandle(IntPtr.Zero); } } #endif | < < < < | 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 | if (handle != IntPtr.Zero) { SQLiteBase.FinalizeStatement(cnn, handle); SetHandle(IntPtr.Zero); } } #endif #if DEBUG return true; #endif } #if !NET_COMPACT_20 && TRACE_HANDLE catch (SQLiteException e) #else |
︙ | ︙ | |||
1944 1945 1946 1947 1948 1949 1950 | #else return true; #endif } /////////////////////////////////////////////////////////////////////// | < < < < < < < < < < | 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 | #else return true; #endif } /////////////////////////////////////////////////////////////////////// public override bool IsInvalid { get { #if PLATFORM_COMPACTFRAMEWORK lock (syncRoot) #endif |
︙ | ︙ | |||
1987 1988 1989 1990 1991 1992 1993 | } #endregion /////////////////////////////////////////////////////////////////////////// #region SQLiteBackupHandle Class // Provides finalization support for unmanaged SQLite backup objects. | | | 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 | } #endregion /////////////////////////////////////////////////////////////////////////// #region SQLiteBackupHandle Class // Provides finalization support for unmanaged SQLite backup objects. internal class SQLiteBackupHandle : CriticalHandle { #if PLATFORM_COMPACTFRAMEWORK internal readonly object syncRoot = new object(); #endif /////////////////////////////////////////////////////////////////////// |
︙ | ︙ | |||
2032 2033 2034 2035 2036 2037 2038 | } /////////////////////////////////////////////////////////////////////// private SQLiteBackupHandle() : base(IntPtr.Zero) { | < < < < | 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 | } /////////////////////////////////////////////////////////////////////// private SQLiteBackupHandle() : base(IntPtr.Zero) { } /////////////////////////////////////////////////////////////////////// protected override bool ReleaseHandle() { try |
︙ | ︙ | |||
2071 2072 2073 2074 2075 2076 2077 | if (handle != IntPtr.Zero) { SQLiteBase.FinishBackup(cnn, handle); SetHandle(IntPtr.Zero); } } #endif | < < < < | 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 | if (handle != IntPtr.Zero) { SQLiteBase.FinishBackup(cnn, handle); SetHandle(IntPtr.Zero); } } #endif #if DEBUG return true; #endif } #if !NET_COMPACT_20 && TRACE_HANDLE catch (SQLiteException e) #else |
︙ | ︙ | |||
2113 2114 2115 2116 2117 2118 2119 | #if DEBUG return false; #else return true; #endif } | < < < < < < < < < < | 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 | #if DEBUG return false; #else return true; #endif } /////////////////////////////////////////////////////////////////////// public override bool IsInvalid { get { #if PLATFORM_COMPACTFRAMEWORK |
︙ | ︙ |
Changes to Tests/all.eagle.
︙ | ︙ | |||
44 45 46 47 48 49 50 | # # NOTE: Run all the unit tests. # set test_time [time { runAllTests $test_channel $path \ [getTestFiles [list $path] $test_flags(-file) $test_flags(-notFile)] \ [list [file tail [info script]] *.tcl pkgIndex.eagle common.eagle \ | | | 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | # # NOTE: Run all the unit tests. # set test_time [time { runAllTests $test_channel $path \ [getTestFiles [list $path] $test_flags(-file) $test_flags(-notFile)] \ [list [file tail [info script]] *.tcl pkgIndex.eagle common.eagle \ constraints.eagle epilogue.eagle prologue.eagle] }] # # NOTE: Run the local test epilogue, if any. # if {[file exists [file join $path epilogue.eagle]]} then { source [file join $path epilogue.eagle] |
︙ | ︙ |
Changes to Tests/backup.eagle.
︙ | ︙ | |||
16 17 18 19 20 21 22 | ############################################################################### package require System.Data.SQLite.Test runSQLiteTestPrologue ############################################################################### | < < < < < < | 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | ############################################################################### package require System.Data.SQLite.Test runSQLiteTestPrologue ############################################################################### set params(pages) [list -1 -1 0 0 1 1 2 2 1000 1000] set params(callbacks) [list null "new SQLiteBackupCallback(BackupCallback)" \ null "new SQLiteBackupCallback(BackupCallback)" \ null "new SQLiteBackupCallback(BackupCallback)" \ null "new SQLiteBackupCallback(BackupCallback)" \ null "new SQLiteBackupCallback(BackupCallback)"] |
︙ | ︙ | |||
107 108 109 110 111 112 113 114 115 116 117 118 119 120 | } set memSource [getDbConnection memDb] unset -nocomplain results errors set code [compileCSharpWith [subst { using System.Data.SQLite; using System.Text; using Eagle._Components.Public; namespace _Dynamic${id} { public static class Test${id} | > | 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 | } set memSource [getDbConnection memDb] unset -nocomplain results errors set code [compileCSharpWith [subst { using System; using System.Data.SQLite; using System.Text; using Eagle._Components.Public; namespace _Dynamic${id} { public static class Test${id} |
︙ | ︙ | |||
229 230 231 232 233 234 235 | [lindex $params(results) $i]]} } ############################################################################### unset -nocomplain i params pages callback | < < < < < < | 224 225 226 227 228 229 230 231 232 233 234 | [lindex $params(results) $i]]} } ############################################################################### unset -nocomplain i params pages callback ############################################################################### runSQLiteTestEpilogue runTestEpilogue |
Changes to Tests/basic.eagle.
︙ | ︙ | |||
310 311 312 313 314 315 316 317 318 319 320 321 322 323 | } -body { set id [object invoke Interpreter.GetActive NextId] set dataSource [file join [getDatabaseDirectory] $fileName] unset -nocomplain results errors set code [compileCSharpWith [subst { using System.Data.SQLite; namespace _Dynamic${id} { public static class Test${id} { public static bool TestSetAvRetry( | > | 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 | } -body { set id [object invoke Interpreter.GetActive NextId] set dataSource [file join [getDatabaseDirectory] $fileName] unset -nocomplain results errors set code [compileCSharpWith [subst { using System.Data; using System.Data.SQLite; namespace _Dynamic${id} { public static class Test${id} { public static bool TestSetAvRetry( |
︙ | ︙ | |||
418 419 420 421 422 423 424 425 426 427 428 429 430 431 | INSERT INTO t1 (x) VALUES(1); \ SELECT x FROM t1; \ } unset -nocomplain results errors set code [compileCSharpWith [subst { using System.Data.SQLite; namespace _Dynamic${id} { public static class Test${id} { public static void Main() | > | 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 | INSERT INTO t1 (x) VALUES(1); \ SELECT x FROM t1; \ } unset -nocomplain results errors set code [compileCSharpWith [subst { using System.Data; using System.Data.SQLite; namespace _Dynamic${id} { public static class Test${id} { public static void Main() |
︙ | ︙ | |||
475 476 477 478 479 480 481 482 483 484 485 486 487 488 | INSERT INTO t1 (x) VALUES(1); \ SELECT x FROM t1; \ } unset -nocomplain results errors set code [compileCSharpWith [subst { using System.Data.SQLite; namespace _Dynamic${id} { public static class Test${id} { public static void Main() | > | 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 | INSERT INTO t1 (x) VALUES(1); \ SELECT x FROM t1; \ } unset -nocomplain results errors set code [compileCSharpWith [subst { using System.Data; using System.Data.SQLite; namespace _Dynamic${id} { public static class Test${id} { public static void Main() |
︙ | ︙ | |||
930 931 932 933 934 935 936 | unset -nocomplain results errors set code [compileCSharpWith [subst { using System; using System.Data.SQLite; using System.Reflection; | < < < < < < < < < < < < < < < < < < < < | 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 | unset -nocomplain results errors set code [compileCSharpWith [subst { using System; using System.Data.SQLite; using System.Reflection; namespace _Dynamic${id} { public static class Test${id} { public static string GetConnectionString( string key, string value, string propertyName ) { SQLiteConnectionStringBuilder builder = |
︙ | ︙ | |||
976 977 978 979 980 981 982 | if (propertyName != null) { propertyValue = typeof(SQLiteConnectionStringBuilder).InvokeMember( propertyName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.GetProperty, null, builder, null); } | | < | 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 | if (propertyName != null) { propertyValue = typeof(SQLiteConnectionStringBuilder).InvokeMember( propertyName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.GetProperty, null, builder, null); } return String.Format("{0}, {1}", propertyValue, builder); } /////////////////////////////////////////////////////////////////////// public static void Main() { // do nothing. |
︙ | ︙ | |||
999 1000 1001 1002 1003 1004 1005 | if {$code eq "Ok"} then { set keys [list null Version Synchronous UseUTF16Encoding Pooling \ BinaryGUID "Data Source" Uri FullUri "Default Timeout" \ Enlist FailIfMissing "Legacy Format" "Read Only" \ Password "Page Size" "Max Page Count" "Cache Size" \ DateTimeFormat DateTimeKind BaseSchemaName \ "Journal Mode" "Default IsolationLevel" "Foreign Keys" \ | | | | | 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 | if {$code eq "Ok"} then { set keys [list null Version Synchronous UseUTF16Encoding Pooling \ BinaryGUID "Data Source" Uri FullUri "Default Timeout" \ Enlist FailIfMissing "Legacy Format" "Read Only" \ Password "Page Size" "Max Page Count" "Cache Size" \ DateTimeFormat DateTimeKind BaseSchemaName \ "Journal Mode" "Default IsolationLevel" "Foreign Keys" \ Flags SetDefaults ToFullPath] set values [list null 3 Normal True False \ True test.db test.db file:test.db 60 \ False True False True \ secret 4096 1024 8192 \ UnixEpoch Utc sqlite_schema \ Memory Serializable False \ Default False False] set propertyNames [list null Version SyncMode UseUTF16Encoding Pooling \ BinaryGUID DataSource Uri FullUri DefaultTimeout \ Enlist FailIfMissing LegacyFormat ReadOnly \ Password PageSize MaxPageCount CacheSize \ DateTimeFormat DateTimeKind BaseSchemaName \ JournalMode DefaultIsolationLevel ForeignKeys \ Flags SetDefaults ToFullPath] foreach key $keys value $values propertyName $propertyNames { set code [catch { object invoke _Dynamic${id}.Test${id} GetConnectionString \ $key $value $propertyName } result] |
︙ | ︙ | |||
1046 1047 1048 1049 1050 1051 1052 | 0 \{True, Read Only=True\} 0 \{secret, Password=secret\} 0 \{4096, Page\ Size=4096\} 0 \{1024, Max Page Count=1024\} 0 \{8192, Cache Size=8192\} 0\ \{UnixEpoch, DateTimeFormat=UnixEpoch\} 0 \{Utc, DateTimeKind=Utc\} 0\ \{sqlite_schema, BaseSchemaName=sqlite_schema\} 0 \{Memory, Journal\ Mode=Memory\} 0 \{Serializable, Default IsolationLevel=Serializable\} 0\ \{False, Foreign Keys=False\} 0 \{(?:Default|LogCallbackException),\ Flags=(?:Default|LogCallbackException)\} 0 \{False, SetDefaults=False\} 0\ | | | | | 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 | 0 \{True, Read Only=True\} 0 \{secret, Password=secret\} 0 \{4096, Page\ Size=4096\} 0 \{1024, Max Page Count=1024\} 0 \{8192, Cache Size=8192\} 0\ \{UnixEpoch, DateTimeFormat=UnixEpoch\} 0 \{Utc, DateTimeKind=Utc\} 0\ \{sqlite_schema, BaseSchemaName=sqlite_schema\} 0 \{Memory, Journal\ Mode=Memory\} 0 \{Serializable, Default IsolationLevel=Serializable\} 0\ \{False, Foreign Keys=False\} 0 \{(?:Default|LogCallbackException),\ Flags=(?:Default|LogCallbackException)\} 0 \{False, SetDefaults=False\} 0\ \{False, ToFullPath=False\}$}} ############################################################################### runTest {test data-1.17 {SQLiteConvert ToDateTime (Julian Day)} -body { set dateTime [object invoke System.Data.SQLite.SQLiteConvert ToDateTime \ 2455928.0 Utc] object invoke $dateTime ToString [getDateTimeFormat] } -cleanup { unset -nocomplain dateTime } -constraints {eagle System.Data.SQLite} -result {2012-01-01 12:00:00Z}} ############################################################################### |
︙ | ︙ | |||
1450 1451 1452 1453 1454 1455 1456 | [object invoke -flags +NonPublic System.Data.SQLite.SQLiteConvert \ TypeNameToDbType "NVARCHAR(1)"] \ [object invoke -flags +NonPublic System.Data.SQLite.SQLiteConvert \ TypeNameToDbType "VARCHAR (1)"] \ [object invoke -flags +NonPublic System.Data.SQLite.SQLiteConvert \ TypeNameToDbType "NVARCHAR (1)"] \ } -constraints {eagle System.Data.SQLite} -result \ | | | 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 | [object invoke -flags +NonPublic System.Data.SQLite.SQLiteConvert \ TypeNameToDbType "NVARCHAR(1)"] \ [object invoke -flags +NonPublic System.Data.SQLite.SQLiteConvert \ TypeNameToDbType "VARCHAR (1)"] \ [object invoke -flags +NonPublic System.Data.SQLite.SQLiteConvert \ TypeNameToDbType "NVARCHAR (1)"] \ } -constraints {eagle System.Data.SQLite} -result \ {String String String String String String}} ############################################################################### runTest {test data-1.28 {SetMemoryStatus method} -setup { # # NOTE: Make sure that SQLite core library is completely shutdown prior to # starting this test. |
︙ | ︙ | |||
1706 1707 1708 1709 1710 1711 1712 | set found(data) [expr \ {[llength [file list $directory(data) $fileName]] == 1}] set t [object create -alias Thread threadStart] sql execute $db "BEGIN TRANSACTION;"; $t Start | | | < | < | 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 | set found(data) [expr \ {[llength [file list $directory(data) $fileName]] == 1}] set t [object create -alias Thread threadStart] sql execute $db "BEGIN TRANSACTION;"; $t Start for {set i 1} {$i < 100} {incr i} { # # NOTE: Execute a query that should force the creation of a temporary file # for its statement journal. # sql execute $db "UPDATE t1 SET x = ?;" [list param1 String $i] # # NOTE: Give the other thread some time to notice the temporary file. # after 1000 # # NOTE: Stop when the other thread confirms that the temporary file was # created in the correct directory. # if {[info exists found(temp)] && $found(temp)} then { break } } $t Join; sql execute $db "COMMIT TRANSACTION;" lappend result $found(data) $found(temp); set result } -cleanup { # # NOTE: Close the database; however, do not attempt to delete the file as # it is not located in the database directory known to the cleanupDb # procedure (i.e. the one returned by getDatabaseDirectory). # cleanupDb $fileName db true false false |
︙ | ︙ | |||
1809 1810 1811 1812 1813 1814 1815 | } -constraints {eagle SQLite System.Data.SQLite} -result \ [string map [list \n \r\n] {CantOpen {unable to open database file this is a test} CantOpen {unable to open database file this is a test} True True}]} ############################################################################### | | < < < | | > | | | | < < < | | < | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | | 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 | } -constraints {eagle SQLite System.Data.SQLite} -result \ [string map [list \n \r\n] {CantOpen {unable to open database file this is a test} CantOpen {unable to open database file this is a test} True True}]} ############################################################################### runTest {test data-1.35 {open unencrypted database, with password} -setup { setupDb [set fileName data-1.35.db] } -body { sql execute $db "CREATE TABLE t1(x);" sql execute $db "INSERT INTO t1 (x) VALUES(1);" cleanupDb $fileName db true false false setupDb $fileName "" "" "" "" "Password=12345;" true false set result [list] lappend result [catch {sql execute -execute scalar $db \ "SELECT COUNT(*) FROM t1;"} error] $error lappend result [catch {sql execute $db \ "INSERT INTO t1 (x) VALUES(1);"} error] $error cleanupDb $fileName db true false false setupDb $fileName "" "" "" "" "" true false lappend result [catch {sql execute -execute scalar $db \ "SELECT COUNT(*) FROM t1;"} error] $error set result } -cleanup { cleanupDb $fileName unset -nocomplain error result db fileName } -constraints \ {eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} \ -match regexp -result {^1 \{System\.Data\.SQLite\.SQLiteException\ \(0x80004005\): file is encrypted or is not a database.*?\} 1\ \{System\.Data\.SQLite\.SQLiteException \(0x80004005\): file is encrypted or is\ not a database.*?\} 0 1$}} ############################################################################### runTest {test data-1.36 {open encrypted database, wrong password} -setup { setupDb [set fileName data-1.36.db] "" "" "" "" "Password=12345;" } -body { sql execute $db "CREATE TABLE t1(x);" sql execute $db "INSERT INTO t1 (x) VALUES(1);" cleanupDb $fileName db true false false setupDb $fileName "" "" "" "" "Password=12346;" true false set result [list] lappend result [catch {sql execute -execute scalar $db \ "SELECT COUNT(*) FROM t1;"} error] $error lappend result [catch {sql execute $db \ "INSERT INTO t1 (x) VALUES(1);"} error] $error cleanupDb $fileName db true false false setupDb $fileName "" "" "" "" "Password=12345;" true false lappend result [catch {sql execute -execute scalar $db \ "SELECT COUNT(*) FROM t1;"} error] $error set result } -cleanup { cleanupDb $fileName unset -nocomplain error result db fileName } -constraints \ {eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} \ -match regexp -result {^1 \{System\.Data\.SQLite\.SQLiteException\ \(0x80004005\): file is encrypted or is not a database.*?\} 1\ \{System\.Data\.SQLite\.SQLiteException \(0x80004005\): file is encrypted or is\ not a database.*?\} 0 1$}} ############################################################################### runTest {test data-1.37 {rollback to nested savepoint} -setup { setupDb [set fileName data-1.37.db] } -body { sql execute $db "BEGIN IMMEDIATE TRANSACTION;" sql execute $db "SAVEPOINT one;" sql execute $db "CREATE TABLE t1(x);" sql execute $db "SAVEPOINT two;" |
︙ | ︙ | |||
2186 2187 2188 2189 2190 2191 2192 | unset -nocomplain result db fileName } -constraints \ {eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} -result \ {1 2 1}} ############################################################################### | | | | 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 | unset -nocomplain result db fileName } -constraints \ {eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} -result \ {1 2 1}} ############################################################################### runTest {test data-1.38 {NoExtensionFunctions connection flag} -setup { setupDb [set fileName data-1.38.db] } -body { set result [list] lappend result [catch {sql execute -execute scalar $db \ "SELECT replicate('1234', 2);"} output] $output cleanupDb $fileName |
︙ | ︙ | |||
2218 2219 2220 2221 2222 2223 2224 | } -constraints \ {eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} -match \ regexp -result {^0 12341234 1 \{System\.Data\.SQLite\.SQLiteException\ \(0x80004005\): SQL logic error or missing database.*?\} 0 1234123412341234$}} ############################################################################### | | | | 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 | } -constraints \ {eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} -match \ regexp -result {^0 12341234 1 \{System\.Data\.SQLite\.SQLiteException\ \(0x80004005\): SQL logic error or missing database.*?\} 0 1234123412341234$}} ############################################################################### runTest {test data-1.39 {column name and index lookup} -setup { setupDb [set fileName data-1.39.db] } -body { sql execute $db { CREATE TABLE t1(x, y, z); INSERT INTO t1 (x, y, z) VALUES(1, 'foo', 1234); } set dataReader [sql execute -execute reader -format datareader \ |
︙ | ︙ | |||
2252 2253 2254 2255 2256 2257 2258 2259 2260 | cleanupDb $fileName unset -nocomplain result db fileName } -constraints \ {eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} -result \ {{x 0 1} {y 1 foo} {z 2 1234}}} ############################################################################### | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 | cleanupDb $fileName unset -nocomplain result db fileName } -constraints \ {eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} -result \ {{x 0 1} {y 1 foo} {z 2 1234}}} ############################################################################### unset -nocomplain systemDataSQLiteDllFile systemDataSQLiteLinqDllFile \ testExeFile testLinqExeFile northwindEfDbFile testLinqOutFile ############################################################################### runSQLiteTestEpilogue runTestEpilogue |
Changes to Tests/common.eagle.
︙ | ︙ | |||
86 87 88 89 90 91 92 | # return 2008; # TODO: Good "fallback" default? } } } } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | | | | | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 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 | # return 2008; # TODO: Good "fallback" default? } } } } proc getBuildConfiguration {} { # # NOTE: See if the "configuration" setting has been overridden by the user # (e.g. on the command line). This helps control exactly which set # of binaries we are testing (i.e. those built in the "Debug" or # "Release" build configurations). To override this value via the # 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 set. If so, use the # directory for the mixed-mode assembly (a.k.a. the native interop # assembly). To enable this option via the command line, enter a # command similar to one of the following (all on one line): # |
︙ | ︙ | |||
267 268 269 270 271 272 273 274 275 276 277 278 279 280 | [string length $::build_directory] > 0} then { # # NOTE: The location of the build directory has been overridden; # therefore, use it verbatim. # return $::build_directory } else { # # NOTE: If the "native" runtime option is set, the mixed-mode assembly # is being tested. In that case, the path to the build directory # will contain the platform name and all the binaries under test # should be present in that directory. If the "native" runtime # option is not set, the build directory will be considered to be # "platform-neutral", with the notable exception of any native | > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 | [string length $::build_directory] > 0} then { # # NOTE: The location of the build directory has been overridden; # therefore, use it verbatim. # return $::build_directory } else { # # NOTE: Figure out the build base directory. This will be the directory # that contains the actual build output directory (e.g. "bin"). # if {[info exists ::build_base_directory] && \ [string length $::build_base_directory] > 0} then { # # NOTE: The location of the build base directory has been overridden; # therefore, use it verbatim. # set path $::build_base_directory } elseif {[info exists ::common_directory] && \ [string length $::common_directory] > 0} then { # # NOTE: Next, fallback to the parent directory of the one containing # this file (i.e. "common.eagle"), if available. # set path [file dirname $::common_directory] } else { # # NOTE: Finally, fallback to the parent directory of the EagleTest # path. The EagleTest package guarantees that this variable # will be set to the directory containing the first file to # execute the [runTestPrologue] script library procedure. # set path [file dirname $::path] } # # NOTE: If the "native" runtime option is set, the mixed-mode assembly # is being tested. In that case, the path to the build directory # will contain the platform name and all the binaries under test # should be present in that directory. If the "native" runtime # option is not set, the build directory will be considered to be # "platform-neutral", with the notable exception of any native |
︙ | ︙ | |||
307 308 309 310 311 312 313 | # # Note that all of the build commands above will default to using # the latest version of MSBuild available and the "test_year" may # need to be adjusted accordingly to actually run the test suite. # Refer to the comments in [getBuildYear] for more information on # how to set this variable. # | | > > > > > | < < | 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 | # # Note that all of the build commands above will default to using # the latest version of MSBuild available and the "test_year" may # need to be adjusted accordingly to actually run the test suite. # Refer to the comments in [getBuildYear] for more information on # how to set this variable. # if {[hasRuntimeOption native]} then { return [file join $path bin [getBuildYear] [machineToPlatform \ $::tcl_platform(machine)] [getBuildConfiguration]] } else { return [file join $path bin [getBuildYear] [getBuildConfiguration] \ bin] } } } proc getBuildFileName { fileName } { # # NOTE: Returns the specified file name as if it were located in the # build directory, discarding any directory information present |
︙ | ︙ | |||
380 381 382 383 384 385 386 | # NOTE: Return the native-only interop assembly file name. # return [file nativename \ [file join [getBinaryDirectory] SQLite.Interop.dll]] } } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | | | | 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 | # NOTE: Return the native-only interop assembly file name. # return [file nativename \ [file join [getBinaryDirectory] SQLite.Interop.dll]] } } proc getDatabaseDirectory {} { # # NOTE: This procedure returns the directory where the test databases # should be located. By default, this just uses the temporary # directory configured for this system. # if {[info exists ::database_directory] && \ [string length $::database_directory] > 0} then { # # NOTE: The location of the database directory has been overridden; # therefore, use it. # return [file normalize $::database_directory] } elseif {[info exists ::scratch_directory] && \ [string length $::scratch_directory] > 0} then { # # NOTE: The location of the scratch directory has been overridden; # therefore, use it. # return [file normalize $::scratch_directory] } else { return [getTemporaryPath] } } proc getTemporaryDirectory {} { # # NOTE: This procedure returns the directory where the temporary files # should be located. By default, this just uses the temporary # directory configured for this system. # if {[info exists ::temporary_directory] && \ [string length $::temporary_directory] > 0} then { # # NOTE: The location of the temporary directory has been overridden; # therefore, use it. # return [file normalize $::temporary_directory] } elseif {[info exists ::scratch_directory] && \ [string length $::scratch_directory] > 0} then { # # NOTE: The location of the scratch directory has been overridden; # therefore, use it. # return [file normalize $::scratch_directory] } else { return [getTemporaryPath] } } proc getTestOverridesPreamble { {extraVarNames ""} } { set varNames [list] |
︙ | ︙ | |||
556 557 558 559 560 561 562 | return [uplevel 1 [list subst [appendArgs $prefix { if {[hasRuntimeOption native]} then { object invoke Interpreter.GetActive AddRuntimeOption native } } [getTestOverridesPreamble [list path test_channel]] $suffix]]] } | | < | < < < < | < < | < < < < < < < < < < < < < < < < < < < < < < | < | 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 | return [uplevel 1 [list subst [appendArgs $prefix { if {[hasRuntimeOption native]} then { object invoke Interpreter.GetActive AddRuntimeOption native } } [getTestOverridesPreamble [list path test_channel]] $suffix]]] } proc 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 { |
︙ | ︙ | |||
634 635 636 637 638 639 640 | "---- deleted binary file \"" $fileName \"\n] } else { tputs $::test_channel [appendArgs \ "---- failed to delete binary file \"" $fileName \"\n] } } | < < < < < < < < < < < < < < < < < < < < | 479 480 481 482 483 484 485 486 487 488 489 490 491 492 | "---- deleted binary file \"" $fileName \"\n] } else { tputs $::test_channel [appendArgs \ "---- failed to delete binary file \"" $fileName \"\n] } } proc tryCopyAssembly { fileName {pdb true} } { tryCopyBuildFile $fileName if {$pdb} then { tryCopyBuildFile [appendArgs [file rootname $fileName] .pdb] } } |
︙ | ︙ | |||
696 697 698 699 700 701 702 | # return $fileName } return "" } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 521 522 523 524 525 526 527 528 529 530 531 532 533 534 | # 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 { # |
︙ | ︙ | |||
937 938 939 940 941 942 943 | {temporary true} {varName db} } { # # NOTE: First, see if our caller has requested an in-memory database. # set isMemory [isMemoryDb $fileName] # | | | < | | 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 | {temporary true} {varName db} } { # # NOTE: First, see if our caller has requested an in-memory database. # set isMemory [isMemoryDb $fileName] # # 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. # if {!$isMemory && $qualify} then { set fileName [file join [getDatabaseDirectory] [file tail $fileName]] } # # NOTE: By default, delete any pre-existing database with the same file |
︙ | ︙ | |||
1039 1040 1041 1042 1043 1044 1045 | set flags [combineFlags $flags $::connection_flags] tputs $::test_channel [appendArgs \ "---- combined connection flags are: " $flags \n] } # | | | | | | 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 | set flags [combineFlags $flags $::connection_flags] tputs $::test_channel [appendArgs \ "---- combined connection flags are: " $flags \n] } # # NOTE: If our caller specified a SQLiteConnectionFlags, add the necessary # portion of the connection string now. # if {[string length $flags] > 0} then { append connection {;Flags=${flags}} } # # NOTE: If our 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 |
︙ | ︙ | |||
1078 1079 1080 1081 1082 1083 1084 | # return $db } proc getDbConnection { {varName db} } { # # NOTE: Refer to the specified variable (e.g. "db") in the context of our | | | | 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 | # return $db } proc getDbConnection { {varName db} } { # # NOTE: Refer to the specified variable (e.g. "db") in the context of our # caller. The handle to the database previously opened by [setupDb] # should be stored there. # upvar 1 $varName db # # NOTE: This returns the ADO.NET IDbConnection object instance for the # specified databse handle. Since getting this object relies upon # Eagle internals, great care should be taken to avoid disposing of |
︙ | ︙ | |||
1111 1112 1113 1114 1115 1116 1117 | $db "\", error: " \n\t $result \n] } } } proc freeDbConnection { {varName connection} } { # | | | | < | | < < < < < < < < < < < < < < < < < < < < < < < | | | | | 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 | $db "\", error: " \n\t $result \n] } } } proc freeDbConnection { {varName connection} } { # # NOTE: Refer to the specified variable (e.g. "connection") in the context # of our caller. The opaque object handle for an ADO.NET connection # previously returned by [getDbConnection] should be stored there. # upvar 1 $varName connection # # NOTE: Attempt to remove the opaque object handle from the interpreter # now. This [object dispose] call will not actually dispose of the # underlying object because the +NoDispose flag was set on it during # creation of the opaque object handle. # if {[info exists connection] && \ [catch {object dispose $connection} error]} then { # # NOTE: We somehow failed to remove the handle, report why. # tputs $::test_channel [appendArgs \ "==== WARNING: failed to remove connection handle \"" $connection \ "\", error: " \n\t $error \n] } } proc cleanupDb { fileName {varName db} {collect true} {qualify true} {delete true} } { # # NOTE: Attempt to force all pending "garbage" objects to be collected, # including SQLite statements and backup objects; this should allow # the underlying database file to be deleted. # if {$collect} then { collectGarbage $::test_channel } # # NOTE: Refer to the specified variable (e.g. "db") in the context of our # caller. The handle to the database previously opened by [setupDb] # should be stored there. # upvar 1 $varName db # # NOTE: Close the connection to the database now. This should allow us to # delete the underlying database file. # if {[info exists db] && [catch {sql close $db} error]} then { # # NOTE: We somehow failed to close the database, report why. # tputs $::test_channel [appendArgs \ "==== WARNING: failed to close database \"" $db "\", error: " \ |
︙ | ︙ | |||
1242 1243 1244 1245 1246 1247 1248 | # set code 0 } return $code } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 | # set code 0 } return $code } proc cleanupFile { fileName {collect true} {force false} } { # # NOTE: Attempt to force all pending "garbage" objects to be collected, # including SQLite statements and backup objects; this should allow # the underlying database file to be deleted. # if {$collect} then { |
︙ | ︙ | |||
1354 1355 1356 1357 1358 1359 1360 | # set code 0 } return $code } | | < < < < < < < < < < < | < < < < < < < < < < < < | | | | | | | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < < < < < | | | 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 | # set code 0 } return $code } proc collectGarbage { channel } { # # NOTE: Attempt to force a full garbage collection now. Report any # error that is encountered if we fail. # if {[catch {object invoke GC GetTotalMemory true} error]} then { tputs $channel [appendArgs \ "==== WARNING: failed full garbage collection, error: " \ \n\t $error \n] } } proc shutdownSQLite { channel {force false} {quiet false} } { # # NOTE: Make sure that SQLite core library is completely shutdown. This # is used by tests that change configuration options and/or those # that need to make sure logging is initialized (i.e. just in case # the SQLite core library was initialized in the process prior to # the SQLiteLog class being able to setup its logging callback). # if {$force || [haveConstraint SQLite]} then { if {[catch {object invoke -flags +NonPublic \ System.Data.SQLite.UnsafeNativeMethods \ sqlite3_shutdown} result] == 0} then { if {!$quiet} then { tputs $channel [appendArgs \ "---- call sqlite3_shutdown()... ok: " $result \n] } } else { if {!$quiet} then { tputs $channel [appendArgs \ |
︙ | ︙ | |||
1606 1607 1608 1609 1610 1611 1612 | } } } } else { tputs $channel no\n # | | < < | | | | < < | | | | | | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < < < < < < | 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 | } } } } else { tputs $channel no\n # # NOTE: Does our caller want to reset the directories? # if {$reset} then { # # NOTE: Now make sure the database and temporary directories are # reset their default values, which should be null for both. # Since the sqlite3_win32_set_directory function does not # appear to be available, use the associated PRAGMA commands # instead. # foreach directory [list data_store_directory temp_store_directory] { set sql [appendArgs "PRAGMA " $directory " = \"\";"] if {[catch {executeSql $sql} result] == 0} then { tputs $channel [appendArgs \ "---- execute PRAGMA " $directory "... ok: " \ $result \n] } else { tputs $channel [appendArgs \ "---- execute PRAGMA " $directory "... error: " \ \n\t $result \n] } } } } # # NOTE: Finally, show the current value of the database and temporary # directories. # foreach directory [list data_store_directory temp_store_directory] { tputs $channel [appendArgs "---- checking " $directory "... "] set sql [appendArgs "PRAGMA " $directory \;] if {[catch {executeSql $sql scalar} result] == 0} then { tputs $channel [appendArgs "ok: \"" $result \"\n] } else { tputs $channel [appendArgs "error: " \n\t $result \n] } } } 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. |
︙ | ︙ | |||
1756 1757 1758 1759 1760 1761 1762 | tryDeleteAssembly System.Data.SQLite.dll removeConstraint file_System.Data.SQLite.dll tryDeleteAssembly System.Data.SQLite.Linq.dll removeConstraint file_System.Data.SQLite.Linq.dll } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 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 | tryDeleteAssembly System.Data.SQLite.dll removeConstraint file_System.Data.SQLite.dll tryDeleteAssembly System.Data.SQLite.Linq.dll removeConstraint file_System.Data.SQLite.Linq.dll } # # NOTE: Skip trying to copy any files if we are so instructed. # if {![info exists ::no(copySqliteFiles)]} then { tryCopyAssembly sqlite3.dll 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 \"sqlite3.dll\"... " \ [file version [getBinaryFileName sqlite3.dll]] \n] } |
︙ | ︙ | |||
1878 1879 1880 1881 1882 1883 1884 | tputs $::test_channel [appendArgs [formatList [lsort \ $defineConstants]] \n] } else { tputs $::test_channel unknown\n } } | < < < < < | < < | < < | | | < < < < > | | < < > > | | > | > > | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < < < < < < < < < < < | | | 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 | tputs $::test_channel [appendArgs [formatList [lsort \ $defineConstants]] \n] } else { tputs $::test_channel unknown\n } } # # NOTE: Now, we need to know if the SQLite core library is available # (i.e. because the managed-only System.Data.SQLite assembly can # load without it; however, it cannot do anything useful without # it). If we are using the mixed-mode assembly and we already # found it (above), this should always succeed. # checkForSQLite $::test_channel # # NOTE: Check the SQLite database and temporary directories. # checkForSQLiteDirectories $::test_channel # # NOTE: Attempt to determine if the custom extension functions were # compiled into the SQLite interop assembly. # checkForSQLiteDefineConstant $::test_channel \ CHECK_STATE checkForSQLiteDefineConstant $::test_channel \ USE_INTEROP_DLL checkForSQLiteDefineConstant $::test_channel \ INTEROP_EXTENSION_FUNCTIONS checkForSQLiteDefineConstant $::test_channel \ INTEROP_TEST_EXTENSION checkForSQLiteDefineConstant $::test_channel \ SQLITE_STANDARD # # NOTE: Check the current build year. Basically, this indicates # which version of MSBuild and/or Visual Studio was used to # compile the assembly binaries under test. # tputs $::test_channel \ "---- checking for System.Data.SQLite build year... " set year [getBuildYear] addConstraint [appendArgs buildYear $year] tputs $::test_channel [appendArgs \" $year \"\n] # # NOTE: Check the current build configuration. This should normally # be either "Debug" or "Release". # tputs $::test_channel \ "---- checking for System.Data.SQLite build configuration... " set configuration [getBuildConfiguration] addConstraint [appendArgs buildConfiguration $configuration] tputs $::test_channel [appendArgs \" $configuration \"\n] # # NOTE: Check for the native runtime option, which would mean we are # using the mixed-mode assembly. # checkForRuntimeOption $::test_channel native # # NOTE: Report the resource usage prior to running any tests. # reportSQLiteResources $::test_channel # # NOTE: Show the active test constraints. # tputs $::test_channel [appendArgs "---- constraints: " \ [formatList [lsort [getConstraints]]] \n] # # NOTE: Show when our tests actually began (now). # tputs $::test_channel [appendArgs \ "---- System.Data.SQLite tests began at " \ [clock format [clock seconds]] \n] } } proc runSQLiteTestEpilogue {} { # # NOTE: Skip running our custom epilogue if the main one has been skipped. # if {![info exists ::no(epilogue.eagle)]} then { # # NOTE: Show when our tests actually ended (now). # tputs $::test_channel [appendArgs \ "---- System.Data.SQLite tests ended at " \ [clock format [clock seconds]] \n] # # NOTE: Also report the resource usage after running the tests. # reportSQLiteResources $::test_channel } } ########################################################################### ############################# END Eagle ONLY ############################## ########################################################################### } # # NOTE: Save the name of the directory containing this file. # if {![info exists ::common_directory]} then { set ::common_directory [file dirname [info script]] } # # NOTE: Provide the System.Data.SQLite test package to the interpreter. # package provide System.Data.SQLite.Test 1.0 } |
Deleted Tests/empty.eagle.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Changes to Tests/installer.eagle.
︙ | ︙ | |||
149 150 151 152 153 154 155 | list $code [expr {$code == 0 ? [string equal [readFile $fileName] \ [subst -nobackslashes [readFile $testInstallVs2005LogFile]]] : $error}] } -cleanup { cleanupFile $fileName unset -nocomplain wow64 is64 code output error fileName | | | 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 | list $code [expr {$code == 0 ? [string equal [readFile $fileName] \ [subst -nobackslashes [readFile $testInstallVs2005LogFile]]] : $error}] } -cleanup { cleanupFile $fileName unset -nocomplain wow64 is64 code output error fileName } -constraints {eagle administrator buildYear2005 visualStudio2005\ System.Data.SQLite.dll_v2.0.50727 file_Installer.exe\ file_System.Data.SQLite.dll file_Installer_Test_Vs2005.log} -result {0 True}} ############################################################################### runTest {test installer-1.2 {uninstaller tool / Visual Studio 2005} -setup { set fileName [file join [getTemporaryPath] [file tail [string map [list \ |
︙ | ︙ | |||
186 187 188 189 190 191 192 | list $code [expr {$code == 0 ? [string equal [readFile $fileName] \ [subst -nobackslashes [readFile $testUninstallVs2005LogFile]]] : $error}] } -cleanup { cleanupFile $fileName unset -nocomplain wow64 is64 code output error fileName | | | 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 | list $code [expr {$code == 0 ? [string equal [readFile $fileName] \ [subst -nobackslashes [readFile $testUninstallVs2005LogFile]]] : $error}] } -cleanup { cleanupFile $fileName unset -nocomplain wow64 is64 code output error fileName } -constraints {eagle administrator buildYear2005 visualStudio2005\ System.Data.SQLite.dll_v2.0.50727 file_Installer.exe\ file_System.Data.SQLite.dll file_Uninstaller_Test_Vs2005.log} -result {0 True}} ############################################################################### runTest {test installer-1.3 {installer tool / Visual Studio 2008} -setup { set fileName [file join [getTemporaryPath] [file tail [string map [list \ |
︙ | ︙ | |||
223 224 225 226 227 228 229 | list $code [expr {$code == 0 ? [string equal [readFile $fileName] \ [subst -nobackslashes [readFile $testInstallVs2008LogFile]]] : $error}] } -cleanup { cleanupFile $fileName unset -nocomplain wow64 is64 code output error fileName | | | 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 | list $code [expr {$code == 0 ? [string equal [readFile $fileName] \ [subst -nobackslashes [readFile $testInstallVs2008LogFile]]] : $error}] } -cleanup { cleanupFile $fileName unset -nocomplain wow64 is64 code output error fileName } -constraints {eagle administrator buildYear2008 visualStudio2008\ System.Data.SQLite.dll_v2.0.50727 file_Installer.exe\ file_System.Data.SQLite.dll file_System.Data.SQLite.Linq.dll\ file_Installer_Test_Vs2008.log} -result {0 True}} ############################################################################### runTest {test installer-1.4 {uninstaller tool / Visual Studio 2008} -setup { |
︙ | ︙ | |||
261 262 263 264 265 266 267 | list $code [expr {$code == 0 ? [string equal [readFile $fileName] \ [subst -nobackslashes [readFile $testUninstallVs2008LogFile]]] : $error}] } -cleanup { cleanupFile $fileName unset -nocomplain wow64 is64 code output error fileName | | | 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 | list $code [expr {$code == 0 ? [string equal [readFile $fileName] \ [subst -nobackslashes [readFile $testUninstallVs2008LogFile]]] : $error}] } -cleanup { cleanupFile $fileName unset -nocomplain wow64 is64 code output error fileName } -constraints {eagle administrator buildYear2008 visualStudio2008\ System.Data.SQLite.dll_v2.0.50727 file_Installer.exe\ file_System.Data.SQLite.dll file_System.Data.SQLite.Linq.dll\ file_Uninstaller_Test_Vs2008.log} -result {0 True}} ############################################################################### runTest {test installer-1.5 {installer tool / Visual Studio 2010} -setup { |
︙ | ︙ | |||
299 300 301 302 303 304 305 | list $code [expr {$code == 0 ? [string equal [readFile $fileName] \ [subst -nobackslashes [readFile $testInstallVs2010LogFile]]] : $error}] } -cleanup { cleanupFile $fileName unset -nocomplain wow64 is64 code output error fileName | | | 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 | list $code [expr {$code == 0 ? [string equal [readFile $fileName] \ [subst -nobackslashes [readFile $testInstallVs2010LogFile]]] : $error}] } -cleanup { cleanupFile $fileName unset -nocomplain wow64 is64 code output error fileName } -constraints {eagle administrator buildYear2010 visualStudio2010\ System.Data.SQLite.dll_v4.0.30319 file_Installer.exe\ file_System.Data.SQLite.dll file_System.Data.SQLite.Linq.dll\ file_Installer_Test_Vs2010.log} -result {0 True}} ############################################################################### runTest {test installer-1.6 {uninstaller tool / Visual Studio 2010} -setup { |
︙ | ︙ | |||
337 338 339 340 341 342 343 | list $code [expr {$code == 0 ? [string equal [readFile $fileName] \ [subst -nobackslashes [readFile $testUninstallVs2010LogFile]]] : $error}] } -cleanup { cleanupFile $fileName unset -nocomplain wow64 is64 code output error fileName | | | 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 | list $code [expr {$code == 0 ? [string equal [readFile $fileName] \ [subst -nobackslashes [readFile $testUninstallVs2010LogFile]]] : $error}] } -cleanup { cleanupFile $fileName unset -nocomplain wow64 is64 code output error fileName } -constraints {eagle administrator buildYear2010 visualStudio2010\ System.Data.SQLite.dll_v4.0.30319 file_Installer.exe\ file_System.Data.SQLite.dll file_System.Data.SQLite.Linq.dll\ file_Uninstaller_Test_Vs2010.log} -result {0 True}} ############################################################################### runTest {test installer-1.7 {installer tool / Visual Studio 2012} -setup { |
︙ | ︙ | |||
375 376 377 378 379 380 381 | list $code [expr {$code == 0 ? [string equal [readFile $fileName] \ [subst -nobackslashes [readFile $testInstallVs2012LogFile]]] : $error}] } -cleanup { cleanupFile $fileName unset -nocomplain wow64 is64 code output error fileName | | | 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 | list $code [expr {$code == 0 ? [string equal [readFile $fileName] \ [subst -nobackslashes [readFile $testInstallVs2012LogFile]]] : $error}] } -cleanup { cleanupFile $fileName unset -nocomplain wow64 is64 code output error fileName } -constraints {eagle administrator buildYear2012 visualStudio2012\ System.Data.SQLite.dll_v4.0.30319 file_Installer.exe\ file_System.Data.SQLite.dll file_System.Data.SQLite.Linq.dll\ file_Installer_Test_Vs2012.log} -result {0 True}} ############################################################################### runTest {test installer-1.8 {uninstaller tool / Visual Studio 2012} -setup { |
︙ | ︙ | |||
413 414 415 416 417 418 419 | list $code [expr {$code == 0 ? [string equal [readFile $fileName] \ [subst -nobackslashes [readFile $testUninstallVs2012LogFile]]] : $error}] } -cleanup { cleanupFile $fileName unset -nocomplain wow64 is64 code output error fileName | | | 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 | list $code [expr {$code == 0 ? [string equal [readFile $fileName] \ [subst -nobackslashes [readFile $testUninstallVs2012LogFile]]] : $error}] } -cleanup { cleanupFile $fileName unset -nocomplain wow64 is64 code output error fileName } -constraints {eagle administrator buildYear2012 visualStudio2012\ System.Data.SQLite.dll_v4.0.30319 file_Installer.exe\ file_System.Data.SQLite.dll file_System.Data.SQLite.Linq.dll\ file_Uninstaller_Test_Vs2012.log} -result {0 True}} ############################################################################### unset -nocomplain testUninstallVs2012LogFile testUninstallVs2010LogFile \ |
︙ | ︙ |
Changes to Tests/stress.eagle.
︙ | ︙ | |||
16 17 18 19 20 21 22 | ############################################################################### package require System.Data.SQLite.Test runSQLiteTestPrologue ############################################################################### | < < < < < < < < < < < < < < < < < < | | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | ############################################################################### package require System.Data.SQLite.Test runSQLiteTestPrologue ############################################################################### # # NOTE: Make sure that SQLite core library is completely shutdown prior to # starting any of the tests in this file. # shutdownSQLite $test_channel ############################################################################### runTest {test stress-1.1 {multithreaded stress testing} -setup { unset -nocomplain result thread index workload noWorkload srcDb db \ fileName compiled options count times logFileName logListener \ connection indicators iterations exitOnFail failures ############################################################################# proc formatWorkloadResult { index } { set result [appendArgs "---- iterations for workload (" $index "): "] append result [expr {[info exists ::iterations($index,ok)] ? \ $::iterations($index,ok) : 0}] " ok, " append result [expr {[info exists ::iterations($index,error)] ? \ $::iterations($index,error) : 0}] " error, " # |
︙ | ︙ | |||
102 103 104 105 106 107 108 | $::failures($indicator) : 0}] " failed\n" return $result } ############################################################################# | < < < < < < < < < < < < < < < < < < < < | < < < < < < < < < < < < < < < < < < < < < < | < < < < < < < < < < < < < > | < | < < < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 | $::failures($indicator) : 0}] " failed\n" return $result } ############################################################################# proc isExpectedError { error } { return [expr {[regexp -- {\sno such table: t1\s} $error] || \ [regexp -- {\sdatabase is locked\s} $error]}] } ############################################################################# proc showTest { indicator } { tputs $::test_channel $indicator append ::indicators $indicator after [expr {int(rand() * 1000 + $::count(2))}] } ############################################################################# proc failTest { indicator error } { # # NOTE: Halt all testing and exit the process now # -OR- just record the failure and continue? # if {$::exitOnFail} then { set level [expr {[info level] - 1}] tputs $::test_channel [appendArgs \ \n [info level $level] ": " \n\t $error \n] exit Failure } else { tputs $::test_channel $indicator if {![info exists ::failures($indicator)]} then { set ::failures($indicator) 0 } incr ::failures($indicator) after [expr {int(rand() * 1000 + $::count(2))}] } } ############################################################################# proc setupLogging { fileName } { if {![info exists ::logListener]} then { set ::logListener [object create -alias \ |
︙ | ︙ | |||
302 303 304 305 306 307 308 309 310 311 312 | tputs $::test_channel [appendArgs \ "---- disabled SQLite trace logging to file \"" $fileName \"\n] } ############################################################################# # # NOTE: Setup the default values for the tunable workload parameters. Any, # all, or none of these may be overriden via the command line. # | > > > > > > > > > > > > > | | | | | < | < | < < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | | < | | < < | | | < | < < < < | | < < < < < < < < < < < < < < < < | 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 | tputs $::test_channel [appendArgs \ "---- disabled SQLite trace logging to file \"" $fileName \"\n] } ############################################################################# # # NOTE: The trace listener used with the SQLiteLog class to capture output # from the core SQLite library requires its own log file because the # TextWriterTraceListener class opens and locks the log file it uses # as the basis of the output stream. Before this test is complete, # the entire contents of this trace log file will be copied into the # main test log file and then deleted. # set logFileName [appendArgs [file rootname $test_log] .trace.log] setupLogging $logFileName ############################################################################# # # NOTE: Setup the default values for the tunable workload parameters. Any, # all, or none of these may be overriden via the command line. # set count(0) 1; # Workload repeat count (i.e. total full runs). set count(1) 20; # Workload iteration count (i.e. within a run). set count(2) 500; # Workload iteration delay, in milliseconds. set count(3) 2000; # Workload "small" data chunk size, in bytes. set count(4) 10000000; # Workload "big" data chunk size, in bytes. set noWorkload [list]; # Workloads to be omitted from the run, by index. set exitOnFail true; # Halt testing and exit process on test failure? ############################################################################# # # NOTE: If command line arguments to the test suite are available, process # them for any options that are applicable to this test (i.e. any of # the tunable workload parameters listed above). # if {[info exists argv] && [llength $argv] > 0} then { parse options -flags \ {-StopOnUnknownOption +IgnoreOnUnknownOption SkipOnUnknownOption} -- \ [list [list null MustHaveIntegerValue -1 -1 -count0 $count(0)] \ [list null MustHaveIntegerValue -1 -1 -count1 $count(1)] \ [list null MustHaveIntegerValue -1 -1 -count2 $count(2)] \ [list null MustHaveIntegerValue -1 -1 -count3 $count(3)] \ [list null MustHaveIntegerValue -1 -1 -count4 $count(4)] \ [list null MustHaveListValue -1 -1 -noWorkload $noWorkload] \ [list null MustHaveBooleanValue -1 -1 -exitOnFail $exitOnFail]] $argv set count(0) $options(-count0,value) set count(1) $options(-count1,value) set count(2) $options(-count2,value) set count(3) $options(-count3,value) set count(4) $options(-count4,value) set noWorkload $options(-noWorkload,value) set exitOnFail $options(-exitOnFail,value) } ############################################################################# tputs $test_channel [appendArgs \ "---- workloads will repeat " $count(0) " time(s)...\n"] tputs $test_channel [appendArgs \ "---- workloads will have " $count(1) " iteration(s)...\n"] tputs $test_channel [appendArgs \ "---- workloads will wait at least " $count(2) " millisecond(s)...\n"] tputs $test_channel [appendArgs \ "---- workload \"small\" chunk size is " $count(3) " byte(s)...\n"] tputs $test_channel [appendArgs \ "---- workload \"big\" chunk size is " $count(4) " byte(s)...\n"] if {[llength $noWorkload] > 0} then { tputs $test_channel [appendArgs \ "---- workloads to be skipped... " $noWorkload \n] } tputs $test_channel [appendArgs \ "---- workload failures " [expr {$exitOnFail ? "will" : "will not"}] \ " halt testing and exit the process...\n"] ############################################################################# # # NOTE: Workloads #12 and #13 contain C# code that should be compiled, but # only once. These variables keep track of that state information. # An integer value in one of these variables means the compilation was |
︙ | ︙ | |||
459 460 461 462 463 464 465 | # NOTE: This is a normal on-disk database. # set fileName(2) [file join [getDatabaseDirectory] [appendArgs \ stress- [pid] - [string trim [clock seconds] -] .db]] ############################################################################# | | | < < < < < < < < < < < < < < < < | < < < | < < < | > > | < < < < | > > | < < < < | | > | | < < < | | > | < < < | < < < | | > | < < < | < < < | < < < | < < < > > < | 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 | # NOTE: This is a normal on-disk database. # set fileName(2) [file join [getDatabaseDirectory] [appendArgs \ stress- [pid] - [string trim [clock seconds] -] .db]] ############################################################################# setupDb $fileName(1) "" "" "" "" "" false false true true srcDb setupDb $fileName(2) ############################################################################# # # NOTE: This serves two purposes. First, it allows us to verify the trace # logging subsystem is working properly. Second, it places the file # name for the associated database file into the trace log file. # set connection [getDbConnection] $connection LogMessage 0 [appendArgs \ "starting stress test using database \"" $fileName(2) \"...] ############################################################################# # WORKLOAD #1 (A) # ############################################################################# set workload(1) [list \ [list srcFileName dstFileName table count1 count2 count3] { # # NOTE: Workload #1, CREATE TABLE statements. # lappend ::times(1) [lindex [time { setupDb $dstFileName "" "" "" "" "" true false for {set index 2} {$index <= $count1} {incr index} { if {[catch { sql execute $db [appendArgs \ "CREATE TABLE IF NOT EXISTS t" \ $index "(x PRIMARY KEY, y, z);"] showTest A } error]} then { if {[isExpectedError $error]} then { showTest a } else { failTest a $error } } } cleanupDb $dstFileName db false true false }] 0] }] ############################################################################# # WORKLOAD #2 (B) # ############################################################################# set workload(2) [list \ [list srcFileName dstFileName table count1 count2 count3] { # # NOTE: Workload #2, DROP TABLE statements. # lappend ::times(2) [lindex [time { setupDb $dstFileName "" "" "" "" "" true false for {set index 2} {$index <= $count1} {incr index} { if {[catch { sql execute $db [appendArgs \ "DROP TABLE IF EXISTS t" $index \;] showTest B } error]} then { if {[isExpectedError $error]} then { showTest b } else { failTest b $error } } } cleanupDb $dstFileName db false true false }] 0] }] ############################################################################# # WORKLOAD #3 (C) # ############################################################################# set workload(3) [list \ [list srcFileName dstFileName table count1 count2 count3] { # # NOTE: Workload #3, "small" SELECT statements. # lappend ::times(3) [lindex [time { setupDb $dstFileName "" "" "" "" "" true false for {set index 1} {$index <= $count1} {incr index} { if {[catch { set sql [appendArgs \ "SELECT x, y FROM " $table " WHERE z = 'small';"] set reader [sql execute -execute reader \ -format dataReader -alias $db $sql] while {[$reader Read]} { # # NOTE: Do nothing. # } unset -nocomplain reader showTest C } error]} then { if {[isExpectedError $error]} then { showTest c } else { failTest c $error } } } cleanupDb $dstFileName db false true false }] 0] }] ############################################################################# # WORKLOAD #4 (D) # ############################################################################# set workload(4) [list \ [list srcFileName dstFileName table count1 count2 count3] { # # NOTE: Workload #4, "big" SELECT statements. # lappend ::times(4) [lindex [time { setupDb $dstFileName "" "" "" "" "" true false for {set index 1} {$index <= $count1} {incr index} { if {[catch { set sql [appendArgs \ "SELECT x, y FROM " $table " WHERE z = 'big';"] set reader [sql execute -execute reader \ -format dataReader -alias $db $sql] while {[$reader Read]} { # # NOTE: Do nothing. # } unset -nocomplain reader showTest D } error]} then { if {[isExpectedError $error]} then { showTest d } else { failTest d $error } } } cleanupDb $dstFileName db false true false }] 0] }] ############################################################################# # WORKLOAD #5 (E) # ############################################################################# set workload(5) [list \ [list srcFileName dstFileName table count1 count2 count3] { # # NOTE: Workload #5, "small" INSERT statements. # lappend ::times(5) [lindex [time { setupDb $dstFileName "" "" "" "" "" true false for {set index 1} {$index <= $count1} {incr index} { if {[catch { sql execute $db [appendArgs \ "INSERT INTO " $table "(x, y, z) VALUES('" \ [format %lX [expr {random()}]] "', '" \ [base64 encode -- [expr {randstr($count2)}]] \ "', 'small');"] showTest E } error]} then { if {[isExpectedError $error]} then { showTest e } else { failTest e $error } } } cleanupDb $dstFileName db false true false }] 0] }] ############################################################################# # WORKLOAD #6 (F) # ############################################################################# set workload(6) [list \ [list srcFileName dstFileName table count1 count2 count3] { # # NOTE: Workload #6, "big" INSERT statements. # lappend ::times(6) [lindex [time { setupDb $dstFileName "" "" "" "" "" true false for {set index 1} {$index <= $count1} {incr index} { if {[catch { sql execute $db [appendArgs \ "INSERT INTO " $table "(x, y, z) VALUES('" \ [format %lX [expr {random()}]] \ "', RANDOMBLOB(" $count3 "), 'big');"] showTest F } error]} then { if {[isExpectedError $error]} then { showTest f } else { failTest f $error } } } cleanupDb $dstFileName db false true false }] 0] }] ############################################################################# # WORKLOAD #7 (G) # ############################################################################# set workload(7) [list \ [list srcFileName dstFileName table count1 count2 count3] { # # NOTE: Workload #7, "small" UPDATE statements. # lappend ::times(7) [lindex [time { setupDb $dstFileName "" "" "" "" "" true false for {set index 1} {$index <= $count1} {incr index} { if {[catch { sql execute $db [appendArgs "UPDATE " $table \ " SET y = '" [base64 encode -- [expr {randstr($count2)}]] \ "' WHERE x LIKE '" [format %X $index] "%' AND z = 'small';"] showTest G } error]} then { if {[isExpectedError $error]} then { showTest g } else { failTest g $error } } } cleanupDb $dstFileName db false true false }] 0] }] ############################################################################# # WORKLOAD #8 (H) # ############################################################################# set workload(8) [list \ [list srcFileName dstFileName table count1 count2 count3] { # # NOTE: Workload #8, "big" UPDATE statements. # lappend ::times(8) [lindex [time { setupDb $dstFileName "" "" "" "" "" true false for {set index 1} {$index <= $count1} {incr index} { if {[catch { sql execute $db [appendArgs "UPDATE " $table \ " SET y = RANDOMBLOB(" $count3 \ ") WHERE x LIKE '" [format %X $index] \ "%' AND z = 'big';"] showTest H } error]} then { if {[isExpectedError $error]} then { showTest h } else { failTest h $error } } } cleanupDb $dstFileName db false true false }] 0] }] ############################################################################# # WORKLOAD #9 (I) # ############################################################################# set workload(9) [list \ [list srcFileName dstFileName table count1 count2 count3] { # # NOTE: Workload #9, "small" DELETE statements. # lappend ::times(9) [lindex [time { setupDb $dstFileName "" "" "" "" "" true false for {set index 1} {$index <= $count1} {incr index} { if {[catch { sql execute $db [appendArgs "DELETE FROM " $table \ " WHERE x LIKE '" [format %X $index] "%' AND z = 'small';"] showTest I } error]} then { if {[isExpectedError $error]} then { showTest i } else { failTest i $error } } } cleanupDb $dstFileName db false true false }] 0] }] ############################################################################# # WORKLOAD #10 (J) # ############################################################################# set workload(10) [list \ [list srcFileName dstFileName table count1 count2 count3] { # # NOTE: Workload #10, "big" DELETE statements. # lappend ::times(10) [lindex [time { setupDb $dstFileName "" "" "" "" "" true false for {set index 1} {$index <= $count1} {incr index} { if {[catch { sql execute $db [appendArgs "DELETE FROM " $table \ " WHERE x LIKE '" [format %X $index] "%' AND z = 'big';"] showTest J } error]} then { if {[isExpectedError $error]} then { showTest j } else { failTest j $error } } } cleanupDb $dstFileName db false true false }] 0] }] ############################################################################# # WORKLOAD #11 (K) # ############################################################################# set workload(11) [list \ [list srcFileName dstFileName table count1 count2 count3] { # # NOTE: Workload #11, VACUUM statement. # lappend ::times(11) [lindex [time { setupDb $dstFileName "" "" "" "" "" true false for {set index 1} {$index <= $count1} {incr index} { if {[catch { sql execute $db "VACUUM;" showTest K } error]} then { if {[isExpectedError $error]} then { showTest k } else { failTest k $error } } } cleanupDb $dstFileName db false true false }] 0] }] ############################################################################# # WORKLOAD #12 (L) # ############################################################################# set workload(12) [list \ [list srcFileName dstFileName table count1 count2 count3] { # # NOTE: Workload #12, backup to in-memory database. # lappend ::times(12) [lindex [time { for {set index 1} {$index <= $count1} {incr index} { if {[string is integer -strict $::compiled(12)]} then { set id $::compiled(12); # NOTE: Already compiled. if {[catch { object invoke _Dynamic${id}.Test${id} BackupAndGetData showTest L } error]} then { if {[isExpectedError $error]} then { showTest l } else { failTest l $error } } } else { set id [object invoke Interpreter.GetActive NextId] set code [compileCSharpWith [subst { using System; using System.Data.SQLite; using System.Text; namespace _Dynamic${id} { public static class Test${id} { public static void BackupAndGetData() { using (SQLiteConnection source = new SQLiteConnection( "FullUri=${dstFileName};")) { source.Open(); using (SQLiteConnection destination = new SQLiteConnection( "FullUri=${srcFileName};")) { destination.Open(); source.BackupDatabase( destination, "main", "main", -1, null, 0); |
︙ | ︙ | |||
926 927 928 929 930 931 932 | } } } else { error $errors } } } | < < < > > < | 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 | } } } else { error $errors } } } }] 0] }] ############################################################################# # WORKLOAD #13 (M) # ############################################################################# set workload(13) [list \ [list srcFileName dstFileName table count1 count2 count3] { # # NOTE: Workload #13, backup from an in-memory database. # lappend ::times(13) [lindex [time { for {set index 1} {$index <= $count1} {incr index} { if {[string is integer -strict $::compiled(13)]} then { set id $::compiled(13); # NOTE: Already compiled. if {[catch { object invoke _Dynamic${id}.Test${id} BackupAndGetData showTest M } error]} then { if {[isExpectedError $error]} then { showTest m } else { failTest m $error } } } else { set id [object invoke Interpreter.GetActive NextId] set code [compileCSharpWith [subst { using System; using System.Data.SQLite; using System.Text; namespace _Dynamic${id} { public static class Test${id} { public static void BackupAndGetData() { using (SQLiteConnection source = new SQLiteConnection( "FullUri=${srcFileName};")) { source.Open(); using (SQLiteConnection destination = new SQLiteConnection( "FullUri=${dstFileName};")) { destination.Open(); source.BackupDatabase( destination, "main", "main", -1, null, 0); |
︙ | ︙ | |||
1008 1009 1010 1011 1012 1013 1014 | } } } else { error $errors } } } | < < < | | > > < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < < < < < < < < < < < < < > > | < < | < < | < < < | < < < < < | | | | < < < < | < < | | 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 | } } } else { error $errors } } } }] 0] }] ############################################################################# # WORKLOAD #14 (N) # ############################################################################# set workload(14) [list \ [list srcFileName dstFileName table count1 count2 count3] { # # NOTE: Workload #14, PRAGMA integrity check statement. # lappend ::times(14) [lindex [time { setupDb $dstFileName "" "" "" "" "" true false for {set index 1} {$index <= $count1} {incr index} { if {[catch { set result [sql execute -execute scalar $db \ "PRAGMA integrity_check;"] if {$result eq "ok"} then { showTest N } else { error [appendArgs "integrity check failed: " $result] } } error]} then { if {[isExpectedError $error]} then { showTest n } else { failTest n $error } } } cleanupDb $dstFileName db false true false }] 0] }] ############################################################################# # WORKLOAD #15 (O) # ############################################################################# set workload(15) [list \ [list srcFileName dstFileName table count1 count2 count3] { # # NOTE: Workload #15, force managed garbage collection # lappend ::times(15) [lindex [time { for {set index 1} {$index <= $count1} {incr index} { if {[catch { collectGarbage $::test_channel showTest O } error]} then { if {[isExpectedError $error]} then { showTest o } else { failTest o $error } } } }] 0] }] } -body { for {set index(0) 0} {$index(0) < $count(0)} {incr index(0)} { sql execute $db "CREATE TABLE IF NOT EXISTS t1(x PRIMARY KEY, y, z);" unset -nocomplain thread foreach index(1) [lsort -integer [array names workload]] { if {[lsearch -exact $noWorkload $index(1)] == -1} then { set thread($index(1)) [object create -alias System.Threading.Thread \ [list apply $workload($index(1)) $fileName(1) $fileName(2) t1 \ $count(1) $count(3) $count(4)] 1048576] } } foreach index(1) [list Start Join] { foreach index(2) [array names thread] { $thread($index(2)) $index(1) } } unset -nocomplain thread } ############################################################################# foreach index(0) [split $indicators ""] { # # NOTE: See if this workload iteration raised an error. If so, the |
︙ | ︙ | |||
1319 1320 1321 1322 1323 1324 1325 | set index(3) [expr {$index(1) ? "ok" : "error"}] if {![info exists iterations($index(2),$index(3))]} then { set iterations($index(2),$index(3)) 0 } | < < < < < | | | > | > | > > > > > > | | | 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 | set index(3) [expr {$index(1) ? "ok" : "error"}] if {![info exists iterations($index(2),$index(3))]} then { set iterations($index(2),$index(3)) 0 } incr iterations($index(2),$index(3)) } ############################################################################# # # NOTE: Advance output to the next line due to the workload iteration # progress indicators. # tputs $test_channel \n ############################################################################# foreach index(0) [lsort -integer [array names times]] { set times(length) [llength $times($index(0))] if {$times(length) > 0} then { tputs $test_channel [appendArgs \ "---- average time for workload (" $index(0) ") is about " \ [expr int(([join $times($index(0)) +])/$times(length)/1000.0)] \ " milliseconds\n"] } else { tputs $test_channel [appendArgs \ "---- no times for workload (" $index(0) ")\n"] } } ############################################################################# foreach index(0) [lsort -integer [array names workload]] { tputs $test_channel [formatWorkloadResult $index(0)] } ############################################################################# set result [sql execute -execute scalar $srcDb "PRAGMA integrity_check;"] if {$result eq "ok"} then { |
︙ | ︙ | |||
1378 1379 1380 1381 1382 1383 1384 | # # NOTE: The overall test result is the total number of failures (i.e. # "unexpected errors") encountered during a workload iteration. # expr {[array size failures] > 0 ? \ [expr [join [array values failures] +]] : 0} } -cleanup { | < < < < < < < < < < < < < < < < < < | < | | | | | | < < < < < < < < < | 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 | # # NOTE: The overall test result is the total number of failures (i.e. # "unexpected errors") encountered during a workload iteration. # expr {[array size failures] > 0 ? \ [expr [join [array values failures] +]] : 0} } -cleanup { rename failTest "" rename showTest "" rename isExpectedError "" rename formatWorkloadResult "" cleanupDb $fileName(2) cleanupDb $fileName(1) srcDb foreach index(0) [array names workload] { catch { object removecallback [list apply $workload($index(0)) $fileName(1) \ $fileName(2) t1 $count(1) $count(3) $count(4)] } } freeDbConnection cleanupLogging $logFileName rename cleanupLogging "" rename setupLogging "" unset -nocomplain result thread index workload noWorkload srcDb db \ fileName compiled options count times logFileName logListener \ connection indicators iterations exitOnFail failures } -constraints \ {eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} \ -result {0}} ############################################################################### runSQLiteTestEpilogue runTestEpilogue |
Changes to Tests/thread.eagle.
︙ | ︙ | |||
17 18 19 20 21 22 23 | package require System.Data.SQLite.Test runSQLiteTestPrologue ############################################################################### checkForSQLiteDirectories $test_channel true | < | | | | < | < < < < < | < < < < | < < < < < < < < < < < < < < < < < < | < < < < < < < < | | | | | | < | | > | < | > < | 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | package require System.Data.SQLite.Test runSQLiteTestPrologue ############################################################################### checkForSQLiteDirectories $test_channel true set memory_used [reportSQLiteResources $test_channel true] ############################################################################### # # NOTE: How many test threads should be created and used for these tests? This # value must be at least two. The first test thread (at index 0) just # repeatedly calls the Thread.Abort() method on the other test threads # that appear to be alive until all test threads appear to be dead. All # other threads will attempt to open a connection, execute one or more # queries against it, and then close it. # set count 10 ############################################################################### runTest {test thread-1.1 {Thread.Abort() impact on native resources} -setup { setupDb [set fileName thread-1.1.db] tputs $test_channel [appendArgs \ "---- using a total of " $count " threads...\n"] } -body { sql execute $db { CREATE TABLE t1(x INTEGER PRIMARY KEY, y BLOB); INSERT INTO t1 (y) VALUES(RANDOMBLOB(1000)); INSERT INTO t1 (y) VALUES(RANDOMBLOB(1000)); INSERT INTO t1 (y) VALUES(RANDOMBLOB(1000)); INSERT INTO t1 (y) VALUES(RANDOMBLOB(1000)); INSERT INTO t1 (y) VALUES(RANDOMBLOB(1000)); } # # NOTE: The temporary directory must be reset here because it allocates # some SQLite memory and this test requires an extremely accurate # reading. # sql execute $db { PRAGMA temp_store_directory = ""; } # # NOTE: Close the database now, freeing any native SQLite memory and/or # resources that it may be using at this point; however, do not # actually delete the database file because it is needed in the C# |
︙ | ︙ | |||
128 129 130 131 132 133 134 | using System.Threading; using Eagle._Containers.Public; namespace _Dynamic${id} { public static class Test${id} { | | | | | | | 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 | using System.Threading; using Eagle._Containers.Public; namespace _Dynamic${id} { public static class Test${id} { public static IntList RunTestThreads() { // // NOTE: This is the total number of data bytes seen in the second // column of the query result rows seen by all test threads. // This value will vary greatly based upon how many loop // iterations are performed prior to each test thread being // aborted. // int sum = 0; // // NOTE: This is the total number of query result rows seen by all // the test threads. // int rows = 0; // // NOTE: This is the total number of exceptions caught by all the // test threads. // int errors = 0; // // NOTE: This is the total number of test threads to create. // int count = ${count}; // // NOTE: Create the array of thread objects. // Thread\[\] thread = new Thread\[count\]; // |
︙ | ︙ | |||
315 316 317 318 319 320 321 | goEvent.WaitOne(); // // NOTE: Give the other test threads a slight head start to // make sure that they are fully alive prior to trying // to abort any of them. // | | | | 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 | goEvent.WaitOne(); // // NOTE: Give the other test threads a slight head start to // make sure that they are fully alive prior to trying // to abort any of them. // Thread.Sleep(1000); // // NOTE: Loop forever until all test threads appear to be dead. // while (true) { // // NOTE: Wait a random number of milliseconds, up to a full // second. // Thread.Sleep(random.Next(0, 1000)); // // NOTE: Select a random thread to abort. // int index = random.Next(1, count); // |
︙ | ︙ | |||
422 423 424 425 426 427 428 | } // // NOTE: Return a list of integers with total number of data bytes // seen, total number of query result rows seen, and the total // number of exceptions caught by all the test threads. // | | | 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 | } // // NOTE: Return a list of integers with total number of data bytes // seen, total number of query result rows seen, and the total // number of exceptions caught by all the test threads. // IntList counts = new IntList(); counts.Add(sum); counts.Add(rows); counts.Add(errors); return counts; } |
︙ | ︙ | |||
446 447 448 449 450 451 452 | }] true true true results errors [list System.Data.SQLite.dll Eagle.dll]] list $code $results \ [expr {[info exists errors] ? $errors : ""}] \ [expr {$code eq "Ok" ? [catch { object invoke _Dynamic${id}.Test${id} RunTestThreads } result] : [set result ""]}] $result \ | | < | | | | | | | 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 | }] true true true results errors [list System.Data.SQLite.dll Eagle.dll]] list $code $results \ [expr {[info exists errors] ? $errors : ""}] \ [expr {$code eq "Ok" ? [catch { object invoke _Dynamic${id}.Test${id} RunTestThreads } result] : [set result ""]}] $result \ [collectGarbage $test_channel] \ [reportSQLiteResources $test_channel true] } -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 [appendArgs "^Ok System#CodeDom#Compiler#CompilerResults#\\d+\ \\{\\} 0 \\{\\d+ \\d+ " $count "\\} \\{\\} " $memory_used \$]} ############################################################################### unset -nocomplain count ############################################################################### unset -nocomplain memory_used ############################################################################### runSQLiteTestEpilogue runTestEpilogue |
Changes to Tests/tkt-17045010df.eagle.
︙ | ︙ | |||
51 52 53 54 55 56 57 | cleanupDb $fileName unset -nocomplain db fileName } -constraints \ {eagle monoBug28 defineConstant.System.Data.SQLite.INTEROP_TEST_EXTENSION\ command.sql compile.DATA SQLite System.Data.SQLite} -result {{0 {}} {1\ | | < | | < | | < | | 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | cleanupDb $fileName unset -nocomplain db fileName } -constraints \ {eagle monoBug28 defineConstant.System.Data.SQLite.INTEROP_TEST_EXTENSION\ command.sql compile.DATA SQLite System.Data.SQLite} -result {{0 {}} {1\ {EXCEPTION System.Data.SQLite.SQLiteException}\ {System.Reflection.TargetInvocationException: Exception has been thrown by the\ target of an invocation. ---> System.Data.SQLite.SQLiteException: SQL logic\ error or missing database, not authorized}} {1 {EXCEPTION\ System.Data.SQLite.SQLiteException} {System.Data.SQLite.SQLiteException\ (0x80004005): SQL logic error or missing database, no such function:\ interopTest}} {1 {EXCEPTION System.Data.SQLite.SQLiteException}\ {System.Data.SQLite.SQLiteException (0x80004005): SQL logic error or missing\ database, no such function: interopTest}} {0 {}} {0 {}} {0 test2} {1 {EXCEPTION\ System.Data.SQLite.SQLiteException} {System.Data.SQLite.SQLiteException\ (0x80004005): SQL logic error or missing database, need exactly one argument}}}} ############################################################################### runSQLiteTestEpilogue runTestEpilogue |
Deleted Tests/tkt-1c456ae75f.eagle.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Changes to Tests/tkt-343d392b51.eagle.
︙ | ︙ | |||
35 36 37 38 39 40 41 | sql execute $db "CREATE TABLE t1(x DATETIME);" set paramDateTime1 [clock format [clock scan $dateTime] -format \ [getDateTimeFormat] -gmt true] switch -exact -- $dateTimeFormat { Ticks { | | < < | < < | | 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | 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 } |
︙ | ︙ | |||
366 367 368 369 370 371 372 373 374 375 376 377 378 379 | set sql(2) [subst { \ SELECT x FROM ${otherTable} ORDER BY x; \ }] unset -nocomplain results errors set code [compileCSharpWith [subst { using System.Data; using System.Data.SQLite; namespace _Dynamic${id} { public static class Test${id} { | > | 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 | 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 static class Test${id} { |
︙ | ︙ |
Deleted Tests/tkt-3567020edf.eagle.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted Tests/tkt-393d954be0.eagle.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Changes to Tests/tkt-3aa50d8413.eagle.
︙ | ︙ | |||
35 36 37 38 39 40 41 42 43 44 45 46 47 48 | SELECT * FROM t1; \ SELECT * FROM t2; \ } unset -nocomplain results errors set code [compileCSharpWith [subst { using System.Data; using System.Data.SQLite; namespace _Dynamic${id} { public static class Test${id} { | > | 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | SELECT * FROM t1; \ SELECT * FROM t2; \ } unset -nocomplain results errors set code [compileCSharpWith [subst { using System; using System.Data; using System.Data.SQLite; namespace _Dynamic${id} { public static class Test${id} { |
︙ | ︙ |
Deleted Tests/tkt-48a6b8e4ca.eagle.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted Tests/tkt-4a791e70ab.eagle.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted Tests/tkt-6434e23a0f.eagle.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted Tests/tkt-6c6ecccc5f.eagle.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Changes to Tests/tkt-72905c9a77.eagle.
︙ | ︙ | |||
16 17 18 19 20 21 22 | ############################################################################### package require System.Data.SQLite.Test runSQLiteTestPrologue ############################################################################### | < < < < < < < < | 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | ############################################################################### package require System.Data.SQLite.Test runSQLiteTestPrologue ############################################################################### # # NOTE: This value is needed as part of the test result; therefore, it must be # set outside of the test setup. # set id [object invoke Interpreter.GetActive NextId] ############################################################################### |
︙ | ︙ | |||
268 269 270 271 272 273 274 | [expr {$code eq "Ok" ? [catch { object invoke _Dynamic${id}.Test${id} GetTraceOutput } result] : [set result ""]}] [string map [list \r\n \n] $result] } -cleanup { cleanupDb $fileName unset -nocomplain result code results errors dataSource fileName | < | | | 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 | [expr {$code eq "Ok" ? [catch { object invoke _Dynamic${id}.Test${id} GetTraceOutput } result] : [set result ""]}] [string map [list \r\n \n] $result] } -cleanup { cleanupDb $fileName unset -nocomplain result code results errors dataSource fileName } -constraints {eagle configuration.Release monoBug28 command.sql compile.DATA\ SQLite System.Data.SQLite} -match regexp -result [appendArgs "^Ok\ System#CodeDom#Compiler#CompilerResults#\\d+ \\{\\} 0 \\{" [string repeat \ "SQLite message \\(0\\): TEST $id " [expr {4 * [info processors]}]] "\\}\$"]} ############################################################################### unset -nocomplain id ############################################################################### runSQLiteTestEpilogue runTestEpilogue |
Changes to Tests/tkt-84718e79fa.eagle.
︙ | ︙ | |||
37 38 39 40 41 42 43 | 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 1048576] } | | | | 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 | 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 1048576] } 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 { |
︙ | ︙ |
Changes to Tests/tkt-996d13cd87.eagle.
︙ | ︙ | |||
27 28 29 30 31 32 33 | runTest {test [appendArgs tkt-996d13cd87-1. $i] {SQLiteConnection stress} \ -setup { set fileName [appendArgs tkt-996d13cd87-1. $i .db] tputs $test_channel [appendArgs \ "---- using a total of " $count " threads...\n"] | | | 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | runTest {test [appendArgs tkt-996d13cd87-1. $i] {SQLiteConnection stress} \ -setup { set fileName [appendArgs tkt-996d13cd87-1. $i .db] tputs $test_channel [appendArgs \ "---- using a total of " $count " threads...\n"] if {[catch { object invoke -flags +NonPublic \ System.Data.SQLite.SQLiteConnectionPool _poolOpened 0 object invoke -flags +NonPublic \ System.Data.SQLite.SQLiteConnectionPool _poolClosed 0 }] == 0} then { set havePoolCounts true |
︙ | ︙ |
Deleted Tests/tkt-ae5267b863.eagle.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Changes to Tests/tkt-bb4b04d457.eagle.
︙ | ︙ | |||
16 17 18 19 20 21 22 | ############################################################################### package require System.Data.SQLite.Test runSQLiteTestPrologue ############################################################################### | | | < < | | 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | ############################################################################### package require System.Data.SQLite.Test runSQLiteTestPrologue ############################################################################### runTest {test tkt-bb4b04d457-1.1 {} -setup { setupDb [set fileName tkt-bb4b04d457-1.1.db] "" Ticks Utc } -body { set dateTime [object invoke -alias DateTime Parse 2011-11-29T12:34:56Z] set dateTime [$dateTime -alias ToUniversalTime] sql execute $db "CREATE TABLE t1(x TIMESTAMP NOT NULL);" sql execute $db "INSERT INTO t1 (x) VALUES(?);" \ [list param1 Int64 [$dateTime Ticks]] sql execute -execute reader -format list -datetimeformat \ |
︙ | ︙ |
Deleted Tests/tkt-c010fa6584.eagle.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted Tests/tkt-e06c4caff3.eagle.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Changes to Tests/tkt-e1b2e0f769.eagle.
︙ | ︙ | |||
120 121 122 123 124 125 126 | set result1 } -cleanup { cleanupDb $fileName unset -nocomplain result2 result1 code results errors sql table dataSource \ id x db fileName } -constraints \ | < | > | | 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 | set result1 } -cleanup { cleanupDb $fileName unset -nocomplain result2 result1 code results errors sql table dataSource \ id x db fileName } -constraints \ {eagle monoBug28 !defineConstant.System.Data.SQLite.CHECK_STATE command.sql\ compile.DATA SQLite System.Data.SQLite} -match regexp -result {^Ok\ System#CodeDom#Compiler#CompilerResults#\d+ \{\} 0 3 Ok\ System#CodeDom#Compiler#CompilerResults#\d+ \{\} 0 0$}} ############################################################################### runSQLiteTestEpilogue runTestEpilogue |
Deleted Tests/tkt-e47b3d8346.eagle.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Changes to Tests/version.eagle.
︙ | ︙ | |||
25 26 27 28 29 30 31 | # # 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 | | | 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | # # NOTE: For these unit tests to be useful and accurate, the following version # numbers must be manually kept synchronized with the version numbers for # the source code files, the built binaries, and the release packages. # set version(major) 1 set version(minor) 0 set version(build) 83; # NOTE: Incremented with each release. set version(revision) 0 ############################################################################### # ********************* END VOLATILE VERSION INFORMATION ********************** ############################################################################### # |
︙ | ︙ | |||
174 175 176 177 178 179 180 | </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>] \ | < < | 174 175 176 177 178 179 180 181 182 183 184 185 186 187 | </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 "\; [format %03d $version(build)] "\;] \ [appendArgs AssemblyVersion\\(\" [string map [list . \\.] \ $version(full)] \"\\)] \ [appendArgs AssemblyFileVersion\\(\" [string map [list . \\.] \ $version(full)] \"\\)] \ [appendArgs AssemblyVersion\\(\" [string map [list . \\.] \ |
︙ | ︙ | |||
241 242 243 244 245 246 247 | $version(full)] \"\\)] \ [appendArgs AssemblyFileVersion\\(\" [string map [list . \\.] \ $version(full)] \"\\)]] set fileNames [list \ readme.htm \ SQLite.nuspec \ | < | 239 240 241 242 243 244 245 246 247 248 249 250 251 252 | $version(full)] \"\\)] \ [appendArgs AssemblyFileVersion\\(\" [string map [list . \\.] \ $version(full)] \"\\)]] set fileNames [list \ readme.htm \ SQLite.nuspec \ SQLite.MSIL.nuspec \ SQLite.x64.nuspec \ SQLite.x86.nuspec \ [file join Doc Extra dbfactorysupport.html] \ [file join Doc Extra welcome.html] \ [file join Membership Properties AssemblyInfo.cs] \ [file join Membership Properties AssemblyInfo.cs] \ |
︙ | ︙ |
Changes to exclude_bin.txt.
1 2 3 4 | *.done *.exp *.lib *.map | < | 1 2 3 4 5 6 | *.done *.exp *.lib *.map *EnvDTE.* *Microsoft.* |
Changes to exclude_src.txt.
1 2 3 4 | *.cache *.chw *.docstates *.fossil | < < < | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | *.cache *.chw *.docstates *.fossil *.ncb *.nupkg *.suo *.user *.zip _FOSSIL_ bin/* Doc/Output/* Externals/Eagle/bin/Eagle.dll Externals/Eagle/bin/EagleShell.exe Externals/Eagle/bin/SQLite.Interop.* Externals/Eagle/bin/sqlite3.* |
︙ | ︙ | |||
34 35 36 37 38 39 40 | Externals/MSVCPP/* Externals/NDoc3/* Membership/* Membership/obj/* Membership/Profile/* Membership/SiteMap/* obj/* | < > | 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | Externals/MSVCPP/* Externals/NDoc3/* Membership/* Membership/obj/* Membership/Profile/* Membership/SiteMap/* obj/* Setup/set_user_*.bat Setup/Output/* SQLite.Designer/obj/* SQLite.Designer/Properties/* SQLite.Designer/VSDesign/* System.Data.SQLite.Linq/obj/* System.Data.SQLite/obj/* System.Data.SQLite/Properties/* test/obj/* testce/obj/* testlinq/obj/* tools/install/obj/* www/* |
Changes to readme.htm.
1 2 3 4 5 6 7 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title></title> </head> <body> ADO.NET SQLite Data Provider<br /> | | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title></title> </head> <body> ADO.NET SQLite Data Provider<br /> Version 1.0.83.0 December XX, 2012 <font color="red">(release scheduled)</font><br /> Using <a href="http://www.sqlite.org/src/info/trunk">SQLite 3.7.15</a><br /> Originally written by Robert Simpson<br /> Released to the public domain, use at your own risk!<br /> Official provider website: <a href="http://system.data.sqlite.org/">http://system.data.sqlite.org/</a><br /> Legacy versions: <a href="http://sqlite.phxsoftware.com/">http://sqlite.phxsoftware.com/</a><br /> <br /> The current development version can be downloaded from <a href="http://system.data.sqlite.org/index.html/timeline?y=ci"> http://system.data.sqlite.org/index.html/timeline?y=ci</a> |
︙ | ︙ | |||
47 48 49 50 51 52 53 | <li> Encrypted database support. Encrypted databases are fully encrypted and support both binary and cleartext password types. </li> <li> Visual Studio design-time Support, works with all versions of Visual Studio | | | | | 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | <li> Encrypted database support. Encrypted databases are fully encrypted and support both binary and cleartext password types. </li> <li> Visual Studio design-time Support, works with all versions of Visual Studio 2005/2008/2010. You can add a SQLite database to the Servers list, design queries with the Query Designer, drag-and-drop tables onto a Typed DataSet, etc. <br /> <font color="red"> Due to Visual Studio licensing restrictions, the Express Editions can no longer be supported. </font> </li> |
︙ | ︙ | |||
142 143 144 145 146 147 148 | app.config file:<br /> <pre> <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" | | | 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 | app.config file:<br /> <pre> <configuration> <system.data> <DbProviderFactories> <remove invariant="System.Data.SQLite" /> <add name="SQLite Data Provider" invariant="System.Data.SQLite" description=".Net Framework Data Provider for SQLite" type="System.Data.SQLite.SQLiteFactory, System.Data.SQLite, Version=1.0.83.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139" /> </DbProviderFactories> </system.data> </configuration> </pre> <p> See the help documentation for further details on implementing both version-specific (GAC enabled) and version independent DBProviderFactories support. |
︙ | ︙ | |||
183 184 185 186 187 188 189 | it to extend its functionality, but the core engine's source is not changed.</p> <p> </p> <h2><b>Version History</b></h2> <p> | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | < < < | < < < < | 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 | it to extend its functionality, but the core engine's source is not changed.</p> <p> </p> <h2><b>Version History</b></h2> <p> <b>1.0.83.0 - December XX, 2012</b> </p> <ul> <li>Updated to <a href="http://www.sqlite.org/src/info/trunk">SQLite 3.7.15</a>.</li> <li>Add Visual Studio 2012 support to all the applicable solution/project files, their associated supporting files, and the test suite.</li> <li>Add Visual Studio 2012 support to the redesigned designer support installer.</li> <li>Allow opened connections to skip adding the extension functions included in the interop assembly via the new NoExtensionFunctions connection flag.</li> <li>Support loading of SQLite extensions via the new EnableExtensions and LoadExtension methods of the SQLiteConnection class. Pursuant to [17045010df].</li> <li>Add notifications before and after any connection is opened and closed, as well as other related notifications, via the new static Changed event.</li> <li>Add an overload of the SQLiteLog.LogMessage method that takes a single string parameter.</li> <li>Add an overload of the SQLiteConnection.LogMessage method that takes a SQLiteErrorCode parameter.</li> <li>All applicable calls into the SQLite core library now return a SQLiteErrorCode instead of an integer error code.</li> <li>Make sure the error code of the SQLiteException class gets serialized.</li> <li>Make the test project for the .NET Compact Framework more flexible.</li> <li>When available, the new sqlite3_errstr function from the core library is used to get the error message for a specific return code.</li> <li>The SetMemoryStatus, Shutdown, ResultCode, ExtendedResultCode, and SetAvRetry methods of the SQLiteConnection class now return a SQLiteErrorCode instead of an integer error code. <b>** Potentially Incompatible Change **</b></li> <li>The public constructor for the SQLiteException now takes a SQLiteErrorCode instead of an integer error code. <b>** Potentially Incompatible Change **</b></li> <li>The ErrorCode property of the SQLiteException is now an Int32, to allow the property inherited from the base class to be properly overridden. <b>** Potentially Incompatible Change **</b></li> <li>The ErrorCode field of the LogEventArgs is now an object instead of an integer. <b>** Potentially Incompatible Change **</b></li> <li>The names and messages associated with the SQLiteErrorCode enumeration values have been normalized to match those in the SQLite core library. <b>** Potentially Incompatible Change **</b></li> <li>Implement more robust locking semantics for the CriticalHandle derived classes when compiled for the .NET Compact Framework.</li> <li>Cache column indexes are they are looked up when using the SQLiteDataReader to improve performance.</li> <li>Prevent the SQLiteConnection.Close method from throwing non-fatal exceptions during its disposal.</li> <li>Rename the interop assembly functions sqlite3_cursor_rowid, sqlite3_context_collcompare, sqlite3_context_collseq, sqlite3_cursor_rowid, and sqlite3_table_cursor to include an "_interop" suffix. <b>** Potentially Incompatible Change **</b></li> <li>Prevent the LastInsertRowId, MemoryUsed, and MemoryHighwater connection properties from throwing NotSupportedException when running on the .NET Compact Framework. Fix for [dd45aba387].</li> <li>Add protection against ThreadAbortException asynchronously interrupting native resource initialization and finalization.</li> <li>Add test automation for the Windows CE binaries.</li> </ul> <p> <b>1.0.82.0 - September 3, 2012</b> </p> <ul> <li>Updated to <a href="http://www.sqlite.org/releaselog/3_7_14.html">SQLite 3.7.14</a>.</li> |
︙ | ︙ |
Changes to test/AssemblyInfo.cs.
︙ | ︙ | |||
34 35 36 37 38 39 40 | // Version information for an assembly consists of the following four values: // // Major Version // Minor Version // Build Number // Revision // | | | | 34 35 36 37 38 39 40 41 42 | // Version information for an assembly consists of the following four values: // // Major Version // Minor Version // Build Number // Revision // [assembly: AssemblyVersion("1.0.83.0")] [assembly: AssemblyFileVersion("1.0.83.0")] |
Changes to test/TestCases.cs.
︙ | ︙ | |||
18 19 20 21 22 23 24 | 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>(); | < < | | 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | internal class TestCases : TestCaseBase { private const int NumThreads = 8; private const int ThreadTimeout = 60000; private List<string> droptables = new List<string>(); private List<string> maydroptable = new List<string>(); private long logevents = 0; internal TestCases() { } internal TestCases(DbProviderFactory factory, string connectionString) : base(factory, connectionString) |
︙ | ︙ | |||
1361 1362 1363 1364 1365 1366 1367 | System.Threading.WaitHandle.WaitAll(events, ThreadTimeout); bool failed = false; Exception e = null; for (int n = 0; n < arr.Length; n++) { | | | 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 | System.Threading.WaitHandle.WaitAll(events, ThreadTimeout); bool failed = false; Exception e = null; for (int n = 0; n < arr.Length; n++) { if (arr[n].t.Join(0) == false) { failed = true; arr[n].t.Abort(); arr[n].t.Join(); } if (arr[n].e != null) e = arr[n].e; arr[n].cnn.Dispose(); |
︙ | ︙ | |||
1627 1628 1629 1630 1631 1632 1633 | SQLiteErrorCode rc = cnn.ResultCode(); SQLiteErrorCode xrc = cnn.ExtendedResultCode(); cnn.Close(); } } | < | 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 | SQLiteErrorCode rc = cnn.ResultCode(); SQLiteErrorCode xrc = cnn.ExtendedResultCode(); cnn.Close(); } } //Logging EventHandler public void OnLogEvent(object sender, LogEventArgs logEvent) { object errorCode = logEvent.ErrorCode; string err_msg = logEvent.Message; logevents++; } |
︙ | ︙ | |||
1669 1670 1671 1672 1673 1674 1675 | cnn.Close(); // remove the log handler before the connection is closed. sqlite_fact.Log -= logHandler; } } | < | 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 | cnn.Close(); // remove the log handler before the connection is closed. sqlite_fact.Log -= logHandler; } } /// <summary> /// Open a reader and then attempt to write to test the writer's command timeout property /// SQLite doesn't allow a write when a reader is active. /// *** NOTE AS OF 3.3.8 this test no longer blocks because SQLite now allows you to update table(s) /// while a reader is active on the same connection. Therefore the timeout test is invalid /// </summary> |
︙ | ︙ |
Changes to test/TestCasesDialog.cs.
︙ | ︙ | |||
58 59 60 61 62 63 64 | foreach (KeyValuePair<string, bool> pair in _testitems.Tests) { ToolStripMenuItem item = (ToolStripMenuItem)testMenu.DropDownItems.Add(pair.Key, null, new EventHandler(_tests_Clicked)); item.Checked = true; item.CheckOnClick = true; } | | | < | 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 | foreach (KeyValuePair<string, bool> pair in _testitems.Tests) { ToolStripMenuItem item = (ToolStripMenuItem)testMenu.DropDownItems.Add(pair.Key, null, new EventHandler(_tests_Clicked)); item.Checked = true; item.CheckOnClick = true; } this.Load += new EventHandler(TestCasesDialog_Load); } private StringBuilder GridToText() { StringBuilder result = new StringBuilder(); foreach (DataGridViewRow row in _grid.Rows) { if (result.Length > 0) result.Append(Environment.NewLine); result.AppendFormat("{0}\t{1}\t{2}\t{3}", row.Cells[0].Value, row.Cells[1].Value, row.Cells[2].Value, row.Cells[3].Value); } return result; } void TestCasesDialog_Load(object sender, EventArgs e) { // // NOTE: In "automatic" mode, run all the tests as soon as the form is // fully loaded. // if (_autoRun) { BeginInvoke(new DelegateWithNoArgs(delegate() { runButton_Click(sender, e); })); } } void _tests_Clicked(object sender, EventArgs e) { |
︙ | ︙ |
Changes to test/app.config.
1 2 3 4 | <configuration> <system.data> <DbProviderFactories> <remove invariant="System.Data.SQLite" /> | | | 1 2 3 4 5 6 7 8 | <configuration> <system.data> <DbProviderFactories> <remove invariant="System.Data.SQLite" /> <add name="SQLite Data Provider" invariant="System.Data.SQLite" description=".Net Framework Data Provider for SQLite" type="System.Data.SQLite.SQLiteFactory, System.Data.SQLite, Version=1.0.83.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139" /> </DbProviderFactories> </system.data> </configuration> |
Changes to test/test.2005.csproj.
︙ | ︙ | |||
78 79 80 81 82 83 84 | <EmbeddedResource Include="TestCasesDialog.resx"> <DependentUpon>TestCasesDialog.cs</DependentUpon> </EmbeddedResource> </ItemGroup> <ItemGroup> <None Include="app.config" /> </ItemGroup> | < | 78 79 80 81 82 83 84 85 86 87 88 89 90 91 | <EmbeddedResource Include="TestCasesDialog.resx"> <DependentUpon>TestCasesDialog.cs</DependentUpon> </EmbeddedResource> </ItemGroup> <ItemGroup> <None Include="app.config" /> </ItemGroup> <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> <!-- To modify your build process, add your task inside one of the targets below and uncomment it. Other similar extension points exist, see Microsoft.Common.targets. <Target Name="BeforeBuild"> </Target> <Target Name="AfterBuild"> </Target> |
︙ | ︙ |
Changes to test/test.2008.csproj.
︙ | ︙ | |||
79 80 81 82 83 84 85 | <EmbeddedResource Include="TestCasesDialog.resx"> <DependentUpon>TestCasesDialog.cs</DependentUpon> </EmbeddedResource> </ItemGroup> <ItemGroup> <None Include="app.config" /> </ItemGroup> | < | 79 80 81 82 83 84 85 86 87 88 89 90 91 92 | <EmbeddedResource Include="TestCasesDialog.resx"> <DependentUpon>TestCasesDialog.cs</DependentUpon> </EmbeddedResource> </ItemGroup> <ItemGroup> <None Include="app.config" /> </ItemGroup> <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> <!-- To modify your build process, add your task inside one of the targets below and uncomment it. Other similar extension points exist, see Microsoft.Common.targets. <Target Name="BeforeBuild"> </Target> <Target Name="AfterBuild"> </Target> |
︙ | ︙ |
Changes to test/test.2010.csproj.
︙ | ︙ | |||
80 81 82 83 84 85 86 | <EmbeddedResource Include="TestCasesDialog.resx"> <DependentUpon>TestCasesDialog.cs</DependentUpon> </EmbeddedResource> </ItemGroup> <ItemGroup> <None Include="app.config" /> </ItemGroup> | < | 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | <EmbeddedResource Include="TestCasesDialog.resx"> <DependentUpon>TestCasesDialog.cs</DependentUpon> </EmbeddedResource> </ItemGroup> <ItemGroup> <None Include="app.config" /> </ItemGroup> <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> <!-- To modify your build process, add your task inside one of the targets below and uncomment it. Other similar extension points exist, see Microsoft.Common.targets. <Target Name="BeforeBuild"> </Target> <Target Name="AfterBuild"> </Target> |
︙ | ︙ |
Changes to test/test.2012.csproj.
︙ | ︙ | |||
79 80 81 82 83 84 85 | <EmbeddedResource Include="TestCasesDialog.resx"> <DependentUpon>TestCasesDialog.cs</DependentUpon> </EmbeddedResource> </ItemGroup> <ItemGroup> <None Include="app.config" /> </ItemGroup> | < | 79 80 81 82 83 84 85 86 87 88 89 90 91 92 | <EmbeddedResource Include="TestCasesDialog.resx"> <DependentUpon>TestCasesDialog.cs</DependentUpon> </EmbeddedResource> </ItemGroup> <ItemGroup> <None Include="app.config" /> </ItemGroup> <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> <!-- To modify your build process, add your task inside one of the targets below and uncomment it. Other similar extension points exist, see Microsoft.Common.targets. <Target Name="BeforeBuild"> </Target> <Target Name="AfterBuild"> </Target> |
︙ | ︙ |
Changes to testce/AssemblyInfo.cs.
︙ | ︙ | |||
34 35 36 37 38 39 40 | // Version information for an assembly consists of the following four values: // // Major Version // Minor Version // Build Number // Revision // | | | | 34 35 36 37 38 39 40 41 42 43 | // Version information for an assembly consists of the following four values: // // Major Version // Minor Version // Build Number // Revision // [assembly: AssemblyVersion("1.0.83.0")] // [assembly: AssemblyFileVersion("1.0.83.0")] |
Changes to testce/Program.cs.
1 2 3 | /******************************************************** * ADO.NET 2.0 Data Provider for SQLite Version 3.X * Written by Robert Simpson (robert@blackcastlesoft.com) | | | | | | > > > > | > > | > > > > > | > > | > | > > > > > | | | | | | | | | | | | | | | | | | | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | | | | | | | | | | | | | | < < < < | < | | | | | | | | | | | | 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 | /******************************************************** * 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! ********************************************************/ using System; using System.Data.Common; using System.Data.SQLite; using System.IO; using System.Reflection; using System.Windows.Forms; namespace test { class Program { private static readonly string DefaultConnectionString = "Data Source={DataDirectory}\\test.db;Password=yVXL39etehPX;"; internal static DbConnection NewConnection() { return new SQLiteConnection(); } [MTAThread] static int Main(string[] args) { bool autoClose = false; int exitCode = 2; /* INCOMPLETE */ Assembly assembly = Assembly.GetExecutingAssembly(); AssemblyName assemblyName = assembly.GetName(); string directory = Path.GetDirectoryName(assemblyName.CodeBase); if (args.Length > 0) autoClose = bool.Parse(args[0]); try { File.Delete(directory + "\\test.db"); } catch { } SQLiteFunction.RegisterFunction(typeof(TestFunc)); SQLiteFunction.RegisterFunction(typeof(MyCount)); SQLiteFunction.RegisterFunction(typeof(MySequence)); using (DbConnection cnn = NewConnection()) { string connectionString = DefaultConnectionString; try { // // NOTE: Attempt to open the configuration file associated with // this test executable. It should contain *EXACTLY* one // line, which will be the connection string to use for // this test run. // using (StreamReader streamReader = File.OpenText( directory + "\\test.cfg")) { connectionString = streamReader.ReadToEnd().Trim(); } } catch { // do nothing. } // // NOTE: If we are unable to obtain a valid connection string // bail out now. // if (connectionString != null) { // // NOTE: Replace the "{DataDirectory}" token, if any, in the // connection string with the actual directory this test // assembly is executing from. // connectionString = connectionString.Replace( "{DataDirectory}", directory); cnn.ConnectionString = connectionString; cnn.Open(); TestCases tests = new TestCases(connectionString, cnn, autoClose); tests.Run(); Application.Run(tests.frm); if (tests.Succeeded()) exitCode = 0; /* SUCCESS */ else exitCode = 1; /* FAILURE */ } } return exitCode; } } } |
Changes to testce/TestCases.cs.
︙ | ︙ | |||
72 73 74 75 76 77 78 | internal class TestCases { internal Form1 frm; private string connectionString; private DbConnection cnn; | < < < | < < < < < < < < < < < < < < < < < < < < < < < | 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 | internal class TestCases { internal Form1 frm; private string connectionString; private DbConnection cnn; private bool autoClose; private int total; private int passed; private int failed; internal TestCases( string connectionString, DbConnection cnn, bool autoExit ) { this.connectionString = connectionString; this.cnn = cnn; this.autoClose = autoExit; } internal bool Succeeded() { return (failed == 0) && (passed == total); } internal void Run() { frm = new Form1(); frm.Show(); Type type = cnn.GetType(); frm.WriteLine("\r\nBeginning Test on " + type.ToString()); SQLiteConnection cnn2 = cnn as SQLiteConnection; if (cnn2 != null) { cnn2 = null; |
︙ | ︙ | |||
176 177 178 179 180 181 182 | catch (Exception) { frm.WriteLine("FAIL - BinaryInsert"); failed++; } total++; try { VerifyBinaryData(cnn); frm.WriteLine("SUCCESS - VerifyBinaryData"); passed++; } catch (Exception) { frm.WriteLine("FAIL - VerifyBinaryData"); failed++; } total++; | | | 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 | catch (Exception) { frm.WriteLine("FAIL - BinaryInsert"); failed++; } total++; try { VerifyBinaryData(cnn); frm.WriteLine("SUCCESS - VerifyBinaryData"); passed++; } catch (Exception) { frm.WriteLine("FAIL - VerifyBinaryData"); failed++; } total++; try { LockTest(cnn); frm.WriteLine("SUCCESS - LockTest"); passed++; } catch (Exception) { frm.WriteLine("FAIL - LockTest"); failed++; } total++; try { ParameterizedInsertMissingParams(cnn); frm.WriteLine("FAIL - ParameterizedInsertMissingParams"); failed++; } catch (Exception) { frm.WriteLine("SUCCESS - ParameterizedInsertMissingParams"); passed++; } total++; |
︙ | ︙ | |||
605 606 607 608 609 610 611 | if (b[1000] != 3) throw new ArgumentException(); if (b[2000] != 4) throw new ArgumentException(); if (b[3000] != 5) throw new ArgumentException(); } } } | | < < | 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 | if (b[1000] != 3) throw new ArgumentException(); if (b[2000] != 4) throw new ArgumentException(); if (b[3000] != 5) throw new ArgumentException(); } } } internal static void LockTest(DbConnection cnn) { using (DbCommand cmd = cnn.CreateCommand()) { cmd.CommandText = "SELECT Field6 FROM TestCase WHERE Field6 IS NOT NULL"; byte[] b = new byte[4000]; using (DbDataReader rd = cmd.ExecuteReader()) { if (rd.Read() == false) throw new ArgumentOutOfRangeException(); rd.GetBytes(0, 0, b, 0, 4000); if (b[0] != 1) throw new ArgumentException(); if (b[100] != 2) throw new ArgumentException(); if (b[1000] != 3) throw new ArgumentException(); if (b[2000] != 4) throw new ArgumentException(); if (b[3000] != 5) throw new ArgumentException(); using (DbConnection clone = (DbConnection)((ICloneable)cnn).Clone()) { using (DbCommand newcmd = clone.CreateCommand()) { newcmd.CommandText = "DELETE FROM TestCase WHERE Field6 IS NULL"; newcmd.CommandTimeout = 2; int cmdStart = Environment.TickCount; int cmdEnd; |
︙ | ︙ |
Deleted testce/test.sql.
Changes to testce/testce.2005.csproj.
︙ | ︙ | |||
89 90 91 92 93 94 95 | <EmbeddedResource Include="Form1.resx"> <DependentUpon>Form1.cs</DependentUpon> <SubType>Designer</SubType> </EmbeddedResource> </ItemGroup> <ItemGroup> <Content Include="test.cfg"> | < < < | 89 90 91 92 93 94 95 96 97 98 99 100 101 102 | <EmbeddedResource Include="Form1.resx"> <DependentUpon>Form1.cs</DependentUpon> <SubType>Designer</SubType> </EmbeddedResource> </ItemGroup> <ItemGroup> <Content Include="test.cfg"> <CopyToOutputDirectory>Always</CopyToOutputDirectory> </Content> </ItemGroup> <ItemGroup> <ProjectReference Include="..\System.Data.SQLite\System.Data.SQLite.Compact.2005.csproj"> <Project>{AC139951-261A-4463-B6FA-AEBC25283A66}</Project> <Name>System.Data.SQLite.Compact.2005</Name> |
︙ | ︙ |
Changes to testce/testce.2008.csproj.
︙ | ︙ | |||
90 91 92 93 94 95 96 | <EmbeddedResource Include="Form1.resx"> <DependentUpon>Form1.cs</DependentUpon> <SubType>Designer</SubType> </EmbeddedResource> </ItemGroup> <ItemGroup> <Content Include="test.cfg"> | < < < | 90 91 92 93 94 95 96 97 98 99 100 101 102 103 | <EmbeddedResource Include="Form1.resx"> <DependentUpon>Form1.cs</DependentUpon> <SubType>Designer</SubType> </EmbeddedResource> </ItemGroup> <ItemGroup> <Content Include="test.cfg"> <CopyToOutputDirectory>Always</CopyToOutputDirectory> </Content> </ItemGroup> <ItemGroup> <ProjectReference Include="..\System.Data.SQLite\System.Data.SQLite.Compact.2008.csproj"> <Project>{AC139951-261A-4463-B6FA-AEBC25283A66}</Project> <Name>System.Data.SQLite.Compact.2008</Name> |
︙ | ︙ |
Changes to testlinq/2008/App.config.
1 2 3 4 5 | <?xml version="1.0"?> <configuration> <system.data> <DbProviderFactories> <remove invariant="System.Data.SQLite" /> | | | 1 2 3 4 5 6 7 8 9 10 11 12 | <?xml version="1.0"?> <configuration> <system.data> <DbProviderFactories> <remove invariant="System.Data.SQLite" /> <add name="SQLite Data Provider" invariant="System.Data.SQLite" description=".Net Framework Data Provider for SQLite" type="System.Data.SQLite.SQLiteFactory, System.Data.SQLite, Version=1.0.83.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139" /> </DbProviderFactories> </system.data> <connectionStrings> <add name="northwindEFEntities" connectionString="metadata=res://*/NorthwindModel2008.csdl|res://*/NorthwindModel2008.ssdl|res://*/NorthwindModel2008.msl;provider=System.Data.SQLite;provider connection string="data source=.\northwindEF.db"" providerName="System.Data.EntityClient" /> </connectionStrings> </configuration> |
Changes to testlinq/2010/App.config.
1 2 3 4 5 | <?xml version="1.0"?> <configuration> <system.data> <DbProviderFactories> <remove invariant="System.Data.SQLite" /> | | | 1 2 3 4 5 6 7 8 9 10 11 12 | <?xml version="1.0"?> <configuration> <system.data> <DbProviderFactories> <remove invariant="System.Data.SQLite" /> <add name="SQLite Data Provider" invariant="System.Data.SQLite" description=".Net Framework Data Provider for SQLite" type="System.Data.SQLite.SQLiteFactory, System.Data.SQLite, Version=1.0.83.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139" /> </DbProviderFactories> </system.data> <connectionStrings> <add name="northwindEFEntities" connectionString="metadata=res://*/NorthwindModel2010.csdl|res://*/NorthwindModel2010.ssdl|res://*/NorthwindModel2010.msl;provider=System.Data.SQLite;provider connection string="data source=.\northwindEF.db"" providerName="System.Data.EntityClient" /> </connectionStrings> </configuration> |
Changes to testlinq/2012/App.config.
1 2 3 4 5 | <?xml version="1.0"?> <configuration> <system.data> <DbProviderFactories> <remove invariant="System.Data.SQLite" /> | | | 1 2 3 4 5 6 7 8 9 10 11 12 | <?xml version="1.0"?> <configuration> <system.data> <DbProviderFactories> <remove invariant="System.Data.SQLite" /> <add name="SQLite Data Provider" invariant="System.Data.SQLite" description=".Net Framework Data Provider for SQLite" type="System.Data.SQLite.SQLiteFactory, System.Data.SQLite, Version=1.0.83.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139" /> </DbProviderFactories> </system.data> <connectionStrings> <add name="northwindEFEntities" connectionString="metadata=res://*/NorthwindModel2012.csdl|res://*/NorthwindModel2012.ssdl|res://*/NorthwindModel2012.msl;provider=System.Data.SQLite;provider connection string="data source=.\northwindEF.db"" providerName="System.Data.EntityClient" /> </connectionStrings> </configuration> |
Changes to testlinq/Program.cs.
︙ | ︙ | |||
322 323 324 325 326 327 328 | } private static int OldTests() { using (northwindEFEntities db = new northwindEFEntities()) { { | | | 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 | } private static int OldTests() { using (northwindEFEntities db = new northwindEFEntities()) { { string entitySQL = "SELECT VALUE o FROM Orders AS o WHERE SQLite.DatePart('yyyy', o.OrderDate) = 1997;"; ObjectQuery<Orders> query = db.CreateQuery<Orders>(entitySQL); foreach (Orders o in query) { Console.WriteLine(o.ShipPostalCode); } } |
︙ | ︙ | |||
355 356 357 358 359 360 361 | Console.WriteLine(c.CompanyName); } { DateTime dt = new DateTime(1997, 1, 1); var query = from order in db.Orders where order.OrderDate < dt | < | 355 356 357 358 359 360 361 362 363 364 365 366 367 368 | Console.WriteLine(c.CompanyName); } { DateTime dt = new DateTime(1997, 1, 1); var query = from order in db.Orders where order.OrderDate < dt select order; foreach (Orders o in query) { Console.WriteLine(o.OrderDate.ToString()); } } |
︙ | ︙ | |||
397 398 399 400 401 402 403 | db.DeleteObject(cust); db.SaveChanges(); } { var query = db.Customers.Where(cust => cust.Country == "Denmark") | | < < | | < | 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 | db.DeleteObject(cust); db.SaveChanges(); } { var query = db.Customers.Where(cust => cust.Country == "Denmark") .SelectMany(cust => cust.Orders.Where(o => o.Freight > 5)); foreach (Orders c in query) { Console.WriteLine(c.Freight); } } { var query = from c in db.Customers where c.Orders.Any(o => o.OrderDate.HasValue == true && o.OrderDate.Value.Year == 1997) select c; foreach (Customers c in query) { Console.WriteLine(c.CompanyName); } } { string entitySQL = "SELECT VALUE o FROM Orders AS o WHERE o.Customers.Country <> 'UK' AND o.Customers.Country <> 'Mexico' AND Year(o.OrderDate) = 1997;"; ObjectQuery<Orders> query = db.CreateQuery<Orders>(entitySQL); foreach (Orders o in query) { Console.WriteLine(o.ShipPostalCode); } } { string entitySQL = "SELECT VALUE o FROM Orders AS o WHERE NewGuid() <> NewGuid();"; ObjectQuery<Orders> query = db.CreateQuery<Orders>(entitySQL); foreach (Orders o in query) { Console.WriteLine(o.ShipPostalCode); } } // This query requires SQLite 3.6.2 to function correctly { var query = from p in db.Products where p.OrderDetails.Count(od => od.Orders.Customers.Country == p.Suppliers.Country) > 2 select p; foreach (Products p in query) { Console.WriteLine(p.ProductName); } } |
︙ | ︙ |
Changes to testlinq/Properties/AssemblyInfo.cs.
︙ | ︙ | |||
37 38 39 40 41 42 43 | // 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.*")] | | | | 37 38 39 40 41 42 43 44 45 | // Minor Version // Build Number // Revision // // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.83.0")] [assembly: AssemblyFileVersion("1.0.83.0")] |
Changes to tools/install/Installer.cs.
︙ | ︙ | |||
42 43 44 45 46 47 48 | string fileName, /* in */ string invariant, /* in */ string name, /* in */ string description, /* in */ string typeName, /* in */ AssemblyName assemblyName, /* in */ object clientData, /* in */ | < < < | 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | string fileName, /* in */ string invariant, /* in */ string name, /* in */ string description, /* in */ string typeName, /* in */ AssemblyName assemblyName, /* in */ object clientData, /* in */ bool wow64, /* in */ bool throwOnMissing, /* in */ bool whatIf, /* in */ bool verbose, /* in */ ref bool saved, /* out */ ref string error /* out */ ); /////////////////////////////////////////////////////////////////////////// internal delegate bool FrameworkRegistryCallback( Installer.MockRegistryKey rootKey, /* in */ string frameworkName, /* in */ Version frameworkVersion, /* in */ string platformName, /* in */ object clientData, /* in */ bool wow64, /* in */ bool throwOnMissing, /* in */ bool whatIf, /* in */ bool verbose, /* in */ ref string error /* out */ ); /////////////////////////////////////////////////////////////////////////// internal delegate bool VisualStudioRegistryCallback( Installer.MockRegistryKey rootKey, /* in */ Version vsVersion, /* in */ string suffix, /* in, optional */ Installer.Package package, /* in */ object clientData, /* in */ bool wow64, /* in */ bool throwOnMissing, /* in */ bool whatIf, /* in */ bool verbose, /* in */ ref string error /* out */ ); #endregion |
︙ | ︙ | |||
3948 3949 3950 3951 3952 3953 3954 | return Object.ReferenceEquals(rootKey, registry.CurrentUser) || Object.ReferenceEquals(rootKey, registry.LocalMachine); } /////////////////////////////////////////////////////////////////////// private static string GetRootKeyName( | < < < < < < < | | 3945 3946 3947 3948 3949 3950 3951 3952 3953 3954 3955 3956 3957 3958 3959 3960 3961 3962 3963 | return Object.ReferenceEquals(rootKey, registry.CurrentUser) || Object.ReferenceEquals(rootKey, registry.LocalMachine); } /////////////////////////////////////////////////////////////////////// private static string GetRootKeyName( bool wow64 ) { return String.Format("{0}{1}", RootKeyName, wow64 && Is64BitProcess() ? "\\" + Wow64SubKeyName : String.Empty); } /////////////////////////////////////////////////////////////////////// private static string GetSystemDirectory( bool wow64 |
︙ | ︙ | |||
4099 4100 4101 4102 4103 4104 4105 | } #endregion /////////////////////////////////////////////////////////////////////// #region .NET Framework Handling private static string GetFrameworkRootKeyName( | < | < | | 4089 4090 4091 4092 4093 4094 4095 4096 4097 4098 4099 4100 4101 4102 4103 4104 4105 4106 4107 4108 4109 4110 4111 4112 4113 4114 4115 4116 4117 4118 4119 4120 4121 4122 4123 | } #endregion /////////////////////////////////////////////////////////////////////// #region .NET Framework Handling private static string GetFrameworkRootKeyName( bool wow64 ) { return String.Format("{0}\\Microsoft\\.NETFramework", GetRootKeyName(wow64)); } /////////////////////////////////////////////////////////////////////// private static string GetFrameworkKeyName( string frameworkName, Version frameworkVersion, string platformName, bool wow64 ) { string format = !String.IsNullOrEmpty(platformName) ? "{0}\\Microsoft\\{1}\\v{2}\\{3}" : "{0}\\Microsoft\\{1}\\v{2}"; return String.Format(format, GetRootKeyName(wow64), frameworkName, frameworkVersion, platformName); } /////////////////////////////////////////////////////////////////////// private static string GetImageRuntimeVersion( string fileName |
︙ | ︙ | |||
4152 4153 4154 4155 4156 4157 4158 | } /////////////////////////////////////////////////////////////////////// private static string GetFrameworkDirectory( MockRegistryKey rootKey, Version frameworkVersion, | < | | | 4140 4141 4142 4143 4144 4145 4146 4147 4148 4149 4150 4151 4152 4153 4154 4155 4156 4157 4158 4159 4160 4161 | } /////////////////////////////////////////////////////////////////////// private static string GetFrameworkDirectory( MockRegistryKey rootKey, Version frameworkVersion, bool wow64, bool whatIf, bool verbose ) { using (MockRegistryKey key = RegistryHelper.OpenSubKey( rootKey, GetFrameworkRootKeyName(wow64), false, whatIf, verbose)) { if (key == null) return null; object value = RegistryHelper.GetValue( key, "InstallRoot", null, whatIf, verbose); |
︙ | ︙ | |||
4266 4267 4268 4269 4270 4271 4272 | /////////////////////////////////////////////////////////////////////// private static bool HaveFrameworkDirectory( MockRegistryKey rootKey, string frameworkName, Version frameworkVersion, string platformName, | < | < | < | 4253 4254 4255 4256 4257 4258 4259 4260 4261 4262 4263 4264 4265 4266 4267 4268 4269 4270 4271 4272 4273 4274 4275 4276 4277 4278 4279 4280 4281 4282 4283 4284 4285 | /////////////////////////////////////////////////////////////////////// private static bool HaveFrameworkDirectory( MockRegistryKey rootKey, string frameworkName, Version frameworkVersion, string platformName, bool wow64, bool whatIf, bool verbose ) { string keyName = GetFrameworkKeyName( frameworkName, frameworkVersion, platformName, wow64); using (MockRegistryKey key = RegistryHelper.OpenSubKey( rootKey, keyName, false, whatIf, verbose)) { if (key == null) return false; if (platformName != null) // NOTE: Skip non-desktop. return true; string directory = GetFrameworkDirectory( rootKey, frameworkVersion, wow64, whatIf, verbose); if (String.IsNullOrEmpty(directory)) return false; if (!Directory.Exists(directory)) return false; |
︙ | ︙ | |||
4312 4313 4314 4315 4316 4317 4318 | /////////////////////////////////////////////////////////////////////// private static bool HaveFrameworkRegistry( MockRegistryKey rootKey, string frameworkName, Version frameworkVersion, string platformName, | < | < | 4296 4297 4298 4299 4300 4301 4302 4303 4304 4305 4306 4307 4308 4309 4310 4311 4312 4313 4314 4315 4316 | /////////////////////////////////////////////////////////////////////// private static bool HaveFrameworkRegistry( MockRegistryKey rootKey, string frameworkName, Version frameworkVersion, string platformName, bool wow64, bool whatIf, bool verbose ) { string keyName = GetFrameworkKeyName( frameworkName, frameworkVersion, platformName, wow64); using (MockRegistryKey key = RegistryHelper.OpenSubKey( rootKey, keyName, false, whatIf, verbose)) { if (key == null) return false; |
︙ | ︙ | |||
4355 4356 4357 4358 4359 4360 4361 | string version, /* NOTE: Optional. */ string invariant, string name, string description, string typeName, AssemblyName assemblyName, object clientData, | < | 4337 4338 4339 4340 4341 4342 4343 4344 4345 4346 4347 4348 4349 4350 | string version, /* NOTE: Optional. */ string invariant, string name, string description, string typeName, AssemblyName assemblyName, object clientData, bool wow64, bool throwOnMissing, bool whatIf, bool verbose, ref bool saved, ref string error ) |
︙ | ︙ | |||
4469 4470 4471 4472 4473 4474 4475 | "frameworkName = {0}, frameworkVersion = {1}, " + "platformName = {2}", ForDisplay(frameworkName), ForDisplay(frameworkVersion), ForDisplay(platformName)), traceCategory); if (!HaveFrameworkDirectory( rootKey, frameworkName, frameworkVersion, | | | < | 4450 4451 4452 4453 4454 4455 4456 4457 4458 4459 4460 4461 4462 4463 4464 4465 4466 4467 4468 4469 4470 4471 4472 4473 4474 4475 4476 4477 4478 | "frameworkName = {0}, frameworkVersion = {1}, " + "platformName = {2}", ForDisplay(frameworkName), ForDisplay(frameworkVersion), ForDisplay(platformName)), traceCategory); if (!HaveFrameworkDirectory( rootKey, frameworkName, frameworkVersion, platformName, wow64, whatIf, verbose)) { TraceOps.DebugAndTrace(TracePriority.Low, debugCallback, traceCallback, ".NET Framework directory not found, skipping...", traceCategory); continue; } if (callback == null) continue; string directory = GetFrameworkDirectory( rootKey, frameworkVersion, wow64, whatIf, verbose); if (String.IsNullOrEmpty(directory)) { TraceOps.DebugAndTrace(TracePriority.Low, debugCallback, traceCallback, String.Format( ".NET Framework {0} directory is invalid, " + "skipping...", ForDisplay(frameworkVersion)), |
︙ | ︙ | |||
4527 4528 4529 4530 4531 4532 4533 | continue; } bool localSaved = false; if (!callback( fileName, invariant, name, description, typeName, | | | < | 4507 4508 4509 4510 4511 4512 4513 4514 4515 4516 4517 4518 4519 4520 4521 4522 | continue; } bool localSaved = false; if (!callback( fileName, invariant, name, description, typeName, assemblyName, clientData, wow64, throwOnMissing, whatIf, verbose, ref localSaved, ref error)) { return false; } else { if (localSaved && !saved) saved = true; |
︙ | ︙ | |||
4560 4561 4562 4563 4564 4565 4566 | [MethodImpl(MethodImplOptions.NoInlining)] private static bool ForEachFrameworkRegistry( MockRegistry registry, FrameworkList frameworkList, FrameworkRegistryCallback callback, string version, /* NOTE: Optional. */ object clientData, | < | 4539 4540 4541 4542 4543 4544 4545 4546 4547 4548 4549 4550 4551 4552 | [MethodImpl(MethodImplOptions.NoInlining)] private static bool ForEachFrameworkRegistry( MockRegistry registry, FrameworkList frameworkList, FrameworkRegistryCallback callback, string version, /* NOTE: Optional. */ object clientData, bool wow64, bool throwOnMissing, bool whatIf, bool verbose, ref string error ) { |
︙ | ︙ | |||
4666 4667 4668 4669 4670 4671 4672 | "frameworkName = {0}, frameworkVersion = {1}, " + "platformName = {2}", ForDisplay(frameworkName), ForDisplay(frameworkVersion), ForDisplay(platformName)), traceCategory); if (!HaveFrameworkRegistry( rootKey, frameworkName, frameworkVersion, | | | | | 4644 4645 4646 4647 4648 4649 4650 4651 4652 4653 4654 4655 4656 4657 4658 4659 4660 4661 4662 4663 4664 4665 4666 4667 4668 4669 4670 4671 4672 4673 4674 | "frameworkName = {0}, frameworkVersion = {1}, " + "platformName = {2}", ForDisplay(frameworkName), ForDisplay(frameworkVersion), ForDisplay(platformName)), traceCategory); if (!HaveFrameworkRegistry( rootKey, frameworkName, frameworkVersion, platformName, wow64, whatIf, verbose)) { TraceOps.DebugAndTrace(TracePriority.Low, debugCallback, traceCallback, ".NET Framework registry not found, skipping...", traceCategory); continue; } if (callback == null) continue; if (!callback( rootKey, frameworkName, frameworkVersion, platformName, clientData, wow64, throwOnMissing, whatIf, verbose, ref error)) { return false; } } } return true; |
︙ | ︙ | |||
4732 4733 4734 4735 4736 4737 4738 | /////////////////////////////////////////////////////////////////////// private static bool HaveVsVersion( MockRegistryKey rootKey, Version vsVersion, string suffix, | < | | 4710 4711 4712 4713 4714 4715 4716 4717 4718 4719 4720 4721 4722 4723 4724 4725 4726 4727 4728 4729 4730 4731 4732 | /////////////////////////////////////////////////////////////////////// private static bool HaveVsVersion( MockRegistryKey rootKey, Version vsVersion, string suffix, bool wow64, bool whatIf, bool verbose ) { if (vsVersion == null) return false; string keyName = GetVsKeyName(vsVersion, suffix, wow64); using (MockRegistryKey key = RegistryHelper.OpenSubKey( rootKey, keyName, false, whatIf, verbose)) { if (key == null) return false; |
︙ | ︙ | |||
4783 4784 4785 4786 4787 4788 4789 | private static bool ForEachVsVersionRegistry( MockRegistry registry, VsList vsList, VisualStudioRegistryCallback callback, string suffix, Package package, object clientData, | < | 4760 4761 4762 4763 4764 4765 4766 4767 4768 4769 4770 4771 4772 4773 | private static bool ForEachVsVersionRegistry( MockRegistry registry, VsList vsList, VisualStudioRegistryCallback callback, string suffix, Package package, object clientData, bool wow64, bool throwOnMissing, bool whatIf, bool verbose, ref string error ) { |
︙ | ︙ | |||
4831 4832 4833 4834 4835 4836 4837 | { TraceOps.DebugAndTrace(TracePriority.Lower, debugCallback, traceCallback, String.Format( "vsVersion = {0}", ForDisplay(vsVersion)), traceCategory); if (!HaveVsVersion( | | < | < | 4807 4808 4809 4810 4811 4812 4813 4814 4815 4816 4817 4818 4819 4820 4821 4822 4823 4824 4825 4826 4827 4828 4829 4830 4831 4832 4833 4834 4835 4836 | { TraceOps.DebugAndTrace(TracePriority.Lower, debugCallback, traceCallback, String.Format( "vsVersion = {0}", ForDisplay(vsVersion)), traceCategory); if (!HaveVsVersion( rootKey, vsVersion, suffix, wow64, whatIf, verbose)) { TraceOps.DebugAndTrace(TracePriority.Low, debugCallback, traceCallback, "Visual Studio version not found, skipping...", traceCategory); continue; } if (callback == null) continue; if (!callback( rootKey, vsVersion, suffix, package, clientData, wow64, throwOnMissing, whatIf, verbose, ref error)) { return false; } } return true; } |
︙ | ︙ | |||
5033 5034 5035 5036 5037 5038 5039 | string fileName, string invariant, string name, string description, string typeName, AssemblyName assemblyName, object clientData, | < | 5007 5008 5009 5010 5011 5012 5013 5014 5015 5016 5017 5018 5019 5020 | string fileName, string invariant, string name, string description, string typeName, AssemblyName assemblyName, object clientData, bool wow64, bool throwOnMissing, bool whatIf, bool verbose, ref bool saved, ref string error ) |
︙ | ︙ | |||
5075 5076 5077 5078 5079 5080 5081 | /////////////////////////////////////////////////////////////////////// #region Assembly Folders Handling private static string GetAssemblyFoldersKeyName( string frameworkName, Version frameworkVersion, string platformName, | < | < | < | 5048 5049 5050 5051 5052 5053 5054 5055 5056 5057 5058 5059 5060 5061 5062 5063 5064 5065 5066 5067 5068 5069 5070 5071 5072 5073 5074 5075 5076 5077 5078 5079 5080 5081 5082 5083 5084 5085 5086 5087 5088 5089 5090 5091 5092 5093 5094 | /////////////////////////////////////////////////////////////////////// #region Assembly Folders Handling private static string GetAssemblyFoldersKeyName( string frameworkName, Version frameworkVersion, string platformName, bool wow64 ) { // // NOTE: This registry key appears to always be 32-bit only // (i.e. probably because it is only used by Visual // Studio, which is currently always 32-bit only). // string format = !String.IsNullOrEmpty(platformName) ? "{0}\\Microsoft\\{1}\\v{2}\\{3}\\AssemblyFoldersEx" : "{0}\\Microsoft\\{1}\\v{2}\\AssemblyFoldersEx"; return String.Format(format, GetRootKeyName(wow64), frameworkName, frameworkVersion, platformName); } /////////////////////////////////////////////////////////////////////// private static bool AddToAssemblyFolders( MockRegistryKey rootKey, string frameworkName, Version frameworkVersion, string platformName, string subKeyName, string directory, bool wow64, bool whatIf, bool verbose, ref string error ) { string keyName = GetAssemblyFoldersKeyName( frameworkName, frameworkVersion, platformName, wow64); using (MockRegistryKey key = RegistryHelper.OpenSubKey( rootKey, keyName, true, whatIf, verbose)) { if (key == null) { error = String.Format( |
︙ | ︙ | |||
5152 5153 5154 5155 5156 5157 5158 | private static bool RemoveFromAssemblyFolders( MockRegistryKey rootKey, string frameworkName, Version frameworkVersion, string platformName, string subKeyName, | < | < | 5122 5123 5124 5125 5126 5127 5128 5129 5130 5131 5132 5133 5134 5135 5136 5137 5138 5139 5140 5141 5142 5143 5144 | private static bool RemoveFromAssemblyFolders( MockRegistryKey rootKey, string frameworkName, Version frameworkVersion, string platformName, string subKeyName, bool wow64, bool throwOnMissing, bool whatIf, bool verbose, ref string error ) { string keyName = GetAssemblyFoldersKeyName( frameworkName, frameworkVersion, platformName, wow64); using (MockRegistryKey key = RegistryHelper.OpenSubKey( rootKey, keyName, true, whatIf, verbose)) { if (key == null) { error = String.Format( |
︙ | ︙ | |||
5191 5192 5193 5194 5195 5196 5197 | private static bool ProcessAssemblyFolders( MockRegistryKey rootKey, string frameworkName, Version frameworkVersion, string platformName, object clientData, | < | | < | | < | < | < < | | 5159 5160 5161 5162 5163 5164 5165 5166 5167 5168 5169 5170 5171 5172 5173 5174 5175 5176 5177 5178 5179 5180 5181 5182 5183 5184 5185 5186 5187 5188 5189 5190 5191 5192 5193 5194 5195 5196 5197 5198 5199 5200 5201 5202 5203 5204 5205 5206 5207 5208 5209 5210 5211 5212 5213 5214 5215 5216 5217 5218 5219 5220 5221 5222 5223 5224 5225 5226 5227 5228 5229 5230 5231 5232 5233 5234 5235 5236 5237 5238 5239 5240 5241 5242 5243 5244 5245 5246 5247 5248 5249 5250 5251 5252 5253 5254 5255 5256 5257 5258 5259 5260 | private static bool ProcessAssemblyFolders( MockRegistryKey rootKey, string frameworkName, Version frameworkVersion, string platformName, object clientData, bool wow64, bool throwOnMissing, bool whatIf, bool verbose, ref string error ) { AnyPair<string, bool> pair = clientData as AnyPair<string, bool>; if (pair == null) { error = "invalid framework callback data"; return false; } if (pair.Y) { return RemoveFromAssemblyFolders( rootKey, frameworkName, frameworkVersion, platformName, LegacyProjectName, wow64, false, whatIf, verbose, ref error) && AddToAssemblyFolders( rootKey, frameworkName, frameworkVersion, platformName, ProjectName, pair.X, wow64, whatIf, verbose, ref error); } else { return RemoveFromAssemblyFolders( rootKey, frameworkName, frameworkVersion, platformName, ProjectName, wow64, throwOnMissing, whatIf, verbose, ref error); } } #endregion /////////////////////////////////////////////////////////////////////// #region Visual Studio Handling private static string GetVsRootKeyName( bool wow64 ) { return String.Format("{0}\\Microsoft\\VisualStudio", GetRootKeyName(wow64)); } /////////////////////////////////////////////////////////////////////// private static string GetVsKeyName( Version vsVersion, string suffix, bool wow64 ) { if (vsVersion == null) return null; return String.Format( "{0}\\{1}{2}", GetVsRootKeyName(wow64), vsVersion, suffix); } /////////////////////////////////////////////////////////////////////// #region Visual Studio Data Source Handling private static bool AddVsDataSource( MockRegistryKey rootKey, Version vsVersion, string suffix, Package package, bool wow64, bool whatIf, bool verbose, ref string error ) { if (vsVersion == null) { error = "invalid VS version"; return false; } if (package == null) { error = "invalid VS package"; return false; } string keyName = GetVsKeyName(vsVersion, suffix, wow64); using (MockRegistryKey key = RegistryHelper.OpenSubKey( rootKey, keyName, false, whatIf, verbose)) { if (key == null) { error = String.Format( |
︙ | ︙ | |||
5355 5356 5357 5358 5359 5360 5361 | /////////////////////////////////////////////////////////////////////// private static bool RemoveVsDataSource( MockRegistryKey rootKey, Version vsVersion, string suffix, Package package, | < | | 5317 5318 5319 5320 5321 5322 5323 5324 5325 5326 5327 5328 5329 5330 5331 5332 5333 5334 5335 5336 5337 5338 5339 5340 5341 5342 5343 5344 5345 5346 5347 5348 5349 | /////////////////////////////////////////////////////////////////////// private static bool RemoveVsDataSource( MockRegistryKey rootKey, Version vsVersion, string suffix, Package package, bool wow64, bool whatIf, bool verbose, ref string error ) { if (vsVersion == null) { error = "invalid VS version"; return false; } if (package == null) { error = "invalid VS package"; return false; } string keyName = GetVsKeyName(vsVersion, suffix, wow64); using (MockRegistryKey key = RegistryHelper.OpenSubKey( rootKey, keyName, false, whatIf, verbose)) { if (key == null) { error = String.Format( |
︙ | ︙ | |||
5417 5418 5419 5420 5421 5422 5423 | private static bool ProcessVsDataSource( MockRegistryKey rootKey, Version vsVersion, string suffix, Package package, object clientData, | < | 5378 5379 5380 5381 5382 5383 5384 5385 5386 5387 5388 5389 5390 5391 | private static bool ProcessVsDataSource( MockRegistryKey rootKey, Version vsVersion, string suffix, Package package, object clientData, bool wow64, bool throwOnMissing, bool whatIf, bool verbose, ref string error ) { |
︙ | ︙ | |||
5442 5443 5444 5445 5446 5447 5448 | error = "invalid VS callback data"; return false; } if (pair.Y) { return AddVsDataSource( | | | | | < | | 5402 5403 5404 5405 5406 5407 5408 5409 5410 5411 5412 5413 5414 5415 5416 5417 5418 5419 5420 5421 5422 5423 5424 5425 5426 5427 5428 5429 5430 5431 5432 5433 5434 5435 5436 5437 5438 5439 5440 5441 5442 5443 5444 5445 5446 5447 5448 5449 5450 5451 5452 5453 5454 5455 | error = "invalid VS callback data"; return false; } if (pair.Y) { return AddVsDataSource( rootKey, vsVersion, suffix, package, wow64, whatIf, verbose, ref error); } else { return RemoveVsDataSource( rootKey, vsVersion, suffix, package, wow64, whatIf, verbose, ref error); } } #endregion /////////////////////////////////////////////////////////////////////// #region Visual Studio Data Provider Handling private static bool AddVsDataProvider( MockRegistryKey rootKey, Version vsVersion, string suffix, Package package, string fileName, bool wow64, bool whatIf, bool verbose, ref string error ) { if (vsVersion == null) { error = "invalid VS version"; return false; } if (package == null) { error = "invalid VS package"; return false; } string keyName = GetVsKeyName(vsVersion, suffix, wow64); using (MockRegistryKey key = RegistryHelper.OpenSubKey( rootKey, keyName, false, whatIf, verbose)) { if (key == null) { error = String.Format( |
︙ | ︙ | |||
5599 5600 5601 5602 5603 5604 5605 | /////////////////////////////////////////////////////////////////////// private static bool RemoveVsDataProvider( MockRegistryKey rootKey, Version vsVersion, string suffix, Package package, | < | | 5558 5559 5560 5561 5562 5563 5564 5565 5566 5567 5568 5569 5570 5571 5572 5573 5574 5575 5576 5577 5578 5579 5580 5581 5582 5583 5584 | /////////////////////////////////////////////////////////////////////// private static bool RemoveVsDataProvider( MockRegistryKey rootKey, Version vsVersion, string suffix, Package package, bool wow64, bool whatIf, bool verbose, ref string error ) { if (vsVersion == null) { error = "invalid VS version"; return false; } string keyName = GetVsKeyName(vsVersion, suffix, wow64); using (MockRegistryKey key = RegistryHelper.OpenSubKey( rootKey, keyName, false, whatIf, verbose)) { if (key == null) { error = String.Format( |
︙ | ︙ | |||
5655 5656 5657 5658 5659 5660 5661 | private static bool ProcessVsDataProvider( MockRegistryKey rootKey, Version vsVersion, string suffix, Package package, object clientData, | < | | | | | 5613 5614 5615 5616 5617 5618 5619 5620 5621 5622 5623 5624 5625 5626 5627 5628 5629 5630 5631 5632 5633 5634 5635 5636 5637 5638 5639 5640 5641 5642 5643 5644 5645 5646 5647 5648 5649 5650 5651 5652 | private static bool ProcessVsDataProvider( MockRegistryKey rootKey, Version vsVersion, string suffix, Package package, object clientData, bool wow64, bool throwOnMissing, bool whatIf, bool verbose, ref string error ) { AnyPair<string, bool> pair = clientData as AnyPair<string, bool>; if (pair == null) { error = "invalid VS callback data"; return false; } if (pair.Y) { return AddVsDataProvider( rootKey, vsVersion, suffix, package, pair.X, wow64, whatIf, verbose, ref error); } else { return RemoveVsDataProvider( rootKey, vsVersion, suffix, package, wow64, whatIf, verbose, ref error); } } #endregion /////////////////////////////////////////////////////////////////////// #region Visual Studio Package Handling |
︙ | ︙ | |||
5727 5728 5729 5730 5731 5732 5733 | private static bool AddVsPackage( MockRegistryKey rootKey, Version vsVersion, string suffix, Package package, string fileName, | < | | 5684 5685 5686 5687 5688 5689 5690 5691 5692 5693 5694 5695 5696 5697 5698 5699 5700 5701 5702 5703 5704 5705 5706 5707 5708 5709 5710 5711 5712 5713 5714 5715 5716 | private static bool AddVsPackage( MockRegistryKey rootKey, Version vsVersion, string suffix, Package package, string fileName, bool wow64, bool whatIf, bool verbose, ref string error ) { if (vsVersion == null) { error = "invalid VS version"; return false; } if (package == null) { error = "invalid VS package"; return false; } string keyName = GetVsKeyName(vsVersion, suffix, wow64); using (MockRegistryKey key = RegistryHelper.OpenSubKey( rootKey, keyName, false, whatIf, verbose)) { if (key == null) { error = String.Format( |
︙ | ︙ | |||
5924 5925 5926 5927 5928 5929 5930 | /////////////////////////////////////////////////////////////////////// private static bool RemoveVsPackage( MockRegistryKey rootKey, Version vsVersion, string suffix, Package package, | < | | 5880 5881 5882 5883 5884 5885 5886 5887 5888 5889 5890 5891 5892 5893 5894 5895 5896 5897 5898 5899 5900 5901 5902 5903 5904 5905 5906 5907 5908 5909 5910 5911 5912 5913 | /////////////////////////////////////////////////////////////////////// private static bool RemoveVsPackage( MockRegistryKey rootKey, Version vsVersion, string suffix, Package package, bool wow64, bool throwOnMissing, bool whatIf, bool verbose, ref string error ) { if (vsVersion == null) { error = "invalid VS version"; return false; } if (package == null) { error = "invalid VS package"; return false; } string keyName = GetVsKeyName(vsVersion, suffix, wow64); using (MockRegistryKey key = RegistryHelper.OpenSubKey( rootKey, keyName, false, whatIf, verbose)) { if (key == null) { error = String.Format( |
︙ | ︙ | |||
6021 6022 6023 6024 6025 6026 6027 | private static bool ProcessVsPackage( MockRegistryKey rootKey, Version vsVersion, string suffix, Package package, object clientData, | < | | | | 5976 5977 5978 5979 5980 5981 5982 5983 5984 5985 5986 5987 5988 5989 5990 5991 5992 5993 5994 5995 5996 5997 5998 5999 6000 6001 6002 6003 6004 6005 6006 6007 6008 6009 6010 6011 6012 6013 6014 | private static bool ProcessVsPackage( MockRegistryKey rootKey, Version vsVersion, string suffix, Package package, object clientData, bool wow64, bool throwOnMissing, bool whatIf, bool verbose, ref string error ) { AnyPair<string, bool> pair = clientData as AnyPair<string, bool>; if (pair == null) { error = "invalid VS callback data"; return false; } if (pair.Y) { return AddVsPackage( rootKey, vsVersion, suffix, package, pair.X, wow64, whatIf, verbose, ref error); } else { return RemoveVsPackage( rootKey, vsVersion, suffix, package, wow64, throwOnMissing, whatIf, verbose, ref error); } } #endregion #endregion /////////////////////////////////////////////////////////////////////// |
︙ | ︙ | |||
6176 6177 6178 6179 6180 6181 6182 | InstallFlags.GlobalAssemblyCache, true) && configuration.HasFlags( InstallFlags.VsPackageGlobalAssemblyCache, true), ref package); /////////////////////////////////////////////////////////// | | < | 6130 6131 6132 6133 6134 6135 6136 6137 6138 6139 6140 6141 6142 6143 6144 | InstallFlags.GlobalAssemblyCache, true) && configuration.HasFlags( InstallFlags.VsPackageGlobalAssemblyCache, true), ref package); /////////////////////////////////////////////////////////// InitializeFrameworkList(registry.LocalMachine, configuration, ref frameworkList); InitializeVsList(configuration.PerUser ? registry.CurrentUser : registry.LocalMachine, configuration, ref vsList); #endregion |
︙ | ︙ | |||
6296 6297 6298 6299 6300 6301 6302 | #region .NET AssemblyFolders if (configuration.HasFlags( InstallFlags.AssemblyFolders, true)) { if (!ForEachFrameworkRegistry(registry, frameworkList, ProcessAssemblyFolders, configuration.RegistryVersion, directoryData, | < | 6249 6250 6251 6252 6253 6254 6255 6256 6257 6258 6259 6260 6261 6262 | #region .NET AssemblyFolders if (configuration.HasFlags( InstallFlags.AssemblyFolders, true)) { if (!ForEachFrameworkRegistry(registry, frameworkList, ProcessAssemblyFolders, configuration.RegistryVersion, directoryData, NetFxIs32BitOnly || configuration.Wow64, configuration.ThrowOnMissing, configuration.WhatIf, configuration.Verbose, ref error)) { TraceOps.ShowMessage(TracePriority.Highest, debugCallback, traceCallback, thisAssembly, |
︙ | ︙ | |||
6329 6330 6331 6332 6333 6334 6335 | bool saved = false; if (!ForEachFrameworkConfig(registry, frameworkList, ProcessDbProviderFactory, configuration.ConfigVersion, InvariantName, ProviderName, Description, FactoryTypeName, coreAssemblyName, directoryData, | < | 6281 6282 6283 6284 6285 6286 6287 6288 6289 6290 6291 6292 6293 6294 | bool saved = false; if (!ForEachFrameworkConfig(registry, frameworkList, ProcessDbProviderFactory, configuration.ConfigVersion, InvariantName, ProviderName, Description, FactoryTypeName, coreAssemblyName, directoryData, NetFxIs32BitOnly || configuration.Wow64, configuration.ThrowOnMissing, configuration.WhatIf, configuration.Verbose, ref saved, ref error)) { TraceOps.ShowMessage(TracePriority.Highest, debugCallback, traceCallback, thisAssembly, |
︙ | ︙ | |||
6358 6359 6360 6361 6362 6363 6364 | #region VS Package if (configuration.HasFlags( InstallFlags.VsPackage, true)) { if (!ForEachVsVersionRegistry(registry, vsList, ProcessVsPackage, configuration.VsVersionSuffix, package, | | | 6309 6310 6311 6312 6313 6314 6315 6316 6317 6318 6319 6320 6321 6322 6323 | #region VS Package if (configuration.HasFlags( InstallFlags.VsPackage, true)) { if (!ForEachVsVersionRegistry(registry, vsList, ProcessVsPackage, configuration.VsVersionSuffix, package, fileNameData, VsIs32BitOnly || configuration.Wow64, configuration.ThrowOnMissing, configuration.WhatIf, configuration.Verbose, ref error)) { TraceOps.ShowMessage(TracePriority.Highest, debugCallback, traceCallback, thisAssembly, |
︙ | ︙ | |||
6387 6388 6389 6390 6391 6392 6393 | #region VS DataSource if (configuration.HasFlags( InstallFlags.VsDataSource, true)) { if (!ForEachVsVersionRegistry(registry, vsList, ProcessVsDataSource, configuration.VsVersionSuffix, package, | | | 6338 6339 6340 6341 6342 6343 6344 6345 6346 6347 6348 6349 6350 6351 6352 | #region VS DataSource if (configuration.HasFlags( InstallFlags.VsDataSource, true)) { if (!ForEachVsVersionRegistry(registry, vsList, ProcessVsDataSource, configuration.VsVersionSuffix, package, fileNameData, VsIs32BitOnly || configuration.Wow64, configuration.ThrowOnMissing, configuration.WhatIf, configuration.Verbose, ref error)) { TraceOps.ShowMessage(TracePriority.Highest, debugCallback, traceCallback, thisAssembly, |
︙ | ︙ | |||
6416 6417 6418 6419 6420 6421 6422 | #region VS DataProvider if (configuration.HasFlags( InstallFlags.VsDataProvider, true)) { if (!ForEachVsVersionRegistry(registry, vsList, ProcessVsDataProvider, configuration.VsVersionSuffix, package, | | | 6367 6368 6369 6370 6371 6372 6373 6374 6375 6376 6377 6378 6379 6380 6381 | #region VS DataProvider if (configuration.HasFlags( InstallFlags.VsDataProvider, true)) { if (!ForEachVsVersionRegistry(registry, vsList, ProcessVsDataProvider, configuration.VsVersionSuffix, package, fileNameData, VsIs32BitOnly || configuration.Wow64, configuration.ThrowOnMissing, configuration.WhatIf, configuration.Verbose, ref error)) { TraceOps.ShowMessage(TracePriority.Highest, debugCallback, traceCallback, thisAssembly, |
︙ | ︙ |
Changes to tools/install/Properties/AssemblyInfo.cs.
︙ | ︙ | |||
24 25 26 27 28 29 30 | // Version information for an assembly consists of the following four values: // // Major Version // Minor Version // Build Number // Revision // | | | | 24 25 26 27 28 29 30 31 32 | // Version information for an assembly consists of the following four values: // // Major Version // Minor Version // Build Number // Revision // [assembly: AssemblyVersion("1.0.83.0")] [assembly: AssemblyFileVersion("1.0.83.0")] |
Changes to www/build.wiki.
︙ | ︙ | |||
120 121 122 123 124 125 126 | <li> Make sure the version information is correct for System.Data.SQLite in the following files: <ul> <li><root>\readme.htm</li> <li><root>\SQLite.nuspec</li> | < | 120 121 122 123 124 125 126 127 128 129 130 131 132 133 | <li> Make sure the version information is correct for System.Data.SQLite in the following files: <ul> <li><root>\readme.htm</li> <li><root>\SQLite.nuspec</li> <li><root>\SQLite.MSIL.nuspec</li> <li><root>\SQLite.x86.nuspec</li> <li><root>\SQLite.x64.nuspec</li> <li><root>\Doc\Extra\dbfactorysupport.html</li> <li><root>\Doc\Extra\welcome.html</li> <li><root>\Membership\Properties\AssemblyInfo.cs</li> <li><root>\SQLite.Designer\AssemblyInfo.cs</li> |
︙ | ︙ |
Changes to www/contrib_agreement.wiki.
1 2 3 4 | <title>System.Data.SQLite Contributor Agreement</title> <p> This agreement applies to your contribution of material to the | | | | | > | | | > | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | <title>System.Data.SQLite Contributor Agreement</title> <p> This agreement applies to your contribution of material to the System.Data.SQLite ADO.NET interfaces ("SDS") that is mananged by Hipp, Wyrick & Company, Inc. ("Hwaci") and sets out the intellectual property rights you grant to Hwaci in the contributed material. The terms "contribution" and "contributed material" mean any source code, object code, patch, tool, sample, graphic, specification, manual, documentation, or any other material posted, submitted, or uploaded by you to the SDS project. The term "you" means the person identified and signing at the bottom of this document. If your contribution is on behalf of a company, the term "you" also means the company identified in the signature area below. </p> <ol> <li> <p> With respect to any worldwide copyrights, or copyright applications and |
︙ | ︙ | |||
100 101 102 103 104 105 106 | set forth in this agreement. Please print clearly. </p> <center> <p> <table width="80%" border="1" cellpadding="0" cellspacing="0"> <tr> | | | 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 | set forth in this agreement. Please print clearly. </p> <center> <p> <table width="80%" border="1" cellpadding="0" cellspacing="0"> <tr> <td width="20%" valign="top">Your name & email:</td> <td width="80%"> <!-- Replace this line with your name and email --> <p> </p> </td> </tr> <tr> <td valign="top">Company name:<br>(if applicable)</td> |
︙ | ︙ |
Changes to www/contribute.wiki.
1 2 3 4 5 6 7 8 9 10 11 12 | <title>Contributing To System.Data.SQLite</title> Users are encouraged to contributed enhancements back to the System.Data.SQLite project. This note outlines some of the procedures for making useful contributions. <h2>1.0 Contributor Agreement</h2> In order to accept your contributions, we <u>must</u> have a [./contrib_agreement.wiki | Contributor Agreement] on file for you. We require this in order to maintain clear title to the System.Data.SQLite code and prevent the introduction of code with incompatible licenses or other entanglements | | | | | | 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 | <title>Contributing To System.Data.SQLite</title> Users are encouraged to contributed enhancements back to the System.Data.SQLite project. This note outlines some of the procedures for making useful contributions. <h2>1.0 Contributor Agreement</h2> In order to accept your contributions, we <u>must</u> have a [./contrib_agreement.wiki | Contributor Agreement] on file for you. We require this in order to maintain clear title to the System.Data.SQLite code and prevent the introduction of code with incompatible licenses or other entanglements that might cause legal problems for System.Data.SQLite users. If you do not wish to submit a Contributor Agreement, we would still welcome your suggestions and example code, but we will not use your code directly - we will be forced to reimplement your changes from scratch which might take longer. <h2>2.0 Submitting Patches</h2> Suggested changes or bug fixes can be submitted by creating a patch against the current source tree. Email patches to <a href="mailto:drh@sqlite.org">drh@sqlite.org</a>. Be sure to describe in detail what the patch does and which version of System.Data.SQLite it is written against. A contributor agreement is not strictly necessary to submit a patch. However, without a contributor agreement on file, your patch will be used for reference only - it will not be applied to the code. This may delay acceptance of your patch. Your patches or changes might not be accepted even if you do have |
︙ | ︙ | |||
43 44 45 46 47 48 49 | of getting check-in privileges are much improved if you have a history of submitting quality patches and/or making thoughtful posts on the [http://www.mail-archive.com/sqlite-users@sqlite.org/ | mailing list]. A contributor agreement is, of course, a prerequisite for check-in privileges.</p> Contributors are asked to make all non-trivial changes on a branch. A | | | | | | | | < < | 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 | of getting check-in privileges are much improved if you have a history of submitting quality patches and/or making thoughtful posts on the [http://www.mail-archive.com/sqlite-users@sqlite.org/ | mailing list]. A contributor agreement is, of course, a prerequisite for check-in privileges.</p> Contributors are asked to make all non-trivial changes on a branch. A System.Data.SQLite admin will review the branch and merge the changes into the trunk.</p> Contributors are required to following the [./checkin.wiki | pre-checkin checklist] prior to every checkin to the System.Data.SQLite self-hosting repository. This checklist is short and succinct and should only require a few seconds to follow. Contributors should print out a copy of the pre-checkin checklist and keep it on a notecard beside their workstations, for quick reference. Contributors should review and try to mimic the coding style used through the rest of the System.Data.SQLite source code. Your code should blend in. A third-party reader should be unable to distinguish your code from any other code in the source corpus. <h2>4.0 Testing</h2> System.Data.SQLite has a simple test harness that excercises the basic System.Data.SQLite functions, but this is an area that needs further work. (Your contributions here are welcomed!) Contributors with check-in privileges are expected to run the test harness on all changes they contribute, and if appropriate add new automated test scripts to cover their additions. <h2>5.0 See Also</h2> * [./release.wiki | Release Procedures] |
Changes to www/downloads.wiki.
1 2 3 4 5 | <title>System.Data.SQLite Download Page</title> <nowiki> <h1>System.Data.SQLite Download Page</h1> <table width="100%" cellpadding="5"> | < < < < < < < < < < < < < < < < < < < < | 1 2 3 4 5 6 7 8 9 10 11 12 | <title>System.Data.SQLite Download Page</title> <nowiki> <h1>System.Data.SQLite Download Page</h1> <table width="100%" cellpadding="5"> <tr> <td colspan="3" class="importantHeader"> <b>Support Notes</b> </td> </tr> <tr> |
︙ | ︙ | |||
271 272 273 274 275 276 277 | <b>Source Code</b> </td> </tr> <tr> <td width="10"> </td> <td width="30%" valign="top" align="right"> | | | | < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < < < < < < < < < < < < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | | | < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | | | | | | | | | | | | | | | | | | | | | | | | | | | 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 | <b>Source Code</b> </td> </tr> <tr> <td width="10"> </td> <td width="30%" valign="top" align="right"> <a href="/downloads/1.0.82.0/sqlite-netFx-source-1.0.82.0.zip">sqlite-netFx-source-1.0.82.0.zip</a> <br /> (2.74 MiB) </td> <td width="5"></td> <td valign="top"> This ZIP archive contains all current source code for System.Data.SQLite 1.0.82.0 (3.7.14) combined into a single archive file. <br /> (sha1: accec84da4a59815078e494afd398eb1b3c64898) </td> </tr> <tr> <td colspan="4"> <b>Setups for 32-bit Windows (.NET Framework 3.5 SP1)</b> </td> </tr> <tr> <td width="10"> </td> <td width="30%" valign="top" align="right"> <a href="/downloads/1.0.82.0/sqlite-netFx35-setup-bundle-x86-2008-1.0.82.0.exe">sqlite-netFx35-setup-bundle-x86-2008-1.0.82.0.exe</a> <br /> (6.07 MiB) </td> <td width="5"></td> <td valign="top"> This setup package features the mixed-mode assembly and will install all the necessary runtime components and dependencies for the x86 version of the System.Data.SQLite 1.0.82.0 (3.7.14) package. The Visual C++ 2008 SP1 runtime for x86 is included. The .NET Framework 3.5 SP1 is required. <br /> <big><b>This setup package is capable of installing the design-time components for Visual Studio 2005 and/or Visual Studio 2008.</b></big> <br /> (sha1: e38165e4f45e4338d81f2da10050826406aa09b8) </td> </tr> <tr> <td width="10"> </td> <td width="30%" valign="top" align="right"> <a href="/downloads/1.0.82.0/sqlite-netFx35-setup-x86-2008-1.0.82.0.exe">sqlite-netFx35-setup-x86-2008-1.0.82.0.exe</a> <br /> (6.06 MiB) </td> <td width="5"></td> <td valign="top"> This setup package will install all the necessary runtime components and dependencies for the x86 version of the System.Data.SQLite 1.0.82.0 (3.7.14) package. The Visual C++ 2008 SP1 runtime for x86 is included. The .NET Framework 3.5 SP1 is required. <br /> (sha1: aed2059188e2ab66a341ce5167b2316c751fdbb1) </td> </tr> <tr> <td colspan="4"> <b>Setups for 64-bit Windows (.NET Framework 3.5 SP1)</b> </td> </tr> <tr> <td width="10"> </td> <td width="30%" valign="top" align="right"> <a href="/downloads/1.0.82.0/sqlite-netFx35-setup-bundle-x64-2008-1.0.82.0.exe">sqlite-netFx35-setup-bundle-x64-2008-1.0.82.0.exe</a> <br /> (6.81 MiB) </td> <td width="5"></td> <td valign="top"> This setup package features the mixed-mode assembly and will install all the necessary runtime components and dependencies for the x64 version of the System.Data.SQLite 1.0.82.0 (3.7.14) package. The Visual C++ 2008 SP1 runtime for x64 is included. The .NET Framework 3.5 SP1 is required. <br /> (sha1: aa0f1f958f9febf466807d79f03fae31508993dd) </td> </tr> <tr> <td width="10"> </td> <td width="30%" valign="top" align="right"> <a href="/downloads/1.0.82.0/sqlite-netFx35-setup-x64-2008-1.0.82.0.exe">sqlite-netFx35-setup-x64-2008-1.0.82.0.exe</a> <br /> (6.80 MiB) </td> <td width="5"></td> <td valign="top"> This setup package will install all the necessary runtime components and dependencies for the x64 version of the System.Data.SQLite 1.0.82.0 (3.7.14) package. The Visual C++ 2008 SP1 runtime for x64 is included. The .NET Framework 3.5 SP1 is required. <br /> (sha1: b5fa5e9c3477a44724356816488ca3fa15a11d4b) </td> </tr> <tr> <td colspan="4"> <b>Setups for 32-bit Windows (.NET Framework 4.0)</b> </td> </tr> <tr> <td width="10"> </td> <td width="30%" valign="top" align="right"> <a href="/downloads/1.0.82.0/sqlite-netFx40-setup-bundle-x86-2010-1.0.82.0.exe">sqlite-netFx40-setup-bundle-x86-2010-1.0.82.0.exe</a> <br /> (10.40 MiB) </td> <td width="5"></td> <td valign="top"> This setup package features the mixed-mode assembly and will install all the necessary runtime components and dependencies for the x86 version of the System.Data.SQLite 1.0.82.0 (3.7.14) package. The Visual C++ 2010 SP1 runtime for x86 is included. The .NET Framework 4.0 is required. <br /> <big><b>This setup package is capable of installing the design-time components for Visual Studio 2010.</b></big> <br /> (sha1: bf3defd3b4250e1aa94ea06e10c4b369416d0e2a) </td> </tr> <tr> <td width="10"> </td> <td width="30%" valign="top" align="right"> <a href="/downloads/1.0.82.0/sqlite-netFx40-setup-x86-2010-1.0.82.0.exe">sqlite-netFx40-setup-x86-2010-1.0.82.0.exe</a> <br /> (10.39 MiB) </td> <td width="5"></td> <td valign="top"> This setup package will install all the necessary runtime components and dependencies for the x86 version of the System.Data.SQLite 1.0.82.0 (3.7.14) package. The Visual C++ 2010 SP1 runtime for x86 is included. The .NET Framework 4.0 is required. <br /> (sha1: 8435fe9fd02655d3df95991e68391d487f6a8776) </td> </tr> <tr> <td colspan="4"> <b>Setups for 64-bit Windows (.NET Framework 4.0)</b> </td> </tr> <tr> <td width="10"> </td> <td width="30%" valign="top" align="right"> <a href="/downloads/1.0.82.0/sqlite-netFx40-setup-bundle-x64-2010-1.0.82.0.exe">sqlite-netFx40-setup-bundle-x64-2010-1.0.82.0.exe</a> <br /> (11.65 MiB) </td> <td width="5"></td> <td valign="top"> This setup package features the mixed-mode assembly and will install all the necessary runtime components and dependencies for the x64 version of the System.Data.SQLite 1.0.82.0 (3.7.14) package. The Visual C++ 2010 SP1 runtime for x64 is included. The .NET Framework 4.0 is required. <br /> (sha1: a7fcc7d410df97817eabbbc6f01e1e448f898aab) </td> </tr> <tr> <td width="10"> </td> <td width="30%" valign="top" align="right"> <a href="/downloads/1.0.82.0/sqlite-netFx40-setup-x64-2010-1.0.82.0.exe">sqlite-netFx40-setup-x64-2010-1.0.82.0.exe</a> <br /> (11.64 MiB) </td> <td width="5"></td> <td valign="top"> This setup package will install all the necessary runtime components and dependencies for the x64 version of the System.Data.SQLite 1.0.82.0 (3.7.14) package. The Visual C++ 2010 SP1 runtime for x64 is included. The .NET Framework 4.0 is required. <br /> (sha1: 0c3d227a1b3c0f3aae1a0b687f17dba18bed6eeb) </td> </tr> <tr> <td colspan="4"> <b>Precompiled Binaries for 32-bit Windows (.NET Framework 3.5 SP1)</b> </td> </tr> <tr> <td width="10"> </td> <td width="30%" valign="top" align="right"> <a href="/downloads/1.0.82.0/sqlite-netFx35-binary-bundle-Win32-2008-1.0.82.0.zip">sqlite-netFx35-binary-bundle-Win32-2008-1.0.82.0.zip</a> <br /> (1.66 MiB) </td> <td width="5"></td> <td valign="top"> This binary package features the mixed-mode assembly and contains all the binaries for the x86 version of the System.Data.SQLite 1.0.82.0 (3.7.14) package. The Visual C++ 2008 SP1 runtime for x86 and the .NET Framework 3.5 SP1 are required. <br /> (sha1: cf6ec0622af7a16c5cf32c02d41a29060b91ec79) </td> </tr> <tr> <td width="10"> </td> <td width="30%" valign="top" align="right"> <a href="/downloads/1.0.82.0/sqlite-netFx35-binary-Win32-2008-1.0.82.0.zip">sqlite-netFx35-binary-Win32-2008-1.0.82.0.zip</a> <br /> (1.65 MiB) </td> <td width="5"></td> <td valign="top"> This binary package contains all the binaries for the x86 version of the System.Data.SQLite 1.0.82.0 (3.7.14) package. The Visual C++ 2008 SP1 runtime for x86 and the .NET Framework 3.5 SP1 are required. <br /> (sha1: 5e4724570d0a9e49450d2c0aac0601db4bebed11) </td> </tr> <tr> <td colspan="4"> <b>Precompiled Binaries for 64-bit Windows (.NET Framework 3.5 SP1)</b> </td> </tr> <tr> <td width="10"> </td> <td width="30%" valign="top" align="right"> <a href="/downloads/1.0.82.0/sqlite-netFx35-binary-bundle-x64-2008-1.0.82.0.zip">sqlite-netFx35-binary-bundle-x64-2008-1.0.82.0.zip</a> <br /> (1.73 MiB) </td> <td width="5"></td> <td valign="top"> This binary package features the mixed-mode assembly and contains all the binaries for the x64 version of the System.Data.SQLite 1.0.82.0 (3.7.14) package. The Visual C++ 2008 SP1 runtime for x64 and the .NET Framework 3.5 SP1 are required. <br /> (sha1: 15b5625a7f5fa1a4a74c61c0c46e3969d2c6adc2) </td> </tr> <tr> <td width="10"> </td> <td width="30%" valign="top" align="right"> <a href="/downloads/1.0.82.0/sqlite-netFx35-binary-x64-2008-1.0.82.0.zip">sqlite-netFx35-binary-x64-2008-1.0.82.0.zip</a> <br /> (1.72 MiB) </td> <td width="5"></td> <td valign="top"> This binary package contains all the binaries for the x64 version of the System.Data.SQLite 1.0.82.0 (3.7.14) package. The Visual C++ 2008 SP1 runtime for x64 and the .NET Framework 3.5 SP1 are required. <br /> (sha1: 25abc0ea78f8f45b93c9c2fc1381c2acd863638d) </td> </tr> <tr> <td colspan="4"> <b>Precompiled Binaries for 32-bit Windows (.NET Framework 4.0)</b> </td> </tr> <tr> <td width="10"> </td> <td width="30%" valign="top" align="right"> <a href="/downloads/1.0.82.0/sqlite-netFx40-binary-bundle-Win32-2010-1.0.82.0.zip">sqlite-netFx40-binary-bundle-Win32-2010-1.0.82.0.zip</a> <br /> (1.71 MiB) </td> <td width="5"></td> <td valign="top"> This binary package features the mixed-mode assembly and contains all the binaries for the x86 version of the System.Data.SQLite 1.0.82.0 (3.7.14) package. The Visual C++ 2010 SP1 runtime for x86 and the .NET Framework 4.0 are required. <br /> (sha1: 6f6cdfddb08f254b744e7088b4825db02bec73da) </td> </tr> <tr> <td width="10"> </td> <td width="30%" valign="top" align="right"> <a href="/downloads/1.0.82.0/sqlite-netFx40-binary-Win32-2010-1.0.82.0.zip">sqlite-netFx40-binary-Win32-2010-1.0.82.0.zip</a> <br /> (1.70 MiB) </td> <td width="5"></td> <td valign="top"> This binary package contains all the binaries for the x86 version of the System.Data.SQLite 1.0.82.0 (3.7.14) package. The Visual C++ 2010 SP1 runtime for x86 and the .NET Framework 4.0 are required. <br /> (sha1: 12ffe8323fcf5af25ef6e6effb4f52300df819ee) </td> </tr> <tr> <td colspan="4"> <b>Precompiled Binaries for 64-bit Windows (.NET Framework 4.0)</b> </td> </tr> <tr> <td width="10"> </td> <td width="30%" valign="top" align="right"> <a href="/downloads/1.0.82.0/sqlite-netFx40-binary-bundle-x64-2010-1.0.82.0.zip">sqlite-netFx40-binary-bundle-x64-2010-1.0.82.0.zip</a> <br /> (1.73 MiB) </td> <td width="5"></td> <td valign="top"> This binary package features the mixed-mode assembly and contains all the binaries for the x64 version of the System.Data.SQLite 1.0.82.0 (3.7.14) package. The Visual C++ 2010 SP1 runtime for x64 and the .NET Framework 4.0 are required. <br /> (sha1: e1b79aa7763853a68068f43c9edb6382a2c67550) </td> </tr> <tr> <td width="10"> </td> <td width="30%" valign="top" align="right"> <a href="/downloads/1.0.82.0/sqlite-netFx40-binary-x64-2010-1.0.82.0.zip">sqlite-netFx40-binary-x64-2010-1.0.82.0.zip</a> <br /> (1.72 MiB) </td> <td width="5"></td> <td valign="top"> This binary package contains all the binaries for the x64 version of the System.Data.SQLite 1.0.82.0 (3.7.14) package. The Visual C++ 2010 SP1 runtime for x64 and the .NET Framework 4.0 are required. <br /> (sha1: a91739243166b9ae27be244722acd480d1ce4537) </td> </tr> <tr> <td colspan="4"> <b>Precompiled Statically-Linked Binaries for 32-bit Windows (.NET Framework 3.5 SP1)</b> </td> </tr> <tr> <td width="10"> </td> <td width="30%" valign="top" align="right"> <a href="/downloads/1.0.82.0/sqlite-netFx35-static-binary-bundle-Win32-2008-1.0.82.0.zip">sqlite-netFx35-static-binary-bundle-Win32-2008-1.0.82.0.zip</a> <br /> (1.87 MiB) </td> <td width="5"></td> <td valign="top"> This binary package features the mixed-mode assembly and contains all the binaries for the x86 version of the System.Data.SQLite 1.0.82.0 (3.7.14) package. The Visual C++ 2008 SP1 runtime for x86 is statically linked. The .NET Framework 3.5 SP1 is required. <br /> (sha1: 43076280a7ee02b1574bb666d3a14c185d6fe84a) </td> </tr> <tr> <td width="10"> </td> <td width="30%" valign="top" align="right"> <a href="/downloads/1.0.82.0/sqlite-netFx35-static-binary-Win32-2008-1.0.82.0.zip">sqlite-netFx35-static-binary-Win32-2008-1.0.82.0.zip</a> <br /> (1.86 MiB) </td> <td width="5"></td> <td valign="top"> This binary package contains all the binaries for the x86 version of the System.Data.SQLite 1.0.82.0 (3.7.14) package. The Visual C++ 2008 SP1 runtime for x86 is statically linked. The .NET Framework 3.5 SP1 is required. <br /> (sha1: 44f8225d4025d2014ded056b31a2b1a5a8de07cc) </td> </tr> <tr> <td colspan="4"> <b>Precompiled Statically-Linked Binaries for 64-bit Windows (.NET Framework 3.5 SP1)</b> </td> </tr> <tr> <td width="10"> </td> <td width="30%" valign="top" align="right"> <a href="/downloads/1.0.82.0/sqlite-netFx35-static-binary-bundle-x64-2008-1.0.82.0.zip">sqlite-netFx35-static-binary-bundle-x64-2008-1.0.82.0.zip</a> <br /> (1.90 MiB) </td> <td width="5"></td> <td valign="top"> This binary package features the mixed-mode assembly and contains all the binaries for the x64 version of the System.Data.SQLite 1.0.82.0 (3.7.14) package. The Visual C++ 2008 SP1 runtime for x64 is statically linked. The .NET Framework 3.5 SP1 is required. <br /> (sha1: 1e29c539c75e106ddbdd18c83563fc0b9df7c1bf) </td> </tr> <tr> <td width="10"> </td> <td width="30%" valign="top" align="right"> <a href="/downloads/1.0.82.0/sqlite-netFx35-static-binary-x64-2008-1.0.82.0.zip">sqlite-netFx35-static-binary-x64-2008-1.0.82.0.zip</a> <br /> (1.90 MiB) </td> <td width="5"></td> <td valign="top"> This binary package contains all the binaries for the x64 version of the System.Data.SQLite 1.0.82.0 (3.7.14) package. The Visual C++ 2008 SP1 runtime for x64 is statically linked. The .NET Framework 3.5 SP1 is required. <br /> (sha1: f10532c9c858465852d179dc88ea6c519212234f) </td> </tr> <tr> <td colspan="4"> <b>Precompiled Statically-Linked Binaries for 32-bit Windows (.NET Framework 4.0)</b> </td> </tr> <tr> <td width="10"> </td> <td width="30%" valign="top" align="right"> <a href="/downloads/1.0.82.0/sqlite-netFx40-static-binary-bundle-Win32-2010-1.0.82.0.zip">sqlite-netFx40-static-binary-bundle-Win32-2010-1.0.82.0.zip</a> <br /> (1.92 MiB) </td> <td width="5"></td> <td valign="top"> This binary package features the mixed-mode assembly and contains all the binaries for the x86 version of the System.Data.SQLite 1.0.82.0 (3.7.14) package. The Visual C++ 2010 SP1 runtime for x86 is statically linked. The .NET Framework 4.0 is required. <br /> (sha1: 335da5c15d56b868f948dbf842ad97c94c5c148c) </td> </tr> <tr> <td width="10"> </td> <td width="30%" valign="top" align="right"> <a href="/downloads/1.0.82.0/sqlite-netFx40-static-binary-Win32-2010-1.0.82.0.zip">sqlite-netFx40-static-binary-Win32-2010-1.0.82.0.zip</a> <br /> (1.91 MiB) </td> <td width="5"></td> <td valign="top"> This binary package contains all the binaries for the x86 version of the System.Data.SQLite 1.0.82.0 (3.7.14) package. The Visual C++ 2010 SP1 runtime for x86 is statically linked. The .NET Framework 4.0 is required. <br /> (sha1: 22d21e6b97b9b79cd51528fda938e3d601eb1ae4) </td> </tr> <tr> <td colspan="4"> <b>Precompiled Statically-Linked Binaries for 64-bit Windows (.NET Framework 4.0)</b> </td> </tr> <tr> <td width="10"> </td> <td width="30%" valign="top" align="right"> <a href="/downloads/1.0.82.0/sqlite-netFx40-static-binary-bundle-x64-2010-1.0.82.0.zip">sqlite-netFx40-static-binary-bundle-x64-2010-1.0.82.0.zip</a> <br /> (1.92 MiB) </td> <td width="5"></td> <td valign="top"> This binary package features the mixed-mode assembly and contains all the binaries for the x64 version of the System.Data.SQLite 1.0.82.0 (3.7.14) package. The Visual C++ 2010 SP1 runtime for x64 is statically linked. The .NET Framework 4.0 is required. <br /> (sha1: 929f1d2a0eb9bb697c4e8725bedef1f4042c076b) </td> </tr> <tr> <td width="10"> </td> <td width="30%" valign="top" align="right"> <a href="/downloads/1.0.82.0/sqlite-netFx40-static-binary-x64-2010-1.0.82.0.zip">sqlite-netFx40-static-binary-x64-2010-1.0.82.0.zip</a> <br /> (1.92 MiB) </td> <td width="5"></td> <td valign="top"> This binary package contains all the binaries for the x64 version of the System.Data.SQLite 1.0.82.0 (3.7.14) package. The Visual C++ 2010 SP1 runtime for x64 is statically linked. The .NET Framework 4.0 is required. <br /> (sha1: 4c12b0ad3aae3510bd573e49a6159f6a3405d312) </td> </tr> <tr> <td colspan="4"> <b>Precompiled Binaries for Windows CE (.NET Compact Framework 3.5)</b> </td> </tr> <tr> <td width="10"> </td> <td width="30%" valign="top" align="right"> <a href="/downloads/1.0.82.0/sqlite-netFx35-binary-PocketPC-2008-1.0.82.0.zip">sqlite-netFx35-binary-PocketPC-2008-1.0.82.0.zip</a> <br /> (0.85 MiB) </td> <td width="5"></td> <td valign="top"> This binary package contains all the binaries for the PocketPC version of the System.Data.SQLite 1.0.82.0 (3.7.14) package. The .NET Compact Framework 3.5 is required. <br /> (sha1: f9b2393dde3ad5d2f507ebad26d2b81ea7544b70) </td> </tr> <tr> <td colspan="4"> <b>Official NuGet Packages</b> </td> </tr> <tr> <td width="10"> </td> <td width="30%" valign="top" align="right"> <a href="http://nuget.org/api/v2/package/System.Data.SQLite/1.0.82.0">System.Data.SQLite.1.0.82.0.nupkg</a> <br /> (2.85 MiB) </td> <td width="5"></td> <td valign="top"> This NuGet package contains all the binaries for both the x86 and x64 versions of System.Data.SQLite 1.0.82.0 (3.7.14). The .NET Framework 3.5 SP1 or 4.0 is required. For the included native binaries, the version of the Visual C++ runtime corresponding to the .NET Framework used by the associated managed assembly is statically linked. <br /> (sha1: 00192e51c6dda124d809c517125c99e46f7de620) </td> </tr> <tr> <td width="10"> </td> <td width="30%" valign="top" align="right"> <a href="http://nuget.org/api/v2/package/System.Data.SQLite.MSIL/1.0.82.0">System.Data.SQLite.MSIL.1.0.82.0.nupkg</a> <br /> (0.26 MiB) </td> <td width="5"></td> <td valign="top"> This NuGet package contains the managed binaries for System.Data.SQLite 1.0.82.0. The .NET Framework 3.5 SP1 or 4.0 is required. <br /> <big><b>This NuGet package does not include any code from the native SQLite core library and will not work properly without the native assembly "SQLite.Interop.dll" compiled for the processor architecture of the host process being present in a directory in the native library search path.</b></big> <br /> (sha1: 8d62c9ff2e22fac2ee0040f6fda49b270e7f27a3) </td> </tr> <tr> <td width="10"> </td> <td width="30%" valign="top" align="right"> <a href="http://nuget.org/api/v2/package/System.Data.SQLite.x86/1.0.82.0">System.Data.SQLite.x86.1.0.82.0.nupkg</a> <br /> (1.47 MiB) </td> <td width="5"></td> <td valign="top"> This NuGet package contains all the binaries for the x86 version of System.Data.SQLite 1.0.82.0 (3.7.14). The .NET Framework 3.5 SP1 or 4.0 is required. For the included native binaries, the version of the Visual C++ runtime corresponding to the .NET Framework used by the associated managed assembly is statically linked. <br /> (sha1: 598242655955a8827cdab065d4224db8341782fc) </td> </tr> <tr> <td width="10"> </td> <td width="30%" valign="top" align="right"> <a href="http://nuget.org/api/v2/package/System.Data.SQLite.x64/1.0.82.0">System.Data.SQLite.x64.1.0.82.0.nupkg</a> <br /> (1.67 MiB) </td> <td width="5"></td> <td valign="top"> This NuGet package contains all the binaries for the x64 version of System.Data.SQLite 1.0.82.0 (3.7.14). The .NET Framework 3.5 SP1 or 4.0 is required. For the included native binaries, the version of the Visual C++ runtime corresponding to the .NET Framework used by the associated managed assembly is statically linked. <br /> (sha1: 1d0a1646f469ea63e74c9ad0778f9911dbde4d30) </td> </tr> <tr> <td colspan="4"> <b>Legacy Versions</b> </td> |
︙ | ︙ | |||
1449 1450 1451 1452 1453 1454 1455 | <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> | < < < | < < < < | 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 | <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 "snapshots" of source code. </p> <p> The <b>framework</b> in templates (3), (4), (5), (6), (7), and (8) will be one of netFx20, netFx35, netFx40, netFx45. </p> <p> The <b>cpu</b> in templates (3) and (4) will be one of x86, x64, arm, ia64. </p> <p> The <b>platform</b> in templates (5), (6), (7), and (8) will be one of Win32, x64, PocketPC. </p> <p> The <b>year</b> in templates (3), (4), (5), (6), (7), and (8) will be one of 2005, 2008, 2010, 2012. </p> <p> The <b>version</b> 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 <b>date</b> in template (9) is of the form: YYYYMMDDHHMM </p> <h3>Canonical Source Code</h3> <p> The canonical System.Data.SQLite source code is maintained in a Fossil repository that is available for anonymous read-only access. Anyone can view the repository contents and download historical versions of individual files or ZIP archives of historical check-ins. |
︙ | ︙ |
Changes to www/faq.wiki.
︙ | ︙ | |||
100 101 102 103 104 105 106 | <li> <a href="#q20">When the System.Data.SQLite project is compiled and run from inside Visual Studio, why do I get a <b>DllNotFoundException</b> or a <b>BadImageFormatException</b> (for "sqlite3.dll" or "SQLite.Interop.dll") when trying to run or debug the application? </a> </li> | < < < < < < | 100 101 102 103 104 105 106 107 108 109 110 111 112 113 | <li> <a href="#q20">When the System.Data.SQLite project is compiled and run from inside Visual Studio, why do I get a <b>DllNotFoundException</b> or a <b>BadImageFormatException</b> (for "sqlite3.dll" or "SQLite.Interop.dll") when trying to run or debug the application? </a> </li> </ol> <hr> <a name="q1"></a> <p> <b>(1) When will the next version of System.Data.SQLite be released?</b> </p> |
︙ | ︙ | |||
488 489 490 491 492 493 494 | managed binaries in-place). However, this post-build step will only be performed if the selected platform matches that of the operating system (e.g. "Win32" for 32-bit Windows and "x64" for 64-bit Windows). Therefore, it is good practice to double-check the selected build platform against the operating system prior to attempting to run a managed project in the solution. </p> | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 482 483 484 485 486 487 488 | managed binaries in-place). However, this post-build step will only be performed if the selected platform matches that of the operating system (e.g. "Win32" for 32-bit Windows and "x64" for 64-bit Windows). Therefore, it is good practice to double-check the selected build platform against the operating system prior to attempting to run a managed project in the solution. </p> |
Changes to www/index.wiki.
︙ | ︙ | |||
30 31 32 33 34 35 36 | options. </p> <p> Please refer to the <a href="downloads.wiki">download page</a> for a complete list of downloadable packages and information on their use. </p> | < < < < < < < < < | 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | options. </p> <p> Please refer to the <a href="downloads.wiki">download page</a> for a complete list of downloadable packages and information on their use. </p> </td> <td width="30%" valign="top"> <table align="right" border="1" cellpadding="10" hspace="10" cellspacing="0"> <tr> <td> <ul> <li><a href="features.wiki">Features</a></li> |
︙ | ︙ |
Changes to www/news.wiki.
1 2 3 4 5 | <title>News</title> <b>Version History</b> <p> | | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < < < | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | <title>News</title> <b>Version History</b> <p> <b>1.0.83.0 - December XX, 2012 <font color="red">(release scheduled)</font></b> </p> <ul> <li>Updated to [http://www.sqlite.org/src/info/trunk|SQLite 3.7.15].</li> <li>Add Visual Studio 2012 support to all the applicable solution/project files, their associated supporting files, and the test suite.</li> <li>Add Visual Studio 2012 support to the redesigned designer support installer.</li> <li>Allow opened connections to skip adding the extension functions included in the interop assembly via the new NoExtensionFunctions connection flag.</li> <li>Support loading of SQLite extensions via the new EnableExtensions and LoadExtension methods of the SQLiteConnection class. Pursuant to [17045010df].</li> <li>Add notifications before and after any connection is opened and closed, as well as other related notifications, via the new static Changed event.</li> <li>Add an overload of the SQLiteLog.LogMessage method that takes a single string parameter.</li> <li>Add an overload of the SQLiteConnection.LogMessage method that takes a SQLiteErrorCode parameter.</li> <li>All applicable calls into the SQLite core library now return a SQLiteErrorCode instead of an integer error code.</li> <li>Make sure the error code of the SQLiteException class gets serialized.</li> <li>Make the test project for the .NET Compact Framework more flexible.</li> <li>When available, the new sqlite3_errstr function from the core library is used to get the error message for a specific return code.</li> <li>The SetMemoryStatus, Shutdown, ResultCode, ExtendedResultCode, and SetAvRetry methods of the SQLiteConnection class now return a SQLiteErrorCode instead of an integer error code. <b>** Potentially Incompatible Change **</b></li> <li>The public constructor for the SQLiteException now takes a SQLiteErrorCode instead of an integer error code. <b>** Potentially Incompatible Change **</b></li> <li>The ErrorCode property of the SQLiteException is now an Int32, to allow the property inherited from the base class to be properly overridden. <b>** Potentially Incompatible Change **</b></li> <li>The ErrorCode field of the LogEventArgs is now an object instead of an integer. <b>** Potentially Incompatible Change **</b></li> <li>The names and messages associated with the SQLiteErrorCode enumeration values have been normalized to match those in the SQLite core library. <b>** Potentially Incompatible Change **</b></li> <li>Implement more robust locking semantics for the CriticalHandle derived classes when compiled for the .NET Compact Framework.</li> <li>Cache column indexes are they are looked up when using the SQLiteDataReader to improve performance.</li> <li>Prevent the SQLiteConnection.Close method from throwing non-fatal exceptions during its disposal.</li> <li>Rename the interop assembly functions sqlite3_cursor_rowid, sqlite3_context_collcompare, sqlite3_context_collseq, sqlite3_cursor_rowid, and sqlite3_table_cursor to include an "_interop" suffix. <b>** Potentially Incompatible Change **</b></li> <li>Prevent the LastInsertRowId, MemoryUsed, and MemoryHighwater connection properties from throwing NotSupportedException when running on the .NET Compact Framework. Fix for [dd45aba387].</li> <li>Add protection against ThreadAbortException asynchronously interrupting native resource initialization and finalization.</li> <li>Add test automation for the Windows CE binaries.</li> </ul> <p> <b>1.0.82.0 - September 3, 2012</b> </p> <ul> <li>Updated to [http://www.sqlite.org/releaselog/3_7_14.html|SQLite 3.7.14].</li> |
︙ | ︙ |
Changes to www/release.wiki.
︙ | ︙ | |||
95 96 97 98 99 100 101 | <li> If the Windows CE binaries were already tested using the <a href="#testCeBinariesAutomated">automation</a> described in the previous section, skip this section. </li> <li> | | | | | < | 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 | <li> If the Windows CE binaries were already tested using the <a href="#testCeBinariesAutomated">automation</a> described in the previous section, skip this section. </li> <li> Launch <b>Visual Studio 2008</b>, "<b>Professional</b>" edition or "better". As of this writing, in January 2012, <b>Visual Studio 2010 and later will not work</b> as they do not include the necessary built-in support for Windows CE and the .NET Compact Framework. </li> <li> Open the "<b>SQLite.NET.2008.sln</b>" solution file in the "<root>" directory. </li> |
︙ | ︙ | |||
340 341 342 343 344 345 346 | </li> </ol> <a name="publishRelease"></a> <h2>Publish Release</h2> <ol> | < < > > | 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 | </li> </ol> <a name="publishRelease"></a> <h2>Publish Release</h2> <ol> <li> Commit pending source code changes to the [http://www.fossil-scm.org/ | Fossil] repository. </li> <li>Tag the release in the Fossil repository.</li> <li>Upload all the release packages to the web site.</li> <li> Push the [http://www.nuget.org/ | NuGet] packages.<br /> <i>Please refer to [http://docs.nuget.org/ | NuGet Documentation] for further details.</i> </li> <li>Announce the release on the System.Data.SQLite mailing list.</li> </ol> |
Changes to www/source.wiki.
1 2 3 4 5 6 | <title>Source Code</title> <p> Follow these steps to obtain the latest (i.e. unreleased) source code for the System.Data.SQLite project. To obtain the latest officially released source code instead, refer to the [./downloads.wiki | downloads page]. Unless | | | | | | | | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | <title>Source Code</title> <p> Follow these steps to obtain the latest (i.e. unreleased) source code for the System.Data.SQLite project. To obtain the latest officially released source code instead, refer to the [./downloads.wiki | downloads page]. Unless otherwise noted, all steps need to be done in the order specified. </p> <a name="assumptions"></a> <h2>Assumptions & Prerequisites</h2> <p> The string "<b><root></b>" represents the directory where you would like a local working copy of source tree (a.k.a. the working check-out directory) for the System.Data.SQLite project to reside (this should be a completely empty directory). </p> <p> The string "<b><repositories></b>" represents the directory where you would like the local clone of the repository for the System.Data.SQLite project (and potentially other projects) to reside. </p> <a name="fossil"></a> <h2>Obtain & Install Fossil</h2> <p> The [http://www.fossil-scm.org | Fossil] open-source [http://en.wikipedia.org/wiki/Distributed_revision_control | distributed version control] system is a computer program that must be installed on your machine before you use it. Fortunately, installing Fossil is very easy. Fossil consists of a single executable file that you simply download and run. For convenience, the Fossil |
︙ | ︙ | |||
51 52 53 54 55 56 57 | command similar to: <b>cd /D <root></b> </li> <li> Enter the following command to create a complete clone (i.e. local copy) of the entire source code repository for the System.Data.SQLite project, including the entire check-in history: | | | | 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | command similar to: <b>cd /D <root></b> </li> <li> Enter the following command to create a complete clone (i.e. local copy) of the entire source code repository for the System.Data.SQLite project, including the entire check-in history: <b>fossil [http://www.fossil-scm.org/index.html/help/clone | clone] http://system.data.sqlite.org/ <repositories>\sds.fossil</b> </li> <li> The repository itself uses an [http://www.fossil-scm.org/index.html/doc/trunk/www/fileformat.wiki | enduring file format] stored in a single [http://www.fossil-scm.org/index.html/doc/trunk/www/tech_overview.wiki | SQLite database file] with a particular schema. </li> <li> |
︙ | ︙ | |||
84 85 86 87 88 89 90 | Change the current directory to "<b><root></b>" using a command similar to: <b>cd /D <root></b> </li> <li> Enter the following command to create a local working copy of all the files that are currently part of the System.Data.SQLite project: | | | | 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 | Change the current directory to "<b><root></b>" using a command similar to: <b>cd /D <root></b> </li> <li> Enter the following command to create a local working copy of all the files that are currently part of the System.Data.SQLite project: <b>fossil [http://www.fossil-scm.org/index.html/help/open | open] <repositories>\sds.fossil</b> </li> <li> The local source tree should now be ready for use as described in the [./build.wiki | build procedures] and/or [./test.wiki | test procedures]. </li> <li> In the future, to update the local working copy with the latest changes from the official System.Data.SQLite repository (i.e. instead of having to re-clone the entire thing), enter the following command from the same directory where a working copy is located: <b>fossil [http://www.fossil-scm.org/index.html/help/update | update]</b> </li> </ol> |