Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Difference From 03add76ac4110987 To aa16dda5d979c4e2
2013-03-23
| ||
11:00 | Update the master archive release manifest. check-in: 24c7a3d1f5 user: mistachkin tags: trunk | |
10:49 | Update Eagle script library in externals to the latest trunk. check-in: aa16dda5d9 user: mistachkin tags: trunk | |
2013-03-22
| ||
23:40 | Add GetAllAsText connection flag to force all column values to be returned as text. Pursuant to [e06c4caff3]. check-in: 2cd9814a44 user: mistachkin tags: trunk | |
2013-01-16
| ||
23:49 | Add interop test SQL function to sleep for X milliseconds. check-in: da3460c70f user: mistachkin tags: trunk | |
2013-01-10
| ||
16:04 | Fix compilation issue for the .NET Compact Framework version included with Visual Studio 2005. check-in: 03add76ac4 user: mistachkin tags: trunk | |
2013-01-09
| ||
22:14 | Update downloads page for release 1.0.84.0. check-in: 8804f074eb user: mistachkin tags: trunk, release, release-1.0.84.0 | |
Changes to .fossil-settings/ignore-glob.
1 2 | *.mistachkin.eagle Externals/Eagle/bin/Eagle*.pdb | > > > > > | 1 2 3 4 5 6 7 | *.mistachkin.eagle *.sln Externals/Eagle/bin/Eagle*.pdb SQLite.Interop/*.vcxproj SQLite.Interop/*.vcxproj.filters System.Data.SQLite/*.csproj testce/*.csproj |
Changes to Doc/Extra/dbfactorysupport.html.
︙ | ︙ | |||
81 82 83 84 85 86 87 | <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.85.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 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 | <td>If this environment variable is set [to anything], the native library pre-loading functionality will be disabled. By default, the native library pre-loading will attempt to load the native SQLite library from architecture-specific (e.g. "x86", "amd64", "x64") or platform-specific (e.g. "Win32") directories that reside underneath the application base directory.</td> </tr> <tr valign="top"> <td>PreLoadSQLite_BaseDirectory</td> <td>If this environment variable is set [to anything], it will be used instead of the application base directory by the native library pre-loader. This environment variable can be especially useful in ASP.NET and other hosted environments where direct control of the location of the managed assemblies is not under the control of the application.</td> </tr> <tr valign="top"> <td>PreLoadSQLite_ProcessorArchitecture</td> <td>If this environment variable is set [to anything], it will be used instead of the processor architecture value contained in the PROCESSOR_ARCHITECTURE environment variable to help build the path of the native library to pre-load.</td> </tr> <tr valign="top"> <td>PROCESSOR_ARCHITECTURE</td> <td>This environment variable is normally set by the operating system itself and should reflect the native processor architecture of the current process (e.g. a 32-bit x86 application running on a 64-bit x64 operating system should have the value "x86"). </td> | > > > > > > > > > > > > > > > > > | 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 | <td>If this environment variable is set [to anything], the native library pre-loading functionality will be disabled. By default, the native library pre-loading will attempt to load the native SQLite library from architecture-specific (e.g. "x86", "amd64", "x64") or platform-specific (e.g. "Win32") directories that reside underneath the application base directory.</td> </tr> <tr valign="top"> <td>No_SQLiteFunctions</td> <td>If this environment variable is set [to anything], the initial search for types in all loaded assemblies that are tagged with the SQLiteFunction attribute will be skipped. Normally, this search is conducted only once per application domain by the static constructor of the SQLiteFunction class; however, these implementation details are subject to change.</td> </tr> <tr valign="top"> <td>PreLoadSQLite_BaseDirectory</td> <td>If this environment variable is set [to anything], it will be used instead of the application base directory by the native library pre-loader. This environment variable can be especially useful in ASP.NET and other hosted environments where direct control of the location of the managed assemblies is not under the control of the application.</td> </tr> <tr valign="top"> <td>PreLoadSQLite_ProcessorArchitecture</td> <td>If this environment variable is set [to anything], it will be used instead of the processor architecture value contained in the PROCESSOR_ARCHITECTURE environment variable to help build the path of the native library to pre-load.</td> </tr> <tr valign="top"> <td>PreLoadSQLite_UseAssemblyDirectory</td> <td>If this environment variable is set [to anything], the location of the currently executing assembly (i.e. the one containing all the managed components for System.Data.SQLite) will be used as the basis for locating the the native library to pre-load (i.e. instead of using the application domain base directory).</td> </tr> <tr valign="top"> <td>PROCESSOR_ARCHITECTURE</td> <td>This environment variable is normally set by the operating system itself and should reflect the native processor architecture of the current process (e.g. a 32-bit x86 application running on a 64-bit x64 operating system should have the value "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 78 79 80 81 82 83 | </td> </tr> </table> </div> <div id="mainSection"> <div id="mainBody"> <h1 class="heading">Version History</h1> <p><b>1.0.85.0 - March XX, 2013 <font color="red">(release scheduled)</font></b></p> <ul> <li>Updated to <a href="http://www.sqlite.org/src/info/66d5f2b767">SQLite 3.7.16</a>.</li> <li>Properly handle embedded NUL characters in parameter and column values. Fix for <a href="http://system.data.sqlite.org/index.html/info/3567020edf">[3567020edf]</a>.</li> <li>Make use of the sqlite3_prepare_v2 function when applicable.</li> <li>Check for a valid row in the SQLiteDataReader.GetValue method.</li> <li>Implement processor architecture detection when running on the .NET Compact Framework (via P/Invoke).</li> <li>Support automated testing when running on the .NET Compact Framework 2.0.</li> <li>Skip checking loaded assemblies for types tagged with the SQLiteFunction attribute when the No_SQLiteFunctions environment variable is set. Pursuant to <a href="http://system.data.sqlite.org/index.html/info/e4c8121f7b">[e4c8121f7b]</a>.</li> <li>Add HexPassword connection string property to work around the inability to include a literal semicolon in a connection string property value. Pursuant to <a href="http://system.data.sqlite.org/index.html/info/1c456ae75f">[1c456ae75f]</a>.</li> <li>Add static Execute method to the SQLiteCommand class.</li> <li>Support custom connection pool implementations by adding the ISQLiteConnectionPool interface, the static SQLiteConnection.ConnectionPool property, and the static CreateHandle method in addition to modifying the SQLiteConnectionPool class. Pursuant to <a href="http://system.data.sqlite.org/index.html/info/393d954be0">[393d954be0]</a>.</li> <li>Add public constructor to the SQLiteDataAdapter class that allows passing the parseViaFramework parameter to the SQLiteConnection constructor.</li> <li>When built with the CHECK_STATE compile-time option, skip throwing exceptions from the SQLiteDataReader class when the object is being disposed.</li> <li>Support automatic value conversions for columns with a declared type of BIGUINT, INTEGER8, INTEGER16, INTEGER32, INTEGER64, SMALLUINT, TINYSINT, UNSIGNEDINTEGER, UNSIGNEDINTEGER8, UNSIGNEDINTEGER16, UNSIGNEDINTEGER32, UNSIGNEDINTEGER64, INT8, INT16, INT32, INT64, UINT, UINT8, UINT16, UINT32, UINT64, or ULONG.</li> <li>Add BindUInt32AsInt64 connection flag to force binding of UInt32 values as Int64 instead. Pursuant to <a href="http://system.data.sqlite.org/index.html/info/c010fa6584">[c010fa6584]</a>.</li> <li>Add BindAllAsText and GetAllAsText connection flags to force binding and returning of all values as text.</li> <li>Remove AUTOINCREMENT from the column type name map. <b>** Potentially Incompatible Change **</b></li> <li>Avoid throwing overflow exceptions from the SQLite3.GetValue method for integral column types. Partial fix for <a href="http://system.data.sqlite.org/index.html/info/c010fa6584">[c010fa6584]</a>. <b>** Potentially Incompatible Change **</b></li> <li>Use the legacy connection closing algorithm when built with the INTEROP_LEGACY_CLOSE compile-time option.</li> <li>Support using the directory containing the primary managed-only assembly as the basis for native library pre-loading.</li> <li>Still further enhancements to the build and test automation.</li> </ul> <p><b>1.0.84.0 - January 9, 2013</b></p> <ul> <li>Updated to <a href="http://www.sqlite.org/releaselog/3_7_15_2.html">SQLite 3.7.15.2</a>.</li> <li>Explicitly dispose of all SQLiteCommand objects managed by the DbDataAdapter class. Fix for <a href="http://system.data.sqlite.org/index.html/info/6434e23a0f">[6434e23a0f]</a>.</li> <li>Add Cancel method to the SQLiteConnection class to interrupt a long running query.</li> <li>Improve thread safety of the SQLiteLog.LogMessage method.</li> </ul> <p><b>1.0.83.0 - December 29, 2012</b></p> <ul> <li>Updated to <a href="http://www.sqlite.org/releaselog/3_7_15_1.html">SQLite 3.7.15.1</a>.</li> <li>Add Visual Studio 2012 support to all the applicable solution/project files, their associated supporting files, and the test suite.</li> <li>Add Visual Studio 2012 support to the redesigned designer support installer.</li> <li>Allow opened connections to skip adding the extension functions included in the interop assembly via the new NoExtensionFunctions connection flag.</li> <li>Support loading of SQLite extensions via the new EnableExtensions and LoadExtension methods of the SQLiteConnection class. Pursuant to <a href="http://system.data.sqlite.org/index.html/info/17045010df">[17045010df]</a>.</li> <li>Remove one set of surrounding single or double quotes from property names and values parsed from the connection string. Fix for <a href="http://system.data.sqlite.org/index.html/info/b4cc611998">[b4cc611998]</a>.</li> |
︙ | ︙ |
Changes to Doc/Extra/welcome.html.
︙ | ︙ | |||
156 157 158 159 160 161 162 | <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. "085"). 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 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/lib/Eagle1.0/init.eagle.
︙ | ︙ | |||
634 635 636 637 638 639 640 641 642 643 644 645 646 647 | lappend command [info nameofexecutable] } 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 | > > > > > > > > > > > > > > > > > > | 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 | lappend command [info nameofexecutable] } if {[llength $args] > 0} then {eval lappend command $args} return [uplevel 1 $command] } proc lshuffle { list } { # # NOTE: This code for this algorithm was stolen from the Tcl library # struct package and modified to conform with the Eagle style # guide. # set result $list for {set length [llength $result]} \ {$length > 1} {lset result $index $element} { set index [expr {int(rand() * $length)}] set element [lindex $result [incr length -1]] lset result $length [lindex $result $index] } return $result } proc ldifference { list1 list2 } { set result [list] foreach element $list1 { if {[lsearch -exact $list2 $element] == -1} then { lappend result $element |
︙ | ︙ | |||
1837 1838 1839 1840 1841 1842 1843 | exportAndImportPackageCommands [namespace current] [list \ isEagle haveGaruda isMono getEnvironmentVariable combineFlags \ getCompileInfo getPlatformInfo getPluginPath appendArgs lappendArgs \ getDictionaryValue getColumnValue getRowColumnValue tqputs tqlog \ readFile readSharedFile writeFile appendFile appendLogFile \ appendSharedFile appendSharedLogFile readAsciiFile writeAsciiFile \ readUnicodeFile writeUnicodeFile getDirResultPath addToPath \ | | | 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 | exportAndImportPackageCommands [namespace current] [list \ isEagle haveGaruda isMono getEnvironmentVariable combineFlags \ getCompileInfo getPlatformInfo getPluginPath appendArgs lappendArgs \ getDictionaryValue getColumnValue getRowColumnValue tqputs tqlog \ readFile readSharedFile writeFile appendFile appendLogFile \ appendSharedFile appendSharedLogFile readAsciiFile writeAsciiFile \ readUnicodeFile writeUnicodeFile getDirResultPath addToPath \ removeFromPath execShell lshuffle ldifference filter map reduce \ getLengthModifier debug findDirectories findFiles findFilesRecursive \ exportAndImportPackageCommands] false false ########################################################################### ############################## END Tcl ONLY ############################### ########################################################################### } |
︙ | ︙ |
Changes to Externals/Eagle/lib/Eagle1.0/test.eagle.
︙ | ︙ | |||
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 -machine -match -no -notFile -platform -postTest -preTest \ -randomOrder -skip -stopOnFailure -suffix -suite -tclsh -threshold] foreach {name value} $args { # # NOTE: Use the [tqputs] command here just in case the test log file # has not been setup yet (i.e. by default, this procedure is # almost always called by the test prologue file prior to the # test log file having been setup and we do not want to just |
︙ | ︙ | |||
486 487 488 489 490 491 492 | # return [file normalize [file dirname [info nameofexecutable]]] } } proc getFiles { directory pattern } { if {[isEagle]} then { | > > | > > > > > > | | 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 | # return [file normalize [file dirname [info nameofexecutable]]] } } proc getFiles { directory pattern } { if {[isEagle]} then { set result [list] foreach fileName [lsort -dictionary [file list $directory $pattern]] { if {[file isfile $fileName] && [file readable $fileName]} then { lappend result $fileName } } return $result } else { return [lsort -dictionary [glob -directory $directory -types \ {f r} -nocomplain -- $pattern]] } } proc getTestFiles { directories matchFilePatterns skipFilePatterns } { set result [list] foreach directory $directories { |
︙ | ︙ | |||
593 594 595 596 597 598 599 600 601 602 603 604 605 606 | return [expr {[info exists ::test_log_id] ? \ [append result . $::test_log_id] : ""}] } proc getTestLog {} { return [expr {[info exists ::test_log] ? $::test_log : ""}] } proc testExec { commandName options args } { set command [list exec] if {[llength $options] > 0} then {eval lappend command $options} lappend command -- $commandName | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 | return [expr {[info exists ::test_log_id] ? \ [append result . $::test_log_id] : ""}] } proc getTestLog {} { return [expr {[info exists ::test_log] ? $::test_log : ""}] } proc getTestSuite {} { # # NOTE: Determine the effective test suite name and return it. If the # test suite name cannot be determined, return the default based # on whether we are running in Eagle or native Tcl. # if {[info exists ::test_flags(-suite)] && \ [string length $::test_flags(-suite)] > 0} then { # # NOTE: The test suite name has been manually overridden via the test # flags; therefore, use it. # return $::test_flags(-suite) } elseif {[info exists ::test_suite]} then { # # NOTE: Use the test suite name. The default value is set by the test # suite prologue; however, this may have been overridden. # return $::test_suite } elseif {[isEagle]} then { # # NOTE: Use the default test suite name for Eagle. # return "Eagle Test Suite for Eagle" } else { # # NOTE: Use the default test suite name for native Tcl. # return "Eagle Test Suite for Tcl" } } proc getTestMachine {} { # # NOTE: Determine the effective test machine and return it. If the # test machine cannot be determined, return an empty string. # if {[info exists ::test_flags(-machine)] && \ [string length $::test_flags(-machine)] > 0} then { # # NOTE: The test machine has been manually overridden via the test # flags; therefore, use it. # return $::test_flags(-machine) } elseif {[info exists ::test_machine]} then { # # NOTE: Use the test machine. The default value is set by the test # suite prologue; however, this may have been overridden. # return $::test_machine } elseif {[info exists ::tcl_platform(machine)]} then { # # NOTE: Use the build machine of Eagle itself. # return $::tcl_platform(machine) } else { # # NOTE: We are missing the machine, return nothing. # return "" } } proc getTestPlatform { {architecture false} } { # # NOTE: Determine the effective test platform and return it. If the # test platform cannot be determined, return an empty string. # if {[info exists ::test_flags(-platform)] && \ [string length $::test_flags(-platform)] > 0} then { # # NOTE: The test platform has been manually overridden via the test # flags; therefore, use it. # return $::test_flags(-platform) } elseif {[info exists ::test_platform]} then { # # NOTE: Use the test platform. The default value is set by the test # suite prologue; however, this may have been overridden. # return $::test_platform } else { set machine [getTestMachine] if {[string length $machine] > 0} then { # # NOTE: Use the machine architecture to figure out the platform # and then return it. # return [machineToPlatform $machine $architecture] } else { # # NOTE: We are missing the machine and we cannot figure out the # platform without it; therefore, return nothing. # return "" } } } proc getTestConfiguration {} { # # NOTE: Determine the effective test configuration and return it. If # the test configuration cannot be determined, return an empty # string. # if {[info exists ::test_flags(-configuration)] && \ [string length $::test_flags(-configuration)] > 0} then { # # NOTE: The test configuration has been manually overridden via the # test flags; therefore, use it. # return $::test_flags(-configuration) } elseif {[info exists ::test_configuration]} then { # # NOTE: Use the test configuration. The default value is set by the # test suite prologue; however, this may have been overridden. # return $::test_configuration } elseif {[info exists ::eagle_platform(configuration)]} then { # # NOTE: Use the build configuration of Eagle itself. This value will # most likely be either "Debug" or "Release". # return $::eagle_platform(configuration) } else { # # NOTE: We are missing the configuration, return nothing. # return "" } } proc getTestSuffix {} { # # NOTE: Determine the effective test suffix and return it. If # the test suffix cannot be determined, return an empty # string. # if {[info exists ::test_flags(-suffix)] && \ [string length $::test_flags(-suffix)] > 0} then { # # NOTE: The test suffix has been manually overridden via the # test flags; therefore, use it. # return $::test_flags(-suffix) } elseif {[info exists ::test_suffix]} then { # # NOTE: Use the test suffix. There is no default value for # this variable (i.e. by default, it does not exist). # return $::test_suffix } elseif {[info exists ::eagle_platform(text)]} then { # # NOTE: Use the build text of Eagle itself. This value will # typically be "NetFx20" or "NetFx40". # return $::eagle_platform(text) } else { # # NOTE: We are missing the suffix, return nothing. # return "" } } proc testExec { commandName options args } { set command [list exec] if {[llength $options] > 0} then {eval lappend command $options} lappend command -- $commandName |
︙ | ︙ | |||
640 641 642 643 644 645 646 647 648 649 650 651 652 653 | tputs $::test_channel [appendArgs \ "---- 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}] } | > > > > > > | 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 | tputs $::test_channel [appendArgs \ "---- running nested shell: exec " \ [string trim [appendArgs $options " " -- " \"" \ [info nameofexecutable] "\" " $args]] \n] return [uplevel 1 execShell [list $options] $args] } proc isRandomOrder {} { return [expr {[info exists ::test_random_order] && \ [string is boolean -strict $::test_random_order] && \ $::test_random_order}] } proc isStopOnFailure {} { return [expr {[info exists ::test_stop_on_failure] && \ [string is boolean -strict $::test_stop_on_failure] && \ $::test_stop_on_failure}] } |
︙ | ︙ | |||
1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 | 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: " \ | > > > > > > > | 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 | if {[isEagle]} then { host title $status } } proc runAllTests { channel path fileNames skipFileNames } { # # NOTE: Are we configured to run the test files in random order? # if {[isRandomOrder]} then { set fileNames [lshuffle $fileNames] } # # 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: " \ |
︙ | ︙ | |||
1265 1266 1267 1268 1269 1270 1271 | } # # NOTE: We evaluated another test file. # incr count | < < < < < < < < < < < < < > > > > > > > > > > > > > | 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 | } # # NOTE: We evaluated another test file. # incr count # # NOTE: Record failed test count after this file. # if {[isEagle]} then { set after $::eagle_tests(failed) } else { set after $::tcltest::numTests(Failed) } # # NOTE: Did this file have any failing tests? # if {$after > $before} then { lappend failed [file tail $fileName] } # # NOTE: In terms of files, not tests, what percent done are we now? # set percent [formatDecimal \ [expr {$total != 0 ? 100.0 * ($count / double($total)) : 100}]] if {$percent != $lastPercent} then { reportTestPercent $channel $percent \ [llength $failed] [llength $leaked] set lastPercent $percent } # # NOTE: Unset the current test file name, it is no longer # needed. # unset -nocomplain ::test_file |
︙ | ︙ | |||
1772 1773 1774 1775 1776 1777 1778 | proc getTkVersion {} { return [testExecTclScript { puts -nonewline stdout [package require Tk]; exit }] } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 | 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 { # |
︙ | ︙ | |||
2063 2064 2065 2066 2067 2068 2069 | configureTcltest [list] [list test testConstraint] false } # # NOTE: We need several of our test related commands in the global # namespace as well. # | | > > | | | < > > | > > | > | < | 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 | configureTcltest [list] [list test testConstraint] false } # # NOTE: We need several of our test related commands in the global # namespace as well. # exportAndImportPackageCommands [namespace current] [list \ tputs tlog getSoftwareRegistryKey haveConstraint addConstraint \ haveOrAddConstraint getConstraints removeConstraint fixConstraints \ calculateBogoCops calculateRelativePerformance sourceIfValid \ processTestArguments getTclShellFileName getTemporaryPath getFiles \ getTestFiles getTestRunId getTestLogId getTestLog getTestSuite \ getTestMachine getTestPlatform getTestConfiguration getTestSuffix \ testExec testClrExec execTestShell isRandomOrder isStopOnFailure \ isExitOnComplete returnInfoScript runTestPrologue runTestEpilogue \ hookPuts unhookPuts runTest testShim tsource recordTestStatistics \ reportTestStatistics formatList formatListAsDict pathToRegexp \ inverseLsearchGlob removePathFromFileNames formatDecimal \ clearTestPercent reportTestPercent runAllTests configureTcltest \ machineToPlatform getPassPercentage getSkipPercentage] false false ########################################################################### ############################## END Tcl ONLY ############################### ########################################################################### } # # NOTE: Provide the Eagle test package to the interpreter. # package provide Eagle.Test \ [expr {[isEagle] ? [info engine PatchLevel] : "1.0"}] } |
Changes to Externals/Eagle/lib/Eagle1.0/vendor.eagle.
︙ | ︙ | |||
181 182 183 184 185 186 187 | # 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 \ | | > | > > > > > > > | 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 | # NOTE: Check for any overridden settings that may have been specified via # the command line, etc. # checkForTestOverrides stdout [expr {[info exists test_overrides] ? \ $test_overrides : [list binary_directory build_base_directory \ build_directory common_directory connection_flags database_directory \ datetime_format scratch_directory temporary_directory \ test_configuration test_configurations test_constraints \ test_machine test_overrides test_platform test_suite test_year \ test_years test_year_clr_v2 test_year_clr_v4 vendor_directory]}] false # # NOTE: Set the name of the running test suite, if necessary. # if {![info exists test_suite]} then { set test_suite "System.Data.SQLite Test Suite for Eagle" } # # NOTE: This variable will contain the name of the directory containing the # vendor-specific testing infrastructure. If the variable does not # already exist, create it; otherwise, it has been overridden and the # existing value should be left intact. # |
︙ | ︙ |
Changes to Externals/Eagle/lib/Test1.0/constraints.eagle.
︙ | ︙ | |||
16 17 18 19 20 21 22 23 24 25 26 27 28 29 | # # NOTE: Use our own namespace here because even though we do not directly # support namespaces ourselves, we do not want to pollute the global # namespace if this script actually ends up being evaluated in Tcl. # namespace eval ::Eagle { proc checkForPlatform { channel } { tputs $channel "---- checking for platform... " if {[info exists ::tcl_platform(platform)]} then { addConstraint $::tcl_platform(platform) tputs $channel [appendArgs $::tcl_platform(platform) \n] | > > > > > > > > > > > | 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | # # NOTE: Use our own namespace here because even though we do not directly # support namespaces ourselves, we do not want to pollute the global # namespace if this script actually ends up being evaluated in Tcl. # namespace eval ::Eagle { proc getKnownMonoVersions {} { # # NOTE: This job of this procedure is to return the list of "known" # versions of Mono supported by the test suite infrastructure. # return [list \ [list 2 0] [list 2 2] [list 2 4] [list 2 6] [list 2 8] [list 2 10] \ [list 2 11] [list 2 12] [list 3 0] [list 3 1] [list 3 2] [list 3 3] \ [list 3 4] [list 3 5] [list 3 6]] } proc checkForPlatform { channel } { tputs $channel "---- checking for platform... " if {[info exists ::tcl_platform(platform)]} then { addConstraint $::tcl_platform(platform) tputs $channel [appendArgs $::tcl_platform(platform) \n] |
︙ | ︙ | |||
40 41 42 43 44 45 46 | 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. # | > > | | | | | 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 | if {![info exists ::no(runtimeVersion)]} then { set constraints [list monoToDo monoBug monoCrash] # # NOTE: Add the necessary constraints for each version of Mono that # we know about. # foreach monoVersion [getKnownMonoVersions] { set constraintVersion [join $monoVersion ""] addConstraint [appendArgs monoToDo $constraintVersion] addConstraint [appendArgs monoBug $constraintVersion] addConstraint [appendArgs monoCrash $constraintVersion] } # # NOTE: Also add just the generic Mono constraints that do not have # a trailing version. # foreach constraint $constraints { |
︙ | ︙ | |||
592 593 594 595 596 597 598 599 600 601 602 603 604 605 | addConstraint [appendArgs command. $name] tputs $channel yes\n } else { tputs $channel no\n } } proc checkForTestConfiguration { channel } { tputs $channel "---- checking for test configuration... " if {[info exists ::test_configuration] && \ [string length $::test_configuration] > 0} then { addConstraint [appendArgs configuration. $::test_configuration] | > > > > > > > > > > > > > > > > > > > > > > > > > > | 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 | addConstraint [appendArgs command. $name] tputs $channel yes\n } else { tputs $channel no\n } } proc checkForTestMachine { channel } { tputs $channel "---- checking for test machine... " if {[info exists ::test_machine] && \ [string length $::test_machine] > 0} then { addConstraint [appendArgs machine. $::test_machine] tputs $channel [appendArgs $::test_machine \n] } else { tputs $channel unknown\n } } proc checkForTestPlatform { channel } { tputs $channel "---- checking for test platform... " if {[info exists ::test_platform] && \ [string length $::test_platform] > 0} then { addConstraint [appendArgs platform. $::test_platform] tputs $channel [appendArgs $::test_platform \n] } else { tputs $channel unknown\n } } proc checkForTestConfiguration { channel } { tputs $channel "---- checking for test configuration... " if {[info exists ::test_configuration] && \ [string length $::test_configuration] > 0} then { addConstraint [appendArgs configuration. $::test_configuration] |
︙ | ︙ | |||
1199 1200 1201 1202 1203 1204 1205 | addConstraint [appendArgs mda. $name] } # # NOTE: Save the list of managed debugging assistants for # later use by the test suite. # | > | > | 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 | addConstraint [appendArgs mda. $name] } # # NOTE: Save the list of managed debugging assistants for # later use by the test suite. # if {![info exists ::no(setMdas)]} then { set ::test_mdas $names } # # NOTE: Yes, it appears that at least one managed debugging # assistant is enabled. # tputs $channel [appendArgs "yes (" $names ")\n"] |
︙ | ︙ | |||
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 | 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] | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > < | < < < < | | < | | | < | < | < | | | > | < | | | < | | < | < | < | | < < | < | | < < < | < < < | < < | | | | < | | | < < < < < | | | > > < < < < < < < | < < | | < < < | | | | > > > > > | > > | | | | 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 | tputs $channel [appendArgs $::eagle_platform(imageRuntimeVersion) \ " " ( $dotVersion ) \n] } else { tputs $channel no\n } } proc checkForFrameworkVersion { channel } { tputs $channel "---- checking for framework version... " if {[info exists ::eagle_platform(frameworkVersion)] && \ [string length $::eagle_platform(frameworkVersion)] > 0} then { # # NOTE: Get the major and minor portions of the version only. # set dotVersion [join [lrange [split \ $::eagle_platform(frameworkVersion) .] 0 1] .] # # NOTE: Now create a version string for use in the constraint name # (remove the periods). # set version [string map [list . ""] $dotVersion] # # NOTE: If the framework version was found, add a test constraint # for it now. # if {[string length $version] > 0} then { addConstraint [appendArgs framework $version] } tputs $channel [appendArgs $::eagle_platform(frameworkVersion) \ " " ( $dotVersion ) \n] } else { tputs $channel no\n } } proc checkForRuntimeVersion { channel } { tputs $channel "---- checking for runtime version... " if {[info exists ::eagle_platform(runtimeVersion)] && \ [string length $::eagle_platform(runtimeVersion)] > 0} then { # # NOTE: Get the major and minor portions of the version only. # set dotVersion [join [lrange [split \ $::eagle_platform(runtimeVersion) .] 0 1] .] # # NOTE: Now create a version string for use in the constraint name # (remove the periods). # set version [string map [list . ""] $dotVersion] if {[isMono]} then { # # NOTE: If the runtime version was found, add a test constraint # for it now. # if {[string length $version] > 0} then { # # NOTE: We are running on Mono. Keep track of the specific # version for usage in test constraints. # addConstraint [appendArgs mono $version] addConstraint [appendArgs mono $version OrHigher] } # # NOTE: Attempt to parse the version into its major and minor # components. # if {[string length $dotVersion] > 0 && [regexp -- {^(\d+)\.(\d+)$} \ $dotVersion dummy majorVersion minorVersion]} then { # # NOTE: This is the list of Mono versions to add test # constraints for. # set monoVersions [list] # # NOTE: Check each Mono version "known" to the test suite. # foreach monoVersion [getKnownMonoVersions] { # # NOTE: Check for any Mono major version X or higher. # if {$majorVersion >= [lindex $monoVersion 0]} then { # # NOTE: Check for any Mono major/minor version higher # than X.Y. # if {$majorVersion > [lindex $monoVersion 0] || \ $minorVersion > [lindex $monoVersion 1]} then { # # NOTE: Add this "known" version of Mono. # lappend monoVersions $monoVersion } } } # # NOTE: Add the necessary constraints for each version of Mono # we should NOT skip bugs for. # foreach monoVersion $monoVersions { set constraintVersion [join $monoVersion ""] addConstraint [appendArgs mono $constraintVersion OrHigher] addConstraint [appendArgs monoToDo $constraintVersion] addConstraint [appendArgs monoBug $constraintVersion] addConstraint [appendArgs monoCrash $constraintVersion] } } } else { # # NOTE: If the runtime version was found, add a test constraint # for it now. # if {[string length $version] > 0} then { # # NOTE: We are running on the .NET Framework. Keep track of the # specific version for usage in test constraints. # addConstraint [appendArgs dotNet $version] addConstraint [appendArgs dotNet $version OrHigher] } # # NOTE: We do not want to skip any Mono bugs on .NET. Add the # necessary constraints for each version of Mono we know # about. # foreach monoVersion [getKnownMonoVersions] { set constraintVersion [join $monoVersion ""] addConstraint [appendArgs monoToDo $constraintVersion] addConstraint [appendArgs monoBug $constraintVersion] addConstraint [appendArgs monoCrash $constraintVersion] } } tputs $channel [appendArgs $::eagle_platform(runtimeVersion) \ " " ( $dotVersion ) \n] } else { tputs $channel no\n |
︙ | ︙ | |||
2062 2063 2064 2065 2066 2067 2068 | # set key [appendArgs HKEY_LOCAL_MACHINE\\ \ [getSoftwareRegistryKey true] {\Microsoft\Windows Installer XML}] # # NOTE: The versions of WiX that we support. # | | | 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 | # set key [appendArgs HKEY_LOCAL_MACHINE\\ \ [getSoftwareRegistryKey true] {\Microsoft\Windows Installer XML}] # # NOTE: The versions of WiX that we support. # set versions [list 3.7 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 |
︙ | ︙ | |||
2127 2128 2129 2130 2131 2132 2133 | # addConstraint wix # # NOTE: Save the directory for later usage by # the test itself. # | > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 | # addConstraint wix # # NOTE: Save the directory for later usage by # the test itself. # if {![info exists ::no(setWix)]} then { set ::test_wix $directory } # # NOTE: Show where we found it. # tputs $channel [appendArgs "yes (" $version ", via " $where ", \"" \ $directory "\")\n"] # # NOTE: We are done here, return now. # return } } tputs $channel no\n } proc checkForTargetFramework { channel } { tputs $channel "---- checking for target framework... " if {[info exists ::eagle_platform(targetFramework)] && \ [string length $::eagle_platform(targetFramework)] > 0} then { # # NOTE: Now create a string for use in the constraint name (remove # the invalid characters). For example: # # ".NETFramework,Version=v2.0" --> "NETFramework.Version.v2.0" # set targetFramework [string trimleft [string map [list , . = .] \ $::eagle_platform(targetFramework)] .] # # NOTE: Keep track of the specific target framework for usage in test # constraints. # addConstraint [appendArgs targetFramework. $targetFramework] tputs $channel [appendArgs $::eagle_platform(targetFramework) \ " " ( $targetFramework ) \n] } else { tputs $channel no\n } } proc checkForNetFx45 { channel } { tputs $channel "---- checking for .NET Framework 4.5... " # # NOTE: Platform must be Windows for this constraint to even be # checked (i.e. we require the registry). |
︙ | ︙ | |||
2247 2248 2249 2250 2251 2252 2253 | # lappend visualStudioVersions [lindex $version 1] # # NOTE: Save the directory for later usage by # the test itself. # | > | > | 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 | # lappend visualStudioVersions [lindex $version 1] # # NOTE: Save the directory for later usage by # the test itself. # if {![info exists ::no(setVisualStudio)]} then { set ::test_visual_studio [file dirname $fileName] } } } } if {[llength $visualStudioVersions] > 0} then { # # NOTE: Show where we found the latest version. |
︙ | ︙ | |||
2370 2371 2372 2373 2374 2375 2376 | ############################# BEGIN Tcl ONLY ############################## ########################################################################### # # NOTE: We need several of our test constraint related commands in the # global namespace. # | | > > > | | > > | | < | < < | | 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 | ############################# BEGIN Tcl ONLY ############################## ########################################################################### # # NOTE: We need several of our test constraint related commands in the # global namespace. # exportAndImportPackageCommands [namespace current] [list \ getKnownMonoVersions checkForPlatform checkForScriptLibrary \ checkForVariable checkForTclOptions checkForWindowsCommandProcessor \ checkForFossil checkForEagle checkForSymbols checkForLogFile \ checkForGaruda checkForShell checkForDebug checkForTk checkForVersion \ checkForCommand checkForTestMachine checkForTestPlatform \ checkForTestConfiguration checkForTestSuffix checkForFile \ checkForPathFile checkForNativeCode checkForTip127 checkForTip194 \ checkForTip241 checkForTip285 checkForTip405 checkForTiming \ checkForPerformance checkForStackIntensive checkForInteractive \ checkForInteractiveCommand checkForUserInteraction checkForNetwork \ checkForCompileOption] false false ########################################################################### ############################## END Tcl ONLY ############################### ########################################################################### } # # NOTE: Provide the Eagle test constraints package to the interpreter. # package provide Eagle.Test.Constraints \ [expr {[isEagle] ? [info engine PatchLevel] : "1.0"}] } |
Changes to Externals/Eagle/lib/Test1.0/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 189 190 191 192 193 194 195 196 197 | # set passedOrSkipped [expr {$eagle_tests(passed) + \ $eagle_tests(skipped)}] if {$passedOrSkipped == $eagle_tests(total)} then { set exitCode Success if {$eagle_tests(total) > 0} then { tresult Ok "OVERALL RESULT: SUCCESS\n" } else { tresult Ok "OVERALL RESULT: NONE\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 if {$eagle_tests(total) > 0} then { tresult Ok [appendArgs \ "OVERALL RESULT: SUCCESS (" $percent "% >= " $test_threshold %)\n] } else { tresult Ok [appendArgs \ "OVERALL RESULT: NONE (" $percent "% >= " $test_threshold %)\n] } } else { set exitCode Failure tresult Error [appendArgs \ "OVERALL RESULT: FAILURE (" $percent "% < " $test_threshold %)\n] } } |
︙ | ︙ | |||
247 248 249 250 251 252 253 | # set passedOrSkipped [expr {$::tcltest::numTests(Passed) + \ $::tcltest::numTests(Skipped)}] if {$passedOrSkipped == $::tcltest::numTests(Total)} then { set exitCode 0; # Success. | > | > > > > | | > > > > | 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 | # set passedOrSkipped [expr {$::tcltest::numTests(Passed) + \ $::tcltest::numTests(Skipped)}] if {$passedOrSkipped == $::tcltest::numTests(Total)} then { set exitCode 0; # Success. if {$::tcltest::numTests(Total) > 0} then { tputs $test_channel "OVERALL RESULT: SUCCESS\n" } else { tputs $test_channel "OVERALL RESULT: NONE\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. if {$::tcltest::numTests(Total) > 0} then { tputs $test_channel [appendArgs \ "OVERALL RESULT: SUCCESS (" $percent "% >= " $test_threshold %)\n] } else { tputs $test_channel [appendArgs \ "OVERALL RESULT: NONE (" $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.
︙ | ︙ | |||
236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 | } ############################################################################# # # 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. set test_flags(-tclsh) ""; # Tcl shell, default to empty. # | > > > > | 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 | } ############################################################################# # # NOTE: If command line arguments were supplied, process them now. # set test_flags(-suite) ""; # test suite name, default to empty. set test_flags(-machine) ""; # machine architecture, default to empty. set test_flags(-platform) ""; # build platform, default to empty. set test_flags(-configuration) ""; # build configuration, default to empty. set test_flags(-suffix) ""; # build suffix, default to empty. set test_flags(-file) [list *.eagle]; # default to running all test files. set test_flags(-notFile) [list l.*.eagle]; # COMPAT: Tcl. set test_flags(-match) [list *]; # default to running all tests. set test_flags(-skip) [list]; # default to skipping no tests. set test_flags(-constraints) [list]; # default to no manual constraints. 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(-randomOrder) ""; # default to deterministic order. set test_flags(-stopOnFailure) ""; # default to continue on failure. set test_flags(-exitOnComplete) ""; # default to not exit after complete. set test_flags(-preTest) ""; # default to not evaluating anything. set test_flags(-postTest) ""; # default to not evaluating anything. set test_flags(-tclsh) ""; # Tcl shell, default to empty. # |
︙ | ︙ | |||
287 288 289 290 291 292 293 294 295 296 297 298 299 300 | [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. # | > > > > > > > > > | 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 | [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(-randomOrder)] && \ [string is boolean -strict $test_flags(-randomOrder)]} then { # # NOTE: Set the test random-order flag to the one provided by the # command line. # set test_random_order $test_flags(-randomOrder) } 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. # |
︙ | ︙ | |||
322 323 324 325 326 327 328 329 330 331 332 333 334 335 | [string length $test_flags(-postTest)] > 0} then { # # NOTE: Set the pre-test script to the one provided by the command line. # set test_script(post) $test_flags(-postTest) } } # # NOTE: Set the default test configuration (i.e. Debug or Release), if # necessary. # if {![info exists test_configuration]} then { set test_configuration [getPlatformInfo configuration Release] | > > > > > > > > > > > > > > > > > > > > > | 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 | [string length $test_flags(-postTest)] > 0} then { # # NOTE: Set the pre-test script to the one provided by the command line. # set test_script(post) $test_flags(-postTest) } } # # NOTE: Set the default test suite name, if necessary. # if {![info exists test_suite]} then { set test_suite [getTestSuite] } # # NOTE: Set the default test machine (e.g. amd64, intel, etc), if necessary. # if {![info exists test_machine]} then { set test_machine [getTestMachine] } # # NOTE: Set the default test platform (e.g. x86, x64, etc), if necessary. # if {![info exists test_platform]} then { set test_platform [getTestPlatform true] } # # NOTE: Set the default test configuration (i.e. Debug or Release), if # necessary. # if {![info exists test_configuration]} then { set test_configuration [getPlatformInfo configuration Release] |
︙ | ︙ | |||
437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 | # this information will not be visible in the log file. # tputs $test_channel [appendArgs "---- testRunId: " \ [getTestRunId] \n] tputs $test_channel [appendArgs "---- processId: " \ [pid] \n] tputs $test_channel [appendArgs "---- test channel: " \ $test_channel \n] tputs $test_channel [appendArgs "---- test configuration: " \ [expr {[info exists test_configuration] ? \ $test_configuration : "<none>"}] \n] tputs $test_channel [appendArgs "---- test suffix: " \ [expr {[info exists test_suffix] ? \ | > > > > > > > > > > > > | 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 | # this information will not be visible in the log file. # tputs $test_channel [appendArgs "---- testRunId: " \ [getTestRunId] \n] tputs $test_channel [appendArgs "---- processId: " \ [pid] \n] tputs $test_channel [appendArgs "---- test suite: " \ [expr {[info exists test_suite] ? \ $test_suite : "<none>"}] \n] tputs $test_channel [appendArgs "---- test channel: " \ $test_channel \n] tputs $test_channel [appendArgs "---- test machine: " \ [expr {[info exists test_machine] ? \ $test_machine : "<none>"}] \n] tputs $test_channel [appendArgs "---- test platform: " \ [expr {[info exists test_platform] ? \ $test_platform : "<none>"}] \n] tputs $test_channel [appendArgs "---- test configuration: " \ [expr {[info exists test_configuration] ? \ $test_configuration : "<none>"}] \n] tputs $test_channel [appendArgs "---- test suffix: " \ [expr {[info exists test_suffix] ? \ |
︙ | ︙ | |||
541 542 543 544 545 546 547 548 549 550 551 552 553 554 | [expr {[info exists test_log] && [string length $test_log] > 0 ? \ [appendArgs \" $test_log \"] : "<none>"}] \n] tputs $test_channel [appendArgs "---- pass threshold: " \ [expr {[info exists test_threshold] && \ [string is integer -strict $test_threshold] ? \ [appendArgs $test_threshold %] : "<none>"}] \n] tputs $test_channel [appendArgs "---- stop on failure: " \ [expr {[info exists test_stop_on_failure] && \ [string is boolean -strict $test_stop_on_failure] ? \ $test_stop_on_failure : "<none>"}] \n] tputs $test_channel [appendArgs "---- exit on complete: " \ | > > > > > | 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 | [expr {[info exists test_log] && [string length $test_log] > 0 ? \ [appendArgs \" $test_log \"] : "<none>"}] \n] tputs $test_channel [appendArgs "---- pass threshold: " \ [expr {[info exists test_threshold] && \ [string is integer -strict $test_threshold] ? \ [appendArgs $test_threshold %] : "<none>"}] \n] tputs $test_channel [appendArgs "---- random order: " \ [expr {[info exists test_random_order] && \ [string is boolean -strict $test_random_order] ? \ $test_random_order : "<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: " \ |
︙ | ︙ | |||
681 682 683 684 685 686 687 | # checking [nearly] first as it may skip other constraints. # if {![info exists no(runtime)]} then { checkForRuntime $test_channel } # | | | > > > > > > > > | | | 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 | # checking [nearly] first as it may skip other constraints. # if {![info exists no(runtime)]} then { checkForRuntime $test_channel } # # NOTE: Check the variant and/or version of the CLR that we are # currently running on. # if {![info exists no(runtimeVersion)]} then { checkForRuntimeVersion $test_channel } # # NOTE: Check the framework version (i.e. regardless of runtime) that # we are currently running on. # if {![info exists no(frameworkVersion)]} then { checkForFrameworkVersion $test_channel } # # NOTE: Check the image runtime version (i.e. the runtime version that # this assembly compiled against). # if {![info exists no(imageRuntimeVersion)]} then { checkForImageRuntimeVersion $test_channel } # # NOTE: Has machine detection support been disabled? |
︙ | ︙ | |||
1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 | # # NOTE: For test "object-4.1". # checkForObjectMember $test_channel Eagle._Tests.Default \ *TestExpr* # # NOTE: For test "object-7.1". # checkForObjectMember $test_channel Eagle._Tests.Default \ *TestByRefValueTypeMethod* checkForObjectMember $test_channel Eagle._Tests.Default \ | > > > > > > > > > | 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 | # # NOTE: For test "object-4.1". # checkForObjectMember $test_channel Eagle._Tests.Default \ *TestExpr* # # NOTE: For test "array-4.1". # checkForObjectMember $test_channel Eagle._Tests.Default \ *TestTwoByteArrays* checkForObjectMember $test_channel Eagle._Tests.Default \ *TestReturnByteArray* # # NOTE: For test "object-7.1". # checkForObjectMember $test_channel Eagle._Tests.Default \ *TestByRefValueTypeMethod* checkForObjectMember $test_channel Eagle._Tests.Default \ |
︙ | ︙ | |||
1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 | if {![info exists no(netFx45)]} then { # # NOTE: For test "object-12.1.*". # checkForNetFx45 $test_channel } # # NOTE: Has Visual Studio testing support been disabled? # if {![info exists no(visualStudio)]} then { checkForVisualStudio $test_channel } | > > > > > > > | 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 | if {![info exists no(netFx45)]} then { # # NOTE: For test "object-12.1.*". # checkForNetFx45 $test_channel } # # NOTE: Has target framework testing support been disabled? # if {![info exists no(targetFramework)]} then { checkForTargetFramework $test_channel } # # NOTE: Has Visual Studio testing support been disabled? # if {![info exists no(visualStudio)]} then { checkForVisualStudio $test_channel } |
︙ | ︙ | |||
1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 | ############################################################################# ####################### 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 } | > > > > > > > > > > > > > > | 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 | ############################################################################# ####################### BEGIN Tcl & Eagle Constraints ####################### ############################################################################# tputs $test_channel [appendArgs \ "---- start of common (Tcl & Eagle) test constraints...\n"] # # NOTE: Has checking for the test machine been disabled? # if {![info exists no(testMachine)]} then { checkForTestMachine $test_channel } # # NOTE: Has checking for the test platform been disabled? # if {![info exists no(testPlatform)]} then { checkForTestPlatform $test_channel } # # NOTE: Has checking for the test configuration been disabled? # if {![info exists no(testConfiguration)]} then { checkForTestConfiguration $test_channel } |
︙ | ︙ | |||
1854 1855 1856 1857 1858 1859 1860 | 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? # | | < | | | 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 | if {![info exists no(sqlite3.dll)]} then { checkForFile $test_channel [file join $bin_path sqlite3.dll] # # NOTE: Did we manage to find the native SQLite library? If not, do we # at least know the machine type? # if {![haveConstraint file_sqlite3.dll]} then { # # NOTE: Ok, now try to check for the machine specific native SQLite # library. # checkForFile $test_channel [file join $bin_path [machineToPlatform \ $test_machine true] sqlite3.dll] # # NOTE: Did we manage to find the native SQLite library yet? # if {![haveConstraint file_sqlite3.dll]} then { # # NOTE: Ok, now try to check for the platform specific native SQLite # library. # checkForFile $test_channel [file join $bin_path [machineToPlatform \ $test_machine false] sqlite3.dll] } } } if {![info exists no(System.Data.SQLite.dll)]} then { checkForFile $test_channel [file join $bin_path System.Data.SQLite.dll] } |
︙ | ︙ | |||
2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 | [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 ? \ | > > > | 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 | [formatList [getPlatformInfo compileOptions <none>]] \n] tputs $test_channel [appendArgs "---- strongName: " \ [getPlatformInfo strongName <none>] \n] tputs $test_channel [appendArgs "---- certificate: " \ [getPlatformInfo certificate <none>] \n] tputs $test_channel [appendArgs "---- targetFramework: " \ [getPlatformInfo targetFramework <none>] \n] } # # NOTE: Show the current test file name, if any. # tputs $test_channel [appendArgs "---- test file: " \ [expr {[info exists test_file] && [string length $test_file] > 0 ? \ |
︙ | ︙ |
Changes to Membership/Properties/AssemblyInfo.cs.
︙ | ︙ | |||
29 30 31 32 33 34 35 | // 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.85.0")] [assembly: AssemblyFileVersion("1.0.85.0")] |
Changes to SQLite.Beta.nuspec.
1 2 3 4 5 6 7 8 9 10 11 12 13 | <?xml version="1.0" encoding="utf-8"?> <!-- * * SQLite.Beta.nuspec - * * Written by Joe Mistachkin. * Released to the public domain, use at your own risk! * --> <package> <metadata> <id>System.Data.SQLite.Beta</id> <title>System.Data.SQLite (x86/x64) Beta</title> | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | <?xml version="1.0" encoding="utf-8"?> <!-- * * SQLite.Beta.nuspec - * * Written by Joe Mistachkin. * Released to the public domain, use at your own risk! * --> <package> <metadata> <id>System.Data.SQLite.Beta</id> <title>System.Data.SQLite (x86/x64) Beta</title> <version>1.0.85.0</version> <authors>SQLite Development Team</authors> <description>The official SQLite database engine for both x86 and x64 along with the ADO.NET provider.</description> <language>en-US</language> <projectUrl>http://system.data.sqlite.org/</projectUrl> <iconUrl>http://system.data.sqlite.org/images/sqlite32.png</iconUrl> <licenseUrl>http://www.sqlite.org/copyright.html</licenseUrl> <tags>sqlite database ado.net provider interop</tags> |
︙ | ︙ |
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.85.0")] [assembly: AssemblyFileVersion("1.0.85.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.85.0</Version> <Description>ADO.NET Data Designer for SQLite</Description> <Locale>1033</Locale> <InstalledByMsi>false</InstalledByMsi> <SupportedProducts> <VisualStudio Version="10.0"> <Edition>Pro</Edition> </VisualStudio> |
︙ | ︙ |
Changes to SQLite.Interop/props/SQLite.Interop.2005.vsprops.
︙ | ︙ | |||
15 16 17 18 19 20 21 | <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 | <UserMacro Name="ConfigurationYear" Value="2005" PerformEnvironmentSet="true" /> <UserMacro Name="INTEROP_BUILD_NUMBER" Value="085" PerformEnvironmentSet="true" /> <UserMacro Name="INTEROP_LINKER_VERSION" Value="1.0" PerformEnvironmentSet="true" /> <UserMacro Name="INTEROP_MANIFEST_VERSION" Value="1.0.85.0" PerformEnvironmentSet="true" /> <UserMacro Name="INTEROP_RC_VERSION" Value="1,0,85,0" PerformEnvironmentSet="true" /> <UserMacro Name="INTEROP_DEBUG_DEFINES" Value="INTEROP_DEBUG=0x31F;INTEROP_LOG=1;INTEROP_TEST_EXTENSION=1" PerformEnvironmentSet="true" /> |
︙ | ︙ |
Changes to SQLite.Interop/props/SQLite.Interop.2008.vsprops.
︙ | ︙ | |||
15 16 17 18 19 20 21 | <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 | <UserMacro Name="ConfigurationYear" Value="2008" PerformEnvironmentSet="true" /> <UserMacro Name="INTEROP_BUILD_NUMBER" Value="085" PerformEnvironmentSet="true" /> <UserMacro Name="INTEROP_LINKER_VERSION" Value="1.0" PerformEnvironmentSet="true" /> <UserMacro Name="INTEROP_MANIFEST_VERSION" Value="1.0.85.0" PerformEnvironmentSet="true" /> <UserMacro Name="INTEROP_RC_VERSION" Value="1,0,85,0" PerformEnvironmentSet="true" /> <UserMacro Name="INTEROP_DEBUG_DEFINES" Value="INTEROP_DEBUG=0x31F;INTEROP_LOG=1;INTEROP_TEST_EXTENSION=1" PerformEnvironmentSet="true" /> |
︙ | ︙ |
Changes to SQLite.Interop/props/SQLite.Interop.2010.props.
1 2 3 4 5 6 7 8 9 10 11 12 | <?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 | <?xml version="1.0" encoding="utf-8"?> <!-- * * SQLite.Interop.2010.props - * * Written by Joe Mistachkin. * Released to the public domain, use at your own risk! * --> <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0"> <PropertyGroup Label="UserMacros"> <ConfigurationYear>2010</ConfigurationYear> <INTEROP_BUILD_NUMBER>085</INTEROP_BUILD_NUMBER> <INTEROP_LINKER_VERSION>1.0</INTEROP_LINKER_VERSION> <INTEROP_MANIFEST_VERSION>1.0.85.0</INTEROP_MANIFEST_VERSION> <INTEROP_RC_VERSION>1,0,85,0</INTEROP_RC_VERSION> <INTEROP_DEBUG_DEFINES>INTEROP_DEBUG=0x31F;INTEROP_LOG=1;INTEROP_TEST_EXTENSION=1</INTEROP_DEBUG_DEFINES> <INTEROP_EXTRA_DEFINES>INTEROP_EXTENSION_FUNCTIONS=1;INTEROP_CODEC=1</INTEROP_EXTRA_DEFINES> <INTEROP_ASSEMBLY_RESOURCES>/ASSEMBLYRESOURCE:..\System.Data.SQLite\SQLiteCommand.bmp,System.Data.SQLite.SQLiteCommand.bmp /ASSEMBLYRESOURCE:..\System.Data.SQLite\SQLiteConnection.bmp,System.Data.SQLite.SQLiteConnection.bmp /ASSEMBLYRESOURCE:..\System.Data.SQLite\SQLiteDataAdapter.bmp,System.Data.SQLite.SQLiteDataAdapter.bmp</INTEROP_ASSEMBLY_RESOURCES> <INTEROP_KEY_FILE>$(ProjectDir)..\System.Data.SQLite\System.Data.SQLite.snk</INTEROP_KEY_FILE> <INTEROP_NATIVE_NAME>SQLite.Interop</INTEROP_NATIVE_NAME> <INTEROP_MIXED_NAME>System.Data.SQLite</INTEROP_MIXED_NAME> </PropertyGroup> |
︙ | ︙ |
Changes to SQLite.Interop/props/SQLite.Interop.2012.props.
1 2 3 4 5 6 7 8 9 10 11 12 | <?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 | <?xml version="1.0" encoding="utf-8"?> <!-- * * SQLite.Interop.2012.props - * * Written by Joe Mistachkin. * Released to the public domain, use at your own risk! * --> <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0"> <PropertyGroup Label="UserMacros"> <ConfigurationYear>2012</ConfigurationYear> <INTEROP_BUILD_NUMBER>085</INTEROP_BUILD_NUMBER> <INTEROP_LINKER_VERSION>1.0</INTEROP_LINKER_VERSION> <INTEROP_MANIFEST_VERSION>1.0.85.0</INTEROP_MANIFEST_VERSION> <INTEROP_RC_VERSION>1,0,85,0</INTEROP_RC_VERSION> <INTEROP_DEBUG_DEFINES>INTEROP_DEBUG=0x31F;INTEROP_LOG=1;INTEROP_TEST_EXTENSION=1</INTEROP_DEBUG_DEFINES> <INTEROP_EXTRA_DEFINES>INTEROP_EXTENSION_FUNCTIONS=1;INTEROP_CODEC=1</INTEROP_EXTRA_DEFINES> <INTEROP_ASSEMBLY_RESOURCES>/ASSEMBLYRESOURCE:..\System.Data.SQLite\SQLiteCommand.bmp,System.Data.SQLite.SQLiteCommand.bmp /ASSEMBLYRESOURCE:..\System.Data.SQLite\SQLiteConnection.bmp,System.Data.SQLite.SQLiteConnection.bmp /ASSEMBLYRESOURCE:..\System.Data.SQLite\SQLiteDataAdapter.bmp,System.Data.SQLite.SQLiteDataAdapter.bmp</INTEROP_ASSEMBLY_RESOURCES> <INTEROP_KEY_FILE>$(ProjectDir)..\System.Data.SQLite\System.Data.SQLite.snk</INTEROP_KEY_FILE> <INTEROP_NATIVE_NAME>SQLite.Interop</INTEROP_NATIVE_NAME> <INTEROP_MIXED_NAME>System.Data.SQLite</INTEROP_MIXED_NAME> </PropertyGroup> |
︙ | ︙ |
Changes to SQLite.Interop/props/sqlite3.props.
1 2 3 4 5 6 7 8 9 10 11 | <?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.16</SQLITE_MANIFEST_VERSION> <SQLITE_RC_VERSION>3,7,16</SQLITE_RC_VERSION> <SQLITE_COMMON_DEFINES>_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;SQLITE_THREADSAFE=1;SQLITE_USE_URI=1;SQLITE_ENABLE_COLUMN_METADATA=1;SQLITE_ENABLE_STAT3=1;SQLITE_ENABLE_FTS3=1;SQLITE_ENABLE_LOAD_EXTENSION=1;SQLITE_ENABLE_RTREE=1;SQLITE_SOUNDEX=1</SQLITE_COMMON_DEFINES> <SQLITE_EXTRA_DEFINES>SQLITE_HAS_CODEC=1</SQLITE_EXTRA_DEFINES> <SQLITE_WINCE_DEFINES>SQLITE_OMIT_WAL=1</SQLITE_WINCE_DEFINES> <SQLITE_DEBUG_DEFINES>SQLITE_DEBUG=1;SQLITE_MEMDEBUG=1;SQLITE_ENABLE_EXPENSIVE_ASSERT=1</SQLITE_DEBUG_DEFINES> <SQLITE_RELEASE_DEFINES>SQLITE_WIN32_MALLOC=1</SQLITE_RELEASE_DEFINES> <SQLITE_DISABLE_WARNINGS>4055;4100;4127;4146;4210;4232;4244;4245;4267;4306;4389;4701;4703;4706</SQLITE_DISABLE_WARNINGS> <SQLITE_DISABLE_X64_WARNINGS></SQLITE_DISABLE_X64_WARNINGS> |
︙ | ︙ |
Changes to SQLite.Interop/props/sqlite3.vsprops.
︙ | ︙ | |||
10 11 12 13 14 15 16 | <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.16" PerformEnvironmentSet="true" /> <UserMacro Name="SQLITE_RC_VERSION" Value="3,7,16" PerformEnvironmentSet="true" /> <UserMacro Name="SQLITE_COMMON_DEFINES" Value="_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;SQLITE_THREADSAFE=1;SQLITE_USE_URI=1;SQLITE_ENABLE_COLUMN_METADATA=1;SQLITE_ENABLE_STAT3=1;SQLITE_ENABLE_FTS3=1;SQLITE_ENABLE_LOAD_EXTENSION=1;SQLITE_ENABLE_RTREE=1;SQLITE_SOUNDEX=1" PerformEnvironmentSet="true" /> |
︙ | ︙ |
Changes to SQLite.Interop/src/contrib/extension-functions.c.
︙ | ︙ | |||
113 114 115 116 117 118 119 | #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> #if !defined(_WIN32_WCE) || defined(HAVE_ERRNO_H) #include <errno.h> /* LMH 2007-03-25 */ #else int errno; #define strerror(x) "" #endif #include <stdlib.h> |
︙ | ︙ |
Changes to SQLite.Interop/src/core/sqlite3.c.
1 2 | /****************************************************************************** ** 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.16. By combining all the individual C code files into this ** single large file, the entire code can be compiled as a single translation ** unit. This allows many compilers to do optimizations that would not be ** possible if the files were compiled separately. Performance improvements ** of 5% or more are commonly seen when SQLite is compiled as a single ** translation unit. ** ** This file is all you need to compile SQLite. To use SQLite in other |
︙ | ︙ | |||
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 | > > > > | 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 | #endif /* Needed for various definitions... */ #ifndef _GNU_SOURCE # define _GNU_SOURCE #endif #if defined(__OpenBSD__) && !defined(_BSD_SOURCE) # define _BSD_SOURCE #endif /* ** Include standard header files as necessary */ #ifdef HAVE_STDINT_H #include <stdint.h> #endif #ifdef HAVE_INTTYPES_H |
︙ | ︙ | |||
436 437 438 439 440 441 442 | ** 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. */ | | > | 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 | ** 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) |
︙ | ︙ | |||
669 670 671 672 673 674 675 | ** 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()]. */ | | | | | 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 | ** string contains the date and time of the check-in (UTC) and an SHA1 ** hash of the entire source tree. ** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ #define SQLITE_VERSION "3.7.16" #define SQLITE_VERSION_NUMBER 3007016 #define SQLITE_SOURCE_ID "2013-03-18 11:39:23 66d5f2b76750f3520eb7a495f6247206758f5b90" /* ** 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 |
︙ | ︙ | |||
850 851 852 853 854 855 856 | ** 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 | | | 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 | ** 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_v2() 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. |
︙ | ︙ | |||
1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 | #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. | > > > > > > > > > > | 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 | #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_READONLY_ROLLBACK (SQLITE_READONLY | (3<<8)) #define SQLITE_ABORT_ROLLBACK (SQLITE_ABORT | (2<<8)) #define SQLITE_CONSTRAINT_CHECK (SQLITE_CONSTRAINT | (1<<8)) #define SQLITE_CONSTRAINT_COMMITHOOK (SQLITE_CONSTRAINT | (2<<8)) #define SQLITE_CONSTRAINT_FOREIGNKEY (SQLITE_CONSTRAINT | (3<<8)) #define SQLITE_CONSTRAINT_FUNCTION (SQLITE_CONSTRAINT | (4<<8)) #define SQLITE_CONSTRAINT_NOTNULL (SQLITE_CONSTRAINT | (5<<8)) #define SQLITE_CONSTRAINT_PRIMARYKEY (SQLITE_CONSTRAINT | (6<<8)) #define SQLITE_CONSTRAINT_TRIGGER (SQLITE_CONSTRAINT | (7<<8)) #define SQLITE_CONSTRAINT_UNIQUE (SQLITE_CONSTRAINT | (8<<8)) #define SQLITE_CONSTRAINT_VTAB (SQLITE_CONSTRAINT | (9<<8)) /* ** CAPI3REF: Flags For File Open Operations ** ** These bit values are intended for use in the ** 3rd parameter to the [sqlite3_open_v2()] interface and ** in the 4th parameter to the [sqlite3_vfs.xOpen] method. |
︙ | ︙ | |||
8236 8237 8238 8239 8240 8241 8242 8243 8244 8245 8246 8247 8248 8249 | /* ** A convenience macro that returns the number of elements in ** an array. */ #define ArraySize(X) ((int)(sizeof(X)/sizeof(X[0]))) /* ** The following value as a destructor means to use sqlite3DbFree(). ** The sqlite3DbFree() routine requires two parameters instead of the ** one parameter that destructors normally want. So we have to introduce ** this magic value that the code knows to handle differently. Any ** pointer will work here as long as it is distinct from SQLITE_STATIC ** and SQLITE_TRANSIENT. | > > > > > | 8251 8252 8253 8254 8255 8256 8257 8258 8259 8260 8261 8262 8263 8264 8265 8266 8267 8268 8269 | /* ** A convenience macro that returns the number of elements in ** an array. */ #define ArraySize(X) ((int)(sizeof(X)/sizeof(X[0]))) /* ** Determine if the argument is a power of two */ #define IsPowerOfTwo(X) (((X)&((X)-1))==0) /* ** The following value as a destructor means to use sqlite3DbFree(). ** The sqlite3DbFree() routine requires two parameters instead of the ** one parameter that destructors normally want. So we have to introduce ** this magic value that the code knows to handle differently. Any ** pointer will work here as long as it is distinct from SQLITE_STATIC ** and SQLITE_TRANSIENT. |
︙ | ︙ | |||
10011 10012 10013 10014 10015 10016 10017 | /* 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 */ | | | 10031 10032 10033 10034 10035 10036 10037 10038 10039 10040 10041 10042 10043 10044 10045 | /* DELETE, or UPDATE and return */ /* the count using a callback. */ #define SQLITE_NullCallback 0x00000020 /* Invoke the callback once if the */ /* result set is empty */ #define SQLITE_SqlTrace 0x00000040 /* Debug print SQL as it executes */ #define SQLITE_VdbeListing 0x00000080 /* Debug listings of VDBE programs */ #define SQLITE_WriteSchema 0x00000100 /* OK to update SQLITE_MASTER */ #define SQLITE_VdbeAddopTrace 0x00000200 /* Trace sqlite3VdbeAddOp() calls */ #define SQLITE_IgnoreChecks 0x00000400 /* Do not enforce check constraints */ #define SQLITE_ReadUncommitted 0x0000800 /* For shared-cache mode */ #define SQLITE_LegacyFileFmt 0x00001000 /* Create new databases in format 1 */ #define SQLITE_FullFSync 0x00002000 /* Use full fsync on the backend */ #define SQLITE_CkptFullFSync 0x00004000 /* Use full fsync for checkpoint */ #define SQLITE_RecoveryMode 0x00008000 /* Ignore schema errors */ #define SQLITE_ReverseOrder 0x00010000 /* Reverse unordered SELECTs */ |
︙ | ︙ | |||
10040 10041 10042 10043 10044 10045 10046 10047 10048 10049 10050 10051 10052 10053 | #define SQLITE_GroupByOrder 0x0004 /* GROUPBY cover of ORDERBY */ #define SQLITE_FactorOutConst 0x0008 /* Constant factoring */ #define SQLITE_IdxRealAsInt 0x0010 /* Store REAL as INT in indices */ #define SQLITE_DistinctOpt 0x0020 /* DISTINCT using indexes */ #define SQLITE_CoverIdxScan 0x0040 /* Covering index scans */ #define SQLITE_OrderByIdxJoin 0x0080 /* ORDER BY of joins via index */ #define SQLITE_SubqCoroutine 0x0100 /* Evaluate subqueries as coroutines */ #define SQLITE_AllOpts 0xffff /* All optimizations */ /* ** Macros for testing whether or not optimizations are enabled or disabled. */ #ifndef SQLITE_OMIT_BUILTIN_TEST #define OptimizationDisabled(db, mask) (((db)->dbOptFlags&(mask))!=0) | > | 10060 10061 10062 10063 10064 10065 10066 10067 10068 10069 10070 10071 10072 10073 10074 | #define SQLITE_GroupByOrder 0x0004 /* GROUPBY cover of ORDERBY */ #define SQLITE_FactorOutConst 0x0008 /* Constant factoring */ #define SQLITE_IdxRealAsInt 0x0010 /* Store REAL as INT in indices */ #define SQLITE_DistinctOpt 0x0020 /* DISTINCT using indexes */ #define SQLITE_CoverIdxScan 0x0040 /* Covering index scans */ #define SQLITE_OrderByIdxJoin 0x0080 /* ORDER BY of joins via index */ #define SQLITE_SubqCoroutine 0x0100 /* Evaluate subqueries as coroutines */ #define SQLITE_Transitive 0x0200 /* Transitive constraints */ #define SQLITE_AllOpts 0xffff /* All optimizations */ /* ** Macros for testing whether or not optimizations are enabled or disabled. */ #ifndef SQLITE_OMIT_BUILTIN_TEST #define OptimizationDisabled(db, mask) (((db)->dbOptFlags&(mask))!=0) |
︙ | ︙ | |||
10551 10552 10553 10554 10555 10556 10557 | ** 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 { | | | | | | | | | | < | > | | | | 10572 10573 10574 10575 10576 10577 10578 10579 10580 10581 10582 10583 10584 10585 10586 10587 10588 10589 10590 10591 10592 10593 10594 10595 10596 10597 10598 10599 | ** must be unique and what to do if they are not. When Index.onError=OE_None, ** it means this is not a unique index. Otherwise it is a unique index ** and the value of Index.onError indicate the which conflict resolution ** algorithm to employ whenever an attempt is made to insert a non-unique ** element. */ struct Index { char *zName; /* Name of this index */ int *aiColumn; /* Which columns are used by this index. 1st is 0 */ tRowcnt *aiRowEst; /* From ANALYZE: Est. rows selected by each column */ Table *pTable; /* The SQL table being indexed */ char *zColAff; /* String defining the affinity of each column */ Index *pNext; /* The next index associated with the same table */ Schema *pSchema; /* Schema containing this index */ u8 *aSortOrder; /* for each column: True==DESC, False==ASC */ char **azColl; /* Array of collation sequence names for index */ int tnum; /* DB Page containing root of this index */ u16 nColumn; /* Number of columns in table used by this index */ u8 onError; /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */ unsigned autoIndex:2; /* 1==UNIQUE, 2==PRIMARY KEY, 0==CREATE INDEX */ unsigned bUnordered:1; /* Use this index for == or IN queries only */ #ifdef SQLITE_ENABLE_STAT3 int nSample; /* Number of elements in aSample[] */ tRowcnt avgEq; /* Average nEq value for key values not in aSample */ IndexSample *aSample; /* Samples of the left-most key */ #endif }; |
︙ | ︙ | |||
10838 10839 10840 10841 10842 10843 10844 10845 10846 10847 10848 10849 | /* ** 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 */ | > > > > > > > > | | | | | > | | | 10859 10860 10861 10862 10863 10864 10865 10866 10867 10868 10869 10870 10871 10872 10873 10874 10875 10876 10877 10878 10879 10880 10881 10882 10883 10884 10885 10886 10887 10888 10889 10890 10891 10892 10893 | /* ** A list of expressions. Each expression may optionally have a ** name. An expr/name combination can be used in several ways, such ** as the list of "expr AS ID" fields following a "SELECT" or in the ** list of "ID = expr" items in an UPDATE. A list of expressions can ** also be used as the argument to a function, in which case the a.zName ** field is not used. ** ** By default the Expr.zSpan field holds a human-readable description of ** the expression that is used in the generation of error messages and ** column labels. In this case, Expr.zSpan is typically the text of a ** column expression as it exists in a SELECT statement. However, if ** the bSpanIsTab flag is set, then zSpan is overloaded to mean the name ** of the result column in the form: DATABASE.TABLE.COLUMN. This later ** form is used for name resolution with nested FROM clauses. */ struct ExprList { int nExpr; /* Number of expressions on the list */ int iECursor; /* VDBE Cursor associated with this ExprList */ struct ExprList_item { /* For each expression in the list */ Expr *pExpr; /* The list of expressions */ char *zName; /* Token associated with this expression */ char *zSpan; /* Original text of the expression */ u8 sortOrder; /* 1 for DESC or 0 for ASC */ unsigned done :1; /* A flag to indicate when processing is finished */ unsigned bSpanIsTab :1; /* zSpan holds DB.TABLE.COLUMN */ u16 iOrderByCol; /* For ORDER BY, column number in result set */ u16 iAlias; /* Index into Parse.aAlias[] for zName */ } *a; /* Alloc a power of two greater or equal to nExpr */ }; /* ** An instance of this structure is used by the parser to record both ** the parse tree for an expression and the span of input text for an ** expression. |
︙ | ︙ | |||
11017 11018 11019 11020 11021 11022 11023 11024 11025 11026 11027 11028 11029 11030 | int p1, p2; /* Operands of the opcode used to ends the loop */ union { /* Information that depends on plan.wsFlags */ struct { int nIn; /* Number of entries in aInLoop[] */ struct InLoop { int iCur; /* The VDBE cursor used by this IN operator */ int addrInTop; /* Top of the IN loop */ } *aInLoop; /* Information about each nested IN operator */ } in; /* Used when plan.wsFlags&WHERE_IN_ABLE */ Index *pCovidx; /* Possible covering index for WHERE_MULTI_OR */ } u; double rOptCost; /* "Optimal" cost for this level */ /* The following field is really not part of the current level. But | > | 11047 11048 11049 11050 11051 11052 11053 11054 11055 11056 11057 11058 11059 11060 11061 | int p1, p2; /* Operands of the opcode used to ends the loop */ union { /* Information that depends on plan.wsFlags */ struct { int nIn; /* Number of entries in aInLoop[] */ struct InLoop { int iCur; /* The VDBE cursor used by this IN operator */ int addrInTop; /* Top of the IN loop */ u8 eEndLoopOp; /* IN Loop terminator. OP_Next or OP_Prev */ } *aInLoop; /* Information about each nested IN operator */ } in; /* Used when plan.wsFlags&WHERE_IN_ABLE */ Index *pCovidx; /* Possible covering index for WHERE_MULTI_OR */ } u; double rOptCost; /* "Optimal" cost for this level */ /* The following field is really not part of the current level. But |
︙ | ︙ | |||
11169 11170 11171 11172 11173 11174 11175 11176 11177 11178 11179 11180 11181 11182 | #define SF_Aggregate 0x0004 /* Contains aggregate functions */ #define SF_UsesEphemeral 0x0008 /* Uses the OpenEphemeral opcode */ #define SF_Expanded 0x0010 /* sqlite3SelectExpand() called on this */ #define SF_HasTypeInfo 0x0020 /* FROM subqueries have Table metadata */ #define SF_UseSorter 0x0040 /* Sort using a sorter */ #define SF_Values 0x0080 /* Synthesized from VALUES clause */ #define SF_Materialize 0x0100 /* Force materialization of views */ /* ** The results of a select can be distributed in several ways. The ** "SRT" prefix means "SELECT Result Type". */ #define SRT_Union 1 /* Store result as keys in an index */ | > | 11200 11201 11202 11203 11204 11205 11206 11207 11208 11209 11210 11211 11212 11213 11214 | #define SF_Aggregate 0x0004 /* Contains aggregate functions */ #define SF_UsesEphemeral 0x0008 /* Uses the OpenEphemeral opcode */ #define SF_Expanded 0x0010 /* sqlite3SelectExpand() called on this */ #define SF_HasTypeInfo 0x0020 /* FROM subqueries have Table metadata */ #define SF_UseSorter 0x0040 /* Sort using a sorter */ #define SF_Values 0x0080 /* Synthesized from VALUES clause */ #define SF_Materialize 0x0100 /* Force materialization of views */ #define SF_NestedFrom 0x0200 /* Part of a parenthesized FROM clause */ /* ** The results of a select can be distributed in several ways. The ** "SRT" prefix means "SELECT Result Type". */ #define SRT_Union 1 /* Store result as keys in an index */ |
︙ | ︙ | |||
11881 11882 11883 11884 11885 11886 11887 | 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*, | | | | 11913 11914 11915 11916 11917 11918 11919 11920 11921 11922 11923 11924 11925 11926 11927 11928 11929 11930 11931 11932 11933 | SQLITE_PRIVATE void sqlite3IdListDelete(sqlite3*, IdList*); SQLITE_PRIVATE void sqlite3SrcListDelete(sqlite3*, SrcList*); SQLITE_PRIVATE Index *sqlite3CreateIndex(Parse*,Token*,Token*,SrcList*,ExprList*,int,Token*, Token*, int, int); SQLITE_PRIVATE void sqlite3DropIndex(Parse*, SrcList*, int); SQLITE_PRIVATE int sqlite3Select(Parse*, Select*, SelectDest*); SQLITE_PRIVATE Select *sqlite3SelectNew(Parse*,ExprList*,SrcList*,Expr*,ExprList*, Expr*,ExprList*,u16,Expr*,Expr*); SQLITE_PRIVATE void sqlite3SelectDelete(sqlite3*, Select*); SQLITE_PRIVATE Table *sqlite3SrcListLookup(Parse*, SrcList*); SQLITE_PRIVATE int sqlite3IsReadOnly(Parse*, Table*, int); SQLITE_PRIVATE void sqlite3OpenTable(Parse*, int iCur, int iDb, Table*, int); #if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY) SQLITE_PRIVATE Expr *sqlite3LimitWhere(Parse*,SrcList*,Expr*,ExprList*,Expr*,Expr*,char*); #endif 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); |
︙ | ︙ | |||
11955 11956 11957 11958 11959 11960 11961 | 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*); | | | 11987 11988 11989 11990 11991 11992 11993 11994 11995 11996 11997 11998 11999 12000 12001 | SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(Parse*,Table*,int,int, int*,int,int,int,int,int*); SQLITE_PRIVATE void sqlite3CompleteInsertion(Parse*, Table*, int, int, int*, int, int, int); SQLITE_PRIVATE int sqlite3OpenTableAndIndices(Parse*, Table*, int, int); SQLITE_PRIVATE void sqlite3BeginWriteOperation(Parse*, int, int); SQLITE_PRIVATE void sqlite3MultiWrite(Parse*); SQLITE_PRIVATE void sqlite3MayAbort(Parse*); SQLITE_PRIVATE void sqlite3HaltConstraint(Parse*, int, int, char*, int); SQLITE_PRIVATE Expr *sqlite3ExprDup(sqlite3*,Expr*,int); SQLITE_PRIVATE ExprList *sqlite3ExprListDup(sqlite3*,ExprList*,int); SQLITE_PRIVATE SrcList *sqlite3SrcListDup(sqlite3*,SrcList*,int); SQLITE_PRIVATE IdList *sqlite3IdListDup(sqlite3*,IdList*); SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3*,Select*,int); SQLITE_PRIVATE void sqlite3FuncDefInsert(FuncDefHash*, FuncDef*); SQLITE_PRIVATE FuncDef *sqlite3FindFunction(sqlite3*,const char*,int,int,u8,u8); |
︙ | ︙ | |||
12068 12069 12070 12071 12072 12073 12074 | ** x = sqlite3GetVarint32( A, &B ); ** x = sqlite3PutVarint32( A, B ); ** ** x = getVarint32( A, B ); ** x = putVarint32( A, B ); ** */ | | > | > > | 12100 12101 12102 12103 12104 12105 12106 12107 12108 12109 12110 12111 12112 12113 12114 12115 12116 12117 12118 | ** 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); |
︙ | ︙ | |||
12138 12139 12140 12141 12142 12143 12144 12145 12146 12147 12148 12149 12150 12151 | SQLITE_PRIVATE void sqlite3AlterFunctions(void); SQLITE_PRIVATE void sqlite3AlterRenameTable(Parse*, SrcList*, Token*); SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *, int *); SQLITE_PRIVATE void sqlite3NestedParse(Parse*, const char*, ...); SQLITE_PRIVATE void sqlite3ExpirePreparedStatements(sqlite3*); SQLITE_PRIVATE int sqlite3CodeSubselect(Parse *, Expr *, int, int); SQLITE_PRIVATE void sqlite3SelectPrep(Parse*, Select*, NameContext*); SQLITE_PRIVATE int sqlite3ResolveExprNames(NameContext*, Expr*); SQLITE_PRIVATE void sqlite3ResolveSelectNames(Parse*, Select*, NameContext*); SQLITE_PRIVATE int sqlite3ResolveOrderGroupBy(Parse*, Select*, ExprList*, const char*); SQLITE_PRIVATE void sqlite3ColumnDefault(Vdbe *, Table *, int, int); SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *, Token *); SQLITE_PRIVATE void sqlite3AlterBeginAddColumn(Parse *, SrcList *); SQLITE_PRIVATE CollSeq *sqlite3GetCollSeq(Parse*, u8, CollSeq *, const char*); | > | 12173 12174 12175 12176 12177 12178 12179 12180 12181 12182 12183 12184 12185 12186 12187 | SQLITE_PRIVATE void sqlite3AlterFunctions(void); SQLITE_PRIVATE void sqlite3AlterRenameTable(Parse*, SrcList*, Token*); SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *, int *); SQLITE_PRIVATE void sqlite3NestedParse(Parse*, const char*, ...); SQLITE_PRIVATE void sqlite3ExpirePreparedStatements(sqlite3*); SQLITE_PRIVATE int sqlite3CodeSubselect(Parse *, Expr *, int, int); SQLITE_PRIVATE void sqlite3SelectPrep(Parse*, Select*, NameContext*); SQLITE_PRIVATE int sqlite3MatchSpanName(const char*, const char*, const char*, const char*); SQLITE_PRIVATE int sqlite3ResolveExprNames(NameContext*, Expr*); SQLITE_PRIVATE void sqlite3ResolveSelectNames(Parse*, Select*, NameContext*); SQLITE_PRIVATE int sqlite3ResolveOrderGroupBy(Parse*, Select*, ExprList*, const char*); SQLITE_PRIVATE void sqlite3ColumnDefault(Vdbe *, Table *, int, int); SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *, Token *); SQLITE_PRIVATE void sqlite3AlterBeginAddColumn(Parse *, SrcList *); SQLITE_PRIVATE CollSeq *sqlite3GetCollSeq(Parse*, u8, CollSeq *, const char*); |
︙ | ︙ | |||
12276 12277 12278 12279 12280 12281 12282 12283 12284 12285 12286 12287 12288 12289 12290 12291 | #define sqlite3FkCheck(a,b,c,d) #define sqlite3FkDropTable(a,b,c) #define sqlite3FkOldmask(a,b) 0 #define sqlite3FkRequired(a,b,c,d) 0 #endif #ifndef SQLITE_OMIT_FOREIGN_KEY SQLITE_PRIVATE void sqlite3FkDelete(sqlite3 *, Table*); #else #define sqlite3FkDelete(a,b) #endif /* ** Available fault injectors. Should be numbered beginning with 0. */ #define SQLITE_FAULTINJECTOR_MALLOC 0 | > > | 12312 12313 12314 12315 12316 12317 12318 12319 12320 12321 12322 12323 12324 12325 12326 12327 12328 12329 | #define sqlite3FkCheck(a,b,c,d) #define sqlite3FkDropTable(a,b,c) #define sqlite3FkOldmask(a,b) 0 #define sqlite3FkRequired(a,b,c,d) 0 #endif #ifndef SQLITE_OMIT_FOREIGN_KEY SQLITE_PRIVATE void sqlite3FkDelete(sqlite3 *, Table*); SQLITE_PRIVATE int sqlite3FkLocateIndex(Parse*,Table*,FKey*,Index**,int**); #else #define sqlite3FkDelete(a,b) #define sqlite3FkLocateIndex(a,b,c,d,e) #endif /* ** Available fault injectors. Should be numbered beginning with 0. */ #define SQLITE_FAULTINJECTOR_MALLOC 0 |
︙ | ︙ | |||
12302 12303 12304 12305 12306 12307 12308 | #else #define sqlite3BeginBenignMalloc() #define sqlite3EndBenignMalloc() #endif #define IN_INDEX_ROWID 1 #define IN_INDEX_EPH 2 | | > | 12340 12341 12342 12343 12344 12345 12346 12347 12348 12349 12350 12351 12352 12353 12354 12355 | #else #define sqlite3BeginBenignMalloc() #define sqlite3EndBenignMalloc() #endif #define IN_INDEX_ROWID 1 #define IN_INDEX_EPH 2 #define IN_INDEX_INDEX_ASC 3 #define IN_INDEX_INDEX_DESC 4 SQLITE_PRIVATE int sqlite3FindInIndex(Parse *, Expr *, int*); #ifdef SQLITE_ENABLE_ATOMIC_WRITE SQLITE_PRIVATE int sqlite3JournalOpen(sqlite3_vfs *, const char *, sqlite3_file *, int, int); SQLITE_PRIVATE int sqlite3JournalSize(sqlite3_vfs *); SQLITE_PRIVATE int sqlite3JournalCreate(sqlite3_file *); SQLITE_PRIVATE int sqlite3JournalExists(sqlite3_file *p); |
︙ | ︙ | |||
13187 13188 13189 13190 13191 13192 13193 | 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) */ | | | 13226 13227 13228 13229 13230 13231 13232 13233 13234 13235 13236 13237 13238 13239 13240 | VdbeFrame *pParent; /* Parent of this frame, or NULL if parent is main */ Op *aOp; /* Program instructions for parent frame */ Mem *aMem; /* Array of memory cells for parent frame */ u8 *aOnceFlag; /* Array of OP_Once flags for parent frame */ VdbeCursor **apCsr; /* Array of Vdbe cursors for parent frame */ void *token; /* Copy of SubProgram.token */ i64 lastRowid; /* Last insert rowid (sqlite3.lastRowid) */ int nCursor; /* Number of entries in apCsr */ int pc; /* Program Counter in parent (calling) frame */ int nOp; /* Size of aOp array */ int nMem; /* Number of entries in aMem */ int nOnceFlag; /* Number of entries in aOnceFlag */ int nChildMem; /* Number of memory cells for child frame */ int nChildCsr; /* Number of cursors for child frame */ int nChange; /* Statement changes (Vdbe.nChanges) */ |
︙ | ︙ | |||
13373 13374 13375 13376 13377 13378 13379 | 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 */ | | | 13412 13413 13414 13415 13416 13417 13418 13419 13420 13421 13422 13423 13424 13425 13426 | Mem *pResultSet; /* Pointer to an array of results */ int nMem; /* Number of memory locations currently allocated */ int nOp; /* Number of instructions in the program */ int nOpAlloc; /* Number of slots allocated for aOp[] */ int nLabel; /* Number of labels used */ int *aLabel; /* Space to hold the labels */ u16 nResColumn; /* Number of columns in one row of the result set */ int nCursor; /* Number of slots in apCsr[] */ u32 magic; /* Magic number for sanity checking */ char *zErrMsg; /* Error message written here */ Vdbe *pPrev,*pNext; /* Linked list of VDBEs with the same Vdbe.db */ VdbeCursor **apCsr; /* One element of this array for each open cursor */ Mem *aVar; /* Values for the OP_Variable opcode. */ char **azVar; /* Name of variables */ ynVar nVar; /* Number of entries in aVar[] */ |
︙ | ︙ | |||
23284 23285 23286 23287 23288 23289 23290 | { "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) | < < < < | 23323 23324 23325 23326 23327 23328 23329 23330 23331 23332 23333 23334 23335 23336 23337 | { "pwrite64", (sqlite3_syscall_ptr)pwrite64, 0 }, #else { "pwrite64", (sqlite3_syscall_ptr)0, 0 }, #endif #define osPwrite64 ((ssize_t(*)(int,const void*,size_t,off_t))\ aSyscall[13].pCurrent) { "fchmod", (sqlite3_syscall_ptr)fchmod, 0 }, #define osFchmod ((int(*)(int,mode_t))aSyscall[14].pCurrent) #if defined(HAVE_POSIX_FALLOCATE) && HAVE_POSIX_FALLOCATE { "fallocate", (sqlite3_syscall_ptr)posix_fallocate, 0 }, #else { "fallocate", (sqlite3_syscall_ptr)0, 0 }, #endif |
︙ | ︙ | |||
23313 23314 23315 23316 23317 23318 23319 | { "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) | < < < | 23348 23349 23350 23351 23352 23353 23354 23355 23356 23357 23358 23359 23360 23361 | { "rmdir", (sqlite3_syscall_ptr)rmdir, 0 }, #define osRmdir ((int(*)(const char*))aSyscall[19].pCurrent) { "fchown", (sqlite3_syscall_ptr)posixFchown, 0 }, #define osFchown ((int(*)(int,uid_t,gid_t))aSyscall[20].pCurrent) }; /* End of the overrideable system calls */ /* ** This is the xSetSystemCall() method of sqlite3_vfs for all of the ** "unix" VFSes. Return SQLITE_OK opon successfully updating the ** system call pointer, or SQLITE_NOTFOUND if there is no configurable ** system call named zName. |
︙ | ︙ | |||
23420 23421 23422 23423 23424 23425 23426 | ** 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; | < < < | < < < < > | > > > > > | | > | > | 23452 23453 23454 23455 23456 23457 23458 23459 23460 23461 23462 23463 23464 23465 23466 23467 23468 23469 23470 23471 23472 23473 23474 23475 23476 23477 23478 23479 23480 23481 23482 23483 23484 23485 23486 23487 | ** In that way, if a database file is -rw-rw-rw or -rw-rw-r-, and a ** transaction crashes and leaves behind hot journals, then any ** process that is able to write to the database will also be able to ** recover the hot journals. */ static int robust_open(const char *z, int f, mode_t m){ int fd; mode_t m2 = m ? m : SQLITE_DEFAULT_FILE_PERMISSIONS; do{ #if defined(O_CLOEXEC) fd = osOpen(z,f|O_CLOEXEC,m2); #else fd = osOpen(z,f,m2); #endif }while( fd<0 && errno==EINTR ); if( fd>=0 ){ if( m!=0 ){ struct stat statbuf; if( osFstat(fd, &statbuf)==0 && statbuf.st_size==0 && (statbuf.st_mode&0777)!=m ){ osFchmod(fd, m); } } #if defined(FD_CLOEXEC) && (!defined(O_CLOEXEC) || O_CLOEXEC==0) osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC); #endif } return fd; } /* ** Helper functions to obtain and relinquish the global mutex. The ** global mutex is used to protect the unixInodeInfo and ** vxworksFileId objects used by this file, all of which may be |
︙ | ︙ | |||
27633 27634 27635 27636 27637 27638 27639 | 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; } | | | 27666 27667 27668 27669 27670 27671 27672 27673 27674 27675 27676 27677 27678 27679 27680 | 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( strcmp(pVfs->zName,"unix-excl")==0 ){ pNew->ctrlFlags |= UNIXFILE_EXCL; } #if OS_VXWORKS pNew->pId = vxworksFindFileId(zFilename); if( pNew->pId==0 ){ ctrlFlags |= UNIXFILE_NOLOCK; |
︙ | ︙ | |||
29866 29867 29868 29869 29870 29871 29872 | UNIXVFS("unix-proxy", proxyIoFinder ), #endif }; unsigned int i; /* Loop counter */ /* Double-check that the aSyscall[] array has been constructed ** correctly. See ticket [bb3a86e890c8e96ab] */ | | | 29899 29900 29901 29902 29903 29904 29905 29906 29907 29908 29909 29910 29911 29912 29913 | UNIXVFS("unix-proxy", proxyIoFinder ), #endif }; unsigned int i; /* Loop counter */ /* Double-check that the aSyscall[] array has been constructed ** correctly. See ticket [bb3a86e890c8e96ab] */ assert( ArraySize(aSyscall)==21 ); /* Register all VFSes defined in the aVfs[] array */ for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){ sqlite3_vfs_register(&aVfs[i], i==0); } return SQLITE_OK; } |
︙ | ︙ | |||
31087 31088 31089 31090 31091 31092 31093 | } /* ** This function outputs the specified (ANSI) string to the Win32 debugger ** (if available). */ | | | 31120 31121 31122 31123 31124 31125 31126 31127 31128 31129 31130 31131 31132 31133 31134 | } /* ** This function outputs the specified (ANSI) string to the Win32 debugger ** (if available). */ SQLITE_API void sqlite3_win32_write_debug(const char *zBuf, int nBuf){ char zDbgBuf[SQLITE_WIN32_DBG_BUF_SIZE]; int nMin = MIN(nBuf, (SQLITE_WIN32_DBG_BUF_SIZE - 1)); /* may be negative. */ if( nMin<-1 ) nMin = -1; /* all negative values become -1. */ assert( nMin==-1 || nMin==0 || nMin<SQLITE_WIN32_DBG_BUF_SIZE ); #if defined(SQLITE_WIN32_HAS_ANSI) if( nMin>0 ){ memset(zDbgBuf, 0, SQLITE_WIN32_DBG_BUF_SIZE); |
︙ | ︙ | |||
31720 31721 31722 31723 31724 31725 31726 31727 | } } #if SQLITE_OS_WINCE /************************************************************************* ** This section contains code for WinCE only. */ /* | > | | | 31753 31754 31755 31756 31757 31758 31759 31760 31761 31762 31763 31764 31765 31766 31767 31768 31769 31770 | } } #if SQLITE_OS_WINCE /************************************************************************* ** This section contains code for WinCE only. */ #if !defined(SQLITE_MSVC_LOCALTIME_API) || !SQLITE_MSVC_LOCALTIME_API /* ** The MSVC CRT on Windows CE may not have a localtime() function. So ** create a substitute. */ /* #include <time.h> */ struct tm *__cdecl localtime(const time_t *t) { static struct tm y; FILETIME uTm, lTm; SYSTEMTIME pTm; |
︙ | ︙ | |||
31746 31747 31748 31749 31750 31751 31752 31753 31754 31755 31756 31757 31758 31759 | y.tm_wday = pTm.wDayOfWeek; y.tm_mday = pTm.wDay; y.tm_hour = pTm.wHour; y.tm_min = pTm.wMinute; y.tm_sec = pTm.wSecond; return &y; } #define HANDLE_TO_WINFILE(a) (winFile*)&((char*)a)[-(int)offsetof(winFile,h)] /* ** Acquire a lock on the handle h */ static void winceMutexAcquire(HANDLE h){ | > | 31780 31781 31782 31783 31784 31785 31786 31787 31788 31789 31790 31791 31792 31793 31794 | y.tm_wday = pTm.wDayOfWeek; y.tm_mday = pTm.wDay; y.tm_hour = pTm.wHour; y.tm_min = pTm.wMinute; y.tm_sec = pTm.wSecond; return &y; } #endif #define HANDLE_TO_WINFILE(a) (winFile*)&((char*)a)[-(int)offsetof(winFile,h)] /* ** Acquire a lock on the handle h */ static void winceMutexAcquire(HANDLE h){ |
︙ | ︙ | |||
31767 31768 31769 31770 31771 31772 31773 | */ #define winceMutexRelease(h) ReleaseMutex(h) /* ** Create the mutex and shared memory used for locking in the file ** descriptor pFile */ | | > > | > | | > | | | | | > | > > > > > > | | | | 31802 31803 31804 31805 31806 31807 31808 31809 31810 31811 31812 31813 31814 31815 31816 31817 31818 31819 31820 31821 31822 31823 31824 31825 31826 31827 31828 31829 31830 31831 31832 31833 31834 31835 31836 31837 31838 31839 31840 31841 31842 31843 31844 31845 31846 31847 31848 31849 31850 31851 31852 31853 31854 31855 31856 31857 31858 31859 31860 31861 31862 31863 31864 31865 31866 31867 31868 31869 31870 31871 31872 31873 31874 31875 31876 31877 31878 31879 31880 31881 31882 31883 31884 31885 31886 31887 31888 31889 31890 31891 31892 31893 31894 31895 31896 31897 31898 31899 31900 31901 31902 31903 31904 31905 | */ #define winceMutexRelease(h) ReleaseMutex(h) /* ** Create the mutex and shared memory used for locking in the file ** descriptor pFile */ static int winceCreateLock(const char *zFilename, winFile *pFile){ LPWSTR zTok; LPWSTR zName; DWORD lastErrno; BOOL bLogged = FALSE; BOOL bInit = TRUE; zName = utf8ToUnicode(zFilename); if( zName==0 ){ /* out of memory */ return SQLITE_IOERR_NOMEM; } /* Initialize the local lockdata */ memset(&pFile->local, 0, sizeof(pFile->local)); /* Replace the backslashes from the filename and lowercase it ** to derive a mutex name. */ zTok = osCharLowerW(zName); for (;*zTok;zTok++){ if (*zTok == '\\') *zTok = '_'; } /* Create/open the named mutex */ pFile->hMutex = osCreateMutexW(NULL, FALSE, zName); if (!pFile->hMutex){ pFile->lastErrno = osGetLastError(); winLogError(SQLITE_IOERR, pFile->lastErrno, "winceCreateLock1", zFilename); sqlite3_free(zName); return SQLITE_IOERR; } /* Acquire the mutex before continuing */ winceMutexAcquire(pFile->hMutex); /* Since the names of named mutexes, semaphores, file mappings etc are ** case-sensitive, take advantage of that by uppercasing the mutex name ** and using that as the shared filemapping name. */ osCharUpperW(zName); pFile->hShared = osCreateFileMappingW(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof(winceLock), zName); /* Set a flag that indicates we're the first to create the memory so it ** must be zero-initialized */ lastErrno = osGetLastError(); if (lastErrno == ERROR_ALREADY_EXISTS){ bInit = FALSE; } sqlite3_free(zName); /* If we succeeded in making the shared memory handle, map it. */ if( pFile->hShared ){ pFile->shared = (winceLock*)osMapViewOfFile(pFile->hShared, FILE_MAP_READ|FILE_MAP_WRITE, 0, 0, sizeof(winceLock)); /* If mapping failed, close the shared memory handle and erase it */ if( !pFile->shared ){ pFile->lastErrno = osGetLastError(); winLogError(SQLITE_IOERR, pFile->lastErrno, "winceCreateLock2", zFilename); bLogged = TRUE; osCloseHandle(pFile->hShared); pFile->hShared = NULL; } } /* If shared memory could not be created, then close the mutex and fail */ if( pFile->hShared==NULL ){ if( !bLogged ){ pFile->lastErrno = lastErrno; winLogError(SQLITE_IOERR, pFile->lastErrno, "winceCreateLock3", zFilename); bLogged = TRUE; } winceMutexRelease(pFile->hMutex); osCloseHandle(pFile->hMutex); pFile->hMutex = NULL; return SQLITE_IOERR; } /* Initialize the shared memory if we're supposed to */ if( bInit ){ memset(pFile->shared, 0, sizeof(winceLock)); } winceMutexRelease(pFile->hMutex); return SQLITE_OK; } /* ** Destroy the part of winFile that deals with wince locks */ static void winceDestroyLock(winFile *pFile){ if (pFile->hMutex){ |
︙ | ︙ | |||
31924 31925 31926 31927 31928 31929 31930 | pFile->shared->nReaders ++; } bReturn = TRUE; } } /* Want a pending lock? */ | | > | > | 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 | 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; } } |
︙ | ︙ | |||
31977 31978 31979 31980 31981 31982 31983 | pFile->local.bExclusive = FALSE; pFile->shared->bExclusive = FALSE; bReturn = TRUE; } /* Did we just have a reader lock? */ else if (pFile->local.nReaders){ | | > | > | > | 32025 32026 32027 32028 32029 32030 32031 32032 32033 32034 32035 32036 32037 32038 32039 32040 32041 32042 32043 32044 32045 32046 32047 32048 32049 32050 32051 32052 32053 32054 32055 32056 32057 32058 32059 32060 32061 | 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; } } |
︙ | ︙ | |||
32162 32163 32164 32165 32166 32167 32168 32169 32170 32171 32172 32173 32174 32175 | winFile *pFile = (winFile*)id; assert( id!=0 ); #ifndef SQLITE_OMIT_WAL assert( pFile->pShm==0 ); #endif OSTRACE(("CLOSE %d\n", pFile->h)); do{ rc = osCloseHandle(pFile->h); /* SimulateIOError( rc=0; cnt=MX_CLOSE_ATTEMPT; ); */ }while( rc==0 && ++cnt < MX_CLOSE_ATTEMPT && (sqlite3_win32_sleep(100), 1) ); #if SQLITE_OS_WINCE #define WINCE_DELETION_ATTEMPTS 3 winceDestroyLock(pFile); | > | 32213 32214 32215 32216 32217 32218 32219 32220 32221 32222 32223 32224 32225 32226 32227 | winFile *pFile = (winFile*)id; assert( id!=0 ); #ifndef SQLITE_OMIT_WAL assert( pFile->pShm==0 ); #endif OSTRACE(("CLOSE %d\n", pFile->h)); assert( pFile->h!=NULL && pFile->h!=INVALID_HANDLE_VALUE ); do{ rc = osCloseHandle(pFile->h); /* SimulateIOError( rc=0; cnt=MX_CLOSE_ATTEMPT; ); */ }while( rc==0 && ++cnt < MX_CLOSE_ATTEMPT && (sqlite3_win32_sleep(100), 1) ); #if SQLITE_OS_WINCE #define WINCE_DELETION_ATTEMPTS 3 winceDestroyLock(pFile); |
︙ | ︙ | |||
32854 32855 32856 32857 32858 32859 32860 | win32IoerrRetryDelay = a[1]; }else{ a[1] = win32IoerrRetryDelay; } return SQLITE_OK; } case SQLITE_FCNTL_TEMPFILENAME: { | | | 32906 32907 32908 32909 32910 32911 32912 32913 32914 32915 32916 32917 32918 32919 32920 | win32IoerrRetryDelay = a[1]; }else{ a[1] = win32IoerrRetryDelay; } return SQLITE_OK; } case SQLITE_FCNTL_TEMPFILENAME: { char *zTFile = sqlite3MallocZero( pFile->pVfs->mxPathname ); if( zTFile ){ getTempname(pFile->pVfs->mxPathname, zTFile); *(char**)pArg = zTFile; } return SQLITE_OK; } } |
︙ | ︙ | |||
33078 33079 33080 33081 33082 33083 33084 | (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")); } | | | 33130 33131 33132 33133 33134 33135 33136 33137 33138 33139 33140 33141 33142 33143 33144 | (int)osGetCurrentProcessId(), i, bRc ? "ok" : "failed")); bRc = osCloseHandle(p->aRegion[i].hMap); OSTRACE(("SHM-PURGE pid-%d close region=%d %s\n", (int)osGetCurrentProcessId(), i, bRc ? "ok" : "failed")); } if( p->hFile.h!=NULL && p->hFile.h!=INVALID_HANDLE_VALUE ){ SimulateIOErrorBenign(1); winClose((sqlite3_file *)&p->hFile); SimulateIOErrorBenign(0); } if( deleteFlag ){ SimulateIOErrorBenign(1); sqlite3BeginBenignMalloc(); |
︙ | ︙ | |||
33158 33159 33160 33161 33162 33163 33164 | 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 */ | | | 33210 33211 33212 33213 33214 33215 33216 33217 33218 33219 33220 33221 33222 33223 33224 | 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, 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. |
︙ | ︙ | |||
33773 33774 33775 33776 33777 33778 33779 | /* 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 ); | | | > < < > | 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 33852 33853 33854 33855 | /* Assert that the upper layer has set one of the "file-type" flags. */ assert( eType==SQLITE_OPEN_MAIN_DB || eType==SQLITE_OPEN_TEMP_DB || eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_TEMP_JOURNAL || eType==SQLITE_OPEN_SUBJOURNAL || eType==SQLITE_OPEN_MASTER_JOURNAL || eType==SQLITE_OPEN_TRANSIENT_DB || eType==SQLITE_OPEN_WAL ); assert( pFile!=0 ); memset(pFile, 0, sizeof(winFile)); pFile->h = INVALID_HANDLE_VALUE; #if SQLITE_OS_WINRT if( !sqlite3_temp_directory ){ sqlite3_log(SQLITE_ERROR, "sqlite3_temp_directory variable should be set for WinRT"); } #endif /* If the second argument to this function is NULL, generate a ** temporary file name to use */ if( !zUtf8Name ){ assert(isDelete && !isOpenJournal); memset(zTmpname, 0, MAX_PATH+2); rc = getTempname(MAX_PATH+2, zTmpname); if( rc!=SQLITE_OK ){ return rc; } zUtf8Name = zTmpname; } |
︙ | ︙ | |||
33912 33913 33914 33915 33916 33917 33918 | 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, | | > > < < < < < < < < < < < < < | | > > > > > > > > > | 33964 33965 33966 33967 33968 33969 33970 33971 33972 33973 33974 33975 33976 33977 33978 33979 33980 33981 33982 33983 33984 33985 33986 33987 33988 33989 33990 33991 33992 33993 33994 33995 33996 33997 33998 33999 34000 34001 34002 34003 34004 34005 34006 34007 34008 34009 34010 34011 34012 34013 34014 34015 34016 34017 | 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; } } #if SQLITE_OS_WINCE if( isReadWrite && eType==SQLITE_OPEN_MAIN_DB && (rc = winceCreateLock(zName, pFile))!=SQLITE_OK ){ osCloseHandle(h); sqlite3_free(zConverted); return rc; } if( isTemp ){ pFile->zDeleteOnClose = zConverted; }else #endif { sqlite3_free(zConverted); } pFile->pMethod = &winIoMethod; pFile->pVfs = pVfs; pFile->h = h; if( sqlite3_uri_boolean(zName, "psow", SQLITE_POWERSAFE_OVERWRITE) ){ pFile->ctrlFlags |= WINFILE_PSOW; } pFile->lastErrno = NO_ERROR; pFile->zPath = zName; OpenCounter(+1); return rc; } /* ** Delete the named file. |
︙ | ︙ | |||
33999 34000 34001 34002 34003 34004 34005 | WIN32_FILE_ATTRIBUTE_DATA sAttrData; memset(&sAttrData, 0, sizeof(sAttrData)); if ( osGetFileAttributesExW(zConverted, GetFileExInfoStandard, &sAttrData) ){ attr = sAttrData.dwFileAttributes; }else{ lastErrno = osGetLastError(); | | > | > | 34049 34050 34051 34052 34053 34054 34055 34056 34057 34058 34059 34060 34061 34062 34063 34064 34065 34066 34067 34068 34069 34070 34071 34072 34073 34074 34075 34076 34077 | WIN32_FILE_ATTRIBUTE_DATA sAttrData; memset(&sAttrData, 0, sizeof(sAttrData)); if ( osGetFileAttributesExW(zConverted, GetFileExInfoStandard, &sAttrData) ){ attr = sAttrData.dwFileAttributes; }else{ lastErrno = osGetLastError(); if( lastErrno==ERROR_FILE_NOT_FOUND || lastErrno==ERROR_PATH_NOT_FOUND ){ rc = SQLITE_IOERR_DELETE_NOENT; /* Already gone? */ }else{ rc = SQLITE_ERROR; } break; } #else attr = osGetFileAttributesW(zConverted); #endif if ( attr==INVALID_FILE_ATTRIBUTES ){ lastErrno = osGetLastError(); if( lastErrno==ERROR_FILE_NOT_FOUND || lastErrno==ERROR_PATH_NOT_FOUND ){ rc = SQLITE_IOERR_DELETE_NOENT; /* Already gone? */ }else{ rc = SQLITE_ERROR; } break; } if ( attr&FILE_ATTRIBUTE_DIRECTORY ){ |
︙ | ︙ | |||
34038 34039 34040 34041 34042 34043 34044 | } #ifdef SQLITE_WIN32_HAS_ANSI else{ do { attr = osGetFileAttributesA(zConverted); if ( attr==INVALID_FILE_ATTRIBUTES ){ lastErrno = osGetLastError(); | | > | 34090 34091 34092 34093 34094 34095 34096 34097 34098 34099 34100 34101 34102 34103 34104 34105 | } #ifdef SQLITE_WIN32_HAS_ANSI else{ do { attr = osGetFileAttributesA(zConverted); if ( attr==INVALID_FILE_ATTRIBUTES ){ lastErrno = osGetLastError(); if( lastErrno==ERROR_FILE_NOT_FOUND || lastErrno==ERROR_PATH_NOT_FOUND ){ rc = SQLITE_IOERR_DELETE_NOENT; /* Already gone? */ }else{ rc = SQLITE_ERROR; } break; } if ( attr&FILE_ATTRIBUTE_DIRECTORY ){ |
︙ | ︙ | |||
34206 34207 34208 34209 34210 34211 34212 | ** 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); | | > < < < < < | | 34259 34260 34261 34262 34263 34264 34265 34266 34267 34268 34269 34270 34271 34272 34273 34274 34275 34276 34277 34278 | ** 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_path(CCP_POSIX_TO_WIN_A|CCP_RELATIVE, zRelative, zOut, MAX_PATH+1); sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s\\%s", sqlite3_data_directory, zOut); }else{ cygwin_conv_path(CCP_POSIX_TO_WIN_A, zRelative, zFull, nFull); } 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. */ |
︙ | ︙ | |||
34373 34374 34375 34376 34377 34378 34379 | sqlite3_free(zConverted); return (void*)h; } static void winDlError(sqlite3_vfs *pVfs, int nBuf, char *zBufOut){ UNUSED_PARAMETER(pVfs); getLastErrorMsg(osGetLastError(), nBuf, zBufOut); } | | | | 34422 34423 34424 34425 34426 34427 34428 34429 34430 34431 34432 34433 34434 34435 34436 34437 34438 | 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 *pH,const char *zSym))(void){ UNUSED_PARAMETER(pVfs); return (void(*)(void))osGetProcAddressA((HANDLE)pH, zSym); } 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 |
︙ | ︙ | |||
34473 34474 34475 34476 34477 34478 34479 | 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 = | | > | 34522 34523 34524 34525 34526 34527 34528 34529 34530 34531 34532 34533 34534 34535 34536 34537 | 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; |
︙ | ︙ | |||
39151 39152 39153 39154 39155 39156 39157 39158 39159 39160 39161 39162 39163 39164 | 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. ** | > > | 39201 39202 39203 39204 39205 39206 39207 39208 39209 39210 39211 39212 39213 39214 39215 39216 | if( rc2==SQLITE_FULL || rc2==SQLITE_IOERR ){ pPager->errCode = rc; pPager->eState = PAGER_ERROR; } return rc; } static int pager_truncate(Pager *pPager, Pgno nPage); /* ** 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. ** |
︙ | ︙ | |||
39204 39205 39206 39207 39208 39209 39210 | ** 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. */ | | | 39256 39257 39258 39259 39260 39261 39262 39263 39264 39265 39266 39267 39268 39269 39270 | ** 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 bCommit){ 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: |
︙ | ︙ | |||
39290 39291 39292 39293 39294 39295 39296 39297 39298 39299 39300 39301 39302 39303 39304 | 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; | > > > > > > > > > > | 39342 39343 39344 39345 39346 39347 39348 39349 39350 39351 39352 39353 39354 39355 39356 39357 39358 39359 39360 39361 39362 39363 39364 39365 39366 | 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 ); }else if( rc==SQLITE_OK && bCommit && pPager->dbFileSize>pPager->dbSize ){ /* This branch is taken when committing a transaction in rollback-journal ** mode if the database file on disk is larger than the database image. ** At this point the journal has been finalized and the transaction ** successfully committed, but the EXCLUSIVE lock is still held on the ** file. So it is safe to truncate the database file to its minimum ** required size. */ assert( pPager->eLock==EXCLUSIVE_LOCK ); rc = pager_truncate(pPager, pPager->dbSize); } if( !pPager->exclusiveMode && (!pagerUseWal(pPager) || sqlite3WalExclusiveMode(pPager->pWal, 0)) ){ rc2 = pagerUnlockDb(pPager, SHARED_LOCK); pPager->changeCountDone = 0; } pPager->eState = PAGER_READER; |
︙ | ︙ | |||
39329 39330 39331 39332 39333 39334 39335 | assert( assert_pager_state(pPager) ); if( pPager->eState>=PAGER_WRITER_LOCKED ){ sqlite3BeginBenignMalloc(); sqlite3PagerRollback(pPager); sqlite3EndBenignMalloc(); }else if( !pPager->exclusiveMode ){ assert( pPager->eState==PAGER_READER ); | | | 39391 39392 39393 39394 39395 39396 39397 39398 39399 39400 39401 39402 39403 39404 39405 | 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, 0); } } pager_unlock(pPager); } /* ** Parameter aData must point to a buffer of pPager->pageSize bytes |
︙ | ︙ | |||
40104 40105 40106 40107 40108 40109 40110 | } if( rc==SQLITE_OK && (pPager->eState>=PAGER_WRITER_DBMOD || pPager->eState==PAGER_OPEN) ){ rc = sqlite3PagerSync(pPager); } if( rc==SQLITE_OK ){ | | | 40166 40167 40168 40169 40170 40171 40172 40173 40174 40175 40176 40177 40178 40179 40180 | } 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', 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); |
︙ | ︙ | |||
41056 41057 41058 41059 41060 41061 41062 41063 41064 41065 41066 41067 | #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; | > > > > > > | > > > > > > > > | 41118 41119 41120 41121 41122 41123 41124 41125 41126 41127 41128 41129 41130 41131 41132 41133 41134 41135 41136 41137 41138 41139 41140 41141 41142 41143 41144 41145 41146 41147 41148 41149 41150 41151 | #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. ** ** This function is only called right before committing a transaction. ** Once this function has been called, the transaction must either be ** rolled back or committed. It is not safe to call this function and ** then continue writing to the database. */ SQLITE_PRIVATE void sqlite3PagerTruncateImage(Pager *pPager, Pgno nPage){ assert( pPager->dbSize>=nPage ); assert( pPager->eState>=PAGER_WRITER_CACHEMOD ); pPager->dbSize = nPage; /* At one point the code here called assertTruncateConstraint() to ** ensure that all pages being truncated away by this operation are, ** if one or more savepoints are open, present in the savepoint ** journal so that they can be restored if the savepoint is rolled ** back. This is no longer necessary as this function is now only ** called right before committing a transaction. So although the ** Pager object may still have open savepoints (Pager.nSavepoint!=0), ** they cannot be rolled back. So the assertTruncateConstraint() call ** is no longer correct. */ } /* ** 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 |
︙ | ︙ | |||
42114 42115 42116 42117 42118 42119 42120 42121 42122 42123 42124 42125 42126 42127 | 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. ** | > > > > > | 42190 42191 42192 42193 42194 42195 42196 42197 42198 42199 42200 42201 42202 42203 42204 42205 42206 42207 42208 | if( pPager->eLock<=SHARED_LOCK ){ rc = hasHotJournal(pPager, &bHotJournal); } if( rc!=SQLITE_OK ){ goto failed; } if( bHotJournal ){ if( pPager->readOnly ){ rc = SQLITE_READONLY_ROLLBACK; goto failed; } /* 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. ** |
︙ | ︙ | |||
43198 43199 43200 43201 43202 43203 43204 | } } #else rc = pager_incr_changecounter(pPager, 0); #endif if( rc!=SQLITE_OK ) goto commit_phase_one_exit; | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 43279 43280 43281 43282 43283 43284 43285 43286 43287 43288 43289 43290 43291 43292 | } } #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; |
︙ | ︙ | |||
43255 43256 43257 43258 43259 43260 43261 | 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); | | | | | > > > | | 43306 43307 43308 43309 43310 43311 43312 43313 43314 43315 43316 43317 43318 43319 43320 43321 43322 43323 43324 43325 43326 43327 | 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 smaller than the database image, use ** pager_truncate to grow the file here. This can happen if the database ** image was extended as part of the current transaction and then the ** last page in the db image moved to the free-list. In this case the ** last page is never written out to disk, leaving the database file ** undersized. Fix this now if it is the case. */ 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. */ |
︙ | ︙ | |||
43332 43333 43334 43335 43336 43337 43338 | ){ assert( pPager->journalOff==JOURNAL_HDR_SZ(pPager) || !pPager->journalOff ); pPager->eState = PAGER_READER; return SQLITE_OK; } PAGERTRACE(("COMMIT %d\n", PAGERID(pPager))); | | | 43386 43387 43388 43389 43390 43391 43392 43393 43394 43395 43396 43397 43398 43399 43400 | ){ 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, 1); 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 |
︙ | ︙ | |||
43377 43378 43379 43380 43381 43382 43383 | 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); | | | | 43431 43432 43433 43434 43435 43436 43437 43438 43439 43440 43441 43442 43443 43444 43445 43446 43447 43448 43449 | 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, 0); 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, 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; |
︙ | ︙ | |||
43779 43780 43781 43782 43783 43784 43785 | ** ** 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; | > | | 43833 43834 43835 43836 43837 43838 43839 43840 43841 43842 43843 43844 43845 43846 43847 43848 | ** ** 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( pPager->journalMode==PAGER_JOURNALMODE_OFF || 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. |
︙ | ︙ | |||
47783 47784 47785 47786 47787 47788 47789 47790 47791 47792 47793 47794 47795 47796 | 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 */ | > | 47838 47839 47840 47841 47842 47843 47844 47845 47846 47847 47848 47849 47850 47851 47852 | 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 */ u8 bDoTruncate; /* True to truncate db on commit */ #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 */ |
︙ | ︙ | |||
48349 48350 48351 48352 48353 48354 48355 48356 48357 48358 48359 48360 48361 48362 | ** 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. ** | > > > > > > > > > > > > > > > > > > > | 48405 48406 48407 48408 48409 48410 48411 48412 48413 48414 48415 48416 48417 48418 48419 48420 48421 48422 48423 48424 48425 48426 48427 48428 48429 48430 48431 48432 48433 48434 48435 48436 48437 | ** 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) /* ** Values passed as the 5th argument to allocateBtreePage() */ #define BTALLOC_ANY 0 /* Allocate any page */ #define BTALLOC_EXACT 1 /* Allocate exact page if possible */ #define BTALLOC_LE 2 /* Allocate any page <= the parameter */ /* ** Macro IfNotOmitAV(x) returns (x) if SQLITE_OMIT_AUTOVACUUM is not ** defined, or 0 if it is. For example: ** ** bIncrVacuum = IfNotOmitAV(pBtShared->incrVacuum); */ #ifndef SQLITE_OMIT_AUTOVACUUM #define IfNotOmitAV(expr) (expr) #else #define IfNotOmitAV(expr) 0 #endif #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. ** |
︙ | ︙ | |||
50901 50902 50903 50904 50905 50906 50907 50908 50909 50910 50911 50912 50913 50914 | /* 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; } | > | 50976 50977 50978 50979 50980 50981 50982 50983 50984 50985 50986 50987 50988 50989 50990 | /* 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; } assert( IfNotOmitAV(pBt->bDoTruncate)==0 ); /* Write transactions are not possible on a read-only database */ if( (pBt->btsFlags & BTS_READ_ONLY)!=0 && wrflag ){ rc = SQLITE_READONLY; goto trans_begun; } |
︙ | ︙ | |||
51217 51218 51219 51220 51221 51222 51223 | return rc; } /* Forward declaration required by incrVacuumStep(). */ static int allocateBtreePage(BtShared *, MemPage **, Pgno *, Pgno, u8); /* | | | | > | | | > > | | | < < < < | | | 51293 51294 51295 51296 51297 51298 51299 51300 51301 51302 51303 51304 51305 51306 51307 51308 51309 51310 51311 51312 51313 51314 51315 51316 51317 51318 51319 51320 51321 51322 51323 | 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. Or, if an error ** occurs, return some other error code. ** ** 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. ** ** Parameter nFin is the number of pages that this database would contain ** were this function called until it returns SQLITE_DONE. ** ** If the bCommit parameter is non-zero, this function assumes that the ** caller will keep calling incrVacuumStep() until it returns SQLITE_DONE ** or an error. bCommit is passed true for an auto-vacuum-on-commmit ** operation, or false for an incremental vacuum. */ static int incrVacuumStep(BtShared *pBt, Pgno nFin, Pgno iLastPg, int bCommit){ 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) ){ |
︙ | ︙ | |||
51259 51260 51261 51262 51263 51264 51265 | return rc; } if( eType==PTRMAP_ROOTPAGE ){ return SQLITE_CORRUPT_BKPT; } if( eType==PTRMAP_FREEPAGE ){ | | | | > > | | > > > > | | < < | < | > | | | | < < > | | | < > | > > > > > > | | > > > > > | > | | < < | | > > > > > > > | | | | | > > > | 51334 51335 51336 51337 51338 51339 51340 51341 51342 51343 51344 51345 51346 51347 51348 51349 51350 51351 51352 51353 51354 51355 51356 51357 51358 51359 51360 51361 51362 51363 51364 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 51420 51421 51422 51423 51424 51425 51426 51427 51428 51429 51430 51431 51432 51433 51434 51435 51436 51437 51438 51439 51440 51441 51442 51443 51444 51445 51446 51447 51448 51449 51450 51451 51452 51453 51454 51455 51456 51457 51458 51459 51460 51461 51462 51463 51464 51465 51466 51467 51468 | return rc; } if( eType==PTRMAP_ROOTPAGE ){ return SQLITE_CORRUPT_BKPT; } if( eType==PTRMAP_FREEPAGE ){ if( bCommit==0 ){ /* Remove the page from the files free-list. This is not required ** if bCommit 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, BTALLOC_EXACT); if( rc!=SQLITE_OK ){ return rc; } assert( iFreePg==iLastPg ); releasePage(pFreePg); } } else { Pgno iFreePg; /* Index of free page to move pLastPg to */ MemPage *pLastPg; u8 eMode = BTALLOC_ANY; /* Mode parameter for allocateBtreePage() */ Pgno iNear = 0; /* nearby parameter for allocateBtreePage() */ rc = btreeGetPage(pBt, iLastPg, &pLastPg, 0); if( rc!=SQLITE_OK ){ return rc; } /* If bCommit 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 bCommit is greater than zero, then keep ** looping until a free-page located within the first nFin pages ** of the file is found. */ if( bCommit==0 ){ eMode = BTALLOC_LE; iNear = nFin; } do { MemPage *pFreePg; rc = allocateBtreePage(pBt, &pFreePg, &iFreePg, iNear, eMode); if( rc!=SQLITE_OK ){ releasePage(pLastPg); return rc; } releasePage(pFreePg); }while( bCommit && iFreePg>nFin ); assert( iFreePg<iLastPg ); rc = relocatePage(pBt, pLastPg, eType, iPtrPage, iFreePg, bCommit); releasePage(pLastPg); if( rc!=SQLITE_OK ){ return rc; } } } if( bCommit==0 ){ do { iLastPg--; }while( iLastPg==PENDING_BYTE_PAGE(pBt) || PTRMAP_ISPAGE(pBt, iLastPg) ); pBt->bDoTruncate = 1; pBt->nPage = iLastPg; } return SQLITE_OK; } /* ** The database opened by the first argument is an auto-vacuum database ** nOrig pages in size containing nFree free pages. Return the expected ** size of the database in pages following an auto-vacuum operation. */ static Pgno finalDbSize(BtShared *pBt, Pgno nOrig, Pgno nFree){ int nEntry; /* Number of entries on one ptrmap page */ Pgno nPtrmap; /* Number of PtrMap pages to be freed */ Pgno nFin; /* Return value */ 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--; } return nFin; } /* ** 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{ Pgno nOrig = btreePagecount(pBt); Pgno nFree = get4byte(&pBt->pPage1->aData[36]); Pgno nFin = finalDbSize(pBt, nOrig, nFree); if( nOrig<nFin ){ rc = SQLITE_CORRUPT_BKPT; }else if( nFree>0 ){ invalidateAllOverflowCache(pBt); rc = incrVacuumStep(pBt, nFin, nOrig, 0); if( rc==SQLITE_OK ){ rc = sqlite3PagerWrite(pBt->pPage1->pDbPage); put4byte(&pBt->pPage1->aData[28], pBt->nPage); } }else{ rc = SQLITE_DONE; } } sqlite3BtreeLeave(p); return rc; } /* |
︙ | ︙ | |||
51383 51384 51385 51386 51387 51388 51389 | 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 */ | < < < | < < < < < < < | | | 51481 51482 51483 51484 51485 51486 51487 51488 51489 51490 51491 51492 51493 51494 51495 51496 51497 51498 51499 51500 51501 51502 51503 51504 51505 51506 51507 51508 51509 51510 51511 51512 51513 51514 51515 51516 51517 51518 51519 | 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]); nFin = finalDbSize(pBt, nOrig, nFree); if( nFin>nOrig ) return SQLITE_CORRUPT_BKPT; for(iFree=nOrig; iFree>nFin && rc==SQLITE_OK; iFree--){ rc = incrVacuumStep(pBt, nFin, iFree, 1); } 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); pBt->bDoTruncate = 1; pBt->nPage = nFin; } if( rc!=SQLITE_OK ){ sqlite3PagerRollback(pPager); } } |
︙ | ︙ | |||
51472 51473 51474 51475 51476 51477 51478 51479 51480 51481 51482 51483 51484 51485 51486 51487 51488 51489 51490 51491 51492 51493 51494 51495 51496 51497 51498 51499 51500 | 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; | > > > > > > | 51560 51561 51562 51563 51564 51565 51566 51567 51568 51569 51570 51571 51572 51573 51574 51575 51576 51577 51578 51579 51580 51581 51582 51583 51584 51585 51586 51587 51588 51589 51590 51591 51592 51593 51594 | if( pBt->autoVacuum ){ rc = autoVacuumCommit(pBt); if( rc!=SQLITE_OK ){ sqlite3BtreeLeave(p); return rc; } } if( pBt->bDoTruncate ){ sqlite3PagerTruncateImage(pBt->pPager, pBt->nPage); } #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) ); #ifndef SQLITE_OMIT_AUTOVACUUM pBt->bDoTruncate = 0; #endif 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; |
︙ | ︙ | |||
53159 53160 53161 53162 53163 53164 53165 | ** 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. ** | | | | | > > | | | | | > | > | | | | | | | | | > > | | > | 53253 53254 53255 53256 53257 53258 53259 53260 53261 53262 53263 53264 53265 53266 53267 53268 53269 53270 53271 53272 53273 53274 53275 53276 53277 53278 53279 53280 53281 53282 53283 53284 53285 53286 53287 53288 53289 53290 53291 53292 53293 53294 53295 53296 53297 53298 53299 53300 53301 53302 53303 53304 53305 53306 53307 53308 53309 53310 53311 53312 53313 53314 53315 53316 53317 53318 53319 53320 53321 53322 53323 53324 53325 53326 53327 53328 53329 53330 53331 53332 53333 53334 53335 53336 53337 53338 | ** 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 an 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 eMode parameter is BTALLOC_EXACT and the nearby page exists ** anywhere on the free-list, then it is guaranteed to be returned. If ** eMode is BTALLOC_LT then the page returned will be less than or equal ** to nearby if any such page exists. If eMode is BTALLOC_ANY then there ** are no restrictions on which page is returned. */ static int allocateBtreePage( BtShared *pBt, /* The btree */ MemPage **ppPage, /* Store pointer to the allocated page here */ Pgno *pPgno, /* Store the page number here */ Pgno nearby, /* Search for a page near this one */ u8 eMode /* BTALLOC_EXACT, BTALLOC_LT, or BTALLOC_ANY */ ){ 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) ); assert( eMode==BTALLOC_ANY || (nearby>0 && IfNotOmitAV(pBt->autoVacuum)) ); 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 eMode==BTALLOC_EXACT 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( eMode==BTALLOC_EXACT ){ if( 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; } } }else if( eMode==BTALLOC_LE ){ searchList = 1; } #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 (eMode==BTALLOC_EXACT) ** or until a page less than 'nearby' is located (eMode==BTALLOC_LT) */ do { pPrevTrunk = pTrunk; if( pPrevTrunk ){ iTrunk = get4byte(&pPrevTrunk->aData[0]); }else{ iTrunk = get4byte(&pPage1->aData[32]); |
︙ | ︙ | |||
53265 53266 53267 53268 53269 53270 53271 | 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 | | > > | | 53366 53367 53368 53369 53370 53371 53372 53373 53374 53375 53376 53377 53378 53379 53380 53381 53382 53383 53384 53385 53386 | 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 || (iTrunk<nearby && eMode==BTALLOC_LE)) ){ /* The list is being searched and this trunk page is the page ** to allocate, regardless of whether it has leaves. */ *pPgno = iTrunk; *ppPage = pTrunk; searchList = 0; rc = sqlite3PagerWrite(pTrunk->pDbPage); if( rc ){ goto end_allocate_page; } if( k==0 ){ |
︙ | ︙ | |||
53332 53333 53334 53335 53336 53337 53338 | }else if( k>0 ){ /* Extract a leaf from the trunk */ u32 closest; Pgno iPage; unsigned char *aData = pTrunk->aData; if( nearby>0 ){ u32 i; | < > > > > > > > > > > | | | | | | > | > > | 53435 53436 53437 53438 53439 53440 53441 53442 53443 53444 53445 53446 53447 53448 53449 53450 53451 53452 53453 53454 53455 53456 53457 53458 53459 53460 53461 53462 53463 53464 53465 53466 53467 53468 53469 53470 53471 53472 53473 53474 53475 53476 53477 53478 53479 53480 53481 53482 | }else if( k>0 ){ /* Extract a leaf from the trunk */ u32 closest; Pgno iPage; unsigned char *aData = pTrunk->aData; if( nearby>0 ){ u32 i; closest = 0; if( eMode==BTALLOC_LE ){ for(i=0; i<k; i++){ iPage = get4byte(&aData[8+i*4]); if( iPage<=nearby ){ closest = i; break; } } }else{ int dist; 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 || (iPage<nearby && eMode==BTALLOC_LE)) ){ 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; |
︙ | ︙ | |||
53380 53381 53382 53383 53384 53385 53386 | searchList = 0; } } releasePage(pPrevTrunk); pPrevTrunk = 0; }while( searchList ); }else{ | | > > > > > > > > > > > > > > > > > > | | | | 53495 53496 53497 53498 53499 53500 53501 53502 53503 53504 53505 53506 53507 53508 53509 53510 53511 53512 53513 53514 53515 53516 53517 53518 53519 53520 53521 53522 53523 53524 53525 53526 53527 53528 53529 53530 53531 53532 53533 53534 53535 53536 53537 53538 53539 53540 53541 53542 53543 53544 53545 53546 53547 53548 53549 53550 53551 53552 53553 53554 53555 53556 53557 | searchList = 0; } } releasePage(pPrevTrunk); pPrevTrunk = 0; }while( searchList ); }else{ /* There are no pages on the freelist, so append a new page to the ** database image. ** ** Normally, new pages allocated by this block can be requested from the ** pager layer with the 'no-content' flag set. This prevents the pager ** from trying to read the pages content from disk. However, if the ** current transaction has already run one or more incremental-vacuum ** steps, then the page we are about to allocate may contain content ** that is required in the event of a rollback. In this case, do ** not set the no-content flag. This causes the pager to load and journal ** the current page content before overwriting it. ** ** Note that the pager will not actually attempt to load or journal ** content for any page that really does lie past the end of the database ** file on disk. So the effects of disabling the no-content optimization ** here are confined to those pages that lie between the end of the ** database image and the end of the database file. */ int bNoContent = (0==IfNotOmitAV(pBt->bDoTruncate)); 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, bNoContent); 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, bNoContent); if( rc ) return rc; rc = sqlite3PagerWrite((*ppPage)->pDbPage); if( rc!=SQLITE_OK ){ releasePage(*ppPage); } TRACE(("ALLOCATE: %d from end of file\n", *pPgno)); } |
︙ | ︙ | |||
55425 55426 55427 55428 55429 55430 55431 | } 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). */ | | | 55558 55559 55560 55561 55562 55563 55564 55565 55566 55567 55568 55569 55570 55571 55572 | } 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, BTALLOC_EXACT); 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 |
︙ | ︙ | |||
56332 56333 56334 56335 56336 56337 56338 | if( !sCheck.aPgRef ){ *pnErr = 1; sqlite3BtreeLeave(p); return 0; } i = PENDING_BYTE_PAGE(pBt); if( i<=sCheck.nPage ) setPageReferenced(&sCheck, i); | | | 56465 56466 56467 56468 56469 56470 56471 56472 56473 56474 56475 56476 56477 56478 56479 | if( !sCheck.aPgRef ){ *pnErr = 1; sqlite3BtreeLeave(p); return 0; } i = PENDING_BYTE_PAGE(pBt); if( i<=sCheck.nPage ) setPageReferenced(&sCheck, i); sqlite3StrAccumInit(&sCheck.errMsg, zErr, sizeof(zErr), SQLITE_MAX_LENGTH); sCheck.errMsg.useMalloc = 2; /* Check the integrity of the freelist */ checkList(&sCheck, 1, get4byte(&pBt->pPage1->aData[32]), get4byte(&pBt->pPage1->aData[36]), "Main freelist: "); |
︙ | ︙ | |||
56867 56868 56869 56870 56871 56872 56873 | } /* ** Parameter zSrcData points to a buffer containing the data for ** page iSrcPg from the source database. Copy this data into the ** destination database. */ | | > > > > > | 57000 57001 57002 57003 57004 57005 57006 57007 57008 57009 57010 57011 57012 57013 57014 57015 57016 57017 57018 57019 | } /* ** Parameter zSrcData points to a buffer containing the data for ** page iSrcPg from the source database. Copy this data into the ** destination database. */ static int backupOnePage( sqlite3_backup *p, /* Backup handle */ Pgno iSrcPg, /* Source database page to backup */ const u8 *zSrcData, /* Source database page data */ int bUpdate /* True for an update, false otherwise */ ){ Pager * const pDestPager = sqlite3BtreePager(p->pDest); const int nSrcPgsz = sqlite3BtreeGetPageSize(p->pSrc); int nDestPgsz = sqlite3BtreeGetPageSize(p->pDest); const int nCopy = MIN(nSrcPgsz, nDestPgsz); const i64 iEnd = (i64)iSrcPg*(i64)nSrcPgsz; #ifdef SQLITE_HAS_CODEC /* Use BtreeGetReserveNoMutex() for the source b-tree, as although it is |
︙ | ︙ | |||
56940 56941 56942 56943 56944 56945 56946 56947 56948 56949 56950 56951 56952 56953 | ** and the pager code use this trick (clearing the first byte ** of the page 'extra' space to invalidate the Btree layers ** cached parse of the page). MemPage.isInit is marked ** "MUST BE FIRST" for this purpose. */ memcpy(zOut, zIn, nCopy); ((u8 *)sqlite3PagerGetExtra(pDestPg))[0] = 0; } sqlite3PagerUnref(pDestPg); } return rc; } | > > > | 57078 57079 57080 57081 57082 57083 57084 57085 57086 57087 57088 57089 57090 57091 57092 57093 57094 | ** and the pager code use this trick (clearing the first byte ** of the page 'extra' space to invalidate the Btree layers ** cached parse of the page). MemPage.isInit is marked ** "MUST BE FIRST" for this purpose. */ memcpy(zOut, zIn, nCopy); ((u8 *)sqlite3PagerGetExtra(pDestPg))[0] = 0; if( iOff==0 && bUpdate==0 ){ sqlite3Put4byte(&zOut[28], sqlite3BtreeLastPage(p->pSrc)); } } sqlite3PagerUnref(pDestPg); } return rc; } |
︙ | ︙ | |||
57046 57047 57048 57049 57050 57051 57052 | 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 ){ | | | 57187 57188 57189 57190 57191 57192 57193 57194 57195 57196 57197 57198 57199 57200 57201 | assert( nSrcPage>=0 ); for(ii=0; (nPage<0 || ii<nPage) && p->iNext<=(Pgno)nSrcPage && !rc; ii++){ const Pgno iSrcPg = p->iNext; /* Source page number */ if( iSrcPg!=PENDING_BYTE_PAGE(p->pSrc->pBt) ){ DbPage *pSrcPg; /* Source page object */ rc = sqlite3PagerGet(pSrcPager, iSrcPg, &pSrcPg); if( rc==SQLITE_OK ){ rc = backupOnePage(p, iSrcPg, sqlite3PagerGetData(pSrcPg), 0); sqlite3PagerUnref(pSrcPg); } } p->iNext++; } if( rc==SQLITE_OK ){ p->nPagecount = nSrcPage; |
︙ | ︙ | |||
57109 57110 57111 57112 57113 57114 57115 | if( nDestTruncate==(int)PENDING_BYTE_PAGE(p->pDest->pBt) ){ nDestTruncate--; } }else{ nDestTruncate = nSrcPage * (pgszSrc/pgszDest); } assert( nDestTruncate>0 ); | < > > | > > > > > > > > > > > > | > | 57250 57251 57252 57253 57254 57255 57256 57257 57258 57259 57260 57261 57262 57263 57264 57265 57266 57267 57268 57269 57270 57271 57272 57273 57274 57275 57276 57277 57278 57279 57280 57281 57282 57283 57284 57285 57286 57287 57288 57289 57290 57291 57292 57293 57294 57295 57296 57297 57298 57299 57300 57301 57302 57303 57304 57305 57306 57307 57308 | if( nDestTruncate==(int)PENDING_BYTE_PAGE(p->pDest->pBt) ){ nDestTruncate--; } }else{ nDestTruncate = nSrcPage * (pgszSrc/pgszDest); } assert( nDestTruncate>0 ); 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); Pgno iPg; int nDstPage; i64 iOff; i64 iEnd; assert( pFile ); assert( nDestTruncate==0 || (i64)nDestTruncate*(i64)pgszDest >= iSize || ( nDestTruncate==(int)(PENDING_BYTE_PAGE(p->pDest->pBt)-1) && iSize>=PENDING_BYTE && iSize<=PENDING_BYTE+pgszDest )); /* This block 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. */ sqlite3PagerPagecount(pDestPager, &nDstPage); for(iPg=nDestTruncate; rc==SQLITE_OK && iPg<=(Pgno)nDstPage; iPg++){ if( iPg!=PENDING_BYTE_PAGE(p->pDest->pBt) ){ DbPage *pPg; rc = sqlite3PagerGet(pDestPager, iPg, &pPg); if( rc==SQLITE_OK ){ rc = sqlite3PagerWrite(pPg); sqlite3PagerUnref(pPg); } } } if( rc==SQLITE_OK ){ 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 |
︙ | ︙ | |||
57166 57167 57168 57169 57170 57171 57172 57173 57174 57175 57176 57177 57178 57179 | } /* 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)) ){ | > | 57321 57322 57323 57324 57325 57326 57327 57328 57329 57330 57331 57332 57333 57334 57335 | } /* Sync the database file to disk. */ if( rc==SQLITE_OK ){ rc = sqlite3PagerSync(pDestPager); } }else{ sqlite3PagerTruncateImage(pDestPager, nDestTruncate); rc = sqlite3PagerCommitPhaseOne(pDestPager, 0, 0); } /* Finish committing the transaction to the destination database. */ if( SQLITE_OK==rc && SQLITE_OK==(rc = sqlite3BtreeCommitPhaseTwo(p->pDest, 0)) ){ |
︙ | ︙ | |||
57294 57295 57296 57297 57298 57299 57300 | /* 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); | | | 57450 57451 57452 57453 57454 57455 57456 57457 57458 57459 57460 57461 57462 57463 57464 | /* The backup process p has already copied page iPage. But now it ** has been modified by a transaction on the source pager. Copy ** the new data into the backup. */ int rc; assert( p->pDestDb ); sqlite3_mutex_enter(p->pDestDb->mutex); rc = backupOnePage(p, iPage, aData, 1); sqlite3_mutex_leave(p->pDestDb->mutex); assert( rc!=SQLITE_BUSY && rc!=SQLITE_LOCKED ); if( rc!=SQLITE_OK ){ p->rc = rc; } } } |
︙ | ︙ | |||
57417 57418 57419 57420 57421 57422 57423 57424 57425 57426 57427 57428 57429 57430 57431 | ** 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) ); | > > | 57573 57574 57575 57576 57577 57578 57579 57580 57581 57582 57583 57584 57585 57586 57587 57588 57589 | ** 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){ #ifndef SQLITE_OMIT_UTF16 int rc; #endif 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) ); |
︙ | ︙ | |||
58562 58563 58564 58565 58566 58567 58568 | ************************************************************************* ** 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. */ | < < < < < < < < < < < < | 58720 58721 58722 58723 58724 58725 58726 58727 58728 58729 58730 58731 58732 58733 | ************************************************************************* ** This file contains code used for creating, destroying, and populating ** a VDBE (or an "sqlite3_stmt" as it is known to the outside world.) Prior ** to version 2.8.7, all this code was combined into the vdbe.c source file. ** But that file was getting too big so this subroutines were split out. */ /* ** Create a new virtual database engine. */ SQLITE_PRIVATE Vdbe *sqlite3VdbeCreate(sqlite3 *db){ Vdbe *p; p = sqlite3DbMallocZero(db, sizeof(Vdbe) ); if( p==0 ) return 0; |
︙ | ︙ | |||
58703 58704 58705 58706 58707 58708 58709 | pOp->p1 = p1; pOp->p2 = p2; pOp->p3 = p3; pOp->p4.p = 0; pOp->p4type = P4_NOTUSED; #ifdef SQLITE_DEBUG pOp->zComment = 0; | > | > | 58849 58850 58851 58852 58853 58854 58855 58856 58857 58858 58859 58860 58861 58862 58863 58864 58865 | pOp->p1 = p1; pOp->p2 = p2; pOp->p3 = p3; pOp->p4.p = 0; pOp->p4type = P4_NOTUSED; #ifdef SQLITE_DEBUG pOp->zComment = 0; if( p->db->flags & SQLITE_VdbeAddopTrace ){ sqlite3VdbePrintOp(0, i, &p->aOp[i]); } #endif #ifdef VDBE_PROFILE pOp->cycles = 0; pOp->cnt = 0; #endif return i; } |
︙ | ︙ | |||
58922 58923 58924 58925 58926 58927 58928 | 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) | | | 59070 59071 59072 59073 59074 59075 59076 59077 59078 59079 59080 59081 59082 59083 59084 | while( (pOp = opIterNext(&sIter))!=0 ){ int opcode = pOp->opcode; if( opcode==OP_Destroy || opcode==OP_VUpdate || opcode==OP_VRename #ifndef SQLITE_OMIT_FOREIGN_KEY || (opcode==OP_FkCounter && pOp->p1==0 && pOp->p2==1) #endif || ((opcode==OP_Halt || opcode==OP_HaltIfNull) && ((pOp->p1&0xff)==SQLITE_CONSTRAINT && pOp->p2==OE_Abort)) ){ hasAbort = 1; break; } } sqlite3DbFree(v->db, sIter.apSub); |
︙ | ︙ | |||
59057 59058 59059 59060 59061 59062 59063 | } pOut->p3 = pIn->p3; pOut->p4type = P4_NOTUSED; pOut->p4.p = 0; pOut->p5 = 0; #ifdef SQLITE_DEBUG pOut->zComment = 0; | | | 59205 59206 59207 59208 59209 59210 59211 59212 59213 59214 59215 59216 59217 59218 59219 | } pOut->p3 = pIn->p3; pOut->p4type = P4_NOTUSED; pOut->p4.p = 0; pOut->p5 = 0; #ifdef SQLITE_DEBUG pOut->zComment = 0; if( p->db->flags & SQLITE_VdbeAddopTrace ){ sqlite3VdbePrintOp(0, i+addr, &p->aOp[i+addr]); } #endif } p->nOp += nOp; } return addr; |
︙ | ︙ | |||
60083 60084 60085 60086 60087 60088 60089 | if( nByte ){ p->pFree = sqlite3DbMallocZero(db, nByte); } zCsr = p->pFree; zEnd = &zCsr[nByte]; }while( nByte && !db->mallocFailed ); | | | 60231 60232 60233 60234 60235 60236 60237 60238 60239 60240 60241 60242 60243 60244 60245 | if( nByte ){ p->pFree = sqlite3DbMallocZero(db, nByte); } zCsr = p->pFree; zEnd = &zCsr[nByte]; }while( nByte && !db->mallocFailed ); p->nCursor = nCursor; p->nOnceFlag = nOnce; if( p->aVar ){ p->nVar = (ynVar)nVar; for(n=0; n<nVar; n++){ p->aVar[n].flags = MEM_Null; p->aVar[n].db = db; } |
︙ | ︙ | |||
60325 60326 60327 60328 60329 60330 60331 | 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 ){ | | | 60473 60474 60475 60476 60477 60478 60479 60480 60481 60482 60483 60484 60485 60486 60487 | return rc; } /* If there are any write-transactions at all, invoke the commit hook */ if( needXcommit && db->xCommitCallback ){ rc = db->xCommitCallback(db->pCommitArg); if( rc ){ return SQLITE_CONSTRAINT_COMMITHOOK; } } /* The simple case - no more than one database file (not counting the ** TEMP database) has a transaction active. There is no need for the ** master-journal. ** |
︙ | ︙ | |||
60617 60618 60619 60620 60621 60622 60623 | /* ** 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 | | | | | 60765 60766 60767 60768 60769 60770 60771 60772 60773 60774 60775 60776 60777 60778 60779 60780 60781 60782 60783 60784 60785 60786 | /* ** This function is called when a transaction opened by the database ** handle associated with the VM passed as an argument is about to be ** committed. If there are outstanding deferred foreign key constraint ** violations, return SQLITE_ERROR. Otherwise, SQLITE_OK. ** ** If there are outstanding FK violations and this function returns ** SQLITE_ERROR, set the result of the VM to SQLITE_CONSTRAINT_FOREIGNKEY ** and write an error message to it. Then return SQLITE_ERROR. */ #ifndef SQLITE_OMIT_FOREIGN_KEY SQLITE_PRIVATE int sqlite3VdbeCheckFk(Vdbe *p, int deferred){ sqlite3 *db = p->db; if( (deferred && db->nDeferredCons>0) || (!deferred && p->nFkConstraint>0) ){ p->rc = SQLITE_CONSTRAINT_FOREIGNKEY; p->errorAction = OE_Abort; sqlite3SetString(&p->zErrMsg, db, "foreign key constraint failed"); return SQLITE_ERROR; } return SQLITE_OK; } #endif |
︙ | ︙ | |||
60739 60740 60741 60742 60743 60744 60745 | 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; } | | | 60887 60888 60889 60890 60891 60892 60893 60894 60895 60896 60897 60898 60899 60900 60901 | if( p->rc==SQLITE_OK || (p->errorAction==OE_Fail && !isSpecialError) ){ rc = sqlite3VdbeCheckFk(p, 1); if( rc!=SQLITE_OK ){ if( NEVER(p->readOnly) ){ sqlite3VdbeLeave(p); return SQLITE_ERROR; } rc = SQLITE_CONSTRAINT_FOREIGNKEY; }else{ /* The auto-commit flag is true, the vdbe program was successful ** or hit an 'OR FAIL' constraint and there are no deferred foreign ** key constraints to hold up the transaction. This means a commit ** is required. */ rc = vdbeCommit(db, p); } |
︙ | ︙ | |||
60782 60783 60784 60785 60786 60787 60788 | ** 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 ){ | | | 60930 60931 60932 60933 60934 60935 60936 60937 60938 60939 60940 60941 60942 60943 60944 | ** do so. If this operation returns an error, and the current statement ** error code is SQLITE_OK or SQLITE_CONSTRAINT, then promote the ** current statement error code. */ if( eStatementOp ){ rc = sqlite3VdbeCloseStatement(p, eStatementOp); if( rc ){ if( p->rc==SQLITE_OK || (p->rc&0xff)==SQLITE_CONSTRAINT ){ p->rc = rc; sqlite3DbFree(db, p->zErrMsg); p->zErrMsg = 0; } sqlite3RollbackAll(db, SQLITE_ABORT_ROLLBACK); sqlite3CloseSavepoints(db); db->autoCommit = 1; |
︙ | ︙ | |||
61023 61024 61025 61026 61027 61028 61029 | 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) | | | 61171 61172 61173 61174 61175 61176 61177 61178 61179 61180 61181 61182 61183 61184 61185 | for(i=p->nzVar-1; i>=0; i--) sqlite3DbFree(db, p->azVar[i]); vdbeFreeOpArray(db, p->aOp, p->nOp); sqlite3DbFree(db, p->aLabel); sqlite3DbFree(db, p->aColName); sqlite3DbFree(db, p->zSql); sqlite3DbFree(db, p->pFree); #if defined(SQLITE_ENABLE_TREE_EXPLAIN) sqlite3DbFree(db, p->zExplain); sqlite3DbFree(db, p->pExplain); #endif } /* ** Delete an entire VDBE. */ |
︙ | ︙ | |||
63005 63006 63007 63008 63009 63010 63011 | int i; if( p==0 ){ return 0; } if( zName ){ for(i=0; i<p->nzVar; i++){ const char *z = p->azVar[i]; | | | 63153 63154 63155 63156 63157 63158 63159 63160 63161 63162 63163 63164 63165 63166 63167 | int i; if( p==0 ){ return 0; } if( zName ){ for(i=0; i<p->nzVar; i++){ const char *z = p->azVar[i]; if( z && strncmp(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){ |
︙ | ︙ | |||
64779 64780 64781 64782 64783 64784 64785 | 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{ | | | 64927 64928 64929 64930 64931 64932 64933 64934 64935 64936 64937 64938 64939 64940 64941 | sqlite3_log(pOp->p1, "constraint failed at %d in [%s]", pc, p->zSql); } rc = sqlite3VdbeHalt(p); assert( rc==SQLITE_BUSY || rc==SQLITE_OK || rc==SQLITE_ERROR ); if( rc==SQLITE_BUSY ){ p->rc = rc = SQLITE_BUSY; }else{ assert( rc==SQLITE_OK || (p->rc&0xff)==SQLITE_CONSTRAINT ); assert( rc==SQLITE_OK || db->nDeferredCons>0 ); rc = p->rc ? SQLITE_ERROR : SQLITE_DONE; } goto vdbe_return; } /* Opcode: Integer P1 P2 * * * |
︙ | ︙ | |||
70111 70112 70113 70114 70115 70116 70117 | 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; } | | | 70259 70260 70261 70262 70263 70264 70265 70266 70267 70268 70269 70270 70271 70272 70273 | rc = u.cr.pModule->xUpdate(u.cr.pVtab, u.cr.nArg, u.cr.apArg, &u.cr.rowid); db->vtabOnConflict = vtabOnConflict; importVtabErrMsg(p, u.cr.pVtab); if( rc==SQLITE_OK && pOp->p1 ){ assert( u.cr.nArg>1 && u.cr.apArg[0] && (u.cr.apArg[0]->flags&MEM_Null) ); db->lastRowid = lastRowid = u.cr.rowid; } if( (rc&0xff)==SQLITE_CONSTRAINT && pOp->p4.pVtab->bConstraint ){ if( pOp->p5==OE_Ignore ){ rc = SQLITE_OK; }else{ p->errorAction = ((pOp->p5==OE_Replace) ? OE_Abort : pOp->p5); } }else{ p->nChange++; |
︙ | ︙ | |||
71888 71889 71890 71891 71892 71893 71894 71895 71896 71897 71898 71899 71900 71901 | rc = sqlite3OsOpen(p->pVfs, p->zJournal, pReal, p->flags, 0); if( rc==SQLITE_OK ){ p->pReal = pReal; if( p->iSize>0 ){ assert(p->iSize<=p->nBuf); rc = sqlite3OsWrite(p->pReal, p->zBuf, p->iSize, 0); } } } return rc; } /* ** Close the file. | > > > > > > > > | 72036 72037 72038 72039 72040 72041 72042 72043 72044 72045 72046 72047 72048 72049 72050 72051 72052 72053 72054 72055 72056 72057 | rc = sqlite3OsOpen(p->pVfs, p->zJournal, pReal, p->flags, 0); if( rc==SQLITE_OK ){ p->pReal = pReal; if( p->iSize>0 ){ assert(p->iSize<=p->nBuf); rc = sqlite3OsWrite(p->pReal, p->zBuf, p->iSize, 0); } if( rc!=SQLITE_OK ){ /* If an error occurred while writing to the file, close it before ** returning. This way, SQLite uses the in-memory journal data to ** roll back changes made to the internal page-cache before this ** function was called. */ sqlite3OsClose(pReal); p->pReal = 0; } } } return rc; } /* ** Close the file. |
︙ | ︙ | |||
72634 72635 72636 72637 72638 72639 72640 72641 72642 72643 72644 72645 72646 72647 | for(k=0; k<pUsing->nId; k++){ if( sqlite3StrICmp(pUsing->a[k].zName, zCol)==0 ) return 1; } } return 0; } /* ** Given the name of a column of the form X.Y.Z or Y.Z or just Z, look up ** that name in the set of source tables in pSrcList and make the pExpr ** expression node refer back to that source column. The following changes ** are made to pExpr: ** | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 72790 72791 72792 72793 72794 72795 72796 72797 72798 72799 72800 72801 72802 72803 72804 72805 72806 72807 72808 72809 72810 72811 72812 72813 72814 72815 72816 72817 72818 72819 72820 72821 72822 72823 72824 72825 72826 72827 72828 72829 72830 72831 72832 | for(k=0; k<pUsing->nId; k++){ if( sqlite3StrICmp(pUsing->a[k].zName, zCol)==0 ) return 1; } } return 0; } /* ** Subqueries stores the original database, table and column names for their ** result sets in ExprList.a[].zSpan, in the form "DATABASE.TABLE.COLUMN". ** Check to see if the zSpan given to this routine matches the zDb, zTab, ** and zCol. If any of zDb, zTab, and zCol are NULL then those fields will ** match anything. */ SQLITE_PRIVATE int sqlite3MatchSpanName( const char *zSpan, const char *zCol, const char *zTab, const char *zDb ){ int n; for(n=0; ALWAYS(zSpan[n]) && zSpan[n]!='.'; n++){} if( zDb && (sqlite3StrNICmp(zSpan, zDb, n)!=0 || zDb[n]!=0) ){ return 0; } zSpan += n+1; for(n=0; ALWAYS(zSpan[n]) && zSpan[n]!='.'; n++){} if( zTab && (sqlite3StrNICmp(zSpan, zTab, n)!=0 || zTab[n]!=0) ){ return 0; } zSpan += n+1; if( zCol && sqlite3StrICmp(zSpan, zCol)!=0 ){ return 0; } return 1; } /* ** Given the name of a column of the form X.Y.Z or Y.Z or just Z, look up ** that name in the set of source tables in pSrcList and make the pExpr ** expression node refer back to that source column. The following changes ** are made to pExpr: ** |
︙ | ︙ | |||
72689 72690 72691 72692 72693 72694 72695 72696 72697 72698 72699 72700 72701 72702 72703 72704 | assert( zCol ); /* The Z in X.Y.Z cannot be NULL */ assert( !ExprHasAnyProperty(pExpr, EP_TokenOnly|EP_Reduced) ); /* Initialize the node to no-match */ pExpr->iTable = -1; pExpr->pTab = 0; ExprSetIrreducible(pExpr); /* Start at the inner-most context and move outward until a match is found */ while( pNC && cnt==0 ){ ExprList *pEList; SrcList *pSrcList = pNC->pSrcList; if( pSrcList ){ for(i=0, pItem=pSrcList->a; i<pSrcList->nSrc; i++, pItem++){ Table *pTab; | > > > > > > > > > > > > > > < < < | > | > | > > | > | < > > | | | | | > > > > > < < < < < < > > > > | > | 72874 72875 72876 72877 72878 72879 72880 72881 72882 72883 72884 72885 72886 72887 72888 72889 72890 72891 72892 72893 72894 72895 72896 72897 72898 72899 72900 72901 72902 72903 72904 72905 72906 72907 72908 72909 72910 72911 72912 72913 72914 72915 72916 72917 72918 72919 72920 72921 72922 72923 72924 72925 72926 72927 72928 72929 72930 72931 72932 72933 72934 72935 72936 72937 72938 72939 72940 72941 72942 72943 72944 72945 72946 72947 72948 72949 72950 72951 72952 72953 72954 72955 72956 72957 72958 72959 72960 72961 72962 72963 72964 72965 72966 | assert( zCol ); /* The Z in X.Y.Z cannot be NULL */ assert( !ExprHasAnyProperty(pExpr, EP_TokenOnly|EP_Reduced) ); /* Initialize the node to no-match */ pExpr->iTable = -1; pExpr->pTab = 0; ExprSetIrreducible(pExpr); /* Translate the schema name in zDb into a pointer to the corresponding ** schema. If not found, pSchema will remain NULL and nothing will match ** resulting in an appropriate error message toward the end of this routine */ if( zDb ){ for(i=0; i<db->nDb; i++){ assert( db->aDb[i].zName ); if( sqlite3StrICmp(db->aDb[i].zName,zDb)==0 ){ pSchema = db->aDb[i].pSchema; break; } } } /* Start at the inner-most context and move outward until a match is found */ while( pNC && cnt==0 ){ ExprList *pEList; SrcList *pSrcList = pNC->pSrcList; if( pSrcList ){ for(i=0, pItem=pSrcList->a; i<pSrcList->nSrc; i++, pItem++){ Table *pTab; Column *pCol; pTab = pItem->pTab; assert( pTab!=0 && pTab->zName!=0 ); assert( pTab->nCol>0 ); if( pItem->pSelect && (pItem->pSelect->selFlags & SF_NestedFrom)!=0 ){ int hit = 0; pEList = pItem->pSelect->pEList; for(j=0; j<pEList->nExpr; j++){ if( sqlite3MatchSpanName(pEList->a[j].zSpan, zCol, zTab, zDb) ){ cnt++; cntTab = 2; pMatch = pItem; pExpr->iColumn = j; hit = 1; } } if( hit || zTab==0 ) continue; } if( zDb && pTab->pSchema!=pSchema ){ continue; } if( zTab ){ const char *zTabName = pItem->zAlias ? pItem->zAlias : pTab->zName; assert( zTabName!=0 ); if( sqlite3StrICmp(zTabName, zTab)!=0 ){ continue; } } if( 0==(cntTab++) ){ pMatch = pItem; } for(j=0, pCol=pTab->aCol; j<pTab->nCol; j++, pCol++){ if( sqlite3StrICmp(pCol->zName, zCol)==0 ){ /* If there has been exactly one prior match and this match ** is for the right-hand table of a NATURAL JOIN or is in a ** USING clause, then skip this match. */ if( cnt==1 ){ if( pItem->jointype & JT_NATURAL ) continue; if( nameInUsingClause(pItem->pUsing, zCol) ) continue; } cnt++; pMatch = pItem; /* Substitute the rowid (column -1) for the INTEGER PRIMARY KEY */ pExpr->iColumn = j==pTab->iPKey ? -1 : (i16)j; break; } } } if( pMatch ){ pExpr->iTable = pMatch->iCursor; pExpr->pTab = pMatch->pTab; pSchema = pExpr->pTab->pSchema; } } /* if( pSrcList ) */ #ifndef SQLITE_OMIT_TRIGGER /* If we have not already resolved the name, then maybe ** it is a new.* or old.* trigger argument reference */ if( zDb==0 && zTab!=0 && cnt==0 && pParse->pTriggerTab!=0 ){ int op = pParse->eTriggerOp; |
︙ | ︙ | |||
73081 73082 73083 73084 73085 73086 73087 | } } #endif if( is_agg && (pNC->ncFlags & NC_AllowAgg)==0 ){ sqlite3ErrorMsg(pParse, "misuse of aggregate function %.*s()", nId,zId); pNC->nErr++; is_agg = 0; | | | 73287 73288 73289 73290 73291 73292 73293 73294 73295 73296 73297 73298 73299 73300 73301 | } } #endif if( is_agg && (pNC->ncFlags & NC_AllowAgg)==0 ){ sqlite3ErrorMsg(pParse, "misuse of aggregate function %.*s()", nId,zId); pNC->nErr++; is_agg = 0; }else if( no_such_func && pParse->db->init.busy==0 ){ sqlite3ErrorMsg(pParse, "no such function: %.*s", nId, zId); pNC->nErr++; }else if( wrong_num_args ){ sqlite3ErrorMsg(pParse,"wrong number of arguments to function %.*s()", nId, zId); pNC->nErr++; } |
︙ | ︙ | |||
73517 73518 73519 73520 73521 73522 73523 | memset(&sNC, 0, sizeof(sNC)); sNC.pParse = pParse; if( sqlite3ResolveExprNames(&sNC, p->pLimit) || sqlite3ResolveExprNames(&sNC, p->pOffset) ){ return WRC_Abort; } | < < < < < < < < < < < < < < < < < | 73723 73724 73725 73726 73727 73728 73729 73730 73731 73732 73733 73734 73735 73736 | memset(&sNC, 0, sizeof(sNC)); sNC.pParse = pParse; if( sqlite3ResolveExprNames(&sNC, p->pLimit) || sqlite3ResolveExprNames(&sNC, p->pOffset) ){ return WRC_Abort; } /* Recursively resolve names in all subqueries */ for(i=0; i<p->pSrc->nSrc; i++){ struct SrcList_item *pItem = &p->pSrc->a[i]; if( pItem->pSelect ){ NameContext *pNC; /* Used to iterate name contexts */ int nRef = 0; /* Refcount for pOuterNC and outer contexts */ |
︙ | ︙ | |||
73560 73561 73562 73563 73564 73565 73566 73567 73568 73569 73570 73571 73572 73573 | if( pParse->nErr || db->mallocFailed ) return WRC_Abort; for(pNC=pOuterNC; pNC; pNC=pNC->pNext) nRef -= pNC->nRef; assert( pItem->isCorrelated==0 && nRef<=0 ); pItem->isCorrelated = (nRef!=0); } } /* If there are no aggregate functions in the result-set, and no GROUP BY ** expression, do not allow aggregates in any of the other expressions. */ assert( (p->selFlags & SF_Aggregate)==0 ); pGroupBy = p->pGroupBy; if( pGroupBy || (sNC.ncFlags & NC_HasAgg)!=0 ){ | > > > > > > > > > > > > > > > > > | 73749 73750 73751 73752 73753 73754 73755 73756 73757 73758 73759 73760 73761 73762 73763 73764 73765 73766 73767 73768 73769 73770 73771 73772 73773 73774 73775 73776 73777 73778 73779 | if( pParse->nErr || db->mallocFailed ) return WRC_Abort; for(pNC=pOuterNC; pNC; pNC=pNC->pNext) nRef -= pNC->nRef; assert( pItem->isCorrelated==0 && nRef<=0 ); pItem->isCorrelated = (nRef!=0); } } /* Set up the local name-context to pass to sqlite3ResolveExprNames() to ** resolve the result-set expression list. */ sNC.ncFlags = NC_AllowAgg; sNC.pSrcList = p->pSrc; sNC.pNext = pOuterNC; /* Resolve names in the result set. */ pEList = p->pEList; assert( pEList!=0 ); for(i=0; i<pEList->nExpr; i++){ Expr *pX = pEList->a[i].pExpr; if( sqlite3ResolveExprNames(&sNC, pX) ){ return WRC_Abort; } } /* If there are no aggregate functions in the result-set, and no GROUP BY ** expression, do not allow aggregates in any of the other expressions. */ assert( (p->selFlags & SF_Aggregate)==0 ); pGroupBy = p->pGroupBy; if( pGroupBy || (sNC.ncFlags & NC_HasAgg)!=0 ){ |
︙ | ︙ | |||
74401 74402 74403 74404 74405 74406 74407 | }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++){ | | | 74607 74608 74609 74610 74611 74612 74613 74614 74615 74616 74617 74618 74619 74620 74621 | }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] && strcmp(pParse->azVar[i],z)==0 ){ pExpr->iColumn = x = (ynVar)i+1; break; } } if( x==0 ) x = pExpr->iColumn = (ynVar)(++pParse->nVar); } if( x>0 ){ |
︙ | ︙ | |||
75219 75220 75221 75222 75223 75224 75225 | ** 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: ** | | > | | | | 75425 75426 75427 75428 75429 75430 75431 75432 75433 75434 75435 75436 75437 75438 75439 75440 75441 75442 75443 | ** 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_ASC - The cursor was opened on an ascending index. ** IN_INDEX_INDEX_DESC - The cursor was opened on a descending 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 |
︙ | ︙ | |||
75345 75346 75347 75348 75349 75350 75351 | 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)); | > | | 75552 75553 75554 75555 75556 75557 75558 75559 75560 75561 75562 75563 75564 75565 75566 75567 | 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)); assert( IN_INDEX_INDEX_DESC == IN_INDEX_INDEX_ASC+1 ); eType = IN_INDEX_INDEX_ASC + pIdx->aSortOrder[0]; sqlite3VdbeJumpHere(v, iAddr); if( prNotFound && !pTab->aCol[iCol].notNull ){ *prNotFound = ++pParse->nMem; sqlite3VdbeAddOp2(v, OP_Null, 0, *prNotFound); } } |
︙ | ︙ | |||
76698 76699 76700 76701 76702 76703 76704 | 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{ | | > | 76906 76907 76908 76909 76910 76911 76912 76913 76914 76915 76916 76917 76918 76919 76920 76921 | sqlite3MayAbort(pParse); } assert( !ExprHasProperty(pExpr, EP_IntValue) ); if( pExpr->affinity==OE_Ignore ){ sqlite3VdbeAddOp4( v, OP_Halt, SQLITE_OK, OE_Ignore, 0, pExpr->u.zToken,0); }else{ sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_TRIGGER, pExpr->affinity, pExpr->u.zToken, 0); } break; } #endif } sqlite3ReleaseTempReg(pParse, regFree1); |
︙ | ︙ | |||
77044 77045 77046 77047 77048 77049 77050 77051 77052 77053 77054 77055 77056 77057 | }else{ sqlite3ExplainPush(pOut); for(i=0; i<pList->nExpr; i++){ sqlite3ExplainPrintf(pOut, "item[%d] = ", i); sqlite3ExplainPush(pOut); sqlite3ExplainExpr(pOut, pList->a[i].pExpr); sqlite3ExplainPop(pOut); if( i<pList->nExpr-1 ){ sqlite3ExplainNL(pOut); } } sqlite3ExplainPop(pOut); } } | > > > > > > | 77253 77254 77255 77256 77257 77258 77259 77260 77261 77262 77263 77264 77265 77266 77267 77268 77269 77270 77271 77272 | }else{ sqlite3ExplainPush(pOut); for(i=0; i<pList->nExpr; i++){ sqlite3ExplainPrintf(pOut, "item[%d] = ", i); sqlite3ExplainPush(pOut); sqlite3ExplainExpr(pOut, pList->a[i].pExpr); sqlite3ExplainPop(pOut); if( pList->a[i].zName ){ sqlite3ExplainPrintf(pOut, " AS %s", pList->a[i].zName); } if( pList->a[i].bSpanIsTab ){ sqlite3ExplainPrintf(pOut, " (%s)", pList->a[i].zSpan); } if( i<pList->nExpr-1 ){ sqlite3ExplainNL(pOut); } } sqlite3ExplainPop(pOut); } } |
︙ | ︙ | |||
79251 79252 79253 79254 79255 79256 79257 | if( v==0 || NEVER(pTab==0) ){ return; } if( pTab->tnum==0 ){ /* Do not gather statistics on views or virtual tables */ return; } | | | 79466 79467 79468 79469 79470 79471 79472 79473 79474 79475 79476 79477 79478 79479 79480 | if( v==0 || NEVER(pTab==0) ){ return; } if( pTab->tnum==0 ){ /* Do not gather statistics on views or virtual tables */ return; } if( sqlite3_strnicmp(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) ); |
︙ | ︙ | |||
79661 79662 79663 79664 79665 79666 79667 | v = v*10 + c - '0'; z++; } if( i==0 ) pTable->nRowEst = v; if( pIndex==0 ) break; pIndex->aiRowEst[i] = v; if( *z==' ' ) z++; | | | 79876 79877 79878 79879 79880 79881 79882 79883 79884 79885 79886 79887 79888 79889 79890 | v = v*10 + c - '0'; z++; } if( i==0 ) pTable->nRowEst = v; if( pIndex==0 ) break; pIndex->aiRowEst[i] = v; if( *z==' ' ) z++; if( strcmp(z, "unordered")==0 ){ pIndex->bUnordered = 1; break; } } return 0; } |
︙ | ︙ | |||
83163 83164 83165 83166 83167 83168 83169 | 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); | | | | 83378 83379 83380 83381 83382 83383 83384 83385 83386 83387 83388 83389 83390 83391 83392 83393 | sqlite3VdbeJumpHere(v, addr1); addr1 = sqlite3VdbeAddOp2(v, OP_SorterSort, iSorter, 0); if( pIndex->onError!=OE_None ){ int j2 = sqlite3VdbeCurrentAddr(v) + 3; sqlite3VdbeAddOp2(v, OP_Goto, 0, j2); addr2 = sqlite3VdbeCurrentAddr(v); sqlite3VdbeAddOp3(v, OP_SorterCompare, iSorter, j2, regRecord); sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_UNIQUE, OE_Abort, "indexed columns are not unique", P4_STATIC ); }else{ addr2 = sqlite3VdbeCurrentAddr(v); } sqlite3VdbeAddOp2(v, OP_SorterData, iSorter, regRecord); sqlite3VdbeAddOp3(v, OP_IdxInsert, iIdx, regRecord, 1); sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT); |
︙ | ︙ | |||
83190 83191 83192 83193 83194 83195 83196 | ** (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); | | | | 83405 83406 83407 83408 83409 83410 83411 83412 83413 83414 83415 83416 83417 83418 83419 83420 | ** (made available to the compiler for reuse) using ** sqlite3ReleaseTempRange(). So in some ways having the OP_IsUnique ** opcode use the values stored within seems dangerous. However, since ** we can be sure that no other temp registers have been allocated ** since sqlite3ReleaseTempRange() was called, it is safe to do so. */ sqlite3VdbeAddOp4(v, OP_IsUnique, iIdx, j2, regRowid, pRegKey, P4_INT32); sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_UNIQUE, "indexed columns are not unique", P4_STATIC); } sqlite3VdbeAddOp3(v, OP_IdxInsert, iIdx, regRecord, 0); sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT); #endif sqlite3ReleaseTempReg(pParse, regRecord); sqlite3VdbeAddOp2(v, OP_SorterNext, iSorter, addr2); sqlite3VdbeJumpHere(v, addr1); |
︙ | ︙ | |||
83310 83311 83312 83313 83314 83315 83316 | iDb = sqlite3SchemaToIndex(db, pTab->pSchema); } pDb = &db->aDb[iDb]; assert( pTab!=0 ); assert( pParse->nErr==0 ); if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0 | | | 83525 83526 83527 83528 83529 83530 83531 83532 83533 83534 83535 83536 83537 83538 83539 | iDb = sqlite3SchemaToIndex(db, pTab->pSchema); } pDb = &db->aDb[iDb]; assert( pTab!=0 ); assert( pParse->nErr==0 ); if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0 && sqlite3StrNICmp(&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; |
︙ | ︙ | |||
84408 84409 84410 84411 84412 84413 84414 | } /* ** 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. */ | | > > > > > > > | | 84623 84624 84625 84626 84627 84628 84629 84630 84631 84632 84633 84634 84635 84636 84637 84638 84639 84640 84641 84642 84643 84644 84645 84646 84647 84648 84649 | } /* ** Code an OP_Halt that causes the vdbe to return an SQLITE_CONSTRAINT ** error. The onError parameter determines which (if any) of the statement ** and/or current transaction is rolled back. */ SQLITE_PRIVATE void sqlite3HaltConstraint( Parse *pParse, /* Parsing context */ int errCode, /* extended error code */ int onError, /* Constraint type */ char *p4, /* Error message */ int p4type /* P4_STATIC or P4_TRANSIENT */ ){ Vdbe *v = sqlite3GetVdbe(pParse); assert( (errCode&0xff)==SQLITE_CONSTRAINT ); if( onError==OE_Abort ){ sqlite3MayAbort(pParse); } sqlite3VdbeAddOp4(v, OP_Halt, errCode, onError, 0, p4, p4type); } /* ** Check to see if pIndex uses the collating sequence pColl. Return ** true if it does and false if it does not. */ #ifndef SQLITE_OMIT_REINDEX |
︙ | ︙ | |||
85158 85159 85160 85161 85162 85163 85164 | 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; | | > | < < < | | | > | | | | | | < < | > | | | | | | 85380 85381 85382 85383 85384 85385 85386 85387 85388 85389 85390 85391 85392 85393 85394 85395 85396 85397 85398 85399 85400 85401 85402 85403 85404 85405 85406 85407 85408 85409 85410 85411 85412 85413 85414 85415 | 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 *pSel; SrcList *pFrom; sqlite3 *db = pParse->db; int iDb = sqlite3SchemaToIndex(db, pView->pSchema); pWhere = sqlite3ExprDup(db, pWhere, 0); pFrom = sqlite3SrcListAppend(db, 0, 0, 0); if( pFrom ){ assert( pFrom->nSrc==1 ); pFrom->a[0].zName = sqlite3DbStrDup(db, pView->zName); pFrom->a[0].zDatabase = sqlite3DbStrDup(db, db->aDb[iDb].zName); assert( pFrom->a[0].pOn==0 ); assert( pFrom->a[0].pUsing==0 ); } pSel = sqlite3SelectNew(pParse, 0, pFrom, pWhere, 0, 0, 0, 0, 0, 0); if( pSel ) pSel->selFlags |= SF_Materialize; sqlite3SelectDestInit(&dest, SRT_EphemTab, iCur); sqlite3Select(pParse, pSel, &dest); sqlite3SelectDelete(db, pSel); } #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. |
︙ | ︙ | |||
86681 86682 86683 86684 86685 86686 86687 86688 86689 86690 86691 86692 86693 86694 | default: { 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, | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 86901 86902 86903 86904 86905 86906 86907 86908 86909 86910 86911 86912 86913 86914 86915 86916 86917 86918 86919 86920 86921 86922 86923 86924 86925 86926 86927 86928 86929 86930 86931 86932 86933 86934 86935 86936 86937 86938 86939 86940 86941 86942 86943 86944 86945 86946 86947 86948 86949 86950 86951 86952 86953 86954 86955 86956 86957 86958 86959 86960 86961 86962 86963 86964 86965 86966 86967 86968 86969 86970 | default: { assert( sqlite3_value_type(argv[0])==SQLITE_NULL ); sqlite3_result_text(context, "NULL", 4, SQLITE_STATIC); break; } } } /* ** The unicode() function. Return the integer unicode code-point value ** for the first character of the input string. */ static void unicodeFunc( sqlite3_context *context, int argc, sqlite3_value **argv ){ const unsigned char *z = sqlite3_value_text(argv[0]); (void)argc; if( z && z[0] ) sqlite3_result_int(context, sqlite3Utf8Read(&z)); } /* ** The char() function takes zero or more arguments, each of which is ** an integer. It constructs a string where each character of the string ** is the unicode character for the corresponding integer argument. */ static void charFunc( sqlite3_context *context, int argc, sqlite3_value **argv ){ unsigned char *z, *zOut; int i; zOut = z = sqlite3_malloc( argc*4 ); if( z==0 ){ sqlite3_result_error_nomem(context); return; } for(i=0; i<argc; i++){ sqlite3_int64 x; unsigned c; x = sqlite3_value_int64(argv[i]); if( x<0 || x>0x10ffff ) x = 0xfffd; c = (unsigned)(x & 0x1fffff); if( c<0x00080 ){ *zOut++ = (u8)(c&0xFF); }else if( c<0x00800 ){ *zOut++ = 0xC0 + (u8)((c>>6)&0x1F); *zOut++ = 0x80 + (u8)(c & 0x3F); }else if( c<0x10000 ){ *zOut++ = 0xE0 + (u8)((c>>12)&0x0F); *zOut++ = 0x80 + (u8)((c>>6) & 0x3F); *zOut++ = 0x80 + (u8)(c & 0x3F); }else{ *zOut++ = 0xF0 + (u8)((c>>18) & 0x07); *zOut++ = 0x80 + (u8)((c>>12) & 0x3F); *zOut++ = 0x80 + (u8)((c>>6) & 0x3F); *zOut++ = 0x80 + (u8)(c & 0x3F); } \ } sqlite3_result_text(context, (char*)z, (int)(zOut-z), sqlite3_free); } /* ** The hex() function. Interpret the argument as a blob. Return ** a hexadecimal rendering as text. */ static void hexFunc( sqlite3_context *context, |
︙ | ︙ | |||
87309 87310 87311 87312 87313 87314 87315 87316 87317 87318 87319 87320 87321 87322 | FUNCTION(max, 0, 1, 1, 0 ), AGGREGATE(max, 1, 1, 1, minmaxStep, minMaxFinalize ), FUNCTION2(typeof, 1, 0, 0, typeofFunc, SQLITE_FUNC_TYPEOF), FUNCTION2(length, 1, 0, 0, lengthFunc, SQLITE_FUNC_LENGTH), FUNCTION(instr, 2, 0, 0, instrFunc ), FUNCTION(substr, 2, 0, 0, substrFunc ), FUNCTION(substr, 3, 0, 0, substrFunc ), FUNCTION(abs, 1, 0, 0, absFunc ), #ifndef SQLITE_OMIT_FLOATING_POINT FUNCTION(round, 1, 0, 0, roundFunc ), FUNCTION(round, 2, 0, 0, roundFunc ), #endif FUNCTION(upper, 1, 0, 0, upperFunc ), FUNCTION(lower, 1, 0, 0, lowerFunc ), | > > | 87585 87586 87587 87588 87589 87590 87591 87592 87593 87594 87595 87596 87597 87598 87599 87600 | FUNCTION(max, 0, 1, 1, 0 ), AGGREGATE(max, 1, 1, 1, minmaxStep, minMaxFinalize ), FUNCTION2(typeof, 1, 0, 0, typeofFunc, SQLITE_FUNC_TYPEOF), FUNCTION2(length, 1, 0, 0, lengthFunc, SQLITE_FUNC_LENGTH), FUNCTION(instr, 2, 0, 0, instrFunc ), FUNCTION(substr, 2, 0, 0, substrFunc ), FUNCTION(substr, 3, 0, 0, substrFunc ), FUNCTION(unicode, 1, 0, 0, unicodeFunc ), FUNCTION(char, -1, 0, 0, charFunc ), 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 ), |
︙ | ︙ | |||
87400 87401 87402 87403 87404 87405 87406 | #ifndef SQLITE_OMIT_TRIGGER /* ** Deferred and Immediate FKs ** -------------------------- ** ** Foreign keys in SQLite come in two flavours: deferred and immediate. | | > | | 87678 87679 87680 87681 87682 87683 87684 87685 87686 87687 87688 87689 87690 87691 87692 87693 87694 | #ifndef SQLITE_OMIT_TRIGGER /* ** Deferred and Immediate FKs ** -------------------------- ** ** Foreign keys in SQLite come in two flavours: deferred and immediate. ** If an immediate foreign key constraint is violated, ** SQLITE_CONSTRAINT_FOREIGNKEY is returned and the current ** statement transaction rolled back. If a ** deferred foreign key constraint is violated, no action is taken ** immediately. However if the application attempts to commit the ** transaction before fixing the constraint violation, the attempt fails. ** ** Deferred constraints are implemented using a simple counter associated ** with the database handle. The counter is set to zero each time a ** database transaction is opened. Each time a statement is executed |
︙ | ︙ | |||
87465 87466 87467 87468 87469 87470 87471 | ** 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 | | > | 87744 87745 87746 87747 87748 87749 87750 87751 87752 87753 87754 87755 87756 87757 87758 87759 | ** If a delete caused by OR REPLACE violates an FK constraint, an exception ** is thrown, even if the FK constraint would be satisfied after the new ** row is inserted. ** ** Immediate constraints are usually handled similarly. The only difference ** is that the counter used is stored as part of each individual statement ** object (struct Vdbe). If, after the statement has run, its immediate ** constraint counter is greater than zero, ** it returns SQLITE_CONSTRAINT_FOREIGNKEY ** and the statement transaction is rolled back. An exception is an INSERT ** statement that inserts a single row only (no triggers). In this case, ** instead of using a counter, an exception is thrown immediately if the ** INSERT violates a foreign key constraint. This is necessary as such ** an INSERT does not open a statement transaction. ** ** TODO: How should dropping a table be handled? How should renaming a |
︙ | ︙ | |||
87521 87522 87523 87524 87525 87526 87527 | ** 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, | | | 87801 87802 87803 87804 87805 87806 87807 87808 87809 87810 87811 87812 87813 87814 87815 | ** Register (x+3): 3.1 (type real) */ /* ** A foreign key constraint requires that the key columns in the parent ** table are collectively subject to a UNIQUE or PRIMARY KEY constraint. ** Given that pParent is the parent table for foreign key constraint pFKey, ** search the schema for a unique index on the parent key columns. ** ** If successful, zero is returned. If the parent key is an INTEGER PRIMARY ** KEY column, then output variable *ppIdx is set to NULL. Otherwise, *ppIdx ** is set to point to the unique index. ** ** If the parent key consists of a single column (the foreign key constraint ** is not a composite foreign key), output variable *paiCol is set to NULL. |
︙ | ︙ | |||
87557 87558 87559 87560 87561 87562 87563 | ** 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. */ | | | 87837 87838 87839 87840 87841 87842 87843 87844 87845 87846 87847 87848 87849 87850 87851 | ** consists of a a different number of columns to the child key in ** the child table. ** ** then non-zero is returned, and a "foreign key mismatch" error loaded ** into pParse. If an OOM error occurs, non-zero is returned and the ** pParse->db->mallocFailed flag is set. */ SQLITE_PRIVATE int sqlite3FkLocateIndex( Parse *pParse, /* Parse context to store any error in */ Table *pParent, /* Parent table of FK constraint pFKey */ FKey *pFKey, /* Foreign key to find index for */ Index **ppIdx, /* OUT: Unique index on parent table */ int **paiCol /* OUT: Map of index columns in pFKey */ ){ Index *pIdx = 0; /* Value to return via *ppIdx */ |
︙ | ︙ | |||
87654 87655 87656 87657 87658 87659 87660 | if( i==nCol ) break; /* pIdx is usable */ } } } if( !pIdx ){ if( !pParse->disableTriggers ){ | | > > | 87934 87935 87936 87937 87938 87939 87940 87941 87942 87943 87944 87945 87946 87947 87948 87949 87950 | if( i==nCol ) break; /* pIdx is usable */ } } } if( !pIdx ){ if( !pParse->disableTriggers ){ sqlite3ErrorMsg(pParse, "foreign key mismatch - \"%w\" referencing \"%w\"", pFKey->pFrom->zName, pFKey->zTo); } sqlite3DbFree(pParse->db, aiCol); return 1; } *ppIdx = pIdx; return 0; |
︙ | ︙ | |||
87803 87804 87805 87806 87807 87808 87809 | 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 ); | | | | 88085 88086 88087 88088 88089 88090 88091 88092 88093 88094 88095 88096 88097 88098 88099 88100 | if( !pFKey->isDeferred && !pParse->pToplevel && !pParse->isMultiWrite ){ /* Special case: If this is an INSERT statement that will insert exactly ** one row into the table, raise a constraint immediately instead of ** incrementing a counter. This is necessary as the VM code is being ** generated for will not open a statement transaction. */ assert( nIncr==1 ); sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_FOREIGNKEY, OE_Abort, "foreign key constraint failed", P4_STATIC ); }else{ if( nIncr>0 && pFKey->isDeferred==0 ){ sqlite3ParseToplevel(pParse)->mayAbort = 1; } sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, nIncr); } |
︙ | ︙ | |||
88044 88045 88046 88047 88048 88049 88050 | 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); | | | | 88326 88327 88328 88329 88330 88331 88332 88333 88334 88335 88336 88337 88338 88339 88340 88341 | pParse->disableTriggers = 0; /* If the DELETE has generated immediate foreign key constraint ** violations, halt the VDBE and return an error at this point, before ** any modifications to the schema are made. This is because statement ** transactions are not able to rollback schema changes. */ sqlite3VdbeAddOp2(v, OP_FkIfZero, 0, sqlite3VdbeCurrentAddr(v)+2); sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_FOREIGNKEY, OE_Abort, "foreign key constraint failed", P4_STATIC ); if( iSkip ){ sqlite3VdbeResolveLabel(v, iSkip); } } } |
︙ | ︙ | |||
88115 88116 88117 88118 88119 88120 88121 | ** 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); } | | | 88397 88398 88399 88400 88401 88402 88403 88404 88405 88406 88407 88408 88409 88410 88411 | ** schema items cannot be located, set an error in pParse and return ** early. */ if( pParse->disableTriggers ){ pTo = sqlite3FindTable(db, pFKey->zTo, zDb); }else{ pTo = sqlite3LocateTable(pParse, 0, pFKey->zTo, zDb); } if( !pTo || sqlite3FkLocateIndex(pParse, pTo, pFKey, &pIdx, &aiFree) ){ assert( isIgnoreErrors==0 || (regOld!=0 && regNew==0) ); if( !isIgnoreErrors || db->mallocFailed ) return; if( pTo==0 ){ /* If isIgnoreErrors is true, then a table is being dropped. In this ** case SQLite runs a "DELETE FROM xxx" on the table being dropped ** before actually dropping it in order to check FK constraints. ** If the parent table of an FK constraint on the current table is |
︙ | ︙ | |||
88195 88196 88197 88198 88199 88200 88201 | 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; } | | | 88477 88478 88479 88480 88481 88482 88483 88484 88485 88486 88487 88488 88489 88490 88491 | if( !pFKey->isDeferred && !pParse->pToplevel && !pParse->isMultiWrite ){ assert( regOld==0 && regNew!=0 ); /* Inserting a single row into a parent table cannot cause an immediate ** foreign key violation. So do nothing in this case. */ continue; } if( sqlite3FkLocateIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ){ if( !isIgnoreErrors || db->mallocFailed ) return; continue; } assert( aiCol || pFKey->nCol==1 ); /* Create a SrcList structure containing a single table (the table ** the foreign key that refers to this table is attached to). This |
︙ | ︙ | |||
88250 88251 88252 88253 88254 88255 88256 | 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; | | | 88532 88533 88534 88535 88536 88537 88538 88539 88540 88541 88542 88543 88544 88545 88546 | FKey *p; int i; for(p=pTab->pFKey; p; p=p->pNextFrom){ for(i=0; i<p->nCol; i++) mask |= COLUMN_MASK(p->aCol[i].iFrom); } for(p=sqlite3FkReferences(pTab); p; p=p->pNextTo){ Index *pIdx = 0; sqlite3FkLocateIndex(pParse, pTab, p, &pIdx, 0); if( pIdx ){ for(i=0; i<pIdx->nColumn; i++) mask |= COLUMN_MASK(pIdx->aiColumn[i]); } } } return mask; } |
︙ | ︙ | |||
88376 88377 88378 88379 88380 88381 88382 | 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 */ | | | 88658 88659 88660 88661 88662 88663 88664 88665 88666 88667 88668 88669 88670 88671 88672 | TriggerStep *pStep = 0; /* First (only) step of trigger program */ Expr *pWhere = 0; /* WHERE clause of trigger step */ ExprList *pList = 0; /* Changes list if ON UPDATE CASCADE */ Select *pSelect = 0; /* If RESTRICT, "SELECT RAISE(...)" */ int i; /* Iterator variable */ Expr *pWhen = 0; /* WHEN clause for the trigger */ if( sqlite3FkLocateIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ) return 0; assert( aiCol || pFKey->nCol==1 ); for(i=0; i<pFKey->nCol; i++){ Token tOld = { "old", 3 }; /* Literal "old" token */ Token tNew = { "new", 3 }; /* Literal "new" token */ Token tFromCol; /* Name of column in child table */ Token tToCol; /* Name of column in parent table */ |
︙ | ︙ | |||
89849 89850 89851 89852 89853 89854 89855 | switch( onError ){ case OE_Abort: sqlite3MayAbort(pParse); case OE_Rollback: case OE_Fail: { char *zMsg; sqlite3VdbeAddOp3(v, OP_HaltIfNull, | | | 90131 90132 90133 90134 90135 90136 90137 90138 90139 90140 90141 90142 90143 90144 90145 | switch( onError ){ case OE_Abort: sqlite3MayAbort(pParse); case OE_Rollback: case OE_Fail: { char *zMsg; sqlite3VdbeAddOp3(v, OP_HaltIfNull, SQLITE_CONSTRAINT_NOTNULL, onError, regData+i); zMsg = sqlite3MPrintf(db, "%s.%s may not be NULL", pTab->zName, pTab->aCol[i].zName); sqlite3VdbeChangeP4(v, -1, zMsg, P4_DYNAMIC); break; } case OE_Ignore: { sqlite3VdbeAddOp2(v, OP_IsNull, regData+i, ignoreDest); |
︙ | ︙ | |||
89889 89890 89891 89892 89893 89894 89895 | 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; } | | > | 90171 90172 90173 90174 90175 90176 90177 90178 90179 90180 90181 90182 90183 90184 90185 90186 | char *zConsName = pCheck->a[i].zName; if( onError==OE_Replace ) onError = OE_Abort; /* IMP: R-15569-63625 */ if( zConsName ){ zConsName = sqlite3MPrintf(db, "constraint %s failed", zConsName); }else{ zConsName = 0; } sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_CHECK, onError, zConsName, P4_DYNAMIC); } sqlite3VdbeResolveLabel(v, allOk); } } #endif /* !defined(SQLITE_OMIT_CHECK) */ /* If we have an INTEGER PRIMARY KEY, make sure the primary key |
︙ | ︙ | |||
89920 89921 89922 89923 89924 89925 89926 | default: { onError = OE_Abort; /* Fall thru into the next case */ } case OE_Rollback: case OE_Abort: case OE_Fail: { | | | | 90203 90204 90205 90206 90207 90208 90209 90210 90211 90212 90213 90214 90215 90216 90217 90218 | default: { onError = OE_Abort; /* Fall thru into the next case */ } case OE_Rollback: case OE_Abort: case OE_Fail: { sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_PRIMARYKEY, onError, "PRIMARY KEY must be unique", P4_STATIC); break; } case OE_Replace: { /* If there are DELETE triggers on this table and the ** recursive-triggers flag is set, call GenerateRowDelete() to ** remove the conflicting row from the table. This will fire ** the triggers and remove both the table and index b-tree entries. |
︙ | ︙ | |||
90048 90049 90050 90051 90052 90053 90054 | sqlite3StrAccumAppend(&errMsg, zSep, -1); zSep = ", "; sqlite3StrAccumAppend(&errMsg, zCol, -1); } sqlite3StrAccumAppend(&errMsg, pIdx->nColumn>1 ? " are not unique" : " is not unique", -1); zErr = sqlite3StrAccumFinish(&errMsg); | | > | 90331 90332 90333 90334 90335 90336 90337 90338 90339 90340 90341 90342 90343 90344 90345 90346 | sqlite3StrAccumAppend(&errMsg, zSep, -1); zSep = ", "; sqlite3StrAccumAppend(&errMsg, zCol, -1); } sqlite3StrAccumAppend(&errMsg, pIdx->nColumn>1 ? " are not unique" : " is not unique", -1); zErr = sqlite3StrAccumFinish(&errMsg); sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_UNIQUE, onError, zErr, 0); sqlite3DbFree(errMsg.db, zErr); break; } case OE_Ignore: { assert( seenReplace==0 ); sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest); break; |
︙ | ︙ | |||
90456 90457 90458 90459 90460 90461 90462 | 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); | | | | 90740 90741 90742 90743 90744 90745 90746 90747 90748 90749 90750 90751 90752 90753 90754 90755 | sqlite3OpenTable(pParse, iSrc, iDbSrc, pSrc, OP_OpenRead); emptySrcTest = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0); regData = sqlite3GetTempReg(pParse); regRowid = sqlite3GetTempReg(pParse); if( pDest->iPKey>=0 ){ addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid); addr2 = sqlite3VdbeAddOp3(v, OP_NotExists, iDest, 0, regRowid); sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_PRIMARYKEY, onError, "PRIMARY KEY must be unique", P4_STATIC); sqlite3VdbeJumpHere(v, addr2); autoIncStep(pParse, regAutoinc, regRowid); }else if( pDest->pIndex==0 ){ addr1 = sqlite3VdbeAddOp2(v, OP_NewRowid, iDest, regRowid); }else{ addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid); assert( (pDest->tabFlags & TF_Autoincrement)==0 ); |
︙ | ︙ | |||
90914 90915 90916 90917 90918 90919 90920 90921 90922 90923 90924 90925 90926 90927 | int (*unlock_notify)(sqlite3*,void(*)(void**,int),void*); int (*wal_autocheckpoint)(sqlite3*,int); int (*wal_checkpoint)(sqlite3*,const char*); void *(*wal_hook)(sqlite3*,int(*)(void*,sqlite3*,const char*,int),void*); int (*blob_reopen)(sqlite3_blob*,sqlite3_int64); int (*vtab_config)(sqlite3*,int op,...); int (*vtab_on_conflict)(sqlite3*); }; /* ** The following macros redefine the API routines so that they are ** redirected throught the global sqlite3_api structure. ** ** This header file is also used by the loadext.c source file | > > > > > > > > > > > > > > | 91198 91199 91200 91201 91202 91203 91204 91205 91206 91207 91208 91209 91210 91211 91212 91213 91214 91215 91216 91217 91218 91219 91220 91221 91222 91223 91224 91225 | int (*unlock_notify)(sqlite3*,void(*)(void**,int),void*); int (*wal_autocheckpoint)(sqlite3*,int); int (*wal_checkpoint)(sqlite3*,const char*); void *(*wal_hook)(sqlite3*,int(*)(void*,sqlite3*,const char*,int),void*); int (*blob_reopen)(sqlite3_blob*,sqlite3_int64); int (*vtab_config)(sqlite3*,int op,...); int (*vtab_on_conflict)(sqlite3*); /* Version 3.7.16 and later */ int (*close_v2)(sqlite3*); const char *(*db_filename)(sqlite3*,const char*); int (*db_readonly)(sqlite3*,const char*); int (*db_release_memory)(sqlite3*); const char *(*errstr)(int); int (*stmt_busy)(sqlite3_stmt*); int (*stmt_readonly)(sqlite3_stmt*); int (*stricmp)(const char*,const char*); int (*uri_boolean)(const char*,const char*,int); sqlite3_int64 (*uri_int64)(const char*,const char*,sqlite3_int64); const char *(*uri_parameter)(const char*,const char*); char *(*vsnprintf)(int,char*,const char*,va_list); int (*wal_checkpoint_v2)(sqlite3*,const char*,int,int*,int*); }; /* ** The following macros redefine the API routines so that they are ** redirected throught the global sqlite3_api structure. ** ** This header file is also used by the loadext.c source file |
︙ | ︙ | |||
91117 91118 91119 91120 91121 91122 91123 91124 91125 91126 91127 91128 91129 91130 | #define sqlite3_unlock_notify sqlite3_api->unlock_notify #define sqlite3_wal_autocheckpoint sqlite3_api->wal_autocheckpoint #define sqlite3_wal_checkpoint sqlite3_api->wal_checkpoint #define sqlite3_wal_hook sqlite3_api->wal_hook #define sqlite3_blob_reopen sqlite3_api->blob_reopen #define sqlite3_vtab_config sqlite3_api->vtab_config #define sqlite3_vtab_on_conflict sqlite3_api->vtab_on_conflict #endif /* SQLITE_CORE */ #define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api = 0; #define SQLITE_EXTENSION_INIT2(v) sqlite3_api = v; #endif /* _SQLITE3EXT_H_ */ | > > > > > > > > > > > > > > | 91415 91416 91417 91418 91419 91420 91421 91422 91423 91424 91425 91426 91427 91428 91429 91430 91431 91432 91433 91434 91435 91436 91437 91438 91439 91440 91441 91442 | #define sqlite3_unlock_notify sqlite3_api->unlock_notify #define sqlite3_wal_autocheckpoint sqlite3_api->wal_autocheckpoint #define sqlite3_wal_checkpoint sqlite3_api->wal_checkpoint #define sqlite3_wal_hook sqlite3_api->wal_hook #define sqlite3_blob_reopen sqlite3_api->blob_reopen #define sqlite3_vtab_config sqlite3_api->vtab_config #define sqlite3_vtab_on_conflict sqlite3_api->vtab_on_conflict /* Version 3.7.16 and later */ #define sqlite3_close_v2 sqlite3_api->close_v2 #define sqlite3_db_filename sqlite3_api->db_filename #define sqlite3_db_readonly sqlite3_api->db_readonly #define sqlite3_db_release_memory sqlite3_api->db_release_memory #define sqlite3_errstr sqlite3_api->errstr #define sqlite3_stmt_busy sqlite3_api->stmt_busy #define sqlite3_stmt_readonly sqlite3_api->stmt_readonly #define sqlite3_stricmp sqlite3_api->stricmp #define sqlite3_uri_boolean sqlite3_api->uri_boolean #define sqlite3_uri_int64 sqlite3_api->uri_int64 #define sqlite3_uri_parameter sqlite3_api->uri_parameter #define sqlite3_uri_vsnprintf sqlite3_api->vsnprintf #define sqlite3_wal_checkpoint_v2 sqlite3_api->wal_checkpoint_v2 #endif /* SQLITE_CORE */ #define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api = 0; #define SQLITE_EXTENSION_INIT2(v) sqlite3_api = v; #endif /* _SQLITE3EXT_H_ */ |
︙ | ︙ | |||
91486 91487 91488 91489 91490 91491 91492 91493 91494 91495 91496 91497 91498 91499 | 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. | > > > > > > > > > > > > > | 91798 91799 91800 91801 91802 91803 91804 91805 91806 91807 91808 91809 91810 91811 91812 91813 91814 91815 91816 91817 91818 91819 91820 91821 91822 91823 91824 | 0, 0, 0, #endif sqlite3_blob_reopen, sqlite3_vtab_config, sqlite3_vtab_on_conflict, sqlite3_close_v2, sqlite3_db_filename, sqlite3_db_readonly, sqlite3_db_release_memory, sqlite3_errstr, sqlite3_stmt_busy, sqlite3_stmt_readonly, sqlite3_stricmp, sqlite3_uri_boolean, sqlite3_uri_int64, sqlite3_uri_parameter, sqlite3_vsnprintf, sqlite3_wal_checkpoint_v2 }; /* ** 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. |
︙ | ︙ | |||
91952 91953 91954 91955 91956 91957 91958 91959 91960 91961 91962 91963 91964 91965 | #ifndef SQLITE_OMIT_AUTOMATIC_INDEX { "automatic_index", SQLITE_AutoIndex }, #endif #ifdef SQLITE_DEBUG { "sql_trace", SQLITE_SqlTrace }, { "vdbe_listing", SQLITE_VdbeListing }, { "vdbe_trace", SQLITE_VdbeTrace }, #endif #ifndef SQLITE_OMIT_CHECK { "ignore_check_constraints", SQLITE_IgnoreChecks }, #endif /* The following is VERY experimental */ { "writable_schema", SQLITE_WriteSchema|SQLITE_RecoveryMode }, | > > > | 92277 92278 92279 92280 92281 92282 92283 92284 92285 92286 92287 92288 92289 92290 92291 92292 92293 | #ifndef SQLITE_OMIT_AUTOMATIC_INDEX { "automatic_index", SQLITE_AutoIndex }, #endif #ifdef SQLITE_DEBUG { "sql_trace", SQLITE_SqlTrace }, { "vdbe_listing", SQLITE_VdbeListing }, { "vdbe_trace", SQLITE_VdbeTrace }, { "vdbe_addoptrace", SQLITE_VdbeAddopTrace}, { "vdbe_debug", SQLITE_SqlTrace | SQLITE_VdbeListing | SQLITE_VdbeTrace }, #endif #ifndef SQLITE_OMIT_CHECK { "ignore_check_constraints", SQLITE_IgnoreChecks }, #endif /* The following is VERY experimental */ { "writable_schema", SQLITE_WriteSchema|SQLITE_RecoveryMode }, |
︙ | ︙ | |||
92716 92717 92718 92719 92720 92721 92722 | ** 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 ){ | | > > > | 93044 93045 93046 93047 93048 93049 93050 93051 93052 93053 93054 93055 93056 93057 93058 93059 93060 93061 93062 93063 93064 93065 | ** dflt_value: The default value for the column, if any. */ if( sqlite3StrICmp(zLeft, "table_info")==0 && zRight ){ Table *pTab; if( sqlite3ReadSchema(pParse) ) goto pragma_out; pTab = sqlite3FindTable(db, zRight, zDb); if( pTab ){ int i, k; int nHidden = 0; Column *pCol; Index *pPk; for(pPk=pTab->pIndex; pPk && pPk->autoIndex!=2; pPk=pPk->pNext){} sqlite3VdbeSetNumCols(v, 6); pParse->nMem = 6; sqlite3CodeVerifySchema(pParse, iDb); sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "cid", SQLITE_STATIC); sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE_STATIC); sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "type", SQLITE_STATIC); sqlite3VdbeSetColName(v, 3, COLNAME_NAME, "notnull", SQLITE_STATIC); sqlite3VdbeSetColName(v, 4, COLNAME_NAME, "dflt_value", SQLITE_STATIC); sqlite3VdbeSetColName(v, 5, COLNAME_NAME, "pk", SQLITE_STATIC); sqlite3ViewGetColumnNames(pParse, pTab); |
︙ | ︙ | |||
92743 92744 92745 92746 92747 92748 92749 | 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); } | > > > > > > > | < > | 93074 93075 93076 93077 93078 93079 93080 93081 93082 93083 93084 93085 93086 93087 93088 93089 93090 93091 93092 93093 93094 93095 93096 93097 93098 93099 93100 93101 93102 93103 93104 93105 93106 93107 93108 93109 93110 93111 | pCol->zType ? pCol->zType : "", 0); sqlite3VdbeAddOp2(v, OP_Integer, (pCol->notNull ? 1 : 0), 4); if( pCol->zDflt ){ sqlite3VdbeAddOp4(v, OP_String8, 0, 5, 0, (char*)pCol->zDflt, 0); }else{ sqlite3VdbeAddOp2(v, OP_Null, 0, 5); } if( (pCol->colFlags & COLFLAG_PRIMKEY)==0 ){ k = 0; }else if( pPk==0 ){ k = 1; }else{ for(k=1; ALWAYS(k<=pTab->nCol) && pPk->aiColumn[k-1]!=i; k++){} } sqlite3VdbeAddOp2(v, OP_Integer, k, 6); sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 6); } } }else if( sqlite3StrICmp(zLeft, "index_info")==0 && zRight ){ Index *pIdx; Table *pTab; if( sqlite3ReadSchema(pParse) ) goto pragma_out; pIdx = sqlite3FindIndex(db, zRight, zDb); if( pIdx ){ int i; pTab = pIdx->pTable; sqlite3VdbeSetNumCols(v, 3); pParse->nMem = 3; sqlite3CodeVerifySchema(pParse, iDb); sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seqno", SQLITE_STATIC); sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "cid", SQLITE_STATIC); sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "name", SQLITE_STATIC); for(i=0; i<pIdx->nColumn; i++){ int cnum = pIdx->aiColumn[i]; sqlite3VdbeAddOp2(v, OP_Integer, i, 1); sqlite3VdbeAddOp2(v, OP_Integer, cnum, 2); |
︙ | ︙ | |||
92786 92787 92788 92789 92790 92791 92792 92793 92794 92795 92796 92797 92798 92799 | if( pTab ){ v = sqlite3GetVdbe(pParse); pIdx = pTab->pIndex; if( pIdx ){ int i = 0; sqlite3VdbeSetNumCols(v, 3); pParse->nMem = 3; sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", SQLITE_STATIC); sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE_STATIC); sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "unique", SQLITE_STATIC); while(pIdx){ sqlite3VdbeAddOp2(v, OP_Integer, i, 1); sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, pIdx->zName, 0); sqlite3VdbeAddOp2(v, OP_Integer, pIdx->onError!=OE_None, 3); | > | 93124 93125 93126 93127 93128 93129 93130 93131 93132 93133 93134 93135 93136 93137 93138 | if( pTab ){ v = sqlite3GetVdbe(pParse); pIdx = pTab->pIndex; if( pIdx ){ int i = 0; sqlite3VdbeSetNumCols(v, 3); pParse->nMem = 3; sqlite3CodeVerifySchema(pParse, iDb); sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", SQLITE_STATIC); sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE_STATIC); sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "unique", SQLITE_STATIC); while(pIdx){ sqlite3VdbeAddOp2(v, OP_Integer, i, 1); sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, pIdx->zName, 0); sqlite3VdbeAddOp2(v, OP_Integer, pIdx->onError!=OE_None, 3); |
︙ | ︙ | |||
92849 92850 92851 92852 92853 92854 92855 92856 92857 92858 92859 92860 92861 92862 | if( pTab ){ v = sqlite3GetVdbe(pParse); pFK = pTab->pFKey; if( pFK ){ int i = 0; sqlite3VdbeSetNumCols(v, 8); pParse->nMem = 8; sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "id", SQLITE_STATIC); sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "seq", SQLITE_STATIC); sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "table", SQLITE_STATIC); sqlite3VdbeSetColName(v, 3, COLNAME_NAME, "from", SQLITE_STATIC); sqlite3VdbeSetColName(v, 4, COLNAME_NAME, "to", SQLITE_STATIC); sqlite3VdbeSetColName(v, 5, COLNAME_NAME, "on_update", SQLITE_STATIC); sqlite3VdbeSetColName(v, 6, COLNAME_NAME, "on_delete", SQLITE_STATIC); | > | 93188 93189 93190 93191 93192 93193 93194 93195 93196 93197 93198 93199 93200 93201 93202 | if( pTab ){ v = sqlite3GetVdbe(pParse); pFK = pTab->pFKey; if( pFK ){ int i = 0; sqlite3VdbeSetNumCols(v, 8); pParse->nMem = 8; sqlite3CodeVerifySchema(pParse, iDb); sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "id", SQLITE_STATIC); sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "seq", SQLITE_STATIC); sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "table", SQLITE_STATIC); sqlite3VdbeSetColName(v, 3, COLNAME_NAME, "from", SQLITE_STATIC); sqlite3VdbeSetColName(v, 4, COLNAME_NAME, "to", SQLITE_STATIC); sqlite3VdbeSetColName(v, 5, COLNAME_NAME, "on_update", SQLITE_STATIC); sqlite3VdbeSetColName(v, 6, COLNAME_NAME, "on_delete", SQLITE_STATIC); |
︙ | ︙ | |||
92882 92883 92884 92885 92886 92887 92888 92889 92890 92891 92892 92893 92894 92895 | 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: "); }else{ sqlite3ParserTrace(0, 0); | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 93222 93223 93224 93225 93226 93227 93228 93229 93230 93231 93232 93233 93234 93235 93236 93237 93238 93239 93240 93241 93242 93243 93244 93245 93246 93247 93248 93249 93250 93251 93252 93253 93254 93255 93256 93257 93258 93259 93260 93261 93262 93263 93264 93265 93266 93267 93268 93269 93270 93271 93272 93273 93274 93275 93276 93277 93278 93279 93280 93281 93282 93283 93284 93285 93286 93287 93288 93289 93290 93291 93292 93293 93294 93295 93296 93297 93298 93299 93300 93301 93302 93303 93304 93305 93306 93307 93308 93309 93310 93311 93312 93313 93314 93315 93316 93317 93318 93319 93320 93321 93322 93323 93324 93325 93326 93327 93328 93329 93330 93331 93332 93333 93334 93335 93336 93337 93338 93339 93340 93341 93342 93343 93344 93345 93346 93347 93348 93349 93350 93351 | pFK = pFK->pNextFrom; } } } }else #endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */ #ifndef SQLITE_OMIT_FOREIGN_KEY #ifndef SQLITE_OMIT_TRIGGER if( sqlite3StrICmp(zLeft, "foreign_key_check")==0 ){ FKey *pFK; /* A foreign key constraint */ Table *pTab; /* Child table contain "REFERENCES" keyword */ Table *pParent; /* Parent table that child points to */ Index *pIdx; /* Index in the parent table */ int i; /* Loop counter: Foreign key number for pTab */ int j; /* Loop counter: Field of the foreign key */ HashElem *k; /* Loop counter: Next table in schema */ int x; /* result variable */ int regResult; /* 3 registers to hold a result row */ int regKey; /* Register to hold key for checking the FK */ int regRow; /* Registers to hold a row from pTab */ int addrTop; /* Top of a loop checking foreign keys */ int addrOk; /* Jump here if the key is OK */ int *aiCols; /* child to parent column mapping */ if( sqlite3ReadSchema(pParse) ) goto pragma_out; regResult = pParse->nMem+1; pParse->nMem += 4; regKey = ++pParse->nMem; regRow = ++pParse->nMem; v = sqlite3GetVdbe(pParse); sqlite3VdbeSetNumCols(v, 4); sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "table", SQLITE_STATIC); sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "rowid", SQLITE_STATIC); sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "parent", SQLITE_STATIC); sqlite3VdbeSetColName(v, 3, COLNAME_NAME, "fkid", SQLITE_STATIC); sqlite3CodeVerifySchema(pParse, iDb); k = sqliteHashFirst(&db->aDb[iDb].pSchema->tblHash); while( k ){ if( zRight ){ pTab = sqlite3LocateTable(pParse, 0, zRight, zDb); k = 0; }else{ pTab = (Table*)sqliteHashData(k); k = sqliteHashNext(k); } if( pTab==0 || pTab->pFKey==0 ) continue; sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName); if( pTab->nCol+regRow>pParse->nMem ) pParse->nMem = pTab->nCol + regRow; sqlite3OpenTable(pParse, 0, iDb, pTab, OP_OpenRead); sqlite3VdbeAddOp4(v, OP_String8, 0, regResult, 0, pTab->zName, P4_TRANSIENT); for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){ pParent = sqlite3LocateTable(pParse, 0, pFK->zTo, zDb); if( pParent==0 ) break; pIdx = 0; sqlite3TableLock(pParse, iDb, pParent->tnum, 0, pParent->zName); x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, 0); if( x==0 ){ if( pIdx==0 ){ sqlite3OpenTable(pParse, i, iDb, pParent, OP_OpenRead); }else{ KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx); sqlite3VdbeAddOp3(v, OP_OpenRead, i, pIdx->tnum, iDb); sqlite3VdbeChangeP4(v, -1, (char*)pKey, P4_KEYINFO_HANDOFF); } }else{ k = 0; break; } } if( pFK ) break; if( pParse->nTab<i ) pParse->nTab = i; addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, 0); for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){ pParent = sqlite3LocateTable(pParse, 0, pFK->zTo, zDb); assert( pParent!=0 ); pIdx = 0; aiCols = 0; x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, &aiCols); assert( x==0 ); addrOk = sqlite3VdbeMakeLabel(v); if( pIdx==0 ){ int iKey = pFK->aCol[0].iFrom; assert( iKey>=0 && iKey<pTab->nCol ); if( iKey!=pTab->iPKey ){ sqlite3VdbeAddOp3(v, OP_Column, 0, iKey, regRow); sqlite3ColumnDefault(v, pTab, iKey, regRow); sqlite3VdbeAddOp2(v, OP_IsNull, regRow, addrOk); sqlite3VdbeAddOp2(v, OP_MustBeInt, regRow, sqlite3VdbeCurrentAddr(v)+3); }else{ sqlite3VdbeAddOp2(v, OP_Rowid, 0, regRow); } sqlite3VdbeAddOp3(v, OP_NotExists, i, 0, regRow); sqlite3VdbeAddOp2(v, OP_Goto, 0, addrOk); sqlite3VdbeJumpHere(v, sqlite3VdbeCurrentAddr(v)-2); }else{ for(j=0; j<pFK->nCol; j++){ sqlite3ExprCodeGetColumnOfTable(v, pTab, 0, aiCols ? aiCols[j] : pFK->aCol[0].iFrom, regRow+j); sqlite3VdbeAddOp2(v, OP_IsNull, regRow+j, addrOk); } sqlite3VdbeAddOp3(v, OP_MakeRecord, regRow, pFK->nCol, regKey); sqlite3VdbeChangeP4(v, -1, sqlite3IndexAffinityStr(v,pIdx), P4_TRANSIENT); sqlite3VdbeAddOp4Int(v, OP_Found, i, addrOk, regKey, 0); } sqlite3VdbeAddOp2(v, OP_Rowid, 0, regResult+1); sqlite3VdbeAddOp4(v, OP_String8, 0, regResult+2, 0, pFK->zTo, P4_TRANSIENT); sqlite3VdbeAddOp2(v, OP_Integer, i-1, regResult+3); sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, 4); sqlite3VdbeResolveLabel(v, addrOk); sqlite3DbFree(db, aiCols); } sqlite3VdbeAddOp2(v, OP_Next, 0, addrTop+1); sqlite3VdbeJumpHere(v, addrTop); } }else #endif /* !defined(SQLITE_OMIT_TRIGGER) */ #endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */ #ifndef NDEBUG if( sqlite3StrICmp(zLeft, "parser_trace")==0 ){ if( zRight ){ if( sqlite3GetBoolean(zRight, 0) ){ sqlite3ParserTrace(stderr, "parser: "); }else{ sqlite3ParserTrace(0, 0); |
︙ | ︙ | |||
93379 93380 93381 93382 93383 93384 93385 | sqlite3_key(db, zKey, i/2); }else{ sqlite3_rekey(db, zKey, i/2); } }else #endif #if defined(SQLITE_HAS_CODEC) || defined(SQLITE_ENABLE_CEROD) | | | 93835 93836 93837 93838 93839 93840 93841 93842 93843 93844 93845 93846 93847 93848 93849 | sqlite3_key(db, zKey, i/2); }else{ sqlite3_rekey(db, zKey, i/2); } }else #endif #if defined(SQLITE_HAS_CODEC) || defined(SQLITE_ENABLE_CEROD) if( sqlite3StrICmp(zLeft, "activate_extensions")==0 && zRight ){ #ifdef SQLITE_HAS_CODEC if( sqlite3StrNICmp(zRight, "see-", 4)==0 ){ sqlite3_activate_see(&zRight[4]); } #endif #ifdef SQLITE_ENABLE_CEROD if( sqlite3StrNICmp(zRight, "cerod-", 6)==0 ){ |
︙ | ︙ | |||
93676 93677 93678 93679 93680 93681 93682 93683 93684 93685 93686 93687 93688 93689 93690 93691 93692 93693 93694 | /* 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; | > > > > | 94132 94133 94134 94135 94136 94137 94138 94139 94140 94141 94142 94143 94144 94145 94146 94147 94148 94149 94150 94151 94152 94153 94154 | /* 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 ){ #ifndef SQLITE_OMIT_UTF16 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 ENC(db) = SQLITE_UTF8; #endif }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; |
︙ | ︙ | |||
94338 94339 94340 94341 94342 94343 94344 | 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 */ | | | 94798 94799 94800 94801 94802 94803 94804 94805 94806 94807 94808 94809 94810 94811 94812 | Parse *pParse, /* Parsing context */ ExprList *pEList, /* which columns to include in the result */ SrcList *pSrc, /* the FROM clause -- which tables to scan */ Expr *pWhere, /* the WHERE clause */ ExprList *pGroupBy, /* the GROUP BY clause */ Expr *pHaving, /* the HAVING clause */ ExprList *pOrderBy, /* the ORDER BY clause */ u16 selFlags, /* Flag parameters, such as SF_Distinct */ Expr *pLimit, /* LIMIT value. NULL means not used */ Expr *pOffset /* OFFSET value. NULL means no offset */ ){ Select *pNew; Select standin; sqlite3 *db = pParse->db; pNew = sqlite3DbMallocZero(db, sizeof(*pNew) ); |
︙ | ︙ | |||
94362 94363 94364 94365 94366 94367 94368 | 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; | | | 94822 94823 94824 94825 94826 94827 94828 94829 94830 94831 94832 94833 94834 94835 94836 | pNew->pEList = pEList; if( pSrc==0 ) pSrc = sqlite3DbMallocZero(db, sizeof(*pSrc)); pNew->pSrc = pSrc; pNew->pWhere = pWhere; pNew->pGroupBy = pGroupBy; pNew->pHaving = pHaving; pNew->pOrderBy = pOrderBy; pNew->selFlags = selFlags; pNew->op = TK_SELECT; pNew->pLimit = pLimit; pNew->pOffset = pOffset; assert( pOffset==0 || pLimit!=0 ); pNew->addrOpenEphm[0] = -1; pNew->addrOpenEphm[1] = -1; pNew->addrOpenEphm[2] = -1; |
︙ | ︙ | |||
95619 95620 95621 95622 95623 95624 95625 | *pnCol = nCol; *paCol = aCol; for(i=0, pCol=aCol; i<nCol; i++, pCol++){ /* Get an appropriate name for the column */ p = sqlite3ExprSkipCollate(pEList->a[i].pExpr); | < < | 96079 96080 96081 96082 96083 96084 96085 96086 96087 96088 96089 96090 96091 96092 | *pnCol = nCol; *paCol = aCol; for(i=0, pCol=aCol; i<nCol; i++, pCol++){ /* Get an appropriate name for the column */ p = sqlite3ExprSkipCollate(pEList->a[i].pExpr); if( (zName = pEList->a[i].zName)!=0 ){ /* If the column contains an "AS <name>" phrase, use <name> as the name */ zName = sqlite3DbStrDup(db, zName); }else{ Expr *pColExpr = p; /* The expression that is the result column name */ Table *pTab; /* Table associated with this expression */ while( pColExpr->op==TK_DOT ){ |
︙ | ︙ | |||
95658 95659 95660 95661 95662 95663 95664 95665 95666 95667 95668 95669 95670 95671 | /* Make sure the column name is unique. If the name is not unique, ** append a integer to the name so that it becomes unique. */ nName = sqlite3Strlen30(zName); for(j=cnt=0; j<i; j++){ if( sqlite3StrICmp(aCol[j].zName, zName)==0 ){ char *zNewName; zName[nName] = 0; zNewName = sqlite3MPrintf(db, "%s:%d", zName, ++cnt); sqlite3DbFree(db, zName); zName = zNewName; j = -1; if( zName==0 ) break; } | > > > | 96116 96117 96118 96119 96120 96121 96122 96123 96124 96125 96126 96127 96128 96129 96130 96131 96132 | /* Make sure the column name is unique. If the name is not unique, ** append a integer to the name so that it becomes unique. */ nName = sqlite3Strlen30(zName); for(j=cnt=0; j<i; j++){ if( sqlite3StrICmp(aCol[j].zName, zName)==0 ){ char *zNewName; int k; for(k=nName-1; k>1 && sqlite3Isdigit(zName[k]); k--){} if( zName[k]==':' ) nName = k; zName[nName] = 0; zNewName = sqlite3MPrintf(db, "%s:%d", zName, ++cnt); sqlite3DbFree(db, zName); zName = zNewName; j = -1; if( zName==0 ) break; } |
︙ | ︙ | |||
95989 95990 95991 95992 95993 95994 95995 95996 95997 95998 95999 96000 96001 96002 | /* Generate code for the left and right SELECT statements. */ switch( p->op ){ case TK_ALL: { int addr = 0; int nLimit; assert( !pPrior->pLimit ); pPrior->pLimit = p->pLimit; pPrior->pOffset = p->pOffset; explainSetInteger(iSub1, pParse->iNextSelectId); rc = sqlite3Select(pParse, pPrior, &dest); p->pLimit = 0; p->pOffset = 0; if( rc ){ | > > | 96450 96451 96452 96453 96454 96455 96456 96457 96458 96459 96460 96461 96462 96463 96464 96465 | /* Generate code for the left and right SELECT statements. */ switch( p->op ){ case TK_ALL: { int addr = 0; int nLimit; assert( !pPrior->pLimit ); pPrior->iLimit = p->iLimit; pPrior->iOffset = p->iOffset; pPrior->pLimit = p->pLimit; pPrior->pOffset = p->pOffset; explainSetInteger(iSub1, pParse->iNextSelectId); rc = sqlite3Select(pParse, pPrior, &dest); p->pLimit = 0; p->pOffset = 0; if( rc ){ |
︙ | ︙ | |||
96646 96647 96648 96649 96650 96651 96652 | ** 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 ); | | > | 97109 97110 97111 97112 97113 97114 97115 97116 97117 97118 97119 97120 97121 97122 97123 97124 | ** 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 = pParse->nMem+1; pParse->nMem += 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); |
︙ | ︙ | |||
96828 96829 96830 96831 96832 96833 96834 | sqlite3VdbeResolveLabel(v, labelCmpr); sqlite3VdbeAddOp4(v, OP_Permutation, 0, 0, 0, (char*)aPermute, P4_INTARRAY); sqlite3VdbeAddOp4(v, OP_Compare, destA.iSdst, destB.iSdst, nOrderBy, (char*)pKeyMerge, P4_KEYINFO_HANDOFF); sqlite3VdbeChangeP5(v, OPFLAG_PERMUTE); sqlite3VdbeAddOp3(v, OP_Jump, addrAltB, addrAeqB, addrAgtB); | < < < < < < | 97292 97293 97294 97295 97296 97297 97298 97299 97300 97301 97302 97303 97304 97305 | sqlite3VdbeResolveLabel(v, labelCmpr); sqlite3VdbeAddOp4(v, OP_Permutation, 0, 0, 0, (char*)aPermute, P4_INTARRAY); sqlite3VdbeAddOp4(v, OP_Compare, destA.iSdst, destB.iSdst, nOrderBy, (char*)pKeyMerge, P4_KEYINFO_HANDOFF); sqlite3VdbeChangeP5(v, OPFLAG_PERMUTE); sqlite3VdbeAddOp3(v, OP_Jump, addrAltB, addrAeqB, addrAgtB); /* Jump to the this point in order to terminate the query. */ sqlite3VdbeResolveLabel(v, labelEnd); /* Set the number of output columns */ if( pDest->eDest==SRT_Output ){ |
︙ | ︙ | |||
97245 97246 97247 97248 97249 97250 97251 97252 97253 97254 97255 97256 97257 97258 97259 97260 97261 97262 97263 97264 | ** ** We call this the "compound-subquery flattening". */ for(pSub=pSub->pPrior; pSub; pSub=pSub->pPrior){ Select *pNew; ExprList *pOrderBy = p->pOrderBy; Expr *pLimit = p->pLimit; Select *pPrior = p->pPrior; p->pOrderBy = 0; p->pSrc = 0; p->pPrior = 0; p->pLimit = 0; pNew = sqlite3SelectDup(db, p, 0); p->pLimit = pLimit; p->pOrderBy = pOrderBy; p->pSrc = pSrc; p->op = TK_ALL; p->pRightmost = 0; if( pNew==0 ){ pNew = pPrior; | > > > | 97703 97704 97705 97706 97707 97708 97709 97710 97711 97712 97713 97714 97715 97716 97717 97718 97719 97720 97721 97722 97723 97724 97725 | ** ** We call this the "compound-subquery flattening". */ for(pSub=pSub->pPrior; pSub; pSub=pSub->pPrior){ Select *pNew; ExprList *pOrderBy = p->pOrderBy; Expr *pLimit = p->pLimit; Expr *pOffset = p->pOffset; Select *pPrior = p->pPrior; p->pOrderBy = 0; p->pSrc = 0; p->pPrior = 0; p->pLimit = 0; p->pOffset = 0; pNew = sqlite3SelectDup(db, p, 0); p->pOffset = pOffset; p->pLimit = pLimit; p->pOrderBy = pOrderBy; p->pSrc = pSrc; p->op = TK_ALL; p->pRightmost = 0; if( pNew==0 ){ pNew = pPrior; |
︙ | ︙ | |||
97443 97444 97445 97446 97447 97448 97449 | sqlite3SelectDelete(db, pSub1); return 1; } #endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */ /* | > | < < < > > | | | > > > > | > > > > | | < < | < < < | | | | > | | > | > > > > | | 97904 97905 97906 97907 97908 97909 97910 97911 97912 97913 97914 97915 97916 97917 97918 97919 97920 97921 97922 97923 97924 97925 97926 97927 97928 97929 97930 97931 97932 97933 97934 97935 97936 97937 97938 97939 97940 97941 97942 97943 97944 97945 97946 97947 97948 97949 97950 97951 97952 97953 97954 | sqlite3SelectDelete(db, pSub1); return 1; } #endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */ /* ** Based on the contents of the AggInfo structure indicated by the first ** argument, this function checks if the following are true: ** ** * the query contains just a single aggregate function, ** * the aggregate function is either min() or max(), and ** * the argument to the aggregate function is a column value. ** ** If all of the above are true, then WHERE_ORDERBY_MIN or WHERE_ORDERBY_MAX ** is returned as appropriate. Also, *ppMinMax is set to point to the ** list of arguments passed to the aggregate before returning. ** ** Or, if the conditions above are not met, *ppMinMax is set to 0 and ** WHERE_ORDERBY_NORMAL is returned. */ static u8 minMaxQuery(AggInfo *pAggInfo, ExprList **ppMinMax){ int eRet = WHERE_ORDERBY_NORMAL; /* Return value */ *ppMinMax = 0; if( pAggInfo->nFunc==1 ){ Expr *pExpr = pAggInfo->aFunc[0].pExpr; /* Aggregate function */ ExprList *pEList = pExpr->x.pList; /* Arguments to agg function */ assert( pExpr->op==TK_AGG_FUNCTION ); if( pEList && pEList->nExpr==1 && pEList->a[0].pExpr->op==TK_AGG_COLUMN ){ const char *zFunc = pExpr->u.zToken; if( sqlite3StrICmp(zFunc, "min")==0 ){ eRet = WHERE_ORDERBY_MIN; *ppMinMax = pEList; }else if( sqlite3StrICmp(zFunc, "max")==0 ){ eRet = WHERE_ORDERBY_MAX; *ppMinMax = pEList; } } } assert( *ppMinMax==0 || (*ppMinMax)->nExpr==1 ); return eRet; } /* ** The select statement passed as the first argument is an aggregate query. ** The second argment is the associated aggregate-info object. This ** function tests if the SELECT is of the form: ** |
︙ | ︙ | |||
97565 97566 97567 97568 97569 97570 97571 97572 97573 97574 97575 | 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; } | > > > | < | 98035 98036 98037 98038 98039 98040 98041 98042 98043 98044 98045 98046 98047 98048 98049 98050 98051 98052 98053 98054 98055 98056 98057 98058 | static int selectExpander(Walker *pWalker, Select *p){ Parse *pParse = pWalker->pParse; int i, j, k; SrcList *pTabList; ExprList *pEList; struct SrcList_item *pFrom; sqlite3 *db = pParse->db; Expr *pE, *pRight, *pExpr; u16 selFlags = p->selFlags; p->selFlags |= SF_Expanded; if( db->mallocFailed ){ return WRC_Abort; } if( NEVER(p->pSrc==0) || (selFlags & SF_Expanded)!=0 ){ return WRC_Prune; } pTabList = p->pSrc; pEList = p->pEList; /* Make sure cursor numbers have been assigned to all entries in ** the FROM clause of the SELECT statement. */ sqlite3SrcListAssignCursors(pParse, pTabList); |
︙ | ︙ | |||
97615 97616 97617 97618 97619 97620 97621 97622 97623 97624 97625 97626 97627 97628 | pTab->tabFlags |= TF_Ephemeral; #endif }else{ /* An ordinary table or view name in the FROM clause */ assert( pFrom->pTab==0 ); pFrom->pTab = pTab = sqlite3LocateTableItem(pParse, 0, pFrom); if( pTab==0 ) return WRC_Abort; pTab->nRef++; #if !defined(SQLITE_OMIT_VIEW) || !defined (SQLITE_OMIT_VIRTUALTABLE) if( pTab->pSelect || IsVirtual(pTab) ){ /* We reach here if the named table is a really a view */ if( sqlite3ViewGetColumnNames(pParse, pTab) ) return WRC_Abort; assert( pFrom->pSelect==0 ); pFrom->pSelect = sqlite3SelectDup(db, pTab->pSelect, 0); | > > > > > > | 98087 98088 98089 98090 98091 98092 98093 98094 98095 98096 98097 98098 98099 98100 98101 98102 98103 98104 98105 98106 | pTab->tabFlags |= TF_Ephemeral; #endif }else{ /* An ordinary table or view name in the FROM clause */ assert( pFrom->pTab==0 ); pFrom->pTab = pTab = sqlite3LocateTableItem(pParse, 0, pFrom); if( pTab==0 ) return WRC_Abort; if( pTab->nRef==0xffff ){ sqlite3ErrorMsg(pParse, "too many references to \"%s\": max 65535", pTab->zName); pFrom->pTab = 0; return WRC_Abort; } pTab->nRef++; #if !defined(SQLITE_OMIT_VIEW) || !defined (SQLITE_OMIT_VIRTUALTABLE) if( pTab->pSelect || IsVirtual(pTab) ){ /* We reach here if the named table is a really a view */ if( sqlite3ViewGetColumnNames(pParse, pTab) ) return WRC_Abort; assert( pFrom->pSelect==0 ); pFrom->pSelect = sqlite3SelectDup(db, pTab->pSelect, 0); |
︙ | ︙ | |||
97650 97651 97652 97653 97654 97655 97656 | ** 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++){ | | > > > > > > > | > | | | < < > > > > > | | | | > > < > > > > > > > > | 98128 98129 98130 98131 98132 98133 98134 98135 98136 98137 98138 98139 98140 98141 98142 98143 98144 98145 98146 98147 98148 98149 98150 98151 98152 98153 98154 98155 98156 98157 98158 98159 98160 98161 98162 98163 98164 98165 98166 98167 98168 98169 98170 98171 98172 98173 98174 98175 98176 98177 98178 98179 98180 98181 98182 98183 98184 98185 98186 98187 98188 98189 98190 98191 98192 98193 98194 98195 98196 98197 98198 98199 98200 98201 98202 98203 98204 98205 98206 98207 98208 98209 98210 98211 98212 98213 98214 98215 98216 98217 98218 98219 98220 98221 98222 98223 98224 98225 98226 98227 98228 98229 98230 98231 | ** The following code just has to locate the TK_ALL expressions and expand ** each one to the list of all columns in all tables. ** ** The first loop just checks to see if there are any "*" operators ** that need expanding. */ for(k=0; k<pEList->nExpr; k++){ pE = pEList->a[k].pExpr; if( pE->op==TK_ALL ) break; assert( pE->op!=TK_DOT || pE->pRight!=0 ); assert( pE->op!=TK_DOT || (pE->pLeft!=0 && pE->pLeft->op==TK_ID) ); if( pE->op==TK_DOT && pE->pRight->op==TK_ALL ) break; } if( k<pEList->nExpr ){ /* ** If we get here it means the result set contains one or more "*" ** operators that need to be expanded. Loop through each expression ** in the result set and expand them one by one. */ struct ExprList_item *a = pEList->a; ExprList *pNew = 0; int flags = pParse->db->flags; int longNames = (flags & SQLITE_FullColNames)!=0 && (flags & SQLITE_ShortColNames)==0; /* When processing FROM-clause subqueries, it is always the case ** that full_column_names=OFF and short_column_names=ON. The ** sqlite3ResultSetOfSelect() routine makes it so. */ assert( (p->selFlags & SF_NestedFrom)==0 || ((flags & SQLITE_FullColNames)==0 && (flags & SQLITE_ShortColNames)!=0) ); for(k=0; k<pEList->nExpr; k++){ pE = a[k].pExpr; pRight = pE->pRight; assert( pE->op!=TK_DOT || pRight!=0 ); if( pE->op!=TK_ALL && (pE->op!=TK_DOT || pRight->op!=TK_ALL) ){ /* This particular expression does not need to be expanded. */ pNew = sqlite3ExprListAppend(pParse, pNew, a[k].pExpr); if( pNew ){ pNew->a[pNew->nExpr-1].zName = a[k].zName; pNew->a[pNew->nExpr-1].zSpan = a[k].zSpan; a[k].zName = 0; a[k].zSpan = 0; } a[k].pExpr = 0; }else{ /* This expression is a "*" or a "TABLE.*" and needs to be ** expanded. */ int tableSeen = 0; /* Set to 1 when TABLE matches */ char *zTName = 0; /* text of name of TABLE */ if( pE->op==TK_DOT ){ assert( pE->pLeft!=0 ); assert( !ExprHasProperty(pE->pLeft, EP_IntValue) ); zTName = pE->pLeft->u.zToken; } for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){ Table *pTab = pFrom->pTab; Select *pSub = pFrom->pSelect; char *zTabName = pFrom->zAlias; const char *zSchemaName = 0; int iDb; if( zTabName==0 ){ zTabName = pTab->zName; } if( db->mallocFailed ) break; if( pSub==0 || (pSub->selFlags & SF_NestedFrom)==0 ){ pSub = 0; if( zTName && sqlite3StrICmp(zTName, zTabName)!=0 ){ continue; } iDb = sqlite3SchemaToIndex(db, pTab->pSchema); zSchemaName = iDb>=0 ? db->aDb[iDb].zName : "*"; } for(j=0; j<pTab->nCol; j++){ char *zName = pTab->aCol[j].zName; char *zColname; /* The computed column name */ char *zToFree; /* Malloced string that needs to be freed */ Token sColname; /* Computed column name as a token */ assert( zName ); if( zTName && pSub && sqlite3MatchSpanName(pSub->pEList->a[j].zSpan, 0, zTName, 0)==0 ){ continue; } /* If a column is marked as 'hidden' (currently only possible ** for virtual tables), do not include it in the expanded ** result-set list. */ if( IsHiddenColumn(&pTab->aCol[j]) ){ assert(IsVirtual(pTab)); continue; } tableSeen = 1; if( i>0 && zTName==0 ){ if( (pFrom->jointype & JT_NATURAL)!=0 && tableAndColumnIndex(pTabList, i, zName, 0, 0) ){ /* In a NATURAL join, omit the join columns from the ** table to the right of the join */ |
︙ | ︙ | |||
97742 97743 97744 97745 97746 97747 97748 97749 97750 97751 97752 97753 97754 97755 97756 97757 97758 97759 97760 97761 97762 97763 97764 97765 97766 | pRight = sqlite3Expr(db, TK_ID, zName); zColname = zName; zToFree = 0; if( longNames || pTabList->nSrc>1 ){ Expr *pLeft; pLeft = sqlite3Expr(db, TK_ID, zTabName); pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight, 0); if( longNames ){ zColname = sqlite3MPrintf(db, "%s.%s", zTabName, zName); zToFree = zColname; } }else{ pExpr = pRight; } pNew = sqlite3ExprListAppend(pParse, pNew, pExpr); sColname.z = zColname; sColname.n = sqlite3Strlen30(zColname); sqlite3ExprListSetName(pParse, pNew, &sColname, 0); sqlite3DbFree(db, zToFree); } } if( !tableSeen ){ if( zTName ){ sqlite3ErrorMsg(pParse, "no such table: %s", zTName); }else{ | > > > > > > > > > > > > > > > > | 98240 98241 98242 98243 98244 98245 98246 98247 98248 98249 98250 98251 98252 98253 98254 98255 98256 98257 98258 98259 98260 98261 98262 98263 98264 98265 98266 98267 98268 98269 98270 98271 98272 98273 98274 98275 98276 98277 98278 98279 98280 | pRight = sqlite3Expr(db, TK_ID, zName); zColname = zName; zToFree = 0; if( longNames || pTabList->nSrc>1 ){ Expr *pLeft; pLeft = sqlite3Expr(db, TK_ID, zTabName); pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight, 0); if( zSchemaName ){ pLeft = sqlite3Expr(db, TK_ID, zSchemaName); pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pExpr, 0); } if( longNames ){ zColname = sqlite3MPrintf(db, "%s.%s", zTabName, zName); zToFree = zColname; } }else{ pExpr = pRight; } pNew = sqlite3ExprListAppend(pParse, pNew, pExpr); sColname.z = zColname; sColname.n = sqlite3Strlen30(zColname); sqlite3ExprListSetName(pParse, pNew, &sColname, 0); if( pNew && (p->selFlags & SF_NestedFrom)!=0 ){ struct ExprList_item *pX = &pNew->a[pNew->nExpr-1]; if( pSub ){ pX->zSpan = sqlite3DbStrDup(db, pSub->pEList->a[j].zSpan); testcase( pX->zSpan==0 ); }else{ pX->zSpan = sqlite3MPrintf(db, "%s.%s.%s", zSchemaName, zTabName, zColname); testcase( pX->zSpan==0 ); } pX->bSpanIsTab = 1; } sqlite3DbFree(db, zToFree); } } if( !tableSeen ){ if( zTName ){ sqlite3ErrorMsg(pParse, "no such table: %s", zTName); }else{ |
︙ | ︙ | |||
97891 97892 97893 97894 97895 97896 97897 97898 97899 97900 97901 97902 97903 97904 | Parse *pParse, /* The parser context */ Select *p, /* The SELECT statement being coded. */ NameContext *pOuterNC /* Name context for container */ ){ sqlite3 *db; if( NEVER(p==0) ) return; db = pParse->db; if( p->selFlags & SF_HasTypeInfo ) return; sqlite3SelectExpand(pParse, p); if( pParse->nErr || db->mallocFailed ) return; sqlite3ResolveSelectNames(pParse, p, pOuterNC); if( pParse->nErr || db->mallocFailed ) return; sqlite3SelectAddTypeInfo(pParse, p); } | > | 98405 98406 98407 98408 98409 98410 98411 98412 98413 98414 98415 98416 98417 98418 98419 | Parse *pParse, /* The parser context */ Select *p, /* The SELECT statement being coded. */ NameContext *pOuterNC /* Name context for container */ ){ sqlite3 *db; if( NEVER(p==0) ) return; db = pParse->db; if( db->mallocFailed ) return; if( p->selFlags & SF_HasTypeInfo ) return; sqlite3SelectExpand(pParse, p); if( pParse->nErr || db->mallocFailed ) return; sqlite3ResolveSelectNames(pParse, p, pOuterNC); if( pParse->nErr || db->mallocFailed ) return; sqlite3SelectAddTypeInfo(pParse, p); } |
︙ | ︙ | |||
98810 98811 98812 98813 98814 98815 98816 | ** ** + 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; | > > > > > | > > > < < | | 99325 99326 99327 99328 99329 99330 99331 99332 99333 99334 99335 99336 99337 99338 99339 99340 99341 99342 99343 99344 99345 99346 99347 99348 99349 | ** ** + The optimizer code in where.c (the thing that decides which ** index or indices to use) should place a different priority on ** satisfying the 'ORDER BY' clause than it does in other cases. ** Refer to code and comments in where.c for details. */ ExprList *pMinMax = 0; u8 flag = WHERE_ORDERBY_NORMAL; assert( p->pGroupBy==0 ); assert( flag==0 ); if( p->pHaving==0 ){ flag = minMaxQuery(&sAggInfo, &pMinMax); } assert( flag==0 || (pMinMax!=0 && pMinMax->nExpr==1) ); if( flag ){ pMinMax = sqlite3ExprListDup(db, pMinMax, 0); pDel = pMinMax; if( pMinMax && !db->mallocFailed ){ pMinMax->a[0].sortOrder = flag!=WHERE_ORDERBY_MIN ?1:0; pMinMax->a[0].pExpr->op = TK_COLUMN; } } |
︙ | ︙ | |||
98970 98971 98972 98973 98974 98975 98976 | } } SQLITE_PRIVATE void sqlite3ExplainSelect(Vdbe *pVdbe, Select *p){ if( p==0 ){ sqlite3ExplainPrintf(pVdbe, "(null-select)"); return; } | | > > > | 99491 99492 99493 99494 99495 99496 99497 99498 99499 99500 99501 99502 99503 99504 99505 99506 99507 99508 | } } SQLITE_PRIVATE void sqlite3ExplainSelect(Vdbe *pVdbe, Select *p){ if( p==0 ){ sqlite3ExplainPrintf(pVdbe, "(null-select)"); return; } while( p->pPrior ){ p->pPrior->pNext = p; p = p->pPrior; } sqlite3ExplainPush(pVdbe); while( p ){ explainOneSelect(pVdbe, p); p = p->pNext; if( p==0 ) break; sqlite3ExplainNL(pVdbe); sqlite3ExplainPrintf(pVdbe, "%s\n", selectOpName(p->op)); |
︙ | ︙ | |||
102547 102548 102549 102550 102551 102552 102553 | 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>" */ | | | | 103071 103072 103073 103074 103075 103076 103077 103078 103079 103080 103081 103082 103083 103084 103085 103086 | typedef struct WhereTerm WhereTerm; struct WhereTerm { Expr *pExpr; /* Pointer to the subexpression that is this term */ int iParent; /* Disable pWC->a[iParent] when this term disabled */ int leftCursor; /* Cursor number of X in "X <op> <expr>" */ union { int leftColumn; /* Column number of X in "X <op> <expr>" */ WhereOrInfo *pOrInfo; /* Extra information if (eOperator & WO_OR)!=0 */ WhereAndInfo *pAndInfo; /* Extra information if (eOperator& WO_AND)!=0 */ } u; u16 eOperator; /* A WO_xx value describing <op> */ u8 wtFlags; /* TERM_xxx bit flags. See below */ u8 nChild; /* Number of children that must disable us */ WhereClause *pWC; /* The clause this term is part of */ Bitmask prereqRight; /* Bitmask of tables used by pExpr->pRight */ Bitmask prereqAll; /* Bitmask of tables referenced by pExpr */ |
︙ | ︙ | |||
102589 102590 102591 102592 102593 102594 102595 | ** 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 */ | < | 103113 103114 103115 103116 103117 103118 103119 103120 103121 103122 103123 103124 103125 103126 | ** There are separate WhereClause objects for the whole clause and for ** the subclauses "(b AND c)" and "(d AND e)". The pOuter field of the ** subclauses points to the WhereClause object for the whole clause. */ struct WhereClause { Parse *pParse; /* The parser context */ WhereMaskSet *pMaskSet; /* Mapping of table cursor numbers to bitmasks */ WhereClause *pOuter; /* Outer conjunction */ u8 op; /* Split operator. TK_AND or TK_OR */ u16 wctrlFlags; /* Might include WHERE_AND_ONLY */ int nTerm; /* Number of terms */ int nSlot; /* Number of entries in a[] */ WhereTerm *a; /* Each a[] describes a term of the WHERE cluase */ #if defined(SQLITE_SMALL_STACK) |
︙ | ︙ | |||
102676 102677 102678 102679 102680 102681 102682 102683 102684 102685 102686 102687 102688 102689 | #define WO_LE (WO_EQ<<(TK_LE-TK_EQ)) #define WO_GT (WO_EQ<<(TK_GT-TK_EQ)) #define WO_GE (WO_EQ<<(TK_GE-TK_EQ)) #define WO_MATCH 0x040 #define WO_ISNULL 0x080 #define WO_OR 0x100 /* Two or more OR-connected terms */ #define WO_AND 0x200 /* Two or more AND-connected terms */ #define WO_NOOP 0x800 /* This term does not restrict search space */ #define WO_ALL 0xfff /* Mask of all possible WO_* values */ #define WO_SINGLE 0x0ff /* Mask of all non-compound WO_* values */ /* ** Value for wsFlags returned by bestIndex() and stored in | > | 103199 103200 103201 103202 103203 103204 103205 103206 103207 103208 103209 103210 103211 103212 103213 | #define WO_LE (WO_EQ<<(TK_LE-TK_EQ)) #define WO_GT (WO_EQ<<(TK_GT-TK_EQ)) #define WO_GE (WO_EQ<<(TK_GE-TK_EQ)) #define WO_MATCH 0x040 #define WO_ISNULL 0x080 #define WO_OR 0x100 /* Two or more OR-connected terms */ #define WO_AND 0x200 /* Two or more AND-connected terms */ #define WO_EQUIV 0x400 /* Of the form A==B, both columns */ #define WO_NOOP 0x800 /* This term does not restrict search space */ #define WO_ALL 0xfff /* Mask of all possible WO_* values */ #define WO_SINGLE 0x0ff /* Mask of all non-compound WO_* values */ /* ** Value for wsFlags returned by bestIndex() and stored in |
︙ | ︙ | |||
102702 102703 102704 102705 102706 102707 102708 | #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 */ | | | 103226 103227 103228 103229 103230 103231 103232 103233 103234 103235 103236 103237 103238 103239 103240 | #define WHERE_ROWID_RANGE 0x00002000 /* rowid<EXPR and/or rowid>EXPR */ #define WHERE_COLUMN_EQ 0x00010000 /* x=EXPR or x IN (...) or x IS NULL */ #define WHERE_COLUMN_RANGE 0x00020000 /* x<EXPR and/or x>EXPR */ #define WHERE_COLUMN_IN 0x00040000 /* x IN (...) */ #define WHERE_COLUMN_NULL 0x00080000 /* x IS NULL */ #define WHERE_INDEXED 0x000f0000 /* Anything that uses an index */ #define WHERE_NOT_FULLSCAN 0x100f3000 /* Does not do a full table scan */ #define WHERE_IN_ABLE 0x080f1000 /* Able to support an IN operator */ #define WHERE_TOP_LIMIT 0x00100000 /* x<EXPR or x<=EXPR constraint */ #define WHERE_BTM_LIMIT 0x00200000 /* x>EXPR or x>=EXPR constraint */ #define WHERE_BOTH_LIMIT 0x00300000 /* Both x>EXPR and x<EXPR */ #define WHERE_IDX_ONLY 0x00400000 /* Use index only - omit table */ #define WHERE_ORDERED 0x00800000 /* Output will appear in correct order */ #define WHERE_REVERSE 0x01000000 /* Scan in reverse order */ #define WHERE_UNIQUE 0x02000000 /* Selects no more than one row */ |
︙ | ︙ | |||
102765 102766 102767 102768 102769 102770 102771 | ){ pWC->pParse = pParse; pWC->pMaskSet = pMaskSet; pWC->pOuter = 0; pWC->nTerm = 0; pWC->nSlot = ArraySize(pWC->aStatic); pWC->a = pWC->aStatic; | < | 103289 103290 103291 103292 103293 103294 103295 103296 103297 103298 103299 103300 103301 103302 | ){ pWC->pParse = pParse; pWC->pMaskSet = pMaskSet; pWC->pOuter = 0; pWC->nTerm = 0; pWC->nSlot = ArraySize(pWC->aStatic); pWC->a = pWC->aStatic; pWC->wctrlFlags = wctrlFlags; } /* Forward reference */ static void whereClauseClear(WhereClause*); /* |
︙ | ︙ | |||
103078 103079 103080 103081 103082 103083 103084 103085 103086 103087 103088 103089 103090 103091 103092 103093 | } /* ** 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 */ ){ | > > > > > > > > > > > > > > > > > | > > > > > > > > > | | > > | | | < | > > | | | < | | | > | < | | > > | | | | | | | | | | | | | > | > > | > > > | | > > > > > > > | > > > > > > > > > > > > > > | | 103601 103602 103603 103604 103605 103606 103607 103608 103609 103610 103611 103612 103613 103614 103615 103616 103617 103618 103619 103620 103621 103622 103623 103624 103625 103626 103627 103628 103629 103630 103631 103632 103633 103634 103635 103636 103637 103638 103639 103640 103641 103642 103643 103644 103645 103646 103647 103648 103649 103650 103651 103652 103653 103654 103655 103656 103657 103658 103659 103660 103661 103662 103663 103664 103665 103666 103667 103668 103669 103670 103671 103672 103673 103674 103675 103676 103677 103678 103679 103680 103681 103682 103683 103684 103685 103686 103687 103688 103689 103690 103691 103692 103693 103694 103695 103696 103697 103698 103699 103700 103701 103702 103703 103704 103705 103706 103707 103708 103709 103710 103711 103712 103713 103714 103715 103716 103717 103718 103719 | } /* ** Search for a term in the WHERE clause that is of the form "X <op> <expr>" ** where X is a reference to the iColumn of table iCur and <op> is one of ** the WO_xx operator codes specified by the op parameter. ** Return a pointer to the term. Return 0 if not found. ** ** The term returned might by Y=<expr> if there is another constraint in ** the WHERE clause that specifies that X=Y. Any such constraints will be ** identified by the WO_EQUIV bit in the pTerm->eOperator field. The ** aEquiv[] array holds X and all its equivalents, with each SQL variable ** taking up two slots in aEquiv[]. The first slot is for the cursor number ** and the second is for the column number. There are 22 slots in aEquiv[] ** so that means we can look for X plus up to 10 other equivalent values. ** Hence a search for X will return <expr> if X=A1 and A1=A2 and A2=A3 ** and ... and A9=A10 and A10=<expr>. ** ** If there are multiple terms in the WHERE clause of the form "X <op> <expr>" ** then try for the one with no dependencies on <expr> - in other words where ** <expr> is a constant expression of some kind. Only return entries of ** the form "X <op> Y" where Y is a column in another table if no terms of ** the form "X <op> <const-expr>" exist. If no terms with a constant RHS ** exist, try to return a term that does not use WO_EQUIV. */ static WhereTerm *findTerm( WhereClause *pWC, /* The WHERE clause to be searched */ int iCur, /* Cursor number of LHS */ int iColumn, /* Column number of LHS */ Bitmask notReady, /* RHS must not overlap with this mask */ u32 op, /* Mask of WO_xx values describing operator */ Index *pIdx /* Must be compatible with this index, if not NULL */ ){ WhereTerm *pTerm; /* Term being examined as possible result */ WhereTerm *pResult = 0; /* The answer to return */ WhereClause *pWCOrig = pWC; /* Original pWC value */ int j, k; /* Loop counters */ Expr *pX; /* Pointer to an expression */ Parse *pParse; /* Parsing context */ int iOrigCol = iColumn; /* Original value of iColumn */ int nEquiv = 2; /* Number of entires in aEquiv[] */ int iEquiv = 2; /* Number of entries of aEquiv[] processed so far */ int aEquiv[22]; /* iCur,iColumn and up to 10 other equivalents */ assert( iCur>=0 ); aEquiv[0] = iCur; aEquiv[1] = iColumn; for(;;){ for(pWC=pWCOrig; pWC; pWC=pWC->pOuter){ for(pTerm=pWC->a, k=pWC->nTerm; k; k--, pTerm++){ if( pTerm->leftCursor==iCur && pTerm->u.leftColumn==iColumn ){ if( (pTerm->prereqRight & notReady)==0 && (pTerm->eOperator & op & WO_ALL)!=0 ){ if( iOrigCol>=0 && pIdx && (pTerm->eOperator & WO_ISNULL)==0 ){ CollSeq *pColl; char idxaff; pX = pTerm->pExpr; pParse = pWC->pParse; idxaff = pIdx->pTable->aCol[iOrigCol].affinity; if( !sqlite3IndexAffinityOk(pX, idxaff) ){ continue; } /* Figure out the collation sequence required from an index for ** it to be useful for optimising expression pX. Store this ** value in variable pColl. */ assert(pX->pLeft); pColl = sqlite3BinaryCompareCollSeq(pParse,pX->pLeft,pX->pRight); if( pColl==0 ) pColl = pParse->db->pDfltColl; for(j=0; pIdx->aiColumn[j]!=iOrigCol; j++){ if( NEVER(j>=pIdx->nColumn) ) return 0; } if( sqlite3StrICmp(pColl->zName, pIdx->azColl[j]) ){ continue; } } if( pTerm->prereqRight==0 ){ pResult = pTerm; goto findTerm_success; }else if( pResult==0 ){ pResult = pTerm; } } if( (pTerm->eOperator & WO_EQUIV)!=0 && nEquiv<ArraySize(aEquiv) ){ pX = sqlite3ExprSkipCollate(pTerm->pExpr->pRight); assert( pX->op==TK_COLUMN ); for(j=0; j<nEquiv; j+=2){ if( aEquiv[j]==pX->iTable && aEquiv[j+1]==pX->iColumn ) break; } if( j==nEquiv ){ aEquiv[j] = pX->iTable; aEquiv[j+1] = pX->iColumn; nEquiv += 2; } } } } } if( iEquiv>=nEquiv ) break; iCur = aEquiv[iEquiv++]; iColumn = aEquiv[iEquiv++]; } findTerm_success: return pResult; } /* Forward reference */ static void exprAnalyze(SrcList*, WhereClause*, int); /* ** Call exprAnalyze on all terms in a WHERE clause. |
︙ | ︙ | |||
103311 103312 103313 103314 103315 103316 103317 | ** (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: ** | | | 103891 103892 103893 103894 103895 103896 103897 103898 103899 103900 103901 103902 103903 103904 103905 | ** (B) x=expr1 OR expr2=x OR x=expr3 ** (C) t1.x=t2.y OR (t1.x=t2.z AND t1.y=15) ** (D) x=expr1 OR (y>11 AND y<22 AND z LIKE '*hello*') ** (E) (p.a=1 AND q.b=2 AND r.c=3) OR (p.x=4 AND q.y=5 AND r.z=6) ** ** CASE 1: ** ** If all subterms are of the form T.C=expr for some single column of C and ** a single table T (as shown in example B above) then create a new virtual ** term that is an equivalent IN expression. In other words, if the term ** being analyzed is: ** ** x = expr1 OR expr2 = x OR x = expr3 ** ** then create a new virtual term like this: |
︙ | ︙ | |||
103399 103400 103401 103402 103403 103404 103405 | if( db->mallocFailed ) return; assert( pOrWc->nTerm>=2 ); /* ** Compute the set of tables that might satisfy cases 1 or 2. */ indexable = ~(Bitmask)0; | | < | 103979 103980 103981 103982 103983 103984 103985 103986 103987 103988 103989 103990 103991 103992 103993 103994 103995 103996 | if( db->mallocFailed ) return; assert( pOrWc->nTerm>=2 ); /* ** Compute the set of tables that might satisfy cases 1 or 2. */ indexable = ~(Bitmask)0; chngToIN = ~(Bitmask)0; for(i=pOrWc->nTerm-1, pOrTerm=pOrWc->a; i>=0 && indexable; i--, pOrTerm++){ if( (pOrTerm->eOperator & WO_SINGLE)==0 ){ WhereAndInfo *pAndInfo; assert( (pOrTerm->wtFlags & (TERM_ANDINFO|TERM_ORINFO))==0 ); chngToIN = 0; pAndInfo = sqlite3DbMallocRaw(db, sizeof(*pAndInfo)); if( pAndInfo ){ WhereClause *pAndWC; WhereTerm *pAndTerm; int j; |
︙ | ︙ | |||
103442 103443 103444 103445 103446 103447 103448 | 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; | | | 104021 104022 104023 104024 104025 104026 104027 104028 104029 104030 104031 104032 104033 104034 104035 | Bitmask b; b = getMask(pMaskSet, pOrTerm->leftCursor); if( pOrTerm->wtFlags & TERM_VIRTUAL ){ WhereTerm *pOther = &pOrWc->a[pOrTerm->iParent]; b |= getMask(pMaskSet, pOther->leftCursor); } indexable &= b; if( (pOrTerm->eOperator & WO_EQ)==0 ){ chngToIN = 0; }else{ chngToIN &= b; } } } |
︙ | ︙ | |||
103493 103494 103495 103496 103497 103498 103499 | ** 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++){ | | | 104072 104073 104074 104075 104076 104077 104078 104079 104080 104081 104082 104083 104084 104085 104086 | ** will be recorded in iCursor and iColumn. There might not be any ** such table and column. Set okToChngToIN if an appropriate table ** and column is found but leave okToChngToIN false if not found. */ for(j=0; j<2 && !okToChngToIN; j++){ pOrTerm = pOrWc->a; for(i=pOrWc->nTerm-1; i>=0; i--, pOrTerm++){ assert( pOrTerm->eOperator & WO_EQ ); pOrTerm->wtFlags &= ~TERM_OR_OK; if( pOrTerm->leftCursor==iCursor ){ /* This is the 2-bit case and we are on the second iteration and ** current term is from the first iteration. So skip this term. */ assert( j==1 ); continue; } |
︙ | ︙ | |||
103519 103520 103521 103522 103523 103524 103525 | iCursor = pOrTerm->leftCursor; break; } if( i<0 ){ /* No candidate table+column was found. This can only occur ** on the second iteration */ assert( j==1 ); | | | | 104098 104099 104100 104101 104102 104103 104104 104105 104106 104107 104108 104109 104110 104111 104112 104113 104114 104115 104116 104117 104118 104119 104120 104121 104122 | iCursor = pOrTerm->leftCursor; break; } if( i<0 ){ /* No candidate table+column was found. This can only occur ** on the second iteration */ assert( j==1 ); assert( IsPowerOfTwo(chngToIN) ); assert( chngToIN==getMask(pMaskSet, iCursor) ); break; } testcase( j==1 ); /* We have found a candidate table and column. Check to see if that ** table and column is common to every term in the OR clause */ okToChngToIN = 1; for(; i>=0 && okToChngToIN; i--, pOrTerm++){ assert( pOrTerm->eOperator & WO_EQ ); if( pOrTerm->leftCursor!=iCursor ){ pOrTerm->wtFlags &= ~TERM_OR_OK; }else if( pOrTerm->u.leftColumn!=iColumn ){ okToChngToIN = 0; }else{ int affLeft, affRight; /* If the right-hand side is also a column, then the affinities |
︙ | ︙ | |||
103565 103566 103567 103568 103569 103570 103571 | 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; | | | 104144 104145 104146 104147 104148 104149 104150 104151 104152 104153 104154 104155 104156 104157 104158 | Expr *pDup; /* A transient duplicate expression */ ExprList *pList = 0; /* The RHS of the IN operator */ Expr *pLeft = 0; /* The LHS of the IN operator */ Expr *pNew; /* The complete IN operator */ for(i=pOrWc->nTerm-1, pOrTerm=pOrWc->a; i>=0; i--, pOrTerm++){ if( (pOrTerm->wtFlags & TERM_OR_OK)==0 ) continue; assert( pOrTerm->eOperator & WO_EQ ); assert( pOrTerm->leftCursor==iCursor ); assert( pOrTerm->u.leftColumn==iColumn ); pDup = sqlite3ExprDup(db, pOrTerm->pExpr->pRight, 0); pList = sqlite3ExprListAppend(pWC->pParse, pList, pDup); pLeft = pOrTerm->pExpr->pLeft; } assert( pLeft!=0 ); |
︙ | ︙ | |||
103594 103595 103596 103597 103598 103599 103600 | sqlite3ExprListDelete(db, pList); } pTerm->eOperator = WO_NOOP; /* case 1 trumps case 2 */ } } } #endif /* !SQLITE_OMIT_OR_OPTIMIZATION && !SQLITE_OMIT_SUBQUERY */ | < | 104173 104174 104175 104176 104177 104178 104179 104180 104181 104182 104183 104184 104185 104186 | sqlite3ExprListDelete(db, pList); } pTerm->eOperator = WO_NOOP; /* case 1 trumps case 2 */ } } } #endif /* !SQLITE_OMIT_OR_OPTIMIZATION && !SQLITE_OMIT_SUBQUERY */ /* ** The input to this routine is an WhereTerm structure with only the ** "pExpr" field filled in. The job of this routine is to analyze the ** subexpression and populate all the other fields of the WhereTerm ** structure. ** |
︙ | ︙ | |||
103664 103665 103666 103667 103668 103669 103670 | 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; | | > | > > > > > > > > | | 104242 104243 104244 104245 104246 104247 104248 104249 104250 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 | extraRight = x-1; /* ON clause terms may not be used with an index ** on left table of a LEFT JOIN. Ticket #3015 */ } pTerm->prereqAll = prereqAll; pTerm->leftCursor = -1; pTerm->iParent = -1; pTerm->eOperator = 0; if( allowedOp(op) ){ Expr *pLeft = sqlite3ExprSkipCollate(pExpr->pLeft); Expr *pRight = sqlite3ExprSkipCollate(pExpr->pRight); u16 opMask = (pTerm->prereqRight & prereqLeft)==0 ? WO_ALL : WO_EQUIV; if( pLeft->op==TK_COLUMN ){ pTerm->leftCursor = pLeft->iTable; pTerm->u.leftColumn = pLeft->iColumn; pTerm->eOperator = operatorMask(op) & opMask; } if( pRight && pRight->op==TK_COLUMN ){ WhereTerm *pNew; Expr *pDup; u16 eExtraOp = 0; /* Extra bits for pNew->eOperator */ if( pTerm->leftCursor>=0 ){ int idxNew; pDup = sqlite3ExprDup(db, pExpr, 0); if( db->mallocFailed ){ sqlite3ExprDelete(db, pDup); return; } idxNew = whereClauseInsert(pWC, pDup, TERM_VIRTUAL|TERM_DYNAMIC); if( idxNew==0 ) return; pNew = &pWC->a[idxNew]; pNew->iParent = idxTerm; pTerm = &pWC->a[idxTerm]; pTerm->nChild = 1; pTerm->wtFlags |= TERM_COPIED; if( pExpr->op==TK_EQ && !ExprHasProperty(pExpr, EP_FromJoin) && OptimizationEnabled(db, SQLITE_Transitive) ){ pTerm->eOperator |= WO_EQUIV; eExtraOp = WO_EQUIV; } }else{ pDup = pExpr; pNew = pTerm; } exprCommute(pParse, pDup); pLeft = sqlite3ExprSkipCollate(pDup->pLeft); pNew->leftCursor = pLeft->iTable; pNew->u.leftColumn = pLeft->iColumn; testcase( (prereqLeft | extraRight) != prereqLeft ); pNew->prereqRight = prereqLeft | extraRight; pNew->prereqAll = prereqAll; pNew->eOperator = (operatorMask(pDup->op) + eExtraOp) & opMask; } } #ifndef SQLITE_OMIT_BETWEEN_OPTIMIZATION /* If a term is the BETWEEN operator, create two new virtual terms ** that define the range that the BETWEEN implements. For example: ** |
︙ | ︙ | |||
104159 104160 104161 104162 104163 104164 104165 | } 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++){ | | | | 104746 104747 104748 104749 104750 104751 104752 104753 104754 104755 104756 104757 104758 104759 104760 104761 104762 104763 104764 104765 104766 104767 104768 104769 104770 104771 104772 104773 104774 104775 104776 104777 104778 104779 104780 104781 | } if( pWC->wctrlFlags & WHERE_AND_ONLY ){ return; } /* Search the WHERE clause terms for a usable WO_OR term. */ for(pTerm=pWC->a; pTerm<pWCEnd; pTerm++){ if( (pTerm->eOperator & WO_OR)!=0 && ((pTerm->prereqAll & ~maskSrc) & p->notReady)==0 && (pTerm->u.pOrInfo->indexable & maskSrc)!=0 ){ WhereClause * const pOrWC = &pTerm->u.pOrInfo->wc; WhereTerm * const pOrWCEnd = &pOrWC->a[pOrWC->nTerm]; WhereTerm *pOrTerm; int flags = WHERE_MULTI_OR; double rTotal = 0; double nRow = 0; Bitmask used = 0; WhereBestIdx sBOI; sBOI = *p; sBOI.pOrderBy = 0; sBOI.pDistinct = 0; sBOI.ppIdxInfo = 0; for(pOrTerm=pOrWC->a; pOrTerm<pOrWCEnd; pOrTerm++){ WHERETRACE(("... Multi-index OR testing for term %d of %d....\n", (pOrTerm - pOrWC->a), (pTerm - pWC->a) )); if( (pOrTerm->eOperator& WO_AND)!=0 ){ sBOI.pWC = &pOrTerm->u.pAndInfo->wc; bestIndex(&sBOI); }else if( pOrTerm->leftCursor==iCur ){ WhereClause tempWC; tempWC.pParse = pWC->pParse; tempWC.pMaskSet = pWC->pMaskSet; tempWC.pOuter = pWC; |
︙ | ︙ | |||
104241 104242 104243 104244 104245 104246 104247 | 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; | | | 104828 104829 104830 104831 104832 104833 104834 104835 104836 104837 104838 104839 104840 104841 104842 | static int termCanDriveIndex( WhereTerm *pTerm, /* WHERE clause term to check */ struct SrcList_item *pSrc, /* Table we are trying to access */ Bitmask notReady /* Tables in outer loops of the join */ ){ char aff; if( pTerm->leftCursor!=pSrc->iCursor ) return 0; if( (pTerm->eOperator & WO_EQ)==0 ) return 0; if( (pTerm->prereqRight & notReady)!=0 ) return 0; aff = pSrc->pTab->aCol[pTerm->u.leftColumn].affinity; if( !sqlite3IndexAffinityOk(pTerm->pExpr, aff) ) return 0; return 1; } #endif |
︙ | ︙ | |||
104503 104504 104505 104506 104507 104508 104509 | 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; | | | | | | 105090 105091 105092 105093 105094 105095 105096 105097 105098 105099 105100 105101 105102 105103 105104 105105 105106 105107 | WHERETRACE(("Recomputing index info for %s...\n", pSrc->pTab->zName)); /* Count the number of possible WHERE clause constraints referring ** to this virtual table */ for(i=nTerm=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){ if( pTerm->leftCursor != pSrc->iCursor ) continue; assert( IsPowerOfTwo(pTerm->eOperator & ~WO_EQUIV) ); testcase( pTerm->eOperator & WO_IN ); testcase( pTerm->eOperator & WO_ISNULL ); if( pTerm->eOperator & (WO_ISNULL) ) continue; if( pTerm->wtFlags & TERM_VNULL ) continue; nTerm++; } /* If the ORDER BY clause contains only columns in the current ** virtual table then allocate space for the aOrderBy part of ** the sqlite3_index_info structure. |
︙ | ︙ | |||
104554 104555 104556 104557 104558 104559 104560 104561 | *(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; | > | | | | > > | | | 105141 105142 105143 105144 105145 105146 105147 105148 105149 105150 105151 105152 105153 105154 105155 105156 105157 105158 105159 105160 105161 105162 105163 105164 105165 105166 105167 105168 105169 105170 105171 105172 105173 105174 105175 105176 | *(int*)&pIdxInfo->nOrderBy = nOrderBy; *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint = pIdxCons; *(struct sqlite3_index_orderby**)&pIdxInfo->aOrderBy = pIdxOrderBy; *(struct sqlite3_index_constraint_usage**)&pIdxInfo->aConstraintUsage = pUsage; for(i=j=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){ u8 op; if( pTerm->leftCursor != pSrc->iCursor ) continue; assert( IsPowerOfTwo(pTerm->eOperator & ~WO_EQUIV) ); testcase( pTerm->eOperator & WO_IN ); testcase( pTerm->eOperator & WO_ISNULL ); if( pTerm->eOperator & (WO_ISNULL) ) continue; if( pTerm->wtFlags & TERM_VNULL ) continue; pIdxCons[j].iColumn = pTerm->u.leftColumn; pIdxCons[j].iTermOffset = i; op = (u8)pTerm->eOperator & WO_ALL; if( op==WO_IN ) op = WO_EQ; pIdxCons[j].op = op; /* The direct assignment in the previous line is possible only because ** the WO_ and SQLITE_INDEX_CONSTRAINT_ codes are identical. The ** following asserts verify this fact. */ assert( WO_EQ==SQLITE_INDEX_CONSTRAINT_EQ ); assert( WO_LT==SQLITE_INDEX_CONSTRAINT_LT ); assert( WO_LE==SQLITE_INDEX_CONSTRAINT_LE ); assert( WO_GT==SQLITE_INDEX_CONSTRAINT_GT ); assert( WO_GE==SQLITE_INDEX_CONSTRAINT_GE ); assert( WO_MATCH==SQLITE_INDEX_CONSTRAINT_MATCH ); assert( pTerm->eOperator & (WO_IN|WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE|WO_MATCH) ); j++; } for(i=0; i<nOrderBy; i++){ Expr *pExpr = pOrderBy->a[i].pExpr; pIdxOrderBy[i].iColumn = pExpr->iColumn; pIdxOrderBy[i].desc = pOrderBy->a[i].sortOrder; } |
︙ | ︙ | |||
104656 104657 104658 104659 104660 104661 104662 | WhereClause *pWC = p->pWC; /* The WHERE clause */ struct SrcList_item *pSrc = p->pSrc; /* The FROM clause term to search */ Table *pTab = pSrc->pTab; sqlite3_index_info *pIdxInfo; struct sqlite3_index_constraint *pIdxCons; struct sqlite3_index_constraint_usage *pUsage; WhereTerm *pTerm; | | > > | 105246 105247 105248 105249 105250 105251 105252 105253 105254 105255 105256 105257 105258 105259 105260 105261 105262 105263 | WhereClause *pWC = p->pWC; /* The WHERE clause */ struct SrcList_item *pSrc = p->pSrc; /* The FROM clause term to search */ Table *pTab = pSrc->pTab; sqlite3_index_info *pIdxInfo; struct sqlite3_index_constraint *pIdxCons; struct sqlite3_index_constraint_usage *pUsage; WhereTerm *pTerm; int i, j, k; int nOrderBy; int sortOrder; /* Sort order for IN clauses */ int bAllowIN; /* Allow IN optimizations */ double rCost; /* Make sure wsFlags is initialized to some sane value. Otherwise, if the ** malloc in allocateIndexInfo() fails and this function returns leaving ** wsFlags in an uninitialized state, the caller may behave unpredictably. */ memset(&p->cost, 0, sizeof(p->cost)); |
︙ | ︙ | |||
104692 104693 104694 104695 104696 104697 104698 | /* 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) ); | > > > > > > > > > > > | | | | | | | | | | | | | | | | | | | | | | | | | > > > | > > > | | | | | | | | | | | | | | | | | | | | > | | | > > | > > > > > > > | > > > > | | > > > > > > | 105284 105285 105286 105287 105288 105289 105290 105291 105292 105293 105294 105295 105296 105297 105298 105299 105300 105301 105302 105303 105304 105305 105306 105307 105308 105309 105310 105311 105312 105313 105314 105315 105316 105317 105318 105319 105320 105321 105322 105323 105324 105325 105326 105327 105328 105329 105330 105331 105332 105333 105334 105335 105336 105337 105338 105339 105340 105341 105342 105343 105344 105345 105346 105347 105348 105349 105350 105351 105352 105353 105354 105355 105356 105357 105358 105359 105360 105361 105362 105363 105364 105365 105366 105367 105368 105369 105370 105371 105372 105373 105374 105375 105376 105377 105378 105379 105380 105381 105382 105383 105384 105385 105386 105387 | /* The module name must be defined. Also, by this point there must ** be a pointer to an sqlite3_vtab structure. Otherwise ** sqlite3ViewGetColumnNames() would have picked up the error. */ assert( pTab->azModuleArg && pTab->azModuleArg[0] ); assert( sqlite3GetVTable(pParse->db, pTab) ); /* Try once or twice. On the first attempt, allow IN optimizations. ** If an IN optimization is accepted by the virtual table xBestIndex ** method, but the pInfo->aConstrainUsage.omit flag is not set, then ** the query will not work because it might allow duplicate rows in ** output. In that case, run the xBestIndex method a second time ** without the IN constraints. Usually this loop only runs once. ** The loop will exit using a "break" statement. */ for(bAllowIN=1; 1; bAllowIN--){ assert( bAllowIN==0 || bAllowIN==1 ); /* Set the aConstraint[].usable fields and initialize all ** output variables to zero. ** ** aConstraint[].usable is true for constraints where the right-hand ** side contains only references to tables to the left of the current ** table. In other words, if the constraint is of the form: ** ** column = expr ** ** and we are evaluating a join, then the constraint on column is ** only valid if all tables referenced in expr occur to the left ** of the table containing column. ** ** The aConstraints[] array contains entries for all constraints ** on the current table. That way we only have to compute it once ** even though we might try to pick the best index multiple times. ** For each attempt at picking an index, the order of tables in the ** join might be different so we have to recompute the usable flag ** each time. */ pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint; pUsage = pIdxInfo->aConstraintUsage; for(i=0; i<pIdxInfo->nConstraint; i++, pIdxCons++){ j = pIdxCons->iTermOffset; pTerm = &pWC->a[j]; if( (pTerm->prereqRight&p->notReady)==0 && (bAllowIN || (pTerm->eOperator & WO_IN)==0) ){ pIdxCons->usable = 1; }else{ pIdxCons->usable = 0; } } memset(pUsage, 0, sizeof(pUsage[0])*pIdxInfo->nConstraint); if( pIdxInfo->needToFreeIdxStr ){ sqlite3_free(pIdxInfo->idxStr); } pIdxInfo->idxStr = 0; pIdxInfo->idxNum = 0; pIdxInfo->needToFreeIdxStr = 0; pIdxInfo->orderByConsumed = 0; /* ((double)2) In case of SQLITE_OMIT_FLOATING_POINT... */ pIdxInfo->estimatedCost = SQLITE_BIG_DBL / ((double)2); nOrderBy = pIdxInfo->nOrderBy; if( !p->pOrderBy ){ pIdxInfo->nOrderBy = 0; } if( vtabBestIndex(pParse, pTab, pIdxInfo) ){ return; } sortOrder = SQLITE_SO_ASC; pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint; for(i=0; i<pIdxInfo->nConstraint; i++, pIdxCons++){ if( pUsage[i].argvIndex>0 ){ j = pIdxCons->iTermOffset; pTerm = &pWC->a[j]; p->cost.used |= pTerm->prereqRight; if( (pTerm->eOperator & WO_IN)!=0 ){ if( pUsage[i].omit==0 ){ /* Do not attempt to use an IN constraint if the virtual table ** says that the equivalent EQ constraint cannot be safely omitted. ** If we do attempt to use such a constraint, some rows might be ** repeated in the output. */ break; } for(k=0; k<pIdxInfo->nOrderBy; k++){ if( pIdxInfo->aOrderBy[k].iColumn==pIdxCons->iColumn ){ sortOrder = pIdxInfo->aOrderBy[k].desc; break; } } } } } if( i>=pIdxInfo->nConstraint ) break; } /* If there is an ORDER BY clause, and the selected virtual table index ** does not satisfy it, increase the cost of the scan accordingly. This ** matches the processing for non-virtual tables in bestBtreeIndex(). */ rCost = pIdxInfo->estimatedCost; if( p->pOrderBy && pIdxInfo->orderByConsumed==0 ){ rCost += estLog(rCost)*rCost; |
︙ | ︙ | |||
104768 104769 104770 104771 104772 104773 104774 | if( (SQLITE_BIG_DBL/((double)2))<rCost ){ p->cost.rCost = (SQLITE_BIG_DBL/((double)2)); }else{ p->cost.rCost = rCost; } p->cost.plan.u.pVtabIdx = pIdxInfo; if( pIdxInfo->orderByConsumed ){ | > | | 105397 105398 105399 105400 105401 105402 105403 105404 105405 105406 105407 105408 105409 105410 105411 105412 | if( (SQLITE_BIG_DBL/((double)2))<rCost ){ p->cost.rCost = (SQLITE_BIG_DBL/((double)2)); }else{ p->cost.rCost = rCost; } p->cost.plan.u.pVtabIdx = pIdxInfo; if( pIdxInfo->orderByConsumed ){ assert( sortOrder==0 || sortOrder==1 ); p->cost.plan.wsFlags |= WHERE_ORDERED + sortOrder*WHERE_REVERSE; p->cost.plan.nOBSat = nOrderBy; }else{ p->cost.plan.nOBSat = p->i ? p->aLevel[p->i-1].plan.nOBSat : 0; } p->cost.plan.nEq = 0; pIdxInfo->nOrderBy = nOrderBy; |
︙ | ︙ | |||
105039 105040 105041 105042 105043 105044 105045 | 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); | | | | | | 105669 105670 105671 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 | tRowcnt iUpper = p->aiRowEst[0]; tRowcnt a[2]; u8 aff = p->pTable->aCol[p->aiColumn[0]].affinity; if( pLower ){ Expr *pExpr = pLower->pExpr->pRight; rc = valueFromExpr(pParse, pExpr, aff, &pRangeVal); assert( (pLower->eOperator & (WO_GT|WO_GE))!=0 ); if( rc==SQLITE_OK && whereKeyStats(pParse, p, pRangeVal, 0, a)==SQLITE_OK ){ iLower = a[0]; if( (pLower->eOperator & WO_GT)!=0 ) iLower += a[1]; } sqlite3ValueFree(pRangeVal); } if( rc==SQLITE_OK && pUpper ){ Expr *pExpr = pUpper->pExpr->pRight; rc = valueFromExpr(pParse, pExpr, aff, &pRangeVal); assert( (pUpper->eOperator & (WO_LT|WO_LE))!=0 ); if( rc==SQLITE_OK && whereKeyStats(pParse, p, pRangeVal, 1, a)==SQLITE_OK ){ iUpper = a[0]; if( (pUpper->eOperator & WO_LE)!=0 ) iUpper += a[1]; } sqlite3ValueFree(pRangeVal); } if( rc==SQLITE_OK ){ if( iUpper<=iLower ){ *pRangeDiv = (double)p->aiRowEst[0]; }else{ |
︙ | ︙ | |||
105364 105365 105366 105367 105368 105369 105370 | /* 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; | | | < < < | | 105994 105995 105996 105997 105998 105999 106000 106001 106002 106003 106004 106005 106006 106007 106008 106009 106010 | /* If X is the column in the index and ORDER BY clause, check to see ** if there are any X= or X IS NULL constraints in the WHERE clause. */ pConstraint = findTerm(p->pWC, base, iColumn, p->notReady, WO_EQ|WO_ISNULL|WO_IN, pIdx); if( pConstraint==0 ){ isEq = 0; }else if( (pConstraint->eOperator & WO_IN)!=0 ){ isEq = 0; }else if( (pConstraint->eOperator & WO_ISNULL)!=0 ){ uniqueNotNull = 0; isEq = 1; /* "X IS NULL" means X has only a single value */ }else if( pConstraint->prereqRight==0 ){ isEq = 1; /* Constraint "X=constant" means X has only a single value */ }else{ Expr *pRight = pConstraint->pExpr->pRight; if( pRight->op==TK_COLUMN ){ |
︙ | ︙ | |||
105672 105673 105674 105675 105676 105677 105678 | /* 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 | | | | 106299 106300 106301 106302 106303 106304 106305 106306 106307 106308 106309 106310 106311 106312 106313 106314 | /* 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 ){ |
︙ | ︙ | |||
105782 105783 105784 105785 105786 105787 105788 | ** 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) ){ | | | > | | 106409 106410 106411 106412 106413 106414 106415 106416 106417 106418 106419 106420 106421 106422 106423 106424 106425 106426 106427 106428 106429 | ** to get a better estimate on the number of rows based on ** VALUE and how common that value is according to the histogram. */ if( pc.plan.nRow>(double)1 && pc.plan.nEq==1 && pFirstTerm!=0 && aiRowEst[1]>1 ){ assert( (pFirstTerm->eOperator & (WO_EQ|WO_ISNULL|WO_IN))!=0 ); if( pFirstTerm->eOperator & (WO_EQ|WO_ISNULL) ){ testcase( pFirstTerm->eOperator & WO_EQ ); testcase( pFirstTerm->eOperator & WO_EQUIV ); testcase( pFirstTerm->eOperator & WO_ISNULL ); whereEqualScanEst(pParse, pProbe, pFirstTerm->pExpr->pRight, &pc.plan.nRow); }else if( bInEst==0 ){ assert( pFirstTerm->eOperator & WO_IN ); whereInScanEst(pParse, pProbe, pFirstTerm->pExpr->x.pList, &pc.plan.nRow); } } #endif /* SQLITE_ENABLE_STAT3 */ /* Adjust the number of output rows and downward to reflect rows |
︙ | ︙ | |||
105934 105935 105936 105937 105938 105939 105940 | ** 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; } | | | 106562 106563 106564 106565 106566 106567 106568 106569 106570 106571 106572 106573 106574 106575 106576 | ** set size by a factor of 3. Indexed range constraints reduce ** the search space by a larger factor: 4. We make indexed range ** more selective intentionally because of the subjective ** observation that indexed range constraints really are more ** selective in practice, on average. */ pc.plan.nRow /= 3; } }else if( (pTerm->eOperator & WO_NOOP)==0 ){ /* Any other expression lowers the output row count by half */ pc.plan.nRow /= 2; } } if( pc.plan.nRow<2 ) pc.plan.nRow = 2; } |
︙ | ︙ | |||
105986 105987 105988 105989 105990 105991 105992 | 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 ); | | | > | 106614 106615 106616 106617 106618 106619 106620 106621 106622 106623 106624 106625 106626 106627 106628 106629 106630 | assert( p->pOrderBy || (p->cost.plan.wsFlags&WHERE_ORDERED)==0 ); assert( p->cost.plan.u.pIdx==0 || (p->cost.plan.wsFlags&WHERE_ROWID_EQ)==0 ); assert( pSrc->pIndex==0 || p->cost.plan.u.pIdx==0 || p->cost.plan.u.pIdx==pSrc->pIndex ); WHERETRACE((" best index is %s cost=%.1f\n", p->cost.plan.u.pIdx ? p->cost.plan.u.pIdx->zName : "ipk", p->cost.rCost)); bestOrClauseIndex(p); bestAutomaticIndex(p); p->cost.plan.wsFlags |= eqTermMask; } /* |
︙ | ︙ | |||
106012 106013 106014 106015 106016 106017 106018 | */ static void bestIndex(WhereBestIdx *p){ #ifndef SQLITE_OMIT_VIRTUALTABLE if( IsVirtual(p->pSrc->pTab) ){ sqlite3_index_info *pIdxInfo = 0; p->ppIdxInfo = &pIdxInfo; bestVirtualIndex(p); | > | | 106641 106642 106643 106644 106645 106646 106647 106648 106649 106650 106651 106652 106653 106654 106655 106656 | */ static void bestIndex(WhereBestIdx *p){ #ifndef SQLITE_OMIT_VIRTUALTABLE if( IsVirtual(p->pSrc->pTab) ){ sqlite3_index_info *pIdxInfo = 0; p->ppIdxInfo = &pIdxInfo; bestVirtualIndex(p); assert( pIdxInfo!=0 || p->pParse->db->mallocFailed ); if( pIdxInfo && pIdxInfo->needToFreeIdxStr ){ sqlite3_free(pIdxInfo->idxStr); } sqlite3DbFree(p->pParse->db, pIdxInfo); }else #endif { bestBtreeIndex(p); |
︙ | ︙ | |||
106118 106119 106120 106121 106122 106123 106124 | ** 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 */ | | > > > > > > > > > > > > > > > | > | 106748 106749 106750 106751 106752 106753 106754 106755 106756 106757 106758 106759 106760 106761 106762 106763 106764 106765 106766 106767 106768 106769 106770 106771 106772 106773 106774 106775 106776 106777 106778 106779 106780 106781 106782 106783 106784 106785 106786 106787 106788 106789 106790 106791 106792 106793 106794 106795 106796 106797 106798 106799 106800 106801 106802 106803 106804 106805 106806 106807 106808 106809 106810 106811 106812 106813 106814 106815 106816 106817 106818 | ** 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, /* The level of the FROM clause we are working on */ int iEq, /* Index of the equality term within this level */ 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; u8 bRev = (pLevel->plan.wsFlags & WHERE_REVERSE)!=0; if( (pLevel->plan.wsFlags & WHERE_INDEXED)!=0 && pLevel->plan.u.pIdx->aSortOrder[iEq] ){ testcase( iEq==0 ); testcase( iEq==pLevel->plan.u.pIdx->nColumn-1 ); testcase( iEq>0 && iEq+1<pLevel->plan.u.pIdx->nColumn ); testcase( bRev ); bRev = !bRev; } assert( pX->op==TK_IN ); iReg = iTarget; eType = sqlite3FindInIndex(pParse, pX, 0); if( eType==IN_INDEX_INDEX_DESC ){ testcase( bRev ); bRev = !bRev; } iTab = pX->iTable; sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iTab, 0); assert( pLevel->plan.wsFlags & WHERE_IN_ABLE ); if( pLevel->u.in.nIn==0 ){ pLevel->addrNxt = sqlite3VdbeMakeLabel(v); } pLevel->u.in.nIn++; pLevel->u.in.aInLoop = sqlite3DbReallocOrFree(pParse->db, pLevel->u.in.aInLoop, sizeof(pLevel->u.in.aInLoop[0])*pLevel->u.in.nIn); pIn = pLevel->u.in.aInLoop; if( pIn ){ pIn += pLevel->u.in.nIn - 1; pIn->iCur = iTab; if( eType==IN_INDEX_ROWID ){ pIn->addrInTop = sqlite3VdbeAddOp2(v, OP_Rowid, iTab, iReg); }else{ pIn->addrInTop = sqlite3VdbeAddOp3(v, OP_Column, iTab, 0, iReg); } pIn->eEndLoopOp = bRev ? OP_Prev : OP_Next; sqlite3VdbeAddOp1(v, OP_IsNull, iReg); }else{ pLevel->u.in.nIn = 0; } #endif } disableTerm(pLevel, pTerm); |
︙ | ︙ | |||
106253 106254 106255 106256 106257 106258 106259 | 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 */ | | | 106899 106900 106901 106902 106903 106904 106905 106906 106907 106908 106909 106910 106911 106912 106913 | 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, j, regBase+j); if( r1!=regBase+j ){ if( nReg==1 ){ sqlite3ReleaseTempReg(pParse, regBase); regBase = r1; }else{ sqlite3VdbeAddOp2(v, OP_SCopy, r1, regBase+j); } |
︙ | ︙ | |||
106513 106514 106515 106516 106517 106518 106519 106520 106521 106522 106523 106524 106525 106526 106527 106528 106529 106530 106531 | #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 ){ | > > > | > > > > | > | | 107159 107160 107161 107162 107163 107164 107165 107166 107167 107168 107169 107170 107171 107172 107173 107174 107175 107176 107177 107178 107179 107180 107181 107182 107183 107184 107185 107186 107187 107188 107189 107190 107191 107192 107193 107194 107195 107196 107197 107198 107199 107200 107201 107202 | #ifndef SQLITE_OMIT_VIRTUALTABLE if( (pLevel->plan.wsFlags & WHERE_VIRTUALTABLE)!=0 ){ /* Case 0: The table is a virtual-table. Use the VFilter and VNext ** to access the data. */ int iReg; /* P3 Value for OP_VFilter */ int addrNotFound; sqlite3_index_info *pVtabIdx = pLevel->plan.u.pVtabIdx; int nConstraint = pVtabIdx->nConstraint; struct sqlite3_index_constraint_usage *aUsage = pVtabIdx->aConstraintUsage; const struct sqlite3_index_constraint *aConstraint = pVtabIdx->aConstraint; sqlite3ExprCachePush(pParse); iReg = sqlite3GetTempRange(pParse, nConstraint+2); addrNotFound = pLevel->addrBrk; for(j=1; j<=nConstraint; j++){ for(k=0; k<nConstraint; k++){ if( aUsage[k].argvIndex==j ){ int iTarget = iReg+j+1; pTerm = &pWC->a[aConstraint[k].iTermOffset]; if( pTerm->eOperator & WO_IN ){ codeEqualityTerm(pParse, pTerm, pLevel, k, iTarget); addrNotFound = pLevel->addrNxt; }else{ sqlite3ExprCode(pParse, pTerm->pExpr->pRight, iTarget); } break; } } if( k==nConstraint ) break; } sqlite3VdbeAddOp2(v, OP_Integer, pVtabIdx->idxNum, iReg); sqlite3VdbeAddOp2(v, OP_Integer, j-1, iReg+1); sqlite3VdbeAddOp4(v, OP_VFilter, iCur, addrNotFound, iReg, pVtabIdx->idxStr, pVtabIdx->needToFreeIdxStr ? P4_MPRINTF : P4_STATIC); pVtabIdx->needToFreeIdxStr = 0; for(j=0; j<nConstraint; j++){ if( aUsage[j].omit ){ int iTerm = aConstraint[j].iTermOffset; disableTerm(pLevel, &pWC->a[iTerm]); } |
︙ | ︙ | |||
106561 106562 106563 106564 106565 106566 106567 | ** 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 ); | < | > | 107215 107216 107217 107218 107219 107220 107221 107222 107223 107224 107225 107226 107227 107228 107229 107230 107231 107232 107233 107234 107235 | ** we reference multiple rows using a "rowid IN (...)" ** construct. */ iReleaseReg = sqlite3GetTempReg(pParse); pTerm = findTerm(pWC, iCur, -1, notReady, WO_EQ|WO_IN, 0); assert( pTerm!=0 ); assert( pTerm->pExpr!=0 ); assert( omitTable==0 ); testcase( pTerm->wtFlags & TERM_VIRTUAL ); /* EV: R-30575-11662 */ iRowidReg = codeEqualityTerm(pParse, pTerm, pLevel, 0, iReleaseReg); addrNxt = pLevel->addrNxt; sqlite3VdbeAddOp2(v, OP_MustBeInt, iRowidReg, addrNxt); sqlite3VdbeAddOp3(v, OP_NotExists, iCur, addrNxt, iRowidReg); sqlite3ExprCacheAffinityChange(pParse, iRowidReg, 1); 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; |
︙ | ︙ | |||
106952 106953 106954 106955 106956 106957 106958 | 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 ); | | | 107606 107607 107608 107609 107610 107611 107612 107613 107614 107615 107616 107617 107618 107619 107620 | int iRetInit; /* Address of regReturn init */ int untestedTerms = 0; /* Some terms not completely tested */ int ii; /* Loop counter */ Expr *pAndExpr = 0; /* An ".. AND (...)" expression */ pTerm = pLevel->plan.u.pTerm; assert( pTerm!=0 ); assert( pTerm->eOperator & WO_OR ); assert( (pTerm->wtFlags & TERM_ORINFO)!=0 ); pOrWc = &pTerm->u.pOrInfo->wc; pLevel->op = OP_Return; pLevel->p1 = regReturn; /* Set up a new SrcList in pOrTab containing the table being scanned ** by this loop in the a[0] slot and all notReady tables in a[1..] slots. |
︙ | ︙ | |||
107025 107026 107027 107028 107029 107030 107031 | if( pAndExpr ){ pAndExpr = sqlite3PExpr(pParse, TK_AND, 0, pAndExpr, 0); } } for(ii=0; ii<pOrWc->nTerm; ii++){ WhereTerm *pOrTerm = &pOrWc->a[ii]; | | | 107679 107680 107681 107682 107683 107684 107685 107686 107687 107688 107689 107690 107691 107692 107693 | if( pAndExpr ){ pAndExpr = sqlite3PExpr(pParse, TK_AND, 0, pAndExpr, 0); } } for(ii=0; ii<pOrWc->nTerm; ii++){ WhereTerm *pOrTerm = &pOrWc->a[ii]; if( pOrTerm->leftCursor==iCur || (pOrTerm->eOperator & WO_AND)!=0 ){ WhereInfo *pSubWInfo; /* Info for single OR-term scan */ Expr *pOrExpr = pOrTerm->pExpr; if( pAndExpr ){ pAndExpr->pLeft = pOrExpr; pOrExpr = pAndExpr; } /* Loop through table entries that match term pOrTerm. */ |
︙ | ︙ | |||
107403 107404 107405 107406 107407 107408 107409 | ** 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. ** | < < < < < < < < < < < | 108057 108058 108059 108060 108061 108062 108063 108064 108065 108066 108067 108068 108069 108070 108071 108072 108073 108074 108075 108076 108077 | ** the bitmask for all FROM clause terms to the left of the N-th term ** is (X-1). An expression from the ON clause of a LEFT JOIN can use ** its Expr.iRightJoinTable value to find the bitmask of the right table ** of the join. Subtracting one from the right table bitmask gives a ** bitmask for all tables to the left of the join. Knowing the bitmask ** for all tables to the left of a left join is important. Ticket #3015. ** ** Note that bitmasks are created for all pTabList->nSrc tables in ** pTabList, not just the first nTabList tables. nTabList is normally ** equal to pTabList->nSrc but might be shortened to 1 if the ** WHERE_ONETABLE_ONLY flag is set. */ for(ii=0; ii<pTabList->nSrc; ii++){ createMask(pMaskSet, pTabList->a[ii].iCursor); } #ifndef NDEBUG { Bitmask toTheLeft = 0; for(ii=0; ii<pTabList->nSrc; ii++){ Bitmask m = getMask(pMaskSet, pTabList->a[ii].iCursor); assert( (m-1)==toTheLeft ); |
︙ | ︙ | |||
107480 107481 107482 107483 107484 107485 107486 107487 107488 107489 107490 107491 107492 107493 | for(sWBI.i=iFrom=0, pLevel=pWInfo->a; sWBI.i<nTabList; sWBI.i++, pLevel++){ WhereCost bestPlan; /* Most efficient plan seen so far */ Index *pIdx; /* Index for FROM table at pTabItem */ int j; /* For looping over FROM tables */ int bestJ = -1; /* The value of j */ Bitmask m; /* Bitmask value for j or bestJ */ int isOptimal; /* Iterator for optimal/non-optimal search */ int nUnconstrained; /* Number tables without INDEXED BY */ Bitmask notIndexed; /* Mask of tables that cannot use an index */ memset(&bestPlan, 0, sizeof(bestPlan)); bestPlan.rCost = SQLITE_BIG_DBL; WHERETRACE(("*** Begin search for loop %d ***\n", sWBI.i)); | > | 108123 108124 108125 108126 108127 108128 108129 108130 108131 108132 108133 108134 108135 108136 108137 | for(sWBI.i=iFrom=0, pLevel=pWInfo->a; sWBI.i<nTabList; sWBI.i++, pLevel++){ WhereCost bestPlan; /* Most efficient plan seen so far */ Index *pIdx; /* Index for FROM table at pTabItem */ int j; /* For looping over FROM tables */ int bestJ = -1; /* The value of j */ Bitmask m; /* Bitmask value for j or bestJ */ int isOptimal; /* Iterator for optimal/non-optimal search */ int ckOptimal; /* Do the optimal scan check */ int nUnconstrained; /* Number tables without INDEXED BY */ Bitmask notIndexed; /* Mask of tables that cannot use an index */ memset(&bestPlan, 0, sizeof(bestPlan)); bestPlan.rCost = SQLITE_BIG_DBL; WHERETRACE(("*** Begin search for loop %d ***\n", sWBI.i)); |
︙ | ︙ | |||
107514 107515 107516 107517 107518 107519 107520 | ** 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. ** | | < < | | > > > > > > < < < < > > > > > > > > > > > > > > > > > > > > > > | 108158 108159 108160 108161 108162 108163 108164 108165 108166 108167 108168 108169 108170 108171 108172 108173 108174 108175 108176 108177 108178 108179 108180 108181 108182 108183 108184 108185 108186 108187 108188 108189 108190 108191 108192 108193 108194 108195 108196 108197 108198 108199 108200 108201 108202 108203 108204 108205 108206 108207 108208 108209 108210 108211 108212 108213 108214 108215 108216 108217 108218 108219 108220 108221 | ** that do not use indices. But this nRow reduction only happens if the ** table really is the innermost join. ** ** The second loop iteration is only performed if no optimal scan ** strategies were found by the first iteration. This second iteration ** is used to search for the lowest cost scan overall. ** ** Without the optimal scan step (the first iteration) a suboptimal ** plan might be chosen for queries like this: ** ** CREATE TABLE t1(a, b); ** CREATE TABLE t2(c, d); ** SELECT * FROM t2, t1 WHERE t2.rowid = t1.a; ** ** The best strategy is to iterate through table t1 first. However it ** is not possible to determine this with a simple greedy algorithm. ** Since the cost of a linear scan through table t2 is the same ** as the cost of a linear scan through table t1, a simple greedy ** algorithm may choose to use t2 for the outer loop, which is a much ** costlier approach. */ nUnconstrained = 0; notIndexed = 0; /* The optimal scan check only occurs if there are two or more tables ** available to be reordered */ if( iFrom==nTabList-1 ){ ckOptimal = 0; /* Common case of just one table in the FROM clause */ }else{ ckOptimal = -1; for(j=iFrom, sWBI.pSrc=&pTabList->a[j]; j<nTabList; j++, sWBI.pSrc++){ m = getMask(pMaskSet, sWBI.pSrc->iCursor); if( (m & sWBI.notValid)==0 ){ if( j==iFrom ) iFrom++; continue; } if( j>iFrom && (sWBI.pSrc->jointype & (JT_LEFT|JT_CROSS))!=0 ) break; if( ++ckOptimal ) break; if( (sWBI.pSrc->jointype & JT_LEFT)!=0 ) break; } } assert( ckOptimal==0 || ckOptimal==1 ); for(isOptimal=ckOptimal; isOptimal>=0 && bestJ<0; isOptimal--){ for(j=iFrom, sWBI.pSrc=&pTabList->a[j]; j<nTabList; j++, sWBI.pSrc++){ if( j>iFrom && (sWBI.pSrc->jointype & (JT_LEFT|JT_CROSS))!=0 ){ /* This break and one like it in the ckOptimal computation loop ** above prevent table reordering across LEFT and CROSS JOINs. ** The LEFT JOIN case is necessary for correctness. The prohibition ** against reordering across a CROSS JOIN is an SQLite feature that ** allows the developer to control table reordering */ break; } m = getMask(pMaskSet, sWBI.pSrc->iCursor); if( (m & sWBI.notValid)==0 ){ assert( j>iFrom ); continue; } sWBI.notReady = (isOptimal ? m : sWBI.notValid); if( sWBI.pSrc->pIndex==0 ) nUnconstrained++; WHERETRACE((" === trying table %d (%s) with isOptimal=%d ===\n", j, sWBI.pSrc->pTab->zName, isOptimal)); assert( sWBI.pSrc->pTab ); |
︙ | ︙ | |||
107571 107572 107573 107574 107575 107576 107577 | || sWBI.cost.plan.u.pIdx==sWBI.pSrc->pIndex ); if( isOptimal && (sWBI.cost.plan.wsFlags & WHERE_NOT_FULLSCAN)==0 ){ notIndexed |= m; } if( isOptimal ){ pWInfo->a[j].rOptCost = sWBI.cost.rCost; | | | | 108237 108238 108239 108240 108241 108242 108243 108244 108245 108246 108247 108248 108249 108250 108251 108252 | || sWBI.cost.plan.u.pIdx==sWBI.pSrc->pIndex ); if( isOptimal && (sWBI.cost.plan.wsFlags & WHERE_NOT_FULLSCAN)==0 ){ notIndexed |= m; } if( isOptimal ){ pWInfo->a[j].rOptCost = sWBI.cost.rCost; }else if( ckOptimal ){ /* If two or more tables have nearly the same outer loop cost, but ** very different inner loop (optimal) cost, we want to choose ** for the outer loop that table which benefits the least from ** being in the inner loop. The following code scales the ** outer loop cost estimate to accomplish that. */ WHERETRACE((" scaling cost from %.1f to %.1f\n", sWBI.cost.rCost, sWBI.cost.rCost/pWInfo->a[j].rOptCost)); |
︙ | ︙ | |||
107617 107618 107619 107620 107621 107622 107623 | " 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; } | | > > > > > > > > | 108283 108284 108285 108286 108287 108288 108289 108290 108291 108292 108293 108294 108295 108296 108297 108298 108299 108300 108301 108302 108303 108304 108305 108306 108307 108308 108309 | " cost=%.1f, nRow=%.1f, nOBSat=%d, wsFlags=%08x\n", j, sWBI.pSrc->pTab->zName, sWBI.cost.rCost, sWBI.cost.plan.nRow, sWBI.cost.plan.nOBSat, sWBI.cost.plan.wsFlags)); bestPlan = sWBI.cost; bestJ = j; } /* In a join like "w JOIN x LEFT JOIN y JOIN z" make sure that ** table y (and not table z) is always the next inner loop inside ** of table x. */ if( (sWBI.pSrc->jointype & JT_LEFT)!=0 ) break; } } assert( bestJ>=0 ); assert( sWBI.notValid & getMask(pMaskSet, pTabList->a[bestJ].iCursor) ); assert( bestJ==iFrom || (pTabList->a[iFrom].jointype & JT_LEFT)==0 ); testcase( bestJ>iFrom && (pTabList->a[iFrom].jointype & JT_CROSS)!=0 ); testcase( bestJ>iFrom && bestJ<nTabList-1 && (pTabList->a[bestJ+1].jointype & JT_LEFT)!=0 ); WHERETRACE(("*** Optimizer selects table %d (%s) for loop %d with:\n" " cost=%.1f, nRow=%.1f, nOBSat=%d, wsFlags=0x%08x\n", bestJ, pTabList->a[bestJ].pTab->zName, pLevel-pWInfo->a, bestPlan.rCost, bestPlan.plan.nRow, bestPlan.plan.nOBSat, bestPlan.plan.wsFlags)); if( (bestPlan.plan.wsFlags & WHERE_DISTINCT)!=0 ){ assert( pWInfo->eDistinct==0 ); |
︙ | ︙ | |||
107873 107874 107875 107876 107877 107878 107879 | } 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); | | | 108547 108548 108549 108550 108551 108552 108553 108554 108555 108556 108557 108558 108559 108560 108561 | } if( pLevel->plan.wsFlags & WHERE_IN_ABLE && pLevel->u.in.nIn>0 ){ struct InLoop *pIn; int j; sqlite3VdbeResolveLabel(v, pLevel->addrNxt); for(j=pLevel->u.in.nIn, pIn=&pLevel->u.in.aInLoop[j-1]; j>0; j--, pIn--){ sqlite3VdbeJumpHere(v, pIn->addrInTop+1); sqlite3VdbeAddOp2(v, pIn->eEndLoopOp, pIn->iCur, pIn->addrInTop); sqlite3VdbeJumpHere(v, pIn->addrInTop-1); } sqlite3DbFree(db, pLevel->u.in.aInLoop); } sqlite3VdbeResolveLabel(v, pLevel->addrBrk); if( pLevel->iLeftJoin ){ int addr; |
︙ | ︙ | |||
108181 108182 108183 108184 108185 108186 108187 108188 108189 108190 108191 108192 108193 108194 | sqlite3ParserTOKENTYPE yy0; struct LimitVal yy64; Expr* yy122; Select* yy159; IdList* yy180; struct {int value; int mask;} yy207; u8 yy258; struct LikeOp yy318; TriggerStep* yy327; ExprSpan yy342; SrcList* yy347; int yy392; struct TrigEvent yy410; ExprList* yy442; | > | 108855 108856 108857 108858 108859 108860 108861 108862 108863 108864 108865 108866 108867 108868 108869 | sqlite3ParserTOKENTYPE yy0; struct LimitVal yy64; Expr* yy122; Select* yy159; IdList* yy180; struct {int value; int mask;} yy207; u8 yy258; u16 yy305; struct LikeOp yy318; TriggerStep* yy327; ExprSpan yy342; SrcList* yy347; int yy392; struct TrigEvent yy410; ExprList* yy442; |
︙ | ︙ | |||
110131 110132 110133 110134 110135 110136 110137 | 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); | < < < | 110806 110807 110808 110809 110810 110811 110812 110813 110814 110815 110816 110817 110818 110819 110820 110821 110822 110823 110824 110825 110826 110827 110828 | case 31: /* temp ::= */ yytestcase(yyruleno==31); case 69: /* autoinc ::= */ yytestcase(yyruleno==69); case 82: /* defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */ yytestcase(yyruleno==82); case 84: /* init_deferred_pred_opt ::= */ yytestcase(yyruleno==84); case 86: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */ yytestcase(yyruleno==86); case 98: /* defer_subclause_opt ::= */ yytestcase(yyruleno==98); case 109: /* ifexists ::= */ yytestcase(yyruleno==109); case 221: /* between_op ::= BETWEEN */ yytestcase(yyruleno==221); case 224: /* in_op ::= IN */ yytestcase(yyruleno==224); {yygotominor.yy392 = 0;} break; case 29: /* ifnotexists ::= IF NOT EXISTS */ case 30: /* temp ::= TEMP */ yytestcase(yyruleno==30); case 70: /* autoinc ::= AUTOINCR */ yytestcase(yyruleno==70); case 85: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */ yytestcase(yyruleno==85); case 108: /* ifexists ::= IF EXISTS */ yytestcase(yyruleno==108); case 222: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==222); case 225: /* in_op ::= NOT IN */ yytestcase(yyruleno==225); {yygotominor.yy392 = 1;} break; case 32: /* create_table_args ::= LP columnlist conslist_opt RP */ { sqlite3EndTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,0); |
︙ | ︙ | |||
110382 110383 110384 110385 110386 110387 110388 | } 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 */ { | | > > > > > > > | 111054 111055 111056 111057 111058 111059 111060 111061 111062 111063 111064 111065 111066 111067 111068 111069 111070 111071 111072 111073 111074 111075 111076 | } break; case 116: /* multiselect_op ::= UNION ALL */ {yygotominor.yy392 = TK_ALL;} break; case 118: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */ { yygotominor.yy159 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy442,yymsp[-5].minor.yy347,yymsp[-4].minor.yy122,yymsp[-3].minor.yy442,yymsp[-2].minor.yy122,yymsp[-1].minor.yy442,yymsp[-7].minor.yy305,yymsp[0].minor.yy64.pLimit,yymsp[0].minor.yy64.pOffset); } break; case 119: /* distinct ::= DISTINCT */ {yygotominor.yy305 = SF_Distinct;} break; case 120: /* distinct ::= ALL */ case 121: /* distinct ::= */ yytestcase(yyruleno==121); {yygotominor.yy305 = 0;} break; case 122: /* sclp ::= selcollist COMMA */ case 246: /* idxlist_opt ::= LP idxlist RP */ yytestcase(yyruleno==246); {yygotominor.yy442 = yymsp[-1].minor.yy442;} break; case 123: /* sclp ::= */ case 151: /* orderby_opt ::= */ yytestcase(yyruleno==151); |
︙ | ︙ | |||
110453 110454 110455 110456 110457 110458 110459 110460 110461 110462 | 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); | > > > > > > > > > > | | 111132 111133 111134 111135 111136 111137 111138 111139 111140 111141 111142 111143 111144 111145 111146 111147 111148 111149 111150 111151 111152 111153 111154 111155 111156 111157 111158 111159 | yygotominor.yy347 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy347,0,0,&yymsp[-2].minor.yy0,yymsp[-4].minor.yy159,yymsp[-1].minor.yy122,yymsp[0].minor.yy180); } break; case 136: /* seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */ { if( yymsp[-6].minor.yy347==0 && yymsp[-2].minor.yy0.n==0 && yymsp[-1].minor.yy122==0 && yymsp[0].minor.yy180==0 ){ yygotominor.yy347 = yymsp[-4].minor.yy347; }else if( yymsp[-4].minor.yy347->nSrc==1 ){ yygotominor.yy347 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy347,0,0,&yymsp[-2].minor.yy0,0,yymsp[-1].minor.yy122,yymsp[0].minor.yy180); if( yygotominor.yy347 ){ struct SrcList_item *pNew = &yygotominor.yy347->a[yygotominor.yy347->nSrc-1]; struct SrcList_item *pOld = yymsp[-4].minor.yy347->a; pNew->zName = pOld->zName; pNew->zDatabase = pOld->zDatabase; pOld->zName = pOld->zDatabase = 0; } sqlite3SrcListDelete(pParse->db, yymsp[-4].minor.yy347); }else{ Select *pSubquery; sqlite3SrcListShiftJoinType(yymsp[-4].minor.yy347); pSubquery = sqlite3SelectNew(pParse,0,yymsp[-4].minor.yy347,0,0,0,0,SF_NestedFrom,0,0); yygotominor.yy347 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy347,0,0,&yymsp[-2].minor.yy0,pSubquery,yymsp[-1].minor.yy122,yymsp[0].minor.yy180); } } break; case 137: /* dbnm ::= */ case 146: /* indexed_opt ::= */ yytestcase(yyruleno==146); {yygotominor.yy0.z=0; yygotominor.yy0.n=0;} |
︙ | ︙ | |||
110689 110690 110691 110692 110693 110694 110695 | 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); | | | 111378 111379 111380 111381 111382 111383 111384 111385 111386 111387 111388 111389 111390 111391 111392 | case 196: /* expr ::= ID LP distinct exprlist RP */ { if( yymsp[-1].minor.yy442 && yymsp[-1].minor.yy442->nExpr>pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG] ){ sqlite3ErrorMsg(pParse, "too many arguments on function %T", &yymsp[-4].minor.yy0); } yygotominor.yy342.pExpr = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy442, &yymsp[-4].minor.yy0); spanSet(&yygotominor.yy342,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0); if( yymsp[-2].minor.yy305 && yygotominor.yy342.pExpr ){ yygotominor.yy342.pExpr->flags |= EP_Distinct; } } break; case 197: /* expr ::= ID LP STAR RP */ { yygotominor.yy342.pExpr = sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0); |
︙ | ︙ | |||
113624 113625 113626 113627 113628 113629 113630 | sqlite3BtreeRollback(p, tripCode); db->aDb[i].inTrans = 0; } } sqlite3VtabRollback(db); sqlite3EndBenignMalloc(); | | | 114313 114314 114315 114316 114317 114318 114319 114320 114321 114322 114323 114324 114325 114326 114327 | sqlite3BtreeRollback(p, tripCode); db->aDb[i].inTrans = 0; } } sqlite3VtabRollback(db); sqlite3EndBenignMalloc(); if( (db->flags&SQLITE_InternChanges)!=0 && db->init.busy==0 ){ sqlite3ExpirePreparedStatements(db); sqlite3ResetAllSchemasOfConnection(db); } /* Any deferred constraint violations have now been resolved. */ db->nDeferredCons = 0; |
︙ | ︙ | |||
136336 136337 136338 136339 136340 136341 136342 | ** 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 */ | | > > > > > > | 137025 137026 137027 137028 137029 137030 137031 137032 137033 137034 137035 137036 137037 137038 137039 137040 137041 137042 137043 137044 137045 137046 137047 137048 137049 137050 137051 137052 137053 137054 137055 137056 137057 137058 137059 137060 137061 137062 137063 137064 | ** This ensures that each node is stored on a single database page. If the ** database page-size is so large that more than RTREE_MAXCELLS entries ** would fit in a single node, use a smaller node-size. */ static int getNodeSize( sqlite3 *db, /* Database handle */ Rtree *pRtree, /* Rtree handle */ int isCreate, /* True for xCreate, false for xConnect */ char **pzErr /* OUT: Error message, if any */ ){ int rc; char *zSql; if( isCreate ){ int iPageSize = 0; zSql = sqlite3_mprintf("PRAGMA %Q.page_size", pRtree->zDb); rc = getIntFromStmt(db, zSql, &iPageSize); if( rc==SQLITE_OK ){ pRtree->iNodeSize = iPageSize-64; if( (4+pRtree->nBytesPerCell*RTREE_MAXCELLS)<pRtree->iNodeSize ){ pRtree->iNodeSize = 4+pRtree->nBytesPerCell*RTREE_MAXCELLS; } }else{ *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db)); } }else{ zSql = sqlite3_mprintf( "SELECT length(data) FROM '%q'.'%q_node' WHERE nodeno = 1", pRtree->zDb, pRtree->zName ); rc = getIntFromStmt(db, zSql, &pRtree->iNodeSize); if( rc!=SQLITE_OK ){ *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db)); } } sqlite3_free(zSql); return rc; } /* |
︙ | ︙ | |||
136419 136420 136421 136422 136423 136424 136425 | 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. */ | | | 137114 137115 137116 137117 137118 137119 137120 137121 137122 137123 137124 137125 137126 137127 137128 | pRtree->nDim = (argc-4)/2; pRtree->nBytesPerCell = 8 + pRtree->nDim*4*2; pRtree->eCoordType = eCoordType; memcpy(pRtree->zDb, argv[1], nDb); memcpy(pRtree->zName, argv[2], nName); /* Figure out the node size to use. */ rc = getNodeSize(db, pRtree, isCreate, pzErr); /* Create/Connect to the underlying relational database schema. If ** that is successful, call sqlite3_declare_vtab() to configure ** the r-tree table schema. */ if( rc==SQLITE_OK ){ if( (rc = rtreeSqlInit(pRtree, db, argv[1], argv[2], isCreate)) ){ |
︙ | ︙ |
Changes to SQLite.Interop/src/core/sqlite3.h.
︙ | ︙ | |||
103 104 105 106 107 108 109 | ** 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.16" #define SQLITE_VERSION_NUMBER 3007016 #define SQLITE_SOURCE_ID "2013-03-18 11:39:23 66d5f2b76750f3520eb7a495f6247206758f5b90" /* ** 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_v2() 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. |
︙ | ︙ | |||
479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 | #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. | > > > > > > > > > > | 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 | #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_READONLY_ROLLBACK (SQLITE_READONLY | (3<<8)) #define SQLITE_ABORT_ROLLBACK (SQLITE_ABORT | (2<<8)) #define SQLITE_CONSTRAINT_CHECK (SQLITE_CONSTRAINT | (1<<8)) #define SQLITE_CONSTRAINT_COMMITHOOK (SQLITE_CONSTRAINT | (2<<8)) #define SQLITE_CONSTRAINT_FOREIGNKEY (SQLITE_CONSTRAINT | (3<<8)) #define SQLITE_CONSTRAINT_FUNCTION (SQLITE_CONSTRAINT | (4<<8)) #define SQLITE_CONSTRAINT_NOTNULL (SQLITE_CONSTRAINT | (5<<8)) #define SQLITE_CONSTRAINT_PRIMARYKEY (SQLITE_CONSTRAINT | (6<<8)) #define SQLITE_CONSTRAINT_TRIGGER (SQLITE_CONSTRAINT | (7<<8)) #define SQLITE_CONSTRAINT_UNIQUE (SQLITE_CONSTRAINT | (8<<8)) #define SQLITE_CONSTRAINT_VTAB (SQLITE_CONSTRAINT | (9<<8)) /* ** CAPI3REF: Flags For File Open Operations ** ** These bit values are intended for use in the ** 3rd parameter to the [sqlite3_open_v2()] interface and ** in the 4th parameter to the [sqlite3_vfs.xOpen] method. |
︙ | ︙ |
Changes to SQLite.Interop/src/core/sqlite3ext.h.
︙ | ︙ | |||
232 233 234 235 236 237 238 239 240 241 242 243 244 245 | int (*unlock_notify)(sqlite3*,void(*)(void**,int),void*); int (*wal_autocheckpoint)(sqlite3*,int); int (*wal_checkpoint)(sqlite3*,const char*); void *(*wal_hook)(sqlite3*,int(*)(void*,sqlite3*,const char*,int),void*); int (*blob_reopen)(sqlite3_blob*,sqlite3_int64); int (*vtab_config)(sqlite3*,int op,...); int (*vtab_on_conflict)(sqlite3*); }; /* ** The following macros redefine the API routines so that they are ** redirected throught the global sqlite3_api structure. ** ** This header file is also used by the loadext.c source file | > > > > > > > > > > > > > > | 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 | int (*unlock_notify)(sqlite3*,void(*)(void**,int),void*); int (*wal_autocheckpoint)(sqlite3*,int); int (*wal_checkpoint)(sqlite3*,const char*); void *(*wal_hook)(sqlite3*,int(*)(void*,sqlite3*,const char*,int),void*); int (*blob_reopen)(sqlite3_blob*,sqlite3_int64); int (*vtab_config)(sqlite3*,int op,...); int (*vtab_on_conflict)(sqlite3*); /* Version 3.7.16 and later */ int (*close_v2)(sqlite3*); const char *(*db_filename)(sqlite3*,const char*); int (*db_readonly)(sqlite3*,const char*); int (*db_release_memory)(sqlite3*); const char *(*errstr)(int); int (*stmt_busy)(sqlite3_stmt*); int (*stmt_readonly)(sqlite3_stmt*); int (*stricmp)(const char*,const char*); int (*uri_boolean)(const char*,const char*,int); sqlite3_int64 (*uri_int64)(const char*,const char*,sqlite3_int64); const char *(*uri_parameter)(const char*,const char*); char *(*vsnprintf)(int,char*,const char*,va_list); int (*wal_checkpoint_v2)(sqlite3*,const char*,int,int*,int*); }; /* ** The following macros redefine the API routines so that they are ** redirected throught the global sqlite3_api structure. ** ** This header file is also used by the loadext.c source file |
︙ | ︙ | |||
435 436 437 438 439 440 441 442 443 444 445 446 447 | #define sqlite3_unlock_notify sqlite3_api->unlock_notify #define sqlite3_wal_autocheckpoint sqlite3_api->wal_autocheckpoint #define sqlite3_wal_checkpoint sqlite3_api->wal_checkpoint #define sqlite3_wal_hook sqlite3_api->wal_hook #define sqlite3_blob_reopen sqlite3_api->blob_reopen #define sqlite3_vtab_config sqlite3_api->vtab_config #define sqlite3_vtab_on_conflict sqlite3_api->vtab_on_conflict #endif /* SQLITE_CORE */ #define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api = 0; #define SQLITE_EXTENSION_INIT2(v) sqlite3_api = v; #endif /* _SQLITE3EXT_H_ */ | > > > > > > > > > > > > > > | 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 | #define sqlite3_unlock_notify sqlite3_api->unlock_notify #define sqlite3_wal_autocheckpoint sqlite3_api->wal_autocheckpoint #define sqlite3_wal_checkpoint sqlite3_api->wal_checkpoint #define sqlite3_wal_hook sqlite3_api->wal_hook #define sqlite3_blob_reopen sqlite3_api->blob_reopen #define sqlite3_vtab_config sqlite3_api->vtab_config #define sqlite3_vtab_on_conflict sqlite3_api->vtab_on_conflict /* Version 3.7.16 and later */ #define sqlite3_close_v2 sqlite3_api->close_v2 #define sqlite3_db_filename sqlite3_api->db_filename #define sqlite3_db_readonly sqlite3_api->db_readonly #define sqlite3_db_release_memory sqlite3_api->db_release_memory #define sqlite3_errstr sqlite3_api->errstr #define sqlite3_stmt_busy sqlite3_api->stmt_busy #define sqlite3_stmt_readonly sqlite3_api->stmt_readonly #define sqlite3_stricmp sqlite3_api->stricmp #define sqlite3_uri_boolean sqlite3_api->uri_boolean #define sqlite3_uri_int64 sqlite3_api->uri_int64 #define sqlite3_uri_parameter sqlite3_api->uri_parameter #define sqlite3_uri_vsnprintf sqlite3_api->vsnprintf #define sqlite3_wal_checkpoint_v2 sqlite3_api->wal_checkpoint_v2 #endif /* SQLITE_CORE */ #define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api = 0; #define SQLITE_EXTENSION_INIT2(v) sqlite3_api = v; #endif /* _SQLITE3EXT_H_ */ |
Changes to SQLite.Interop/src/win/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 59 60 61 62 63 64 65 66 67 68 | } /* Create a cryptographic context. Use the enhanced provider because it is available on ** most platforms */ static BOOL InitializeProvider() { MUTEX_LOGIC( sqlite3_mutex *pMaster = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER); ) sqlite3_mutex_enter(pMaster); if (g_hProvider) { sqlite3_mutex_leave(pMaster); return TRUE; } if (!CryptAcquireContext(&g_hProvider, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { sqlite3_mutex_leave(pMaster); return FALSE; } sqlite3_mutex_leave(pMaster); return TRUE; } /* Create or update a cryptographic context for a pager. ** This function will automatically determine if the encryption algorithm requires ** extra padding, and if it does, will create a temp buffer big enough to provide ** space to hold it. |
︙ | ︙ | |||
224 225 226 227 228 229 230 | if (!pKey || !nKeyLen) return 0; if (!InitializeProvider()) { return MAXDWORD; } | > > > > | | | | | | | | > > > > | 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 | if (!pKey || !nKeyLen) return 0; if (!InitializeProvider()) { return MAXDWORD; } { MUTEX_LOGIC( sqlite3_mutex *pMaster = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER); ) sqlite3_mutex_enter(pMaster); if (CryptCreateHash(g_hProvider, CALG_SHA1, 0, 0, &hHash)) { if (CryptHashData(hHash, (LPBYTE)pKey, nKeyLen, 0)) { CryptDeriveKey(g_hProvider, CALG_RC4, hHash, 0, &hKey); } CryptDestroyHash(hHash); } sqlite3_mutex_leave(pMaster); } return hKey; } /* Called by sqlite and sqlite3_key_interop to attach a key to a database. */ int sqlite3CodecAttach(sqlite3 *db, int nDb, const void *pKey, int nKeyLen) { int rc = SQLITE_ERROR; |
︙ | ︙ |
Changes to SQLite.Interop/src/win/interop.c.
︙ | ︙ | |||
73 74 75 76 77 78 79 | SQLITE_PRIVATE int logConfigured = 0; SQLITE_PRIVATE void sqlite3InteropLogCallback(void *pArg, int iCode, const char *zMsg){ sqlite3InteropDebug("INTEROP_LOG (%d) %s\n", iCode, zMsg); } #endif | | | 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 | SQLITE_PRIVATE int logConfigured = 0; SQLITE_PRIVATE void sqlite3InteropLogCallback(void *pArg, int iCode, const char *zMsg){ sqlite3InteropDebug("INTEROP_LOG (%d) %s\n", iCode, zMsg); } #endif #if defined(INTEROP_LEGACY_CLOSE) || SQLITE_VERSION_NUMBER < 3007014 SQLITE_PRIVATE void * sqlite3DbMallocZero_interop(sqlite3 *db, int n) { void *p; if (db) { sqlite3_mutex_enter(db->mutex); } p = sqlite3DbMallocZero(db,n); |
︙ | ︙ | |||
118 119 120 121 122 123 124 | 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; | | | 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 | that memory was deallocated. BAD. So, what we need to do is make a copy of each statement, and call finalize() on the copy -- so that the original statement's memory is preserved, and marked as BAD, but we can still manage to finalize everything and forcibly close the database. Later when the GC gets around to calling finalize_interop() on the "bad" statement, we detect that and finish deallocating the pointer. */ SQLITE_API int WINAPI sqlite3_close_interop(sqlite3 *db) { int ret; #if !defined(INTEROP_LEGACY_CLOSE) && SQLITE_VERSION_NUMBER >= 3007014 #if defined(INTEROP_DEBUG) && (INTEROP_DEBUG & INTEROP_DEBUG_CLOSE) sqlite3InteropDebug("sqlite3_close_interop(): calling sqlite3_close_v2(%p)...\n", db); #endif ret = sqlite3_close_v2(db); |
︙ | ︙ | |||
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 | { 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; | > > > > > > > > | 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 | { 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 #if SQLITE_VERSION_NUMBER >= 3003009 n = sqlite3_prepare_v2(db, sql, nbytes, ppstmt, pztail); #else n = sqlite3_prepare(db, sql, nbytes, ppstmt, pztail); #endif #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 #if SQLITE_VERSION_NUMBER >= 3003009 n = sqlite3_prepare16_v2(db, sql, nchars * sizeof(wchar_t), ppstmt, pztail); #else n = sqlite3_prepare16(db, sql, nchars * sizeof(wchar_t), ppstmt, pztail); #endif #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; |
︙ | ︙ | |||
387 388 389 390 391 392 393 | { *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); | | | | | | 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 | { *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 = sqlite3_column_bytes(stmt, iCol); 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 = sqlite3_column_bytes16(stmt, iCol); return pval; } SQLITE_API int WINAPI sqlite3_finalize_interop(sqlite3_stmt *stmt) { int ret; #if !defined(INTEROP_LEGACY_CLOSE) && SQLITE_VERSION_NUMBER >= 3007014 #if defined(INTEROP_DEBUG) && (INTEROP_DEBUG & INTEROP_DEBUG_FINALIZE) Vdbe *p = (Vdbe *)stmt; sqlite3 *db = p->db; sqlite3InteropDebug("sqlite3_finalize_interop(): calling sqlite3_finalize(%p, %p)...\n", db, stmt); #endif ret = sqlite3_finalize(stmt); #if defined(INTEROP_DEBUG) && (INTEROP_DEBUG & INTEROP_DEBUG_FINALIZE) sqlite3InteropDebug("sqlite3_finalize_interop(): sqlite3_finalize(%p, %p) returned %d.\n", db, stmt, ret); #endif return ret; #else Vdbe *p; ret = SQLITE_OK; p = (Vdbe *)stmt; if (p) { sqlite3 *db = p->db; if (db != NULL) |
︙ | ︙ | |||
467 468 469 470 471 472 473 | return ret; } SQLITE_API int WINAPI sqlite3_reset_interop(sqlite3_stmt *stmt) { int ret; | | | 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 | return ret; } SQLITE_API int WINAPI sqlite3_reset_interop(sqlite3_stmt *stmt) { int ret; #if !defined(INTEROP_LEGACY_CLOSE) && SQLITE_VERSION_NUMBER >= 3007014 #if defined(INTEROP_DEBUG) && (INTEROP_DEBUG & INTEROP_DEBUG_RESET) sqlite3InteropDebug("sqlite3_reset_interop(): calling sqlite3_reset(%p)...\n", stmt); #endif ret = sqlite3_reset(stmt); |
︙ | ︙ | |||
523 524 525 526 527 528 529 | { *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); | | | | 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 | { *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 = sqlite3_value_bytes(val); return pval; } SQLITE_API const void * WINAPI sqlite3_value_text16_interop(sqlite3_value *val, int *plen) { const void *pval = sqlite3_value_text16(val); *plen = sqlite3_value_bytes16(val); return pval; } SQLITE_API void WINAPI sqlite3_result_double_interop(sqlite3_context *pctx, double *val) { sqlite3_result_double(pctx, *val); } |
︙ | ︙ | |||
773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 | 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) | > > > > > > > > > > > > > > > > > > > > > > > > | > > > | > > | 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 | z = sqlite3_value_text(argv[0]); if( z ){ sqlite3_result_text(context, (char*)z, -1, SQLITE_STATIC); }else{ sqlite3_result_null(context); } } /* ** The interopSleep() SQL function waits the specified number of milliseconds ** or raises an error if there are not enough arguments. */ SQLITE_PRIVATE void interopSleepFunc( sqlite3_context *context, int argc, sqlite3_value **argv ){ int m; if( argc!=1 ){ sqlite3_result_error(context, "need exactly one argument", -1); return; } m = sqlite3_value_int(argv[0]); #if SQLITE_OS_WINCE Sleep(m); sqlite3_result_int(context, WAIT_OBJECT_0); #else sqlite3_result_int(context, SleepEx(m, TRUE)); #endif } /* SQLite invokes this routine once when it loads the extension. ** Create new functions, collating sequences, and virtual table ** modules here. This is usually the only exported symbol in ** the shared library. */ SQLITE_API int interop_test_extension_init( sqlite3 *db, char **pzErrMsg, const sqlite3_api_routines *pApi ){ int rc; SQLITE_EXTENSION_INIT2(pApi) rc = sqlite3_create_function(db, "interopTest", -1, SQLITE_ANY, 0, interopTestFunc, 0, 0); if( rc==SQLITE_OK ){ rc = sqlite3_create_function(db, "interopSleep", 1, SQLITE_ANY, 0, interopSleepFunc, 0, 0); } return rc; } #endif |
Changes to SQLite.Interop/src/win/interop.h.
1 2 3 4 5 6 7 8 | /* * 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.85.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 | <?xml version="1.0" encoding="utf-8"?> <!-- * * SQLite.MSIL.nuspec - * * Written by Joe Mistachkin. * Released to the public domain, use at your own risk! * --> <package> <metadata> <id>System.Data.SQLite.MSIL</id> <version>1.0.85.0</version> <authors>SQLite Development Team</authors> <description>An ADO.NET provider for SQLite (managed-only).</description> <language>en-US</language> <projectUrl>http://system.data.sqlite.org/</projectUrl> <iconUrl>http://system.data.sqlite.org/images/sqlite32.png</iconUrl> <licenseUrl>http://www.sqlite.org/copyright.html</licenseUrl> <tags>sqlite database ado.net provider interop</tags> |
︙ | ︙ |
Changes to SQLite.NET.Settings.targets.
︙ | ︙ | |||
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | <!-- NOTE: If the per-framework settings files exist, import them now. The contained settings, if any, will override the default ones provided below. --> <Import Project="$(SQLiteNetDir)\SQLite.NET.Settings.targets.netFx20" Condition="'$(NetFx20)' != '' And '$(NetFx20)' != 'false' And Exists('$(SQLiteNetDir)\SQLite.NET.Settings.targets.netFx20')" /> <Import Project="$(SQLiteNetDir)\SQLite.NET.Settings.targets.netFx35" Condition="'$(NetFx35)' != '' And '$(NetFx35)' != 'false' And Exists('$(SQLiteNetDir)\SQLite.NET.Settings.targets.netFx35')" /> <Import Project="$(SQLiteNetDir)\SQLite.NET.Settings.targets.netFx40" Condition="'$(NetFx40)' != '' And '$(NetFx40)' != 'false' And Exists('$(SQLiteNetDir)\SQLite.NET.Settings.targets.netFx40')" /> <Import Project="$(SQLiteNetDir)\SQLite.NET.Settings.targets.netFx45" Condition="'$(NetFx45)' != '' And '$(NetFx45)' != 'false' And Exists('$(SQLiteNetDir)\SQLite.NET.Settings.targets.netFx45')" /> <!-- ****************************************************************************** ** [Fairly] Generic Properties ** ****************************************************************************** --> | > > > > | 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | <!-- NOTE: If the per-framework settings files exist, import them now. The contained settings, if any, will override the default ones provided below. --> <Import Project="$(SQLiteNetDir)\SQLite.NET.Settings.targets.netFx20" Condition="'$(NetFx20)' != '' And '$(NetFx20)' != 'false' And ('$(NetFx20Settings)' == '' Or '$(NetFx20Settings)' != 'false') And Exists('$(SQLiteNetDir)\SQLite.NET.Settings.targets.netFx20')" /> <Import Project="$(SQLiteNetDir)\SQLite.NET.Settings.targets.netFx35" Condition="'$(NetFx35)' != '' And '$(NetFx35)' != 'false' And ('$(NetFx35Settings)' == '' Or '$(NetFx35Settings)' != 'false') And Exists('$(SQLiteNetDir)\SQLite.NET.Settings.targets.netFx35')" /> <Import Project="$(SQLiteNetDir)\SQLite.NET.Settings.targets.netFx40" Condition="'$(NetFx40)' != '' And '$(NetFx40)' != 'false' And ('$(NetFx40Settings)' == '' Or '$(NetFx40Settings)' != 'false') And Exists('$(SQLiteNetDir)\SQLite.NET.Settings.targets.netFx40')" /> <Import Project="$(SQLiteNetDir)\SQLite.NET.Settings.targets.netFx45" Condition="'$(NetFx45)' != '' And '$(NetFx45)' != 'false' And ('$(NetFx45Settings)' == '' Or '$(NetFx45Settings)' != 'false') And Exists('$(SQLiteNetDir)\SQLite.NET.Settings.targets.netFx45')" /> <!-- ****************************************************************************** ** [Fairly] Generic Properties ** ****************************************************************************** --> |
︙ | ︙ | |||
121 122 123 124 125 126 127 128 129 130 131 132 133 134 | NOTE: Only use functionality available in the .NET Framework 4.5? By default, this is disabled. This must be enabled to successfully build the project using Visual Studio 2012 and/or the .NET Framework 4.5 (if necessary, it will typically be enabled from within the project file itself). --> <NetFx45 Condition="'$(NetFx45)' == ''">false</NetFx45> </PropertyGroup> <!-- ****************************************************************************** ** Feature Properties ** ****************************************************************************** --> | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 | NOTE: Only use functionality available in the .NET Framework 4.5? By default, this is disabled. This must be enabled to successfully build the project using Visual Studio 2012 and/or the .NET Framework 4.5 (if necessary, it will typically be enabled from within the project file itself). --> <NetFx45 Condition="'$(NetFx45)' == ''">false</NetFx45> <!-- NOTE: Load the version-specific settings for the .NET Framework 2.0? By default, this is disabled. If this is enabled when compiling for the .NET Framework 2.0, the version-specific settings file "SQLite.NET.Settings.targets.netFx20" will be loaded if it is actually present, before any other settings in this file are processed. --> <NetFx20Settings Condition="'$(NetFx20Settings)' == ''">false</NetFx20Settings> <!-- NOTE: Load the version-specific settings for the .NET Framework 3.5? By default, this is disabled. If this is enabled when compiling for the .NET Framework 3.5, the version-specific settings file "SQLite.NET.Settings.targets.netFx35" will be loaded if it is actually present, before any other settings in this file are processed. --> <NetFx35Settings Condition="'$(NetFx35Settings)' == ''">false</NetFx35Settings> <!-- NOTE: Load the version-specific settings for the .NET Framework 4.0? By default, this is disabled. If this is enabled when compiling for the .NET Framework 4.0, the version-specific settings file "SQLite.NET.Settings.targets.netFx40" will be loaded if it is actually present, before any other settings in this file are processed. --> <NetFx40Settings Condition="'$(NetFx40Settings)' == ''">false</NetFx40Settings> <!-- NOTE: Load the version-specific settings for the .NET Framework 4.5? By default, this is disabled. If this is enabled when compiling for the .NET Framework 4.5, the version-specific settings file "SQLite.NET.Settings.targets.netFx45" will be loaded if it is actually present, before any other settings in this file are processed. --> <NetFx45Settings Condition="'$(NetFx45Settings)' == ''">false</NetFx45Settings> </PropertyGroup> <!-- ****************************************************************************** ** Feature Properties ** ****************************************************************************** --> |
︙ | ︙ | |||
159 160 161 162 163 164 165 166 167 168 169 170 171 172 | 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. --> | > > > > > > > > | 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 | 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 sqlite3_prepare_v2() function when preparing queries? By default, this is enabled. When using a native SQLite implementation prior to version 3.3.9, this must be disabled. --> <UsePrepareV2 Condition="'$(UsePrepareV2)' == ''">true</UsePrepareV2> <!-- 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. --> |
︙ | ︙ | |||
276 277 278 279 280 281 282 283 284 285 286 287 288 289 | INTEROP_DEBUG_RESET (0x0080) INTEROP_DEBUG_CHANGES (0x0100) INTEROP_DEBUG_BREAK (0x0200) --> <InteropDebug Condition="'$(InteropDebug)' == '' And '$(Configuration)' == 'Debug'">true</InteropDebug> <InteropDebug Condition="'$(InteropDebug)' == '' And '$(Configuration)' != 'Debug'">false</InteropDebug> <!-- NOTE: Enable the logging callback in the custom built interop DLL (i.e. "SQLite.Interop.dll")? By default, this is enabled in the Debug build configuration. If this is disabled, the logging callback will be unavailable and diagnostic messages may not be seen if another native logging callback is not configured. If this is enabled, it must also be enabled via the "INTEROP_LOG=1" | > > > > > > > > > > > > > > | 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 | INTEROP_DEBUG_RESET (0x0080) INTEROP_DEBUG_CHANGES (0x0100) INTEROP_DEBUG_BREAK (0x0200) --> <InteropDebug Condition="'$(InteropDebug)' == '' And '$(Configuration)' == 'Debug'">true</InteropDebug> <InteropDebug Condition="'$(InteropDebug)' == '' And '$(Configuration)' != 'Debug'">false</InteropDebug> <!-- NOTE: Disable all use of the sqlite3_close_v2() native API and use the legacy System.Data.SQLite connection closing algorithm instead. By default, this is disabled. If this is enabled, it must also be enabled via the "INTEROP_LEGACY_CLOSE=1" preprocessor define being present in the "INTEROP_EXTRA_DEFINES" macro in the build properties file: "SQLite.Interop\props\SQLite.Interop.20YY.[vs]props" for the corresponding version(s) of Visual Studio. --> <InteropLegacyClose Condition="'$(InteropLegacyClose)' == ''">false</InteropLegacyClose> <!-- NOTE: Enable the logging callback in the custom built interop DLL (i.e. "SQLite.Interop.dll")? By default, this is enabled in the Debug build configuration. If this is disabled, the logging callback will be unavailable and diagnostic messages may not be seen if another native logging callback is not configured. If this is enabled, it must also be enabled via the "INTEROP_LOG=1" |
︙ | ︙ |
Changes to SQLite.nuspec.
1 2 3 4 5 6 7 8 9 10 11 12 13 | <?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 | <?xml version="1.0" encoding="utf-8"?> <!-- * * SQLite.nuspec - * * Written by Joe Mistachkin. * Released to the public domain, use at your own risk! * --> <package> <metadata> <id>System.Data.SQLite</id> <title>System.Data.SQLite (x86/x64)</title> <version>1.0.85.0</version> <authors>SQLite Development Team</authors> <description>The official SQLite database engine for both x86 and x64 along with the ADO.NET provider.</description> <language>en-US</language> <projectUrl>http://system.data.sqlite.org/</projectUrl> <iconUrl>http://system.data.sqlite.org/images/sqlite32.png</iconUrl> <licenseUrl>http://www.sqlite.org/copyright.html</licenseUrl> <tags>sqlite database ado.net provider interop</tags> |
︙ | ︙ |
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 | <?xml version="1.0" encoding="utf-8"?> <!-- * * SQLite.x64.nuspec - * * Written by Joe Mistachkin. * Released to the public domain, use at your own risk! * --> <package> <metadata> <id>System.Data.SQLite.x64</id> <version>1.0.85.0</version> <authors>SQLite Development Team</authors> <description>The official SQLite database engine combined with a complete ADO.NET provider all rolled into a single mixed-mode assembly for x64.</description> <language>en-US</language> <projectUrl>http://system.data.sqlite.org/</projectUrl> <iconUrl>http://system.data.sqlite.org/images/sqlite32.png</iconUrl> <licenseUrl>http://www.sqlite.org/copyright.html</licenseUrl> <tags>sqlite database ado.net provider interop</tags> |
︙ | ︙ |
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 | <?xml version="1.0" encoding="utf-8"?> <!-- * * SQLite.x86.nuspec - * * Written by Joe Mistachkin. * Released to the public domain, use at your own risk! * --> <package> <metadata> <id>System.Data.SQLite.x86</id> <version>1.0.85.0</version> <authors>SQLite Development Team</authors> <description>The official SQLite database engine combined with a complete ADO.NET provider all rolled into a single mixed-mode assembly for x86.</description> <language>en-US</language> <projectUrl>http://system.data.sqlite.org/</projectUrl> <iconUrl>http://system.data.sqlite.org/images/sqlite32.png</iconUrl> <licenseUrl>http://www.sqlite.org/copyright.html</licenseUrl> <tags>sqlite database ado.net provider interop</tags> |
︙ | ︙ |
Changes to Setup/CheckForNetFx.pas.
︙ | ︙ | |||
28 29 30 31 32 33 34 35 36 37 38 39 40 41 | NetFx4Version: String; NetFx4SetupVersion: String; NetFx4HasServicePack: String; NetFx4ServicePack: Integer; NetFx4ErrorMessage: String; VcRuntimeRedistributable: String; function CheckForNetFx2(const NeedServicePack: Integer): Boolean; var SubKeyName: String; IsInstalled: Cardinal; HasServicePack: Cardinal; begin | > > > > > > > > > > > > > > > > > | 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 | NetFx4Version: String; NetFx4SetupVersion: String; NetFx4HasServicePack: String; NetFx4ServicePack: Integer; NetFx4ErrorMessage: String; VcRuntimeRedistributable: String; function TrimSlash(const Path: String): String; var LastCharacter: String; begin Result := Path; if Result <> '' then begin LastCharacter := Copy(Result, Length(Result), 1); if (LastCharacter = '\') or (LastCharacter = '/') then begin Result := Copy(Result, 1, Length(Result) - 1); end; end; end; function CheckForNetFx2(const NeedServicePack: Integer): Boolean; var SubKeyName: String; IsInstalled: Cardinal; HasServicePack: Cardinal; begin |
︙ | ︙ | |||
119 120 121 122 123 124 125 | InstallRoot: String; begin Result := ''; if RegQueryStringValue(HKEY_LOCAL_MACHINE, NetFxSubKeyName, NetFxInstallRoot, InstallRoot) then begin | > > | | | | > > > | | | | > | 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 | InstallRoot: String; begin Result := ''; if RegQueryStringValue(HKEY_LOCAL_MACHINE, NetFxSubKeyName, NetFxInstallRoot, InstallRoot) then begin if InstallRoot <> '' then begin Result := TrimSlash(InstallRoot) + '\' + NetFx2Version; if FileName <> '' then begin Result := TrimSlash(Result) + '\' + FileName; end; end; end; end; function GetNetFx4InstallRoot(const FileName: String): String; var InstallRoot: String; begin Result := ''; if RegQueryStringValue(HKEY_LOCAL_MACHINE, NetFxSubKeyName, NetFxInstallRoot, InstallRoot) then begin if InstallRoot <> '' then begin Result := TrimSlash(InstallRoot) + '\' + NetFx4Version; if FileName <> '' then begin Result := TrimSlash(Result) + '\' + FileName; end; end; end; end; function CheckIsNetFx2Setup(): Boolean; begin Result := IsNetFx2Setup; |
︙ | ︙ |
Changes to Setup/build_ce.bat.
︙ | ︙ | |||
30 31 32 33 34 35 36 | %_VECHO% Tools = '%TOOLS%' SET BUILD_CONFIGURATIONS=Debug Release SET BASE_CONFIGURATIONSUFFIX=Compact SET PLATFORMS="Pocket PC 2003 (ARMV4)" SET PROCESSORS=arm | | | 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | %_VECHO% Tools = '%TOOLS%' SET BUILD_CONFIGURATIONS=Debug Release SET BASE_CONFIGURATIONSUFFIX=Compact SET PLATFORMS="Pocket PC 2003 (ARMV4)" SET PROCESSORS=arm SET YEARS=2005 2008 SET BASE_PLATFORM=PocketPC CALL :fn_ResetErrorLevel %__ECHO3% CALL "%TOOLS%\build_all.bat" IF ERRORLEVEL 1 ( |
︙ | ︙ |
Changes to Setup/deployAndTestCe.eagle.
︙ | ︙ | |||
127 128 129 130 131 132 133 | # # NOTE: Grab the culture instance based on the configured culture name. # set cultureInfo [object invoke -alias System.Globalization.CultureInfo \ GetCultureInfo $culture] # | | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > | | | | > > | > | | | 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 | # # 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 2.0 packages that need to # be deployed to the target device, if necessary. # if {![info exists packages(2005)]} then { # # NOTE: The three letter Windows language name is needed when building # the default list of .NET Compact Framework packages because one # of them is a localized resource package. # set language3 [string toupper \ [$cultureInfo ThreeLetterWindowsLanguageName]] # # NOTE: The default list of .NET Compact Framework 2.0 packages contains # the .NET Compact Framework 2.0 installation CAB file for ARMV4 # on the Pocket PC and its associated resource installation CAB # files. # set packages(2005) [list \ abd785f0-cda7-41c5-8375-2451a7cbff26 \ \\Windows\\NETCFv2.ppc.armv4.cab \ c0ccf48e-4bfb-4d84-827c-981a595e40b4 \ [appendArgs \\Windows\\System_SR_ $language3 .cab]] } # # NOTE: Build the list of .NET Compact Framework 3.5 packages that need to # be deployed to the target device, if necessary. # if {![info exists packages(2008)]} 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 language2 [string toupper \ [$cultureInfo TwoLetterISOLanguageName]] # # NOTE: The default list of .NET Compact Framework 3.5 packages contains # the .NET Compact Framework 3.5 installation CAB file for ARMV4 # on the Pocket PC and its associated resource installation CAB # files. # set packages(2008) [list \ abd785f0-cda7-41c5-8375-2451a7cbff37 \ \\Windows\\NETCFv35.ppc.armv4.cab \ c0ccf48e-4bfb-4d84-827c-981a595e40c5 \ [appendArgs \\Windows\\NETCFv35.Messages. $language2 .cab]] } # # NOTE: Save the path where this script is running from. # set path [file dirname [info script]] |
︙ | ︙ | |||
237 238 239 240 241 242 243 | # # 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] # | > > > > > | | | | | | | | | | | | | | > | 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 | # # 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: If the list of packages related to the configured build year do not # exist, skip this step. # if {[info exists packages($year)]} then { # # 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($year) { 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/verify.lst.
︙ | ︙ | |||
132 133 134 135 136 137 138 139 140 141 142 143 144 145 | Setup/SQLite.iss Setup/test_all.bat Setup/test_ce.bat Setup/updateFileInfo.tcl Setup/verify.eagle Setup/verify.lst Setup/vsSp.bat SQLite.Designer/ SQLite.Designer/AssemblyInfo.cs SQLite.Designer/ChangePasswordDialog.cs SQLite.Designer/ChangePasswordDialog.Designer.cs SQLite.Designer/ChangePasswordDialog.resx SQLite.Designer/ChangeScriptDialog.cs SQLite.Designer/ChangeScriptDialog.Designer.cs | > | 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 | Setup/SQLite.iss Setup/test_all.bat Setup/test_ce.bat Setup/updateFileInfo.tcl Setup/verify.eagle Setup/verify.lst Setup/vsSp.bat SQLite.Beta.nuspec SQLite.Designer/ SQLite.Designer/AssemblyInfo.cs SQLite.Designer/ChangePasswordDialog.cs SQLite.Designer/ChangePasswordDialog.Designer.cs SQLite.Designer/ChangePasswordDialog.resx SQLite.Designer/ChangeScriptDialog.cs SQLite.Designer/ChangeScriptDialog.Designer.cs |
︙ | ︙ | |||
235 236 237 238 239 240 241 | SQLite.Interop/src/core/sqlite3ext.h SQLite.Interop/src/win/ SQLite.Interop/src/win/AssemblyInfo.cpp SQLite.Interop/src/win/crypt.c SQLite.Interop/src/win/interop.c SQLite.Interop/src/win/interop.h SQLite.Interop/src/win/SQLite.Interop.rc | < | 236 237 238 239 240 241 242 243 244 245 246 247 248 249 | SQLite.Interop/src/core/sqlite3ext.h SQLite.Interop/src/win/ SQLite.Interop/src/win/AssemblyInfo.cpp SQLite.Interop/src/win/crypt.c SQLite.Interop/src/win/interop.c SQLite.Interop/src/win/interop.h SQLite.Interop/src/win/SQLite.Interop.rc SQLite.MSIL.nuspec SQLite.NET.2005.MSBuild.sln SQLite.NET.2005.sln SQLite.NET.2008.MSBuild.sln SQLite.NET.2008.sln SQLite.NET.2010.MSBuild.sln SQLite.NET.2010.sln |
︙ | ︙ |
Changes to System.Data.SQLite.Linq/AssemblyInfo.cs.
︙ | ︙ | |||
40 41 42 43 44 45 46 | // 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.*")] | | | | 40 41 42 43 44 45 46 47 48 | // Minor Version // Build Number // Revision // // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.85.0")] [assembly: AssemblyFileVersion("1.0.85.0")] |
Changes to System.Data.SQLite/AssemblyInfo.cs.
︙ | ︙ | |||
60 61 62 63 64 65 66 | // 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: | | | | 60 61 62 63 64 65 66 67 68 69 70 | // Major Version // Minor Version // Build Number // Revision // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: [assembly: AssemblyVersion("1.0.85.0")] #if !PLATFORM_COMPACTFRAMEWORK [assembly: AssemblyFileVersion("1.0.85.0")] #endif |
Changes to System.Data.SQLite/LINQ/SQLiteFactory_Linq.cs.
︙ | ︙ | |||
22 23 24 25 26 27 28 | 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 37 38 39 40 41 42 43 | static SQLiteFactory() { #if (SQLITE_STANDARD || USE_INTEROP_DLL || PLATFORM_COMPACTFRAMEWORK) && PRELOAD_NATIVE_LIBRARY UnsafeNativeMethods.Initialize(); #endif #if INTEROP_LOG if (UnsafeNativeMethods.sqlite3_config_log_interop() == SQLiteErrorCode.Ok) { UnsafeNativeMethods.sqlite3_log( SQLiteErrorCode.Ok, SQLiteConvert.ToUTF8("logging initialized.")); } #else SQLiteLog.Initialize(); #endif string version = #if NET_40 || NET_45 "4.0.0.0"; #else "3.5.0.0"; |
︙ | ︙ |
Changes to System.Data.SQLite/SQLite3.cs.
︙ | ︙ | |||
53 54 55 56 57 58 59 | 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.85.0"; #endif /// <summary> /// The opaque pointer returned to us by the sqlite provider /// </summary> protected internal SQLiteConnectionHandle _sql; protected string _fileName; |
︙ | ︙ | |||
514 515 516 517 518 519 520 | "{0}.", baseSchemaName), String.Empty); } } SQLiteConnectionFlags flags = (cnn != null) ? cnn.Flags : SQLiteConnectionFlags.Default; | < < | 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); |
︙ | ︙ | |||
552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 | // 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 | > > > > | 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 | // 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 #if USE_PREPARE_V2 n = UnsafeNativeMethods.sqlite3_prepare_v2(_sql, psql, b.Length - 1, out stmt, out ptr); #else n = UnsafeNativeMethods.sqlite3_prepare(_sql, psql, b.Length - 1, out stmt, out ptr); #endif len = -1; #endif #if !NET_COMPACT_20 && TRACE_STATEMENT Trace.WriteLine(String.Format("Prepare ({0}): {1}", n, stmt)); #endif |
︙ | ︙ | |||
649 650 651 652 653 654 655 | } finally { handle.Free(); } } | < | 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)); |
︙ | ︙ | |||
724 725 726 727 728 729 730 | { 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>")); } | < < > < < > > > > > > > > > > > > > > | > | 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 | { IntPtr handleIntPtr = handle; SQLiteLog.LogMessage(String.Format( "Binding statement {0} paramter #{1} as type {2} with value {{{3}}}...", handleIntPtr, index, typeof(Byte[]), (value != null) ? ToHexadecimalString(value) : "<null>")); } internal override void Bind_Double(SQLiteStatement stmt, SQLiteConnectionFlags flags, int index, double value) { SQLiteStatementHandle handle = stmt._sqlite_stmt; if ((flags & SQLiteConnectionFlags.LogBind) == SQLiteConnectionFlags.LogBind) { LogBind(handle, index, value); } #if !PLATFORM_COMPACTFRAMEWORK SQLiteErrorCode n = UnsafeNativeMethods.sqlite3_bind_double(handle, index, value); #else SQLiteErrorCode n = UnsafeNativeMethods.sqlite3_bind_double_interop(handle, index, ref value); #endif if (n != SQLiteErrorCode.Ok) throw new SQLiteException(n, GetLastError()); } internal override void Bind_Int32(SQLiteStatement stmt, SQLiteConnectionFlags flags, int index, int value) { SQLiteStatementHandle handle = stmt._sqlite_stmt; if ((flags & SQLiteConnectionFlags.LogBind) == SQLiteConnectionFlags.LogBind) { LogBind(handle, index, value); } SQLiteErrorCode n = UnsafeNativeMethods.sqlite3_bind_int(handle, index, value); if (n != SQLiteErrorCode.Ok) throw new SQLiteException(n, GetLastError()); } internal override void Bind_UInt32(SQLiteStatement stmt, SQLiteConnectionFlags flags, int index, uint value) { SQLiteStatementHandle handle = stmt._sqlite_stmt; #if !PLATFORM_COMPACTFRAMEWORK if ((flags & SQLiteConnectionFlags.LogBind) == SQLiteConnectionFlags.LogBind) { LogBind(handle, index, value); } #endif SQLiteErrorCode n; if ((flags & SQLiteConnectionFlags.BindUInt32AsInt64) == SQLiteConnectionFlags.BindUInt32AsInt64) { long value2 = value; #if !PLATFORM_COMPACTFRAMEWORK n = UnsafeNativeMethods.sqlite3_bind_int64(handle, index, value2); #else n = UnsafeNativeMethods.sqlite3_bind_int64_interop(handle, index, ref value2); #endif } else { n = UnsafeNativeMethods.sqlite3_bind_uint(handle, index, value); } if (n != SQLiteErrorCode.Ok) throw new SQLiteException(n, GetLastError()); } internal override void Bind_Int64(SQLiteStatement stmt, SQLiteConnectionFlags flags, int index, long value) { SQLiteStatementHandle handle = stmt._sqlite_stmt; |
︙ | ︙ | |||
948 949 950 951 952 953 954 | } internal override int Bind_ParamCount(SQLiteStatement stmt, SQLiteConnectionFlags flags) { SQLiteStatementHandle handle = stmt._sqlite_stmt; int value = UnsafeNativeMethods.sqlite3_bind_parameter_count(handle); | < < < < < < | 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); |
︙ | ︙ | |||
1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 | #if !PLATFORM_COMPACTFRAMEWORK value = UnsafeNativeMethods.sqlite3_column_double(stmt._sqlite_stmt, index); #else UnsafeNativeMethods.sqlite3_column_double_interop(stmt._sqlite_stmt, index, out value); #endif return value; } internal override int GetInt32(SQLiteStatement stmt, int index) { return UnsafeNativeMethods.sqlite3_column_int(stmt._sqlite_stmt, index); } internal override long GetInt64(SQLiteStatement stmt, int index) { long value; #if !PLATFORM_COMPACTFRAMEWORK value = UnsafeNativeMethods.sqlite3_column_int64(stmt._sqlite_stmt, index); #else UnsafeNativeMethods.sqlite3_column_int64_interop(stmt._sqlite_stmt, index, out value); #endif return value; } internal override string GetText(SQLiteStatement stmt, int index) { #if !SQLITE_STANDARD int len; return UTF8ToString(UnsafeNativeMethods.sqlite3_column_text_interop(stmt._sqlite_stmt, index, out len), len); #else | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > | > | 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 | #if !PLATFORM_COMPACTFRAMEWORK value = UnsafeNativeMethods.sqlite3_column_double(stmt._sqlite_stmt, index); #else UnsafeNativeMethods.sqlite3_column_double_interop(stmt._sqlite_stmt, index, out value); #endif return value; } internal override sbyte GetSByte(SQLiteStatement stmt, int index) { return unchecked((sbyte)(GetInt32(stmt, index) & byte.MaxValue)); } internal override byte GetByte(SQLiteStatement stmt, int index) { return unchecked((byte)(GetInt32(stmt, index) & byte.MaxValue)); } internal override short GetInt16(SQLiteStatement stmt, int index) { return unchecked((short)(GetInt32(stmt, index) & ushort.MaxValue)); } internal override ushort GetUInt16(SQLiteStatement stmt, int index) { return unchecked((ushort)(GetInt32(stmt, index) & ushort.MaxValue)); } internal override int GetInt32(SQLiteStatement stmt, int index) { return UnsafeNativeMethods.sqlite3_column_int(stmt._sqlite_stmt, index); } internal override uint GetUInt32(SQLiteStatement stmt, int index) { return unchecked((uint)GetInt32(stmt, index)); } internal override long GetInt64(SQLiteStatement stmt, int index) { long value; #if !PLATFORM_COMPACTFRAMEWORK value = UnsafeNativeMethods.sqlite3_column_int64(stmt._sqlite_stmt, index); #else UnsafeNativeMethods.sqlite3_column_int64_interop(stmt._sqlite_stmt, index, out value); #endif return value; } internal override ulong GetUInt64(SQLiteStatement stmt, int index) { return unchecked((ulong)GetInt64(stmt, index)); } internal override string GetText(SQLiteStatement stmt, int index) { #if !SQLITE_STANDARD int len; return UTF8ToString(UnsafeNativeMethods.sqlite3_column_text_interop(stmt._sqlite_stmt, index, out len), len); #else return UTF8ToString(UnsafeNativeMethods.sqlite3_column_text(stmt._sqlite_stmt, index), UnsafeNativeMethods.sqlite3_column_bytes(stmt._sqlite_stmt, index)); #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), UnsafeNativeMethods.sqlite3_column_bytes(stmt._sqlite_stmt, index)); #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); |
︙ | ︙ | |||
1395 1396 1397 1398 1399 1400 1401 | internal override string GetParamValueText(IntPtr ptr) { #if !SQLITE_STANDARD int len; return UTF8ToString(UnsafeNativeMethods.sqlite3_value_text_interop(ptr, out len), len); #else | | > | 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 | 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), UnsafeNativeMethods.sqlite3_value_bytes(ptr)); #endif } internal override TypeAffinity GetParamValueType(IntPtr ptr) { return UnsafeNativeMethods.sqlite3_value_type(ptr); } |
︙ | ︙ | |||
1842 1843 1844 1845 1846 1847 1848 | { // // BUGFIX: Prevent races with other threads for this entire block, due // to the try/finally semantics. See ticket [72905c9a77]. // lock (syncRoot) { | < < < < > | > > > < | > | > > > > > | | 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 | { // // 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> /// <param name="flags">The flags associated with the connection.</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, SQLiteConnectionFlags flags, 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); } if ((flags & SQLiteConnectionFlags.GetAllAsText) == SQLiteConnectionFlags.GetAllAsText) return GetText(stmt, index); 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); return Convert.ChangeType(GetDouble(stmt, index), t, null); case TypeAffinity.Int64: if (t == null) return GetInt64(stmt, index); if (t == typeof(SByte)) return GetSByte(stmt, index); if (t == typeof(Byte)) return GetByte(stmt, index); if (t == typeof(Int16)) return GetInt16(stmt, index); if (t == typeof(UInt16)) return GetUInt16(stmt, index); if (t == typeof(Int32)) return GetInt32(stmt, index); if (t == typeof(UInt32)) return GetUInt32(stmt, index); if (t == typeof(UInt64)) return GetUInt64(stmt, index); return Convert.ChangeType(GetInt64(stmt, index), t, null); default: return GetText(stmt, index); } } internal override int GetCursorForTable(SQLiteStatement stmt, int db, int rootPage) { |
︙ | ︙ |
Changes to System.Data.SQLite/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 228 | 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), UnsafeNativeMethods.sqlite3_column_bytes16(stmt._sqlite_stmt, index)); #endif } internal override string ColumnOriginalName(SQLiteStatement stmt, int index) { #if !SQLITE_STANDARD int len; |
︙ | ︙ | |||
253 254 255 256 257 258 259 | internal override string GetParamValueText(IntPtr ptr) { #if !SQLITE_STANDARD int len; return UTF16ToString(UnsafeNativeMethods.sqlite3_value_text16_interop(ptr, out len), len); #else | | > | 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 | 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), UnsafeNativeMethods.sqlite3_value_bytes16(ptr)); #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.
︙ | ︙ | |||
159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 | internal abstract string ColumnOriginalName(SQLiteStatement stmt, int index); internal abstract string ColumnDatabaseName(SQLiteStatement stmt, int index); internal abstract string ColumnTableName(SQLiteStatement stmt, int index); internal abstract void ColumnMetaData(string dataBase, string table, string column, out string dataType, out string collateSequence, out bool notNull, out bool primaryKey, out bool autoIncrement); internal abstract void GetIndexColumnExtendedInfo(string database, string index, string column, out int sortMode, out int onError, out string collationSequence); internal abstract double GetDouble(SQLiteStatement stmt, int index); internal abstract Int32 GetInt32(SQLiteStatement stmt, int index); internal abstract Int64 GetInt64(SQLiteStatement stmt, int index); internal abstract string GetText(SQLiteStatement stmt, int index); internal abstract long GetBytes(SQLiteStatement stmt, int index, int nDataoffset, byte[] bDest, int nStart, int nLength); internal abstract long GetChars(SQLiteStatement stmt, int index, int nDataoffset, char[] bDest, int nStart, int nLength); internal abstract DateTime GetDateTime(SQLiteStatement stmt, int index); internal abstract bool IsNull(SQLiteStatement stmt, int index); internal abstract void CreateCollation(string strCollation, SQLiteCollation func, SQLiteCollation func16); | > > > > > > | 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 | internal abstract string ColumnOriginalName(SQLiteStatement stmt, int index); internal abstract string ColumnDatabaseName(SQLiteStatement stmt, int index); internal abstract string ColumnTableName(SQLiteStatement stmt, int index); internal abstract void ColumnMetaData(string dataBase, string table, string column, out string dataType, out string collateSequence, out bool notNull, out bool primaryKey, out bool autoIncrement); internal abstract void GetIndexColumnExtendedInfo(string database, string index, string column, out int sortMode, out int onError, out string collationSequence); internal abstract double GetDouble(SQLiteStatement stmt, int index); internal abstract SByte GetSByte(SQLiteStatement stmt, int index); internal abstract Byte GetByte(SQLiteStatement stmt, int index); internal abstract Int16 GetInt16(SQLiteStatement stmt, int index); internal abstract UInt16 GetUInt16(SQLiteStatement stmt, int index); internal abstract Int32 GetInt32(SQLiteStatement stmt, int index); internal abstract UInt32 GetUInt32(SQLiteStatement stmt, int index); internal abstract Int64 GetInt64(SQLiteStatement stmt, int index); internal abstract UInt64 GetUInt64(SQLiteStatement stmt, int index); internal abstract string GetText(SQLiteStatement stmt, int index); internal abstract long GetBytes(SQLiteStatement stmt, int index, int nDataoffset, byte[] bDest, int nStart, int nLength); internal abstract long GetChars(SQLiteStatement stmt, int index, int nDataoffset, char[] bDest, int nStart, int nLength); internal abstract DateTime GetDateTime(SQLiteStatement stmt, int index); internal abstract bool IsNull(SQLiteStatement stmt, int index); internal abstract void CreateCollation(string strCollation, SQLiteCollation func, SQLiteCollation func16); |
︙ | ︙ | |||
261 262 263 264 265 266 267 | /// 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); | | | 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 | /// 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, SQLiteConnectionFlags flags, int index, SQLiteType typ); internal abstract bool AutoCommit { get; } internal abstract SQLiteErrorCode FileControl(string zDbName, int op, IntPtr pArg); |
︙ | ︙ | |||
586 587 588 589 590 591 592 593 594 595 596 597 598 599 | SQLiteErrorCode n = UnsafeNativeMethods.sqlite3_close(db); #endif if (n != SQLiteErrorCode.Ok) throw new SQLiteException(n, GetLastError(hdl, db)); } } } internal static void CloseConnectionV2(SQLiteConnectionHandle hdl, IntPtr db) { if ((hdl == null) || (db == IntPtr.Zero)) return; try { // do nothing. | > | 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 | SQLiteErrorCode n = UnsafeNativeMethods.sqlite3_close(db); #endif if (n != SQLiteErrorCode.Ok) throw new SQLiteException(n, GetLastError(hdl, db)); } } } #if !INTEROP_LEGACY_CLOSE internal static void CloseConnectionV2(SQLiteConnectionHandle hdl, IntPtr db) { if ((hdl == null) || (db == IntPtr.Zero)) return; try { // do nothing. |
︙ | ︙ | |||
613 614 615 616 617 618 619 620 621 622 623 624 625 626 | SQLiteErrorCode n = UnsafeNativeMethods.sqlite3_close_v2(db); #endif if (n != SQLiteErrorCode.Ok) throw new SQLiteException(n, GetLastError(hdl, db)); } } } internal static bool ResetConnection(SQLiteConnectionHandle hdl, IntPtr db, bool canThrow) { if ((hdl == null) || (db == IntPtr.Zero)) return false; bool result = false; | > | 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 | SQLiteErrorCode n = UnsafeNativeMethods.sqlite3_close_v2(db); #endif if (n != SQLiteErrorCode.Ok) throw new SQLiteException(n, GetLastError(hdl, db)); } } } #endif internal static bool ResetConnection(SQLiteConnectionHandle hdl, IntPtr db, bool canThrow) { if ((hdl == null) || (db == IntPtr.Zero)) return false; bool result = false; |
︙ | ︙ | |||
772 773 774 775 776 777 778 779 780 781 782 783 784 785 | /// <summary> /// Skip adding the extension functions provided by the native /// interop assembly. /// </summary> NoExtensionFunctions = 0x20, /// <summary> /// Enable all logging. /// </summary> LogAll = LogPrepare | LogPreBind | LogBind | LogCallbackException | LogBackup, /// <summary> | > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 | /// <summary> /// Skip adding the extension functions provided by the native /// interop assembly. /// </summary> NoExtensionFunctions = 0x20, /// <summary> /// When binding parameter values with the <see cref="UInt32" /> /// type, use the interop method that accepts an <see cref="Int64" /> /// value. /// </summary> BindUInt32AsInt64 = 0x40, /// <summary> /// When binding parameter values, always bind them as though they were /// plain text (i.e. no numeric, date/time, or other conversions should /// be attempted). /// </summary> BindAllAsText = 0x80, /// <summary> /// When returning column values, always return them as though they were /// plain text (i.e. no numeric, date/time, or other conversions should /// be attempted). /// </summary> GetAllAsText = 0x100, /// <summary> /// When binding and returning column values, always treat them as though /// they were plain text (i.e. no numeric, date/time, or other conversions /// should be attempted). /// </summary> BindAndGetAllAsText = BindAllAsText | GetAllAsText, /// <summary> /// Enable all logging. /// </summary> LogAll = LogPrepare | LogPreBind | LogBind | LogCallbackException | LogBackup, /// <summary> |
︙ | ︙ |
Changes to System.Data.SQLite/SQLiteCommand.cs.
︙ | ︙ | |||
18 19 20 21 22 23 24 25 26 27 28 29 30 31 | /// SQLite implementation of DbCommand. /// </summary> #if !PLATFORM_COMPACTFRAMEWORK [Designer("SQLite.Designer.SQLiteCommandDesigner, SQLite.Designer, Version=" + SQLite3.DesignerVersion + ", Culture=neutral, PublicKeyToken=db937bc2d44ff139"), ToolboxItem(true)] #endif public sealed class SQLiteCommand : DbCommand, ICloneable { /// <summary> /// The command text this command is based on /// </summary> private string _commandText; /// <summary> /// The connection the command is associated with /// </summary> | > > > > > > > | 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | /// SQLite implementation of DbCommand. /// </summary> #if !PLATFORM_COMPACTFRAMEWORK [Designer("SQLite.Designer.SQLiteCommandDesigner, SQLite.Designer, Version=" + SQLite3.DesignerVersion + ", Culture=neutral, PublicKeyToken=db937bc2d44ff139"), ToolboxItem(true)] #endif public sealed class SQLiteCommand : DbCommand, ICloneable { /// <summary> /// The default connection string to be used when creating a temporary /// connection to execute a command via the static <see cref="Execute" /> /// method. /// </summary> private static readonly string DefaultConnectionString = "Data Source=:memory:;"; /// <summary> /// The command text this command is based on /// </summary> private string _commandText; /// <summary> /// The connection the command is associated with /// </summary> |
︙ | ︙ | |||
223 224 225 226 227 228 229 230 231 232 233 234 235 236 | } finally { base.Dispose(disposing); } } #endregion /////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// Clears and destroys all statements currently prepared /// </summary> internal void ClearCommands() | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 | } finally { base.Dispose(disposing); } } #endregion /////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// This method attempts to query the flags associated with the database /// connection in use. If the database connection is disposed or any other /// error occurs, the default flags will be returned. /// </summary> /// <param name="command"> /// The command containing the databse connection to query the flags from. /// </param> /// <returns> /// The connection flags value. /// </returns> internal static SQLiteConnectionFlags GetFlags( SQLiteCommand command ) { try { if (command != null) { SQLiteConnection cnn = command._cnn; if (cnn != null) return cnn.Flags; } } catch (ObjectDisposedException) { // do nothing. } return SQLiteConnectionFlags.Default; } /////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// Clears and destroys all statements currently prepared /// </summary> internal void ClearCommands() |
︙ | ︙ | |||
591 592 593 594 595 596 597 598 599 600 601 602 603 604 | /// </summary> /// <param name="behavior">The behavior the data reader should adopt</param> /// <returns>Returns a SQLiteDataReader object</returns> protected override DbDataReader ExecuteDbDataReader(CommandBehavior behavior) { return ExecuteReader(behavior); } /// <summary> /// Overrides the default behavior to return a SQLiteDataReader specialization class /// </summary> /// <param name="behavior">The flags to be associated with the reader</param> /// <returns>A SQLiteDataReader</returns> public new SQLiteDataReader ExecuteReader(CommandBehavior behavior) | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 | /// </summary> /// <param name="behavior">The behavior the data reader should adopt</param> /// <returns>Returns a SQLiteDataReader object</returns> protected override DbDataReader ExecuteDbDataReader(CommandBehavior behavior) { return ExecuteReader(behavior); } /// <summary> /// This method creates a new connection, executes the query using the given /// execution type, closes the connection, and returns the results. If the /// connection string is null, a temporary in-memory database connection will /// be used. /// </summary> /// <param name="commandText"> /// The text of the command to be executed. /// </param> /// <param name="executeType"> /// The execution type for the command. This is used to determine which method /// of the command object to call, which then determines the type of results /// returned, if any. /// </param> /// <param name="connectionString"> /// The connection string to the database to be opened, used, and closed. If /// this parameter is null, a temporary in-memory databse will be used. /// </param> /// <param name="args"> /// The SQL parameter values to be used when building the command object to be /// executed, if any. /// </param> /// <returns> /// The results of the query -OR- null if no results were produced from the /// given execution type. /// </returns> public static object Execute( string commandText, SQLiteExecuteType executeType, string connectionString, params object[] args ) { if (connectionString == null) connectionString = DefaultConnectionString; using (SQLiteConnection connection = new SQLiteConnection(connectionString)) { connection.Open(); using (SQLiteCommand command = connection.CreateCommand()) { command.CommandText = commandText; if (args != null) { foreach (object arg in args) { if (arg is SQLiteParameter) command.Parameters.Add((SQLiteParameter)arg); else command.Parameters.Add(new SQLiteParameter(DbType.Object, arg)); } } switch (executeType) { case SQLiteExecuteType.None: { // // NOTE: Do nothing. // break; } case SQLiteExecuteType.NonQuery: { return command.ExecuteNonQuery(); } case SQLiteExecuteType.Scalar: { return command.ExecuteScalar(); } case SQLiteExecuteType.Reader: { return command.ExecuteReader(); } } } } return null; } /// <summary> /// Overrides the default behavior to return a SQLiteDataReader specialization class /// </summary> /// <param name="behavior">The flags to be associated with the reader</param> /// <returns>A SQLiteDataReader</returns> public new SQLiteDataReader ExecuteReader(CommandBehavior behavior) |
︙ | ︙ |
Changes to System.Data.SQLite/SQLiteConnection.cs.
︙ | ︙ | |||
12 13 14 15 16 17 18 19 20 21 22 23 24 25 | using System.Data.Common; using System.Diagnostics; using System.Collections.Generic; using System.Globalization; using System.ComponentModel; using System.Runtime.InteropServices; using System.IO; ///////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// Event data for connection event handlers. /// </summary> public class ConnectionEventArgs : EventArgs | > | 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | using System.Data.Common; using System.Diagnostics; using System.Collections.Generic; using System.Globalization; using System.ComponentModel; using System.Runtime.InteropServices; using System.IO; using System.Text; ///////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// Event data for connection event handlers. /// </summary> public class ConnectionEventArgs : EventArgs |
︙ | ︙ | |||
177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 | /// </item> /// <item> /// <description>Password</description> /// <description>{password} - Using this parameter requires that the CryptoAPI based codec be enabled at compile-time for both the native interop assembly and the core managed assemblies; otherwise, using this parameter may result in an exception being thrown when attempting to open the connection.</description> /// <description>N</description> /// <description></description> /// </item> /// <item> /// <description>Enlist</description> /// <description><b>Y</b> - Automatically enlist in distributed transactions<br/><b>N</b> - No automatic enlistment</description> /// <description>N</description> /// <description>Y</description> /// </item> /// <item> /// <description>Pooling</description> | > > > > > > > > | > > > > > | 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 | /// </item> /// <item> /// <description>Password</description> /// <description>{password} - Using this parameter requires that the CryptoAPI based codec be enabled at compile-time for both the native interop assembly and the core managed assemblies; otherwise, using this parameter may result in an exception being thrown when attempting to open the connection.</description> /// <description>N</description> /// <description></description> /// </item> /// <item> /// <description>HexPassword</description> /// <description>{hexPassword} - Must contain a sequence of zero or more hexadecimal encoded byte values without a leading "0x" prefix. Using this parameter requires that the CryptoAPI based codec be enabled at compile-time for both the native interop assembly and the core managed assemblies; otherwise, using this parameter may result in an exception being thrown when attempting to open the connection.</description> /// <description>N</description> /// <description></description> /// </item> /// <item> /// <description>Enlist</description> /// <description><b>Y</b> - Automatically enlist in distributed transactions<br/><b>N</b> - No automatic enlistment</description> /// <description>N</description> /// <description>Y</description> /// </item> /// <item> /// <description>Pooling</description> /// <description> /// <b>True</b> - Use connection pooling.<br/> /// <b>False</b> - Do not use connection pooling.<br/><br/> /// <b>WARNING:</b> When using the default connection pool implementation, /// setting this property to True should be avoided by applications that make /// use of COM (either directly or indirectly) due to possible deadlocks that /// can occur during the finalization of some COM objects. /// </description> /// <description>N</description> /// <description>False</description> /// </item> /// <item> /// <description>FailIfMissing</description> /// <description><b>True</b> - Don't create the database if it does not exist, throw an error instead<br/><b>False</b> - Automatically create the database if it does not exist</description> /// <description>N</description> |
︙ | ︙ | |||
292 293 294 295 296 297 298 299 300 301 302 303 304 305 | private const SQLiteJournalModeEnum DefaultJournalMode = SQLiteJournalModeEnum.Default; private const IsolationLevel DefaultIsolationLevel = IsolationLevel.Serializable; private const SQLiteDateFormats DefaultDateTimeFormat = SQLiteDateFormats.ISO8601; private const DateTimeKind DefaultDateTimeKind = DateTimeKind.Unspecified; private const string DefaultDataSource = null; private const string DefaultUri = null; private const string DefaultFullUri = null; private const string DefaultPassword = null; private const int DefaultVersion = 3; private const int DefaultPageSize = 1024; private const int DefaultMaxPageCount = 0; private const int DefaultCacheSize = 2000; private const int DefaultMaxPoolSize = 100; private const int DefaultConnectionTimeout = 30; | > | 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 | private const SQLiteJournalModeEnum DefaultJournalMode = SQLiteJournalModeEnum.Default; private const IsolationLevel DefaultIsolationLevel = IsolationLevel.Serializable; private const SQLiteDateFormats DefaultDateTimeFormat = SQLiteDateFormats.ISO8601; private const DateTimeKind DefaultDateTimeKind = DateTimeKind.Unspecified; private const string DefaultDataSource = null; private const string DefaultUri = null; private const string DefaultFullUri = null; private const string DefaultHexPassword = null; private const string DefaultPassword = null; private const int DefaultVersion = 3; private const int DefaultPageSize = 1024; private const int DefaultMaxPageCount = 0; private const int DefaultCacheSize = 2000; private const int DefaultMaxPoolSize = 100; private const int DefaultConnectionTimeout = 30; |
︙ | ︙ | |||
472 473 474 475 476 477 478 | /// </param> public SQLiteConnection(string connectionString, bool parseViaFramework) { #if (SQLITE_STANDARD || USE_INTEROP_DLL || PLATFORM_COMPACTFRAMEWORK) && PRELOAD_NATIVE_LIBRARY UnsafeNativeMethods.Initialize(); #endif | | > | | 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 | /// </param> public SQLiteConnection(string connectionString, bool parseViaFramework) { #if (SQLITE_STANDARD || USE_INTEROP_DLL || PLATFORM_COMPACTFRAMEWORK) && PRELOAD_NATIVE_LIBRARY UnsafeNativeMethods.Initialize(); #endif #if !INTEROP_LOG SQLiteLog.Initialize(); #endif #if !PLATFORM_COMPACTFRAMEWORK && !INTEROP_LEGACY_CLOSE && SQLITE_STANDARD // // NOTE: Check if the sqlite3_close_v2() native API should be available // to use. This must be done dynamically because the delegate set // here is used by the SQLiteConnectionHandle class, which is a // CriticalHandle derived class (i.e. protected by a constrained // execution region). Therefore, if the underlying native entry // point is unavailable, an exception will be raised even if it is |
︙ | ︙ | |||
498 499 500 501 502 503 504 | _versionNumber = SQLite3.SQLiteVersionNumber; if (_versionNumber >= 3007014) SQLiteConnectionHandle.closeConnection = SQLiteBase.CloseConnectionV2; } } #endif | > | | 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 | _versionNumber = SQLite3.SQLiteVersionNumber; if (_versionNumber >= 3007014) SQLiteConnectionHandle.closeConnection = SQLiteBase.CloseConnectionV2; } } #endif #if INTEROP_LOG if (UnsafeNativeMethods.sqlite3_config_log_interop() == SQLiteErrorCode.Ok) { UnsafeNativeMethods.sqlite3_log( SQLiteErrorCode.Ok, SQLiteConvert.ToUTF8("logging initialized.")); } #endif |
︙ | ︙ | |||
620 621 622 623 624 625 626 627 628 629 630 631 632 633 | _handlers -= value; } } } /////////////////////////////////////////////////////////////////////////////////////////////// #region Backup API Members /// <summary> /// Backs up the database, using the specified database connection as the /// destination. /// </summary> /// <param name="destination">The destination database connection.</param> /// <param name="destinationName">The destination database name.</param> | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 | _handlers -= value; } } } /////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// This property is used to obtain or set the custom connection pool /// implementation to use, if any. Setting this property to null will /// cause the default connection pool implementation to be used. /// </summary> public static ISQLiteConnectionPool ConnectionPool { get { return SQLiteConnectionPool.GetConnectionPool(); } set { SQLiteConnectionPool.SetConnectionPool(value); } } /////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// Creates and returns a new managed database connection handle. This /// method is intended to be used by implementations of the /// <see cref="ISQLiteConnectionPool" /> interface only. In theory, it /// could be used by other classes; however, that usage is not supported. /// </summary> /// <param name="nativeHandle"> /// This must be a native database connection handle returned by the /// SQLite core library and it must remain valid and open during the /// entire duration of the calling method. /// </param> /// <returns> /// The new managed database connection handle or null if it cannot be /// created. /// </returns> public static object CreateHandle( IntPtr nativeHandle ) { if (nativeHandle == IntPtr.Zero) return null; return new SQLiteConnectionHandle(nativeHandle); } /////////////////////////////////////////////////////////////////////////////////////////////// #region Backup API Members /// <summary> /// Backs up the database, using the specified database connection as the /// destination. /// </summary> /// <param name="destination">The destination database connection.</param> /// <param name="destinationName">The destination database name.</param> |
︙ | ︙ | |||
715 716 717 718 719 720 721 | // 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; } } | < < | 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 | // NOTE: There is no point in calling the native API to copy // zero pages as it does nothing; therefore, stop now. // if (pages == 0) break; } } catch (Exception e) { if ((_flags & SQLiteConnectionFlags.LogBackup) == SQLiteConnectionFlags.LogBackup) { SQLiteLog.LogMessage(String.Format( CultureInfo.CurrentCulture, "Caught exception while backing up database: {0}", e)); } throw; } finally { if (backup != null) sqliteBase.FinishBackup(backup); /* throw */ } } #endregion |
︙ | ︙ | |||
1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 | /// </item> /// <item> /// <description>Password</description> /// <description>{password} - Using this parameter requires that the CryptoAPI based codec be enabled at compile-time for both the native interop assembly and the core managed assemblies; otherwise, using this parameter may result in an exception being thrown when attempting to open the connection.</description> /// <description>N</description> /// <description></description> /// </item> /// <item> /// <description>Enlist</description> /// <description><b>Y</b> - Automatically enlist in distributed transactions<br/><b>N</b> - No automatic enlistment</description> /// <description>N</description> /// <description>Y</description> /// </item> /// <item> /// <description>Pooling</description> | > > > > > > > > | > > > > > | 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 | /// </item> /// <item> /// <description>Password</description> /// <description>{password} - Using this parameter requires that the CryptoAPI based codec be enabled at compile-time for both the native interop assembly and the core managed assemblies; otherwise, using this parameter may result in an exception being thrown when attempting to open the connection.</description> /// <description>N</description> /// <description></description> /// </item> /// <item> /// <description>HexPassword</description> /// <description>{hexPassword} - Must contain a sequence of zero or more hexadecimal encoded byte values without a leading "0x" prefix. Using this parameter requires that the CryptoAPI based codec be enabled at compile-time for both the native interop assembly and the core managed assemblies; otherwise, using this parameter may result in an exception being thrown when attempting to open the connection.</description> /// <description>N</description> /// <description></description> /// </item> /// <item> /// <description>Enlist</description> /// <description><b>Y</b> - Automatically enlist in distributed transactions<br/><b>N</b> - No automatic enlistment</description> /// <description>N</description> /// <description>Y</description> /// </item> /// <item> /// <description>Pooling</description> /// <description> /// <b>True</b> - Use connection pooling.<br/> /// <b>False</b> - Do not use connection pooling.<br/><br/> /// <b>WARNING:</b> When using the default connection pool implementation, /// setting this property to True should be avoided by applications that /// make use of COM (either directly or indirectly) due to possible /// deadlocks that can occur during the finalization of some COM objects. /// </description> /// <description>N</description> /// <description>False</description> /// </item> /// <item> /// <description>FailIfMissing</description> /// <description><b>True</b> - Don't create the database if it does not exist, throw an error instead<br/><b>False</b> - Automatically create the database if it does not exist</description> /// <description>N</description> |
︙ | ︙ | |||
1331 1332 1333 1334 1335 1336 1337 | /// <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); | | < | 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 | /// <returns>An array of key-value pairs representing each parameter of the connection string</returns> internal static SortedList<string, string> ParseConnectionString(string connectionString) { string s = connectionString; int n; SortedList<string, string> ls = new SortedList<string, string>(StringComparer.OrdinalIgnoreCase); // First split into semi-colon delimited values. string[] arParts = s.Split(';'); int x = arParts.Length; // For each semi-colon piece, split into key and value pairs by the presence of the = sign for (n = 0; n < x; n++) { if (arParts[n] == null) |
︙ | ︙ | |||
1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 | catch { // do nothing. } return null; } /// <summary> /// Enables or disabled extension loading. /// </summary> /// <param name="enable"> /// True to enable loading of extensions, false to disable. /// </param> | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 | catch { // do nothing. } return null; } /// <summary> /// Attempts to convert an input string into a byte value. /// </summary> /// <param name="value"> /// The string value to be converted. /// </param> /// <param name="style"> /// The number styles to use for the conversion. /// </param> /// <param name="result"> /// Upon sucess, this will contain the parsed byte value. /// Upon failure, the value of this parameter is undefined. /// </param> /// <returns> /// Non-zero upon success; zero on failure. /// </returns> private static bool TryParseByte( string value, NumberStyles style, out byte result ) { #if !PLATFORM_COMPACTFRAMEWORK return byte.TryParse(value, style, null, out result); #else try { result = byte.Parse(value, style); return true; } catch { result = 0; return false; } #endif } /// <summary> /// Enables or disabled extension loading. /// </summary> /// <param name="enable"> /// True to enable loading of extensions, false to disable. /// </param> |
︙ | ︙ | |||
1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 | if (_sql == null) throw new InvalidOperationException( "Database connection not valid for loading extensions."); _sql.LoadExtension(fileName, procName); } /// <summary> /// Opens the connection using the parameters found in the <see cref="ConnectionString" />. /// </summary> public override void Open() { CheckDisposed(); | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 | if (_sql == null) throw new InvalidOperationException( "Database connection not valid for loading extensions."); _sql.LoadExtension(fileName, procName); } /// <summary> /// Parses a string containing a sequence of zero or more hexadecimal /// encoded byte values and returns the resulting byte array. The /// "0x" prefix is not allowed on the input string. /// </summary> /// <param name="text"> /// The input string containing zero or more hexadecimal encoded byte /// values. /// </param> /// <returns> /// A byte array containing the parsed byte values or null if an error /// was encountered. /// </returns> internal static byte[] FromHexString( string text ) { string error = null; return FromHexString(text, ref error); } /// <summary> /// Creates and returns a string containing the hexadecimal encoded byte /// values from the input array. /// </summary> /// <param name="array"> /// The input array of bytes. /// </param> /// <returns> /// The resulting string or null upon failure. /// </returns> internal static string ToHexString( byte[] array ) { if (array == null) return null; StringBuilder result = new StringBuilder(); int length = array.Length; for (int index = 0; index < length; index++) #if NET_COMPACT_20 result.Append(String.Format("{0:x2}", array[index])); #else result.AppendFormat("{0:x2}", array[index]); #endif return result.ToString(); } /// <summary> /// Parses a string containing a sequence of zero or more hexadecimal /// encoded byte values and returns the resulting byte array. The /// "0x" prefix is not allowed on the input string. /// </summary> /// <param name="text"> /// The input string containing zero or more hexadecimal encoded byte /// values. /// </param> /// <param name="error"> /// Upon failure, this will contain an appropriate error message. /// </param> /// <returns> /// A byte array containing the parsed byte values or null if an error /// was encountered. /// </returns> private static byte[] FromHexString( string text, ref string error ) { if (String.IsNullOrEmpty(text)) { error = "string is null or empty"; return null; } if (text.Length % 2 != 0) { error = "string contains an odd number of characters"; return null; } byte[] result = new byte[text.Length / 2]; for (int index = 0; index < text.Length; index += 2) { string value = text.Substring(index, 2); if (!TryParseByte(value, NumberStyles.HexNumber, out result[index / 2])) { error = String.Format( "string contains \"{0}\", which cannot be converted to a byte value", value); return null; } } return result; } /// <summary> /// Opens the connection using the parameters found in the <see cref="ConnectionString" />. /// </summary> public override void Open() { CheckDisposed(); |
︙ | ︙ | |||
1682 1683 1684 1685 1686 1687 1688 | flags |= SQLiteOpenFlagsEnum.Uri; _sql.Open(fileName, _flags, flags, maxPoolSize, usePooling); _binaryGuid = SQLiteConvert.ToBoolean(FindKey(opts, "BinaryGUID", DefaultBinaryGUID.ToString())); #if INTEROP_CODEC | > > > > > > > > > > > > > > > > > > | | | | | | | 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 | flags |= SQLiteOpenFlagsEnum.Uri; _sql.Open(fileName, _flags, flags, maxPoolSize, usePooling); _binaryGuid = SQLiteConvert.ToBoolean(FindKey(opts, "BinaryGUID", DefaultBinaryGUID.ToString())); #if INTEROP_CODEC string hexPassword = FindKey(opts, "HexPassword", DefaultHexPassword); if (!String.IsNullOrEmpty(hexPassword)) { string error = null; byte[] hexPasswordBytes = FromHexString(hexPassword, ref error); if (hexPasswordBytes == null) { throw new FormatException(String.Format( "Cannot parse 'HexPassword' property value into byte values: {0}", error)); } _sql.SetPassword(hexPasswordBytes); } else { string password = FindKey(opts, "Password", DefaultPassword); if (!String.IsNullOrEmpty(password)) _sql.SetPassword(UTF8Encoding.UTF8.GetBytes(password)); else if (_password != null) _sql.SetPassword(_password); } _password = null; #endif if (!fullUri) _dataSource = Path.GetFileNameWithoutExtension(fileName); else _dataSource = fileName; |
︙ | ︙ | |||
2133 2134 2135 2136 2137 2138 2139 | /// 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(); | | | 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 | /// and if it already was password protected, the existing password must already have been supplied. /// </remarks> /// <param name="newPassword">The new password to assign to the database</param> public void ChangePassword(string newPassword) { CheckDisposed(); ChangePassword(String.IsNullOrEmpty(newPassword) ? null : UTF8Encoding.UTF8.GetBytes(newPassword)); } /// <summary> /// Change the password (or assign a password) to an open database. /// </summary> /// <remarks> /// No readers or writers may be active for this process. The database must already be open |
︙ | ︙ | |||
2163 2164 2165 2166 2167 2168 2169 | /// 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(); | | | 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 | /// unusable for any operation until the password has been set. /// </summary> /// <param name="databasePassword">The password for the database</param> public void SetPassword(string databasePassword) { CheckDisposed(); SetPassword(String.IsNullOrEmpty(databasePassword) ? null : UTF8Encoding.UTF8.GetBytes(databasePassword)); } /// <summary> /// Sets the password for a password-protected database. A password-protected database is /// unusable for any operation until the password has been set. /// </summary> /// <param name="databasePassword">The password for the database</param> |
︙ | ︙ |
Changes to System.Data.SQLite/SQLiteConnectionPool.cs.
1 2 3 4 5 6 7 8 9 | /******************************************************** * 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 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 | /******************************************************** * ADO.NET 2.0 Data Provider for SQLite Version 3.X * Written by Robert Simpson (robert@blackcastlesoft.com) * * Released to the public domain, use at your own risk! ********************************************************/ namespace System.Data.SQLite { using System; using System.Collections.Generic; #if !PLATFORM_COMPACTFRAMEWORK && DEBUG using System.Text; #endif using System.Threading; /////////////////////////////////////////////////////////////////////////// #region Null Connection Pool Class #if !PLATFORM_COMPACTFRAMEWORK && DEBUG /// <summary> /// This class implements a connection pool where all methods of the /// <see cref="ISQLiteConnectionPool" /> interface are NOPs. This class /// is used for testing purposes only. /// </summary> internal sealed class NullConnectionPool : ISQLiteConnectionPool { #region Private Data /// <summary> /// This field keeps track of all method calls made into the /// <see cref="ISQLiteConnectionPool" /> interface methods of this /// class. /// </summary> private StringBuilder log; /////////////////////////////////////////////////////////////////////// /// <summary> /// Non-zero to dispose of database connection handles received via the /// <see cref="Add" /> method. /// </summary> private bool dispose; #endregion /////////////////////////////////////////////////////////////////////// #region Private Constructors /// <summary> /// Constructs a connection pool object where all methods of the /// <see cref="ISQLiteConnectionPool" /> interface are NOPs. This /// class is used for testing purposes only. /// </summary> private NullConnectionPool() { log = new StringBuilder(); } #endregion /////////////////////////////////////////////////////////////////////// #region Public Constructors /// <summary> /// Constructs a connection pool object where all methods of the /// <see cref="ISQLiteConnectionPool" /> interface are NOPs. This /// class is used for testing purposes only. /// </summary> /// <param name="dispose"> /// Non-zero to dispose of database connection handles received via the /// <see cref="Add" /> method. /// </param> public NullConnectionPool( bool dispose ) : this() { this.dispose = dispose; } #endregion /////////////////////////////////////////////////////////////////////// #region ISQLiteConnectionPool Members /// <summary> /// Counts the number of pool entries matching the specified file name. /// </summary> /// <param name="fileName"> /// The file name to match or null to match all files. /// </param> /// <param name="counts"> /// The pool entry counts for each matching file. /// </param> /// <param name="openCount"> /// The total number of connections successfully opened from any pool. /// </param> /// <param name="closeCount"> /// The total number of connections successfully closed from any pool. /// </param> /// <param name="totalCount"> /// The total number of pool entries for all matching files. /// </param> public void GetCounts( string fileName, ref Dictionary<string, int> counts, ref int openCount, ref int closeCount, ref int totalCount ) { if (log != null) { log.AppendFormat( "GetCounts(\"{0}\", {1}, {2}, {3}, {4}){5}", fileName, counts, openCount, closeCount, totalCount, Environment.NewLine); } } /////////////////////////////////////////////////////////////////////// /// <summary> /// Disposes of all pooled connections associated with the specified /// database file name. /// </summary> /// <param name="fileName"> /// The database file name. /// </param> public void ClearPool( string fileName ) { if (log != null) { log.AppendFormat( "ClearPool(\"{0}\"){1}", fileName, Environment.NewLine); } } /////////////////////////////////////////////////////////////////////// /// <summary> /// Disposes of all pooled connections. /// </summary> public void ClearAllPools() { if (log != null) { log.AppendFormat( "ClearAllPools(){0}", Environment.NewLine); } } /////////////////////////////////////////////////////////////////////// /// <summary> /// Adds a connection to the pool of those associated with the /// specified database file name. /// </summary> /// <param name="fileName"> /// The database file name. /// </param> /// <param name="handle"> /// The database connection handle. /// </param> /// <param name="version"> /// The connection pool version at the point the database connection /// handle was received from the connection pool. This is also the /// connection pool version that the database connection handle was /// created under. /// </param> public void Add( string fileName, object handle, int version ) { if (log != null) { log.AppendFormat( "Add(\"{0}\", {1}, {2}){3}", fileName, handle, version, Environment.NewLine); } // // NOTE: If configured to do so, dispose of the received connection // handle now. // if (dispose) { IDisposable disposable = handle as IDisposable; if (disposable != null) disposable.Dispose(); } } /////////////////////////////////////////////////////////////////////// /// <summary> /// Removes a connection from the pool of those associated with the /// specified database file name with the intent of using it to /// interact with the database. /// </summary> /// <param name="fileName"> /// The database file name. /// </param> /// <param name="maxPoolSize"> /// The new maximum size of the connection pool for the specified /// database file name. /// </param> /// <param name="version"> /// The connection pool version associated with the returned database /// connection handle, if any. /// </param> /// <returns> /// The database connection handle associated with the specified /// database file name or null if it cannot be obtained. /// </returns> public object Remove( string fileName, int maxPoolSize, out int version ) { version = 0; if (log != null) { log.AppendFormat( "Remove(\"{0}\", {1}, {2}){3}", fileName, maxPoolSize, version, Environment.NewLine); } return null; } #endregion /////////////////////////////////////////////////////////////////////// #region System.Object Overrides /// <summary> /// Overrides the default <see cref="System.Object.ToString" /> method /// to provide a log of all methods called on the /// <see cref="ISQLiteConnectionPool" /> interface. /// </summary> /// <returns> /// A string containing a log of all method calls into the /// <see cref="ISQLiteConnectionPool" /> interface, along with their /// parameters, delimited by <see cref="Environment.NewLine" />. /// </returns> public override string ToString() { return (log != null) ? log.ToString() : String.Empty; } #endregion } #endif #endregion /////////////////////////////////////////////////////////////////////////// #region Public Connection Pool Interface /// <summary> /// This interface represents a custom connection pool implementation /// usable by System.Data.SQLite. /// </summary> public interface ISQLiteConnectionPool { /// <summary> /// Counts the number of pool entries matching the specified file name. /// </summary> /// <param name="fileName"> /// The file name to match or null to match all files. /// </param> /// <param name="counts"> /// The pool entry counts for each matching file. /// </param> /// <param name="openCount"> /// The total number of connections successfully opened from any pool. /// </param> /// <param name="closeCount"> /// The total number of connections successfully closed from any pool. /// </param> /// <param name="totalCount"> /// The total number of pool entries for all matching files. /// </param> void GetCounts(string fileName, ref Dictionary<string, int> counts, ref int openCount, ref int closeCount, ref int totalCount); /// <summary> /// Disposes of all pooled connections associated with the specified /// database file name. /// </summary> /// <param name="fileName"> /// The database file name. /// </param> void ClearPool(string fileName); /// <summary> /// Disposes of all pooled connections. /// </summary> void ClearAllPools(); /// <summary> /// Adds a connection to the pool of those associated with the /// specified database file name. /// </summary> /// <param name="fileName"> /// The database file name. /// </param> /// <param name="handle"> /// The database connection handle. /// </param> /// <param name="version"> /// The connection pool version at the point the database connection /// handle was received from the connection pool. This is also the /// connection pool version that the database connection handle was /// created under. /// </param> void Add(string fileName, object handle, int version); /// <summary> /// Removes a connection from the pool of those associated with the /// specified database file name with the intent of using it to /// interact with the database. /// </summary> /// <param name="fileName"> /// The database file name. /// </param> /// <param name="maxPoolSize"> /// The new maximum size of the connection pool for the specified /// database file name. /// </param> /// <param name="version"> /// The connection pool version associated with the returned database /// connection handle, if any. /// </param> /// <returns> /// The database connection handle associated with the specified /// database file name or null if it cannot be obtained. /// </returns> object Remove(string fileName, int maxPoolSize, out int version); } #endregion /////////////////////////////////////////////////////////////////////////// #region Connection Pool Subsystem & Default Implementation /// <summary> /// This default method implementations in this class should not be used by /// applications that make use of COM (either directly or indirectly) due /// to possible deadlocks that can occur during finalization of some COM /// objects. /// </summary> internal static class SQLiteConnectionPool { #region Private Pool Class /// <summary> /// Keeps track of connections made on a specified file. The PoolVersion /// dictates whether old objects get returned to the pool or discarded /// when no longer in use. /// </summary> private sealed class PoolQueue { #region Private Data /// <summary> /// The queue of weak references to the actual database connection /// handles. /// </summary> internal readonly Queue<WeakReference> Queue = new Queue<WeakReference>(); /////////////////////////////////////////////////////////////////// /// <summary> /// This pool version associated with the database connection /// handles in this pool queue. /// </summary> internal int PoolVersion; /////////////////////////////////////////////////////////////////// /// <summary> /// The maximum size of this pool queue. /// </summary> internal int MaxPoolSize; #endregion /////////////////////////////////////////////////////////////////// #region Private Constructors /// <summary> /// Constructs a connection pool queue using the specified version /// and maximum size. Normally, all the database connection /// handles in this pool are associated with a single database file /// name. /// </summary> /// <param name="version"> /// The initial pool version for this connection pool queue. /// </param> /// <param name="maxSize"> /// The initial maximum size for this connection pool queue. /// </param> internal PoolQueue( int version, int maxSize ) { PoolVersion = version; MaxPoolSize = maxSize; } #endregion } #endregion /////////////////////////////////////////////////////////////////////// #region Private Static Data /// <summary> /// This field is used to synchronize access to the private static data /// in this class. /// </summary> private static readonly object _syncRoot = new object(); /////////////////////////////////////////////////////////////////////// /// <summary> /// When this field is non-null, it will be used to provide the /// implementation of all the connection pool methods; otherwise, /// the default method implementations will be used. /// </summary> private static ISQLiteConnectionPool _connectionPool = null; /////////////////////////////////////////////////////////////////////// /// <summary> /// The dictionary of connection pools, based on the normalized file /// name of the SQLite database. /// </summary> private static SortedList<string, PoolQueue> _queueList = new SortedList<string, PoolQueue>(StringComparer.OrdinalIgnoreCase); /////////////////////////////////////////////////////////////////////// /// <summary> /// The default version number new pools will get. /// </summary> private static int _poolVersion = 1; /////////////////////////////////////////////////////////////////////// /// <summary> /// The number of connections successfully opened from any pool. /// This value is incremented by the Remove method. /// </summary> private static int _poolOpened = 0; /////////////////////////////////////////////////////////////////////// /// <summary> /// The number of connections successfully closed from any pool. /// This value is incremented by the Add method. /// </summary> private static int _poolClosed = 0; #endregion /////////////////////////////////////////////////////////////////////// #region ISQLiteConnectionPool Members (Static, Non-Formal) /// <summary> /// Counts the number of pool entries matching the specified file name. /// </summary> /// <param name="fileName"> /// The file name to match or null to match all files. /// </param> /// <param name="counts"> /// The pool entry counts for each matching file. /// </param> /// <param name="openCount"> /// The total number of connections successfully opened from any pool. /// </param> /// <param name="closeCount"> /// The total number of connections successfully closed from any pool. /// </param> /// <param name="totalCount"> /// The total number of pool entries for all matching files. /// </param> internal static void GetCounts( string fileName, ref Dictionary<string, int> counts, ref int openCount, ref int closeCount, ref int totalCount ) { ISQLiteConnectionPool connectionPool = GetConnectionPool(); if (connectionPool != null) { connectionPool.GetCounts( fileName, ref counts, ref openCount, ref closeCount, ref totalCount); } else { lock (_syncRoot) { openCount = _poolOpened; closeCount = _poolClosed; if (counts == null) { counts = new Dictionary<string, int>( StringComparer.OrdinalIgnoreCase); } if (fileName != null) { PoolQueue queue; if (_queueList.TryGetValue(fileName, out queue)) { Queue<WeakReference> poolQueue = queue.Queue; int count = (poolQueue != null) ? poolQueue.Count : 0; counts.Add(fileName, count); totalCount += count; } } else { foreach (KeyValuePair<string, PoolQueue> pair in _queueList) { if (pair.Value == null) continue; Queue<WeakReference> poolQueue = pair.Value.Queue; int count = (poolQueue != null) ? poolQueue.Count : 0; counts.Add(pair.Key, count); totalCount += count; } } } } } /////////////////////////////////////////////////////////////////////// /// <summary> /// Disposes of all pooled connections associated with the specified /// database file name. /// </summary> /// <param name="fileName"> /// The database file name. /// </param> internal static void ClearPool(string fileName) { ISQLiteConnectionPool connectionPool = GetConnectionPool(); if (connectionPool != null) { connectionPool.ClearPool(fileName); } else { lock (_syncRoot) { PoolQueue queue; if (_queueList.TryGetValue(fileName, out queue)) { queue.PoolVersion++; Queue<WeakReference> poolQueue = queue.Queue; if (poolQueue == null) return; while (poolQueue.Count > 0) { WeakReference connection = poolQueue.Dequeue(); if (connection == null) continue; SQLiteConnectionHandle handle = connection.Target as SQLiteConnectionHandle; if (handle != null) handle.Dispose(); GC.KeepAlive(handle); } } } } } /////////////////////////////////////////////////////////////////////// /// <summary> /// Disposes of all pooled connections. /// </summary> internal static void ClearAllPools() { ISQLiteConnectionPool connectionPool = GetConnectionPool(); if (connectionPool != null) { connectionPool.ClearAllPools(); } else { lock (_syncRoot) { foreach (KeyValuePair<string, PoolQueue> pair in _queueList) { if (pair.Value == null) continue; Queue<WeakReference> poolQueue = pair.Value.Queue; while (poolQueue.Count > 0) { WeakReference connection = poolQueue.Dequeue(); if (connection == null) continue; SQLiteConnectionHandle handle = connection.Target as SQLiteConnectionHandle; if (handle != null) handle.Dispose(); GC.KeepAlive(handle); } // // NOTE: Keep track of the highest revision so we can // go one higher when we are finished. // if (_poolVersion <= pair.Value.PoolVersion) _poolVersion = pair.Value.PoolVersion + 1; } // // NOTE: All pools are cleared and we have a new highest // version number to force all old version active // items to get discarded instead of going back to // the queue when they are closed. We can get away // with this because we have pumped up the pool // version out of range of all active connections, // so they will all get discarded when they try to // put themselves back into their pools. // _queueList.Clear(); } } } /////////////////////////////////////////////////////////////////////// /// <summary> /// Adds a connection to the pool of those associated with the /// specified database file name. /// </summary> /// <param name="fileName"> /// The database file name. /// </param> /// <param name="handle"> /// The database connection handle. /// </param> /// <param name="version"> /// The connection pool version at the point the database connection /// handle was received from the connection pool. This is also the /// connection pool version that the database connection handle was /// created under. /// </param> internal static void Add( string fileName, SQLiteConnectionHandle handle, int version ) { ISQLiteConnectionPool connectionPool = GetConnectionPool(); if (connectionPool != null) { connectionPool.Add(fileName, handle, version); } else { lock (_syncRoot) { // // NOTE: If the queue does not exist in the pool, then it // must have been cleared sometime after the // connection was created. // PoolQueue queue; if (_queueList.TryGetValue(fileName, out queue) && (version == queue.PoolVersion)) { ResizePool(queue, true); Queue<WeakReference> poolQueue = queue.Queue; if (poolQueue == null) return; poolQueue.Enqueue(new WeakReference(handle, false)); Interlocked.Increment(ref _poolClosed); } else { handle.Close(); } GC.KeepAlive(handle); } } } /////////////////////////////////////////////////////////////////////// /// <summary> /// Removes a connection from the pool of those associated with the /// specified database file name with the intent of using it to /// interact with the database. /// </summary> /// <param name="fileName"> /// The database file name. /// </param> /// <param name="maxPoolSize"> /// The new maximum size of the connection pool for the specified /// database file name. /// </param> /// <param name="version"> /// The connection pool version associated with the returned database /// connection handle, if any. /// </param> /// <returns> /// The database connection handle associated with the specified /// database file name or null if it cannot be obtained. /// </returns> internal static SQLiteConnectionHandle Remove( string fileName, int maxPoolSize, out int version ) { ISQLiteConnectionPool connectionPool = GetConnectionPool(); if (connectionPool != null) { return connectionPool.Remove(fileName, maxPoolSize, out version) as SQLiteConnectionHandle; } else { int localVersion; Queue<WeakReference> poolQueue; // // NOTE: This lock cannot be held while checking the queue for // available connections because other methods of this // class are called from the GC finalizer thread and we // use the WaitForPendingFinalizers method (below). // Holding this lock while calling that method would // therefore result in a deadlock. Instead, this lock // is held only while a temporary copy of the queue is // created, and if necessary, when committing changes // back to that original queue prior to returning from // this method. // lock (_syncRoot) { PoolQueue queue; // // NOTE: Default to the highest pool version. // version = _poolVersion; // // NOTE: If we didn't find a pool for this file, create one // even though it will be empty. We have to do this // here because otherwise calling ClearPool() on the // file will not work for active connections that have // never seen the pool yet. // if (!_queueList.TryGetValue(fileName, out queue)) { queue = new PoolQueue(_poolVersion, maxPoolSize); _queueList.Add(fileName, queue); return null; } // // NOTE: We found a pool for this file, so use its version // number. // version = localVersion = queue.PoolVersion; queue.MaxPoolSize = maxPoolSize; // // NOTE: Now, resize the pool to the new maximum size, if // necessary. // ResizePool(queue, false); // // NOTE: Try and get a pooled connection from the queue. // poolQueue = queue.Queue; if (poolQueue == null) return null; // // NOTE: Temporarily tranfer the queue for this file into // a local variable. The queue for this file will // be modified and then committed back to the real // pool list (below) prior to returning from this // method. // _queueList.Remove(fileName); poolQueue = new Queue<WeakReference>(poolQueue); } try { while (poolQueue.Count > 0) { WeakReference connection = poolQueue.Dequeue(); if (connection == null) continue; SQLiteConnectionHandle handle = connection.Target as SQLiteConnectionHandle; if (handle == null) continue; // // BUGFIX: For ticket [996d13cd87], step #1. After // this point, make sure that the finalizer for // the connection handle just obtained from the // queue cannot START running (i.e. it may // still be pending but it will no longer start // after this point). // GC.SuppressFinalize(handle); try { // // BUGFIX: For ticket [996d13cd87], step #2. Now, // we must wait for all pending finalizers // which have STARTED running and have not // yet COMPLETED. This must be done just // in case the finalizer for the connection // handle just obtained from the queue has // STARTED running at some point before // SuppressFinalize was called on it. // // After this point, checking properties of // the connection handle (e.g. IsClosed) // should work reliably without having to // worry that they will (due to the // finalizer) change out from under us. // GC.WaitForPendingFinalizers(); // // BUGFIX: For ticket [996d13cd87], step #3. Next, // verify that the connection handle is // actually valid and [still?] not closed // prior to actually returning it to our // caller. // if (!handle.IsInvalid && !handle.IsClosed) { Interlocked.Increment(ref _poolOpened); return handle; } } finally { // // BUGFIX: For ticket [996d13cd87], step #4. Next, // we must re-register the connection // handle for finalization now that we have // a strong reference to it (i.e. the // finalizer will not run at least until // the connection is subsequently closed). // GC.ReRegisterForFinalize(handle); } GC.KeepAlive(handle); } } finally { // // BUGFIX: For ticket [996d13cd87], step #5. Finally, // commit any changes to the pool/queue for this // database file. // lock (_syncRoot) { // // NOTE: We must check [again] if a pool exists for // this file because one may have been added // while the search for an available connection // was in progress (above). // PoolQueue queue; Queue<WeakReference> newPoolQueue; bool addPool; if (_queueList.TryGetValue(fileName, out queue)) { addPool = false; } else { addPool = true; queue = new PoolQueue(localVersion, maxPoolSize); } newPoolQueue = queue.Queue; while (poolQueue.Count > 0) newPoolQueue.Enqueue(poolQueue.Dequeue()); ResizePool(queue, false); if (addPool) _queueList.Add(fileName, queue); } } return null; } } #endregion /////////////////////////////////////////////////////////////////////// #region Private Helper Methods /// <summary> /// This method is used to obtain a reference to the custom connection /// pool implementation currently in use, if any. /// </summary> /// <returns> /// The custom connection pool implementation or null if the default /// connection pool implementation should be used. /// </returns> internal static ISQLiteConnectionPool GetConnectionPool() { lock (_syncRoot) { return _connectionPool; } } /////////////////////////////////////////////////////////////////////// /// <summary> /// This method is used to set the reference to the custom connection /// pool implementation to use, if any. /// </summary> /// <param name="connectionPool"> /// The custom connection pool implementation to use or null if the /// default connection pool implementation should be used. /// </param> internal static void SetConnectionPool( ISQLiteConnectionPool connectionPool ) { lock (_syncRoot) { _connectionPool = connectionPool; } } /////////////////////////////////////////////////////////////////////// /// <summary> /// We do not have to thread-lock anything in this function, because it /// is only called by other functions above which already take the lock. /// </summary> /// <param name="queue"> /// The pool queue to resize. /// </param> /// <param name="add"> /// If a function intends to add to the pool, this is true, which /// forces the resize to take one more than it needs from the pool. /// </param> private static void ResizePool( PoolQueue queue, bool add ) { int target = queue.MaxPoolSize; if (add && target > 0) target--; Queue<WeakReference> poolQueue = queue.Queue; if (poolQueue == null) return; while (poolQueue.Count > target) { WeakReference connection = poolQueue.Dequeue(); if (connection == null) continue; SQLiteConnectionHandle handle = connection.Target as SQLiteConnectionHandle; if (handle != null) handle.Dispose(); GC.KeepAlive(handle); } } #endregion } #endregion } |
Changes to System.Data.SQLite/SQLiteConnectionStringBuilder.cs.
︙ | ︙ | |||
342 343 344 345 346 347 348 349 350 351 352 353 354 355 | return value.ToString(); } set { this["password"] = value; } } /// <summary> /// Gets/Sets the page size for the connection. /// </summary> [DisplayName("Page Size")] [Browsable(true)] [DefaultValue(1024)] | > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 | return value.ToString(); } set { this["password"] = value; } } /// <summary> /// Gets/sets the database encryption hexadecimal password /// </summary> [Browsable(true)] [PasswordPropertyText(true)] [DefaultValue(null)] public byte[] HexPassword { get { object value; if (TryGetValue("hexpassword", out value)) { if (value is string) return SQLiteConnection.FromHexString((string)value); else if (value != null) return (byte[])value; } return null; } set { this["hexpassword"] = SQLiteConnection.ToHexString(value); } } /// <summary> /// Gets/Sets the page size for the connection. /// </summary> [DisplayName("Page Size")] [Browsable(true)] [DefaultValue(1024)] |
︙ | ︙ | |||
643 644 645 646 647 648 649 | 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); | | | 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 | if (pd == null) return b; // Attempt to coerce the value into something more solid if (b) { if (pd.PropertyType == typeof(Boolean)) value = SQLiteConvert.ToBoolean(value); else if (pd.PropertyType != typeof(byte[])) value = TypeDescriptor.GetConverter(pd.PropertyType).ConvertFrom(value); } else { DefaultValueAttribute att = pd.Attributes[typeof(DefaultValueAttribute)] as DefaultValueAttribute; if (att != null) { |
︙ | ︙ |
Changes to System.Data.SQLite/SQLiteConvert.cs.
1 2 3 | /******************************************************** * 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 183 184 | /// 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 (nativestring == IntPtr.Zero || nativestringlen == 0) return String.Empty; if (nativestringlen < 0) { nativestringlen = 0; while (Marshal.ReadByte(nativestring, nativestringlen) != 0) nativestringlen++; if (nativestringlen == 0) return String.Empty; } byte[] byteArray = new byte[nativestringlen]; Marshal.Copy(nativestring, byteArray, 0, nativestringlen); return _utf8.GetString(byteArray, 0, nativestringlen); } #endregion |
︙ | ︙ | |||
570 571 572 573 574 575 576 | if (t.Type == DbType.Object) return _affinitytotype[(int)t.Affinity]; else return SQLiteConvert.DbTypeToType(t.Type); } private static Type[] _affinitytotype = { | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | > | | | | 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 | if (t.Type == DbType.Object) return _affinitytotype[(int)t.Affinity]; else return SQLiteConvert.DbTypeToType(t.Type); } private static Type[] _affinitytotype = { typeof(object), // Uninitialized (0) typeof(Int64), // Int64 (1) typeof(Double), // Double (2) typeof(string), // Text (3) typeof(byte[]), // Blob (4) typeof(DBNull), // Null (5) typeof(DateTime), // DateTime (10) typeof(object) // None (11) }; /// <summary> /// For a given intrinsic type, return a DbType /// </summary> /// <param name="typ">The native type to convert</param> /// <returns>The corresponding (closest match) DbType</returns> internal static DbType TypeToDbType(Type typ) { TypeCode tc = Type.GetTypeCode(typ); if (tc == TypeCode.Object) { if (typ == typeof(byte[])) return DbType.Binary; if (typ == typeof(Guid)) return DbType.Guid; return DbType.String; } return _typetodbtype[(int)tc]; } private static DbType[] _typetodbtype = { DbType.Object, // Empty (0) DbType.Binary, // Object (1) DbType.Object, // DBNull (2) DbType.Boolean, // Boolean (3) DbType.SByte, // Char (4) DbType.SByte, // SByte (5) DbType.Byte, // Byte (6) DbType.Int16, // Int16 (7) DbType.UInt16, // UInt16 (8) DbType.Int32, // Int32 (9) DbType.UInt32, // UInt32 (10) DbType.Int64, // Int64 (11) DbType.UInt64, // UInt64 (12) DbType.Single, // Single (13) DbType.Double, // Double (14) DbType.Decimal, // Decimal (15) DbType.DateTime, // DateTime (16) DbType.Object, // ?? (17) DbType.String // String (18) }; /// <summary> /// Returns the ColumnSize for the given DbType /// </summary> /// <param name="typ">The DbType to get the size of</param> /// <returns></returns> internal static int DbTypeToColumnSize(DbType typ) { return _dbtypetocolumnsize[(int)typ]; } private static int[] _dbtypetocolumnsize = { int.MaxValue, // AnsiString (0) int.MaxValue, // Binary (1) 1, // Byte (2) 1, // Boolean (3) 8, // Currency (4) 8, // Date (5) 8, // DateTime (6) 8, // Decimal (7) 8, // Double (8) 16, // Guid (9) 2, // Int16 (10) 4, // Int32 (11) 8, // Int64 (12) int.MaxValue, // Object (13) 1, // SByte (14) 4, // Single (15) int.MaxValue, // String (16) 8, // Time (17) 2, // UInt16 (18) 4, // UInt32 (19) 8, // UInt64 (20) 8, // VarNumeric (21) int.MaxValue, // AnsiStringFixedLength (22) int.MaxValue, // StringFixedLength (23) int.MaxValue, // ?? (24) int.MaxValue // Xml (25) }; internal static object DbTypeToNumericPrecision(DbType typ) { return _dbtypetonumericprecision[(int)typ]; } private static object[] _dbtypetonumericprecision = { DBNull.Value, // AnsiString (0) DBNull.Value, // Binary (1) 3, // Byte (2) DBNull.Value, // Boolean (3) 19, // Currency (4) DBNull.Value, // Date (5) DBNull.Value, // DateTime (6) 53, // Decimal (7) 53, // Double (8) DBNull.Value, // Guid (9) 5, // Int16 (10) 10, // Int32 (11) 19, // Int64 (12) DBNull.Value, // Object (13) 3, // SByte (14) 24, // Single (15) DBNull.Value, // String (16) DBNull.Value, // Time (17) 5, // UInt16 (18) 10, // UInt32 (19) 19, // UInt64 (20) 53, // VarNumeric (21) DBNull.Value, // AnsiStringFixedLength (22) DBNull.Value, // StringFixedLength (23) DBNull.Value, // ?? (24) DBNull.Value // Xml (25) }; internal static object DbTypeToNumericScale(DbType typ) { return _dbtypetonumericscale[(int)typ]; } private static object[] _dbtypetonumericscale = { DBNull.Value, // AnsiString (0) DBNull.Value, // Binary (1) 0, // Byte (2) DBNull.Value, // Boolean (3) 4, // Currency (4) DBNull.Value, // Date (5) DBNull.Value, // DateTime (6) DBNull.Value, // Decimal (7) DBNull.Value, // Double (8) DBNull.Value, // Guid (9) 0, // Int16 (10) 0, // Int32 (11) 0, // Int64 (12) DBNull.Value, // Object (13) 0, // SByte (14) DBNull.Value, // Single (15) DBNull.Value, // String (16) DBNull.Value, // Time (17) 0, // UInt16 (18) 0, // UInt32 (19) 0, // UInt64 (20) 0, // VarNumeric (21) DBNull.Value, // AnsiStringFixedLength (22) DBNull.Value, // StringFixedLength (23) DBNull.Value, // ?? (24) DBNull.Value // Xml (25) }; internal static string DbTypeToTypeName(DbType typ) { for (int n = 0; n < _dbtypeNames.Length; n++) { if (_dbtypeNames[n].dataType == typ) |
︙ | ︙ | |||
743 744 745 746 747 748 749 | "WARNING: Type mapping failed, returning default name \"{0}\" for type {1}.", defaultTypeName, typ)); #endif return defaultTypeName; } | | | < < < < < < < < < < < < < < < | | | | | | | | | | | | | | | | | | | | | | | | | | | 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 | "WARNING: Type mapping failed, returning default name \"{0}\" for type {1}.", defaultTypeName, typ)); #endif return defaultTypeName; } private static SQLiteTypeNames[] _dbtypeNames = GetSQLiteTypeNames(); /// <summary> /// Convert a DbType to a Type /// </summary> /// <param name="typ">The DbType to convert from</param> /// <returns>The closest-match .NET type</returns> internal static Type DbTypeToType(DbType typ) { return _dbtypeToType[(int)typ]; } private static Type[] _dbtypeToType = { typeof(string), // AnsiString (0) typeof(byte[]), // Binary (1) typeof(byte), // Byte (2) typeof(bool), // Boolean (3) typeof(decimal), // Currency (4) typeof(DateTime), // Date (5) typeof(DateTime), // DateTime (6) typeof(decimal), // Decimal (7) typeof(double), // Double (8) typeof(Guid), // Guid (9) typeof(Int16), // Int16 (10) typeof(Int32), // Int32 (11) typeof(Int64), // Int64 (12) typeof(object), // Object (13) typeof(sbyte), // SByte (14) typeof(float), // Single (15) typeof(string), // String (16) typeof(DateTime), // Time (17) typeof(UInt16), // UInt16 (18) typeof(UInt32), // UInt32 (19) typeof(UInt64), // UInt64 (20) typeof(double), // VarNumeric (21) typeof(string), // AnsiStringFixedLength (22) typeof(string), // StringFixedLength (23) typeof(string), // ?? (24) typeof(string), // Xml (25) }; /// <summary> /// For a given type, return the closest-match SQLite TypeAffinity, which only understands a very limited subset of types. /// </summary> /// <param name="typ">The type to evaluate</param> /// <returns>The SQLite type affinity for that type.</returns> |
︙ | ︙ | |||
818 819 820 821 822 823 824 | else return TypeAffinity.Text; } return _typecodeAffinities[(int)tc]; } private static TypeAffinity[] _typecodeAffinities = { | | | | | | | | | | | | | | | | | | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 | else return TypeAffinity.Text; } return _typecodeAffinities[(int)tc]; } private static TypeAffinity[] _typecodeAffinities = { TypeAffinity.Null, // Empty (0) TypeAffinity.Blob, // Object (1) TypeAffinity.Null, // DBNull (2) TypeAffinity.Int64, // Boolean (3) TypeAffinity.Int64, // Char (4) TypeAffinity.Int64, // SByte (5) TypeAffinity.Int64, // Byte (6) TypeAffinity.Int64, // Int16 (7) TypeAffinity.Int64, // UInt16 (8) TypeAffinity.Int64, // Int32 (9) TypeAffinity.Int64, // UInt32 (10) TypeAffinity.Int64, // Int64 (11) TypeAffinity.Int64, // UInt64 (12) TypeAffinity.Double, // Single (13) TypeAffinity.Double, // Double (14) TypeAffinity.Double, // Decimal (15) TypeAffinity.DateTime, // DateTime (16) TypeAffinity.Null, // ?? (17) TypeAffinity.Text // String (18) }; /// <summary> /// Builds and returns an array containing the database column types /// recognized by this provider. /// </summary> /// <returns> /// An array containing the database column types recognized by this /// provider. /// </returns> private static SQLiteTypeNames[] GetSQLiteTypeNames() { return new SQLiteTypeNames[] { new SQLiteTypeNames("BIGINT", DbType.Int64), new SQLiteTypeNames("BIGUINT", DbType.UInt64), new SQLiteTypeNames("BINARY", DbType.Binary), new SQLiteTypeNames("BIT", DbType.Boolean), new SQLiteTypeNames("BLOB", DbType.Binary), new SQLiteTypeNames("BOOL", DbType.Boolean), new SQLiteTypeNames("BOOLEAN", DbType.Boolean), new SQLiteTypeNames("CHAR", DbType.AnsiStringFixedLength), new SQLiteTypeNames("COUNTER", DbType.Int64), new SQLiteTypeNames("CURRENCY", DbType.Decimal), new SQLiteTypeNames("DATE", DbType.DateTime), new SQLiteTypeNames("DATETIME", DbType.DateTime), new SQLiteTypeNames("DECIMAL", DbType.Decimal), new SQLiteTypeNames("DOUBLE", DbType.Double), new SQLiteTypeNames("FLOAT", DbType.Double), new SQLiteTypeNames("GENERAL", DbType.Binary), new SQLiteTypeNames("GUID", DbType.Guid), new SQLiteTypeNames("IDENTITY", DbType.Int64), new SQLiteTypeNames("IMAGE", DbType.Binary), new SQLiteTypeNames("INT", DbType.Int32), new SQLiteTypeNames("INT8", DbType.SByte), new SQLiteTypeNames("INT16", DbType.Int16), new SQLiteTypeNames("INT32", DbType.Int32), new SQLiteTypeNames("INT64", DbType.Int64), new SQLiteTypeNames("INTEGER", DbType.Int64), new SQLiteTypeNames("INTEGER8", DbType.SByte), new SQLiteTypeNames("INTEGER16", DbType.Int16), new SQLiteTypeNames("INTEGER32", DbType.Int32), new SQLiteTypeNames("INTEGER64", DbType.Int64), new SQLiteTypeNames("LOGICAL", DbType.Boolean), new SQLiteTypeNames("LONG", DbType.Int64), new SQLiteTypeNames("LONGCHAR", DbType.String), new SQLiteTypeNames("LONGTEXT", DbType.String), new SQLiteTypeNames("LONGVARCHAR", DbType.String), new SQLiteTypeNames("MEMO", DbType.String), new SQLiteTypeNames("MONEY", DbType.Decimal), new SQLiteTypeNames("NCHAR", DbType.StringFixedLength), new SQLiteTypeNames("NOTE", DbType.String), new SQLiteTypeNames("NTEXT", DbType.String), new SQLiteTypeNames("NUMERIC", DbType.Decimal), new SQLiteTypeNames("NVARCHAR", DbType.String), new SQLiteTypeNames("OLEOBJECT", DbType.Binary), new SQLiteTypeNames("REAL", DbType.Double), new SQLiteTypeNames("SMALLDATE", DbType.DateTime), new SQLiteTypeNames("SMALLINT", DbType.Int16), new SQLiteTypeNames("SMALLUINT", DbType.UInt16), new SQLiteTypeNames("STRING", DbType.String), new SQLiteTypeNames("TEXT", DbType.String), new SQLiteTypeNames("TIME", DbType.DateTime), new SQLiteTypeNames("TIMESTAMP", DbType.DateTime), new SQLiteTypeNames("TINYINT", DbType.Byte), new SQLiteTypeNames("TINYSINT", DbType.SByte), new SQLiteTypeNames("UINT", DbType.UInt32), new SQLiteTypeNames("UINT8", DbType.Byte), new SQLiteTypeNames("UINT16", DbType.UInt16), new SQLiteTypeNames("UINT32", DbType.UInt32), new SQLiteTypeNames("UINT64", DbType.UInt64), new SQLiteTypeNames("ULONG", DbType.UInt64), new SQLiteTypeNames("UNIQUEIDENTIFIER", DbType.Guid), new SQLiteTypeNames("UNSIGNEDINTEGER", DbType.UInt64), new SQLiteTypeNames("UNSIGNEDINTEGER8", DbType.Byte), new SQLiteTypeNames("UNSIGNEDINTEGER16", DbType.UInt16), new SQLiteTypeNames("UNSIGNEDINTEGER32", DbType.UInt32), new SQLiteTypeNames("UNSIGNEDINTEGER64", DbType.UInt64), new SQLiteTypeNames("VARBINARY", DbType.Binary), new SQLiteTypeNames("VARCHAR", DbType.AnsiString), new SQLiteTypeNames("YESNO", DbType.Boolean) }; } /// <summary> /// For a given type name, return a closest-match .NET type /// </summary> /// <param name="Name">The name of the type to match</param> /// <returns>The .NET DBType the text evaluates to.</returns> internal static DbType TypeNameToDbType(string Name) { lock (_syncRoot) { if (_typeNames == null) { _typeNames = new Dictionary<string, SQLiteTypeNames>( new TypeNameStringComparer()); foreach (SQLiteTypeNames typeName in GetSQLiteTypeNames()) _typeNames.Add(typeName.typeName, typeName); } } if (String.IsNullOrEmpty(Name)) return DbType.Object; SQLiteTypeNames value; |
︙ | ︙ | |||
1056 1057 1058 1059 1060 1061 1062 | /// 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. | | | | 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 | /// and JulianDay. /// </summary> /// <remarks> /// ISO8601 is more compatible, readable, fully-processable, but less accurate as it doesn't provide time down to fractions of a second. /// JulianDay is the numeric format the SQLite uses internally and is arguably the most compatible with 3rd party tools. It is /// not readable as text without post-processing. /// Ticks less compatible with 3rd party tools that query the database, and renders the DateTime field unreadable as text without post-processing. /// /// The preferred order of choosing a datetime format is JulianDay, ISO8601, and then Ticks. Ticks is mainly present for legacy /// code support. /// </remarks> public enum SQLiteDateFormats { /// <summary> /// Use the value of DateTime.Ticks. This value is not recommended and is not well supported with LINQ. /// </summary> |
︙ | ︙ | |||
1100 1101 1102 1103 1104 1105 1106 | /// <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. | | | 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 | /// <summary> /// This enum determines how SQLite treats its journal file. /// </summary> /// <remarks> /// By default SQLite will create and delete the journal file when needed during a transaction. /// However, for some computers running certain filesystem monitoring tools, the rapid /// creation and deletion of the journal file can cause those programs to fail, or to interfere with SQLite. /// /// If a program or virus scanner is interfering with SQLite's journal file, you may receive errors like "unable to open database file" /// when starting a transaction. If this is happening, you may want to change the default journal mode to Persist. /// </remarks> public enum SQLiteJournalModeEnum { /// <summary> /// The default mode, this causes SQLite to use the existing journaling mode for the database. |
︙ | ︙ | |||
1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 | /// all content is safely written to the disk surface prior to continuing. /// This ensures that an operating system crash or power failure will not /// corrupt the database. FULL synchronous is very safe, but it is also /// slower. /// </summary> Full = 2 } /// <summary> /// Struct used internally to determine the datatype of a column in a resultset /// </summary> internal class SQLiteType { /// <summary> | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 | /// all content is safely written to the disk surface prior to continuing. /// This ensures that an operating system crash or power failure will not /// corrupt the database. FULL synchronous is very safe, but it is also /// slower. /// </summary> Full = 2 } /// <summary> /// The requested command execution type. This controls which method of the /// <see cref="SQLiteCommand" /> object will be called. /// </summary> public enum SQLiteExecuteType { /// <summary> /// Do nothing. No method will be called. /// </summary> None = 0, /// <summary> /// The command is not expected to return a result -OR- the result is not /// needed. The <see cref="SQLiteCommand.ExecuteNonQuery" /> method will /// be called. /// </summary> NonQuery = 1, /// <summary> /// The command is expected to return a scalar result -OR- the result should /// be limited to a scalar result. The <see cref="SQLiteCommand.ExecuteScalar" /> /// method will be called. /// </summary> Scalar = 2, /// <summary> /// The command is expected to return <see cref="SQLiteDataReader"/> result. /// The <see cref="SQLiteCommand.ExecuteReader()" /> method will be called. /// </summary> Reader = 3, /// <summary> /// Use the default command execution type. Using this value is the same /// as using the <see cref="SQLiteExecuteType.None" /> value. /// </summary> Default = NonQuery /* TODO: Good default? */ } /// <summary> /// Struct used internally to determine the datatype of a column in a resultset /// </summary> internal class SQLiteType { /// <summary> |
︙ | ︙ | |||
1227 1228 1229 1230 1231 1232 1233 | public int GetHashCode( string value ) { // // NOTE: The only thing that we must guarantee here, according | | | | 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 | public int GetHashCode( string value ) { // // NOTE: The only thing that we must guarantee here, according // to the MSDN documentation for IEqualityComparer, is // that for two given strings, if Equals return true then // the two strings must hash to the same value. // if (value != null) #if !PLATFORM_COMPACTFRAMEWORK return value.ToLowerInvariant().GetHashCode(); #else return value.ToLower().GetHashCode(); |
︙ | ︙ |
Changes to System.Data.SQLite/SQLiteDataAdapter.cs.
︙ | ︙ | |||
20 21 22 23 24 25 26 27 | [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> | > > > | > > > > | > > > | > > | > | > > > > | > > | > > | > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > | 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 | [Designer("Microsoft.VSDesigner.Data.VS.SqlDataAdapterDesigner, Microsoft.VSDesigner, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] #endif public sealed class SQLiteDataAdapter : DbDataAdapter { private static object _updatingEventPH = new object(); private static object _updatedEventPH = new object(); /////////////////////////////////////////////////////////////////////////////////////////////// #region Public Constructors /// <overloads> /// This class is just a shell around the DbDataAdapter. Nothing from /// DbDataAdapter is overridden here, just a few constructors are defined. /// </overloads> /// <summary> /// Default constructor. /// </summary> public SQLiteDataAdapter() { } /////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// Constructs a data adapter using the specified select command. /// </summary> /// <param name="cmd"> /// The select command to associate with the adapter. /// </param> public SQLiteDataAdapter(SQLiteCommand cmd) { SelectCommand = cmd; } /////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// Constructs a data adapter with the supplied select command text and /// associated with the specified connection. /// </summary> /// <param name="commandText"> /// The select command text to associate with the data adapter. /// </param> /// <param name="connection"> /// The connection to associate with the select command. /// </param> public SQLiteDataAdapter(string commandText, SQLiteConnection connection) { SelectCommand = new SQLiteCommand(commandText, connection); } /////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// Constructs a data adapter with the specified select command text, /// and using the specified database connection string. /// </summary> /// <param name="commandText"> /// The select command text to use to construct a select command. /// </param> /// <param name="connectionString"> /// A connection string suitable for passing to a new SQLiteConnection, /// which is associated with the select command. /// </param> public SQLiteDataAdapter( string commandText, string connectionString ) : this(commandText, connectionString, false) { // do nothing. } /////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// Constructs a data adapter with the specified select command text, /// and using the specified database connection string. /// </summary> /// <param name="commandText"> /// The select command text to use to construct a select command. /// </param> /// <param name="connectionString"> /// A connection string suitable for passing to a new SQLiteConnection, /// which is associated with the select command. /// </param> /// <param name="parseViaFramework"> /// Non-zero to parse the connection string using the built-in (i.e. /// framework provided) parser when opening the connection. /// </param> public SQLiteDataAdapter( string commandText, string connectionString, bool parseViaFramework ) { SQLiteConnection cnn = new SQLiteConnection( connectionString, parseViaFramework); SelectCommand = new SQLiteCommand(commandText, cnn); } #endregion /////////////////////////////////////////////////////////////////////////////////////////////// #region IDisposable "Pattern" Members private bool disposed; private void CheckDisposed() /* throw */ { |
︙ | ︙ |
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(); if (_throwOnDisposed) SQLiteCommand.Check(_command); // // NOTE: First, check if the column name cache has been initialized yet. // If not, do it now. // if (_fieldIndexes == null) _fieldIndexes = new Dictionary<string, int>(new ColumnNameComparer()); |
︙ | ︙ | |||
850 851 852 853 854 855 856 | 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(); if (_throwOnDisposed) SQLiteCommand.Check(_command); // // BUGFIX: We need to quickly scan all the fields in the current // "result set" to see how many distinct tables are actually // involved. This information is necessary so that some // intelligent decisions can be made when constructing the // metadata below. For example, we need to be very careful |
︙ | ︙ | |||
1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 | /// 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); | > | > | 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 | /// 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(); CheckValidRow(); if (i >= VisibleFieldCount && _keyInfo != null) return _keyInfo.GetValue(i - VisibleFieldCount); SQLiteType typ = GetSQLiteType(i); return _activeStatement._sql.GetValue( _activeStatement, SQLiteCommand.GetFlags(_command), 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> |
︙ | ︙ | |||
1217 1218 1219 1220 1221 1222 1223 | /// 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(); | | | 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 | /// Moves to the next resultset in multiple row-returning SQL command. /// </summary> /// <returns>True if the command was successful and a new resultset is available, False otherwise.</returns> public override bool NextResult() { CheckDisposed(); CheckClosed(); if (_throwOnDisposed) SQLiteCommand.Check(_command); SQLiteStatement stmt = null; int fieldCount; while (true) { if (stmt == null && _activeStatement != null && _activeStatement._sql != null && _activeStatement._sql.IsOpen()) |
︙ | ︙ | |||
1343 1344 1345 1346 1347 1348 1349 | /// 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(); | | | 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 | /// Reads the next row from the resultset /// </summary> /// <returns>True if a new row was successfully loaded and is ready for processing</returns> public override bool Read() { CheckDisposed(); CheckClosed(); if (_throwOnDisposed) SQLiteCommand.Check(_command); if (_readingState == -1) // First step was already done at the NextResult() level, so don't step again, just return true. { _readingState = 0; return true; } else if (_readingState == 0) // Actively reading rows |
︙ | ︙ |
Changes to System.Data.SQLite/SQLiteDefineConstants.cs.
︙ | ︙ | |||
31 32 33 34 35 36 37 38 39 40 41 42 43 44 | #if INTEROP_DEBUG "INTEROP_DEBUG", #endif #if INTEROP_EXTENSION_FUNCTIONS "INTEROP_EXTENSION_FUNCTIONS", #endif #if INTEROP_LOG "INTEROP_LOG", #endif #if INTEROP_TEST_EXTENSION "INTEROP_TEST_EXTENSION", | > > > > | 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | #if INTEROP_DEBUG "INTEROP_DEBUG", #endif #if INTEROP_EXTENSION_FUNCTIONS "INTEROP_EXTENSION_FUNCTIONS", #endif #if INTEROP_LEGACY_CLOSE "INTEROP_LEGACY_CLOSE", #endif #if INTEROP_LOG "INTEROP_LOG", #endif #if INTEROP_TEST_EXTENSION "INTEROP_TEST_EXTENSION", |
︙ | ︙ | |||
107 108 109 110 111 112 113 114 115 116 117 118 | #if TRACE_WARNING "TRACE_WARNING", #endif #if USE_INTEROP_DLL "USE_INTEROP_DLL", #endif null }); } } | > > > > > > > > | 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 | #if TRACE_WARNING "TRACE_WARNING", #endif #if USE_INTEROP_DLL "USE_INTEROP_DLL", #endif #if USE_PREPARE_V2 "USE_PREPARE_V2", #endif #if WINDOWS "WINDOWS", #endif null }); } } |
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 | { try { _context = context; SetReturnValue(context, Invoke(ConvertParams(nArgs, argsptr))); /* throw */ } | < < < < < < < < < < < < < < | 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 | { try { _context = context; SetReturnValue(context, Invoke(ConvertParams(nArgs, argsptr))); /* throw */ } catch (Exception e) /* NOTE: Must catch ALL. */ { try { if ((_flags & SQLiteConnectionFlags.LogCallbackException) == SQLiteConnectionFlags.LogCallbackException) { SQLiteLog.LogMessage(COR_E_EXCEPTION, String.Format( CultureInfo.CurrentCulture, "Caught exception in \"Invoke\" method: {0}", e)); /* throw */ } } catch { // do nothing. } } } /// <summary> /// Internal collation sequence function, which wraps up the raw string pointers and executes the Compare() virtual function. /// WARNING: Must not throw exceptions. /// </summary> /// <param name="ptr">Not used</param> /// <param name="len1">Length of the string pv1</param> /// <param name="ptr1">Pointer to the first string to compare</param> /// <param name="len2">Length of the string pv2</param> /// <param name="ptr2">Pointer to the second string to compare</param> /// <returns>Returns -1 if the first string is less than the second. 0 if they are equal, or 1 if the first string is greater /// than the second. Returns 0 if an exception is caught.</returns> internal int CompareCallback(IntPtr ptr, int len1, IntPtr ptr1, int len2, IntPtr ptr2) { try { return Compare(SQLiteConvert.UTF8ToString(ptr1, len1), SQLiteConvert.UTF8ToString(ptr2, len2)); /* throw */ } catch (Exception e) /* NOTE: Must catch ALL. */ { try { if ((_flags & SQLiteConnectionFlags.LogCallbackException) == SQLiteConnectionFlags.LogCallbackException) { SQLiteLog.LogMessage(COR_E_EXCEPTION, String.Format( CultureInfo.CurrentCulture, "Caught exception in \"Compare\" (UTF8) method: {0}", e)); /* throw */ } } catch { // do nothing. } } // // NOTE: This must be done to prevent the core SQLite library from // using our (invalid) result. // if (_base != null) _base.Cancel(); |
︙ | ︙ | |||
478 479 480 481 482 483 484 | 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 */ } | < < < < < < < | 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 | internal int CompareCallback16(IntPtr ptr, int len1, IntPtr ptr1, int len2, IntPtr ptr2) { try { return Compare(SQLite3_UTF16.UTF16ToString(ptr1, len1), SQLite3_UTF16.UTF16ToString(ptr2, len2)); /* throw */ } catch (Exception e) /* NOTE: Must catch ALL. */ { try { if ((_flags & SQLiteConnectionFlags.LogCallbackException) == SQLiteConnectionFlags.LogCallbackException) { SQLiteLog.LogMessage(COR_E_EXCEPTION, String.Format( CultureInfo.CurrentCulture, "Caught exception in \"Compare\" (UTF16) method: {0}", e)); /* throw */ } } catch { // do nothing. } } // // NOTE: This must be done to prevent the core SQLite library from // using our (invalid) result. // if (_base != null) _base.Cancel(); |
︙ | ︙ | |||
558 559 560 561 562 563 564 | data._count, ref data._data); /* throw */ } finally { data._count++; } } | < < < < < < < | 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 | data._count, ref data._data); /* throw */ } finally { data._count++; } } catch (Exception e) /* NOTE: Must catch ALL. */ { try { if ((_flags & SQLiteConnectionFlags.LogCallbackException) == SQLiteConnectionFlags.LogCallbackException) { SQLiteLog.LogMessage(COR_E_EXCEPTION, String.Format( CultureInfo.CurrentCulture, "Caught exception in \"Step\" method: {1}", e)); /* throw */ } } catch { // do nothing. } } } /// <summary> /// An internal aggregate Final function callback, which wraps the context pointer and calls the virtual Final() method. /// WARNING: Must not throw exceptions. /// </summary> /// <param name="context">A raw context pointer</param> |
︙ | ︙ | |||
620 621 622 623 624 625 626 | } finally { IDisposable disp = obj as IDisposable; if (disp != null) disp.Dispose(); /* throw */ } } | < < < < < < < > > > > > > > | 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 | } finally { IDisposable disp = obj as IDisposable; if (disp != null) disp.Dispose(); /* throw */ } } catch (Exception e) /* NOTE: Must catch ALL. */ { try { if ((_flags & SQLiteConnectionFlags.LogCallbackException) == SQLiteConnectionFlags.LogCallbackException) { SQLiteLog.LogMessage(COR_E_EXCEPTION, String.Format( CultureInfo.CurrentCulture, "Caught exception in \"Final\" method: {1}", e)); /* throw */ } } catch { // do nothing. } } } /// <summary> /// Using reflection, enumerate all assemblies in the current appdomain looking for classes that /// have a SQLiteFunctionAttribute attribute, and registering them accordingly. /// </summary> #if !PLATFORM_COMPACTFRAMEWORK [Security.Permissions.FileIOPermission(Security.Permissions.SecurityAction.Assert, AllFiles = Security.Permissions.FileIOPermissionAccess.PathDiscovery)] #endif static SQLiteFunction() { _registeredFunctions = new List<SQLiteFunctionAttribute>(); try { #if !PLATFORM_COMPACTFRAMEWORK // // NOTE: If the "No_SQLiteFunctions" environment variable is set, // skip all our special code and simply return. // if (Environment.GetEnvironmentVariable("No_SQLiteFunctions") != null) return; SQLiteFunctionAttribute at; System.Reflection.Assembly[] arAssemblies = System.AppDomain.CurrentDomain.GetAssemblies(); int w = arAssemblies.Length; System.Reflection.AssemblyName sqlite = System.Reflection.Assembly.GetCallingAssembly().GetName(); for (int n = 0; n < w; n++) { |
︙ | ︙ |
Changes to System.Data.SQLite/SQLiteLog.cs.
︙ | ︙ | |||
62 63 64 65 66 67 68 | /// </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); /////////////////////////////////////////////////////////////////////////// | < > > > > > > > > > > > > > > > > > > > > > | 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 | /// </summary> /// <param name="sender">The current connection</param> /// <param name="e">Event arguments of the trace</param> public delegate void SQLiteLogEventHandler(object sender, LogEventArgs e); /////////////////////////////////////////////////////////////////////////// /// <summary> /// Manages the SQLite custom logging functionality and the associated /// callback for the whole process. /// </summary> public static class SQLiteLog { /// <summary> /// Object used to synchronize access to the static instance data /// for this class. /// </summary> private static object syncRoot = new object(); /////////////////////////////////////////////////////////////////////// #if !PLATFORM_COMPACTFRAMEWORK /// <summary> /// Member variable to store the AppDomain.DomainUnload event handler. /// </summary> private static EventHandler _domainUnload; #endif /////////////////////////////////////////////////////////////////////// /// <summary> /// Member variable to store the application log handler to call. /// </summary> private static event SQLiteLogEventHandler _handlers; /////////////////////////////////////////////////////////////////////// /// <summary> /// The default log event handler. /// </summary> private static SQLiteLogEventHandler _defaultHandler; /////////////////////////////////////////////////////////////////////// /// <summary> /// The log callback passed to native SQLite engine. This must live /// as long as the SQLite library has a pointer to it. /// </summary> private static SQLiteLogCallback _callback; /////////////////////////////////////////////////////////////////////// /// <summary> /// The base SQLite object to interop with. /// </summary> private static SQLiteBase _sql; /////////////////////////////////////////////////////////////////////// /// <summary> /// This will be non-zero if logging is currently enabled. /// </summary> private static bool _enabled; /////////////////////////////////////////////////////////////////////// /// <summary> /// Initializes the SQLite logging facilities. /// </summary> public static void Initialize() { // // BUFXIX: We cannot initialize the logging interface if the SQLite // core library has already been initialized anywhere in // the process (see ticket [2ce0870fad]). // if (SQLite3.StaticIsInitialized()) return; #if !PLATFORM_COMPACTFRAMEWORK // // BUGFIX: To avoid nasty situations where multiple AppDomains are // attempting to initialize and/or shutdown what is really // a shared native resource (i.e. the SQLite core library // is loaded per-process and has only one logging callback, // not one per-AppDomain, which it knows nothing about), // prevent all non-default AppDomains from registering a // log handler unless the "Force_SQLiteLog" environment // variable is used to manually override this safety check. // if (!AppDomain.CurrentDomain.IsDefaultAppDomain() && Environment.GetEnvironmentVariable("Force_SQLiteLog") == null) { return; } #endif lock (syncRoot) { #if !PLATFORM_COMPACTFRAMEWORK // // NOTE: Add an event handler for the DomainUnload event so // that we can unhook our logging managed function // pointer from the native SQLite code prior to it // being invalidated. // // BUGFIX: Make sure this event handler is only added one // time (per-AppDomain). // if (_domainUnload == null) { _domainUnload = new EventHandler(DomainUnload); AppDomain.CurrentDomain.DomainUnload += _domainUnload; } #endif // // NOTE: Create an instance of the SQLite wrapper class. // if (_sql == null) _sql = new SQLite3(SQLiteDateFormats.Default, DateTimeKind.Unspecified); |
︙ | ︙ | |||
188 189 190 191 192 193 194 195 196 197 198 199 200 201 | // // NOTE: For now, always setup the default log event handler. // AddDefaultHandler(); } } /// <summary> /// Handles the AppDomain being unloaded. /// </summary> /// <param name="sender">Should be null.</param> /// <param name="e">The data associated with this event.</param> private static void DomainUnload( object sender, | > > > | 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 | // // NOTE: For now, always setup the default log event handler. // AddDefaultHandler(); } } /////////////////////////////////////////////////////////////////////// #if !PLATFORM_COMPACTFRAMEWORK /// <summary> /// Handles the AppDomain being unloaded. /// </summary> /// <param name="sender">Should be null.</param> /// <param name="e">The data associated with this event.</param> private static void DomainUnload( object sender, |
︙ | ︙ | |||
254 255 256 257 258 259 260 261 262 263 264 265 266 267 | if (_domainUnload != null) { AppDomain.CurrentDomain.DomainUnload -= _domainUnload; _domainUnload = null; } } } /// <summary> /// This event is raised whenever SQLite raises a logging event. /// Note that this should be set as one of the first things in the /// application. /// </summary> public static event SQLiteLogEventHandler Log | > > > | 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 | if (_domainUnload != null) { AppDomain.CurrentDomain.DomainUnload -= _domainUnload; _domainUnload = null; } } } #endif /////////////////////////////////////////////////////////////////////// /// <summary> /// This event is raised whenever SQLite raises a logging event. /// Note that this should be set as one of the first things in the /// application. /// </summary> public static event SQLiteLogEventHandler Log |
︙ | ︙ | |||
284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 | lock (syncRoot) { _handlers -= value; } } } /// <summary> /// If this property is true, logging is enabled; otherwise, logging is /// disabled. When logging is disabled, no logging events will fire. /// </summary> public static bool Enabled { get { lock (syncRoot) { return _enabled; } } set { lock (syncRoot) { _enabled = value; } } } /// <summary> /// Log a message to all the registered log event handlers without going /// through the SQLite library. /// </summary> /// <param name="message">The message to be logged.</param> public static void LogMessage( string message ) { LogMessage(null, message); } /// <summary> /// Log a message to all the registered log event handlers without going /// through the SQLite library. /// </summary> /// <param name="errorCode">The SQLite error code.</param> /// <param name="message">The message to be logged.</param> public static void LogMessage( SQLiteErrorCode errorCode, string message ) { LogMessage((object)errorCode, message); } /// <summary> /// Log a message to all the registered log event handlers without going /// through the SQLite library. /// </summary> /// <param name="errorCode">The integer error code.</param> /// <param name="message">The message to be logged.</param> public static void LogMessage( int errorCode, string message ) { LogMessage((object)errorCode, message); } /// <summary> /// Log a message to all the registered log event handlers without going /// through the SQLite library. /// </summary> /// <param name="errorCode"> /// The error code. The type of this object value should be | > > > > > > > > > > | 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 | lock (syncRoot) { _handlers -= value; } } } /////////////////////////////////////////////////////////////////////// /// <summary> /// If this property is true, logging is enabled; otherwise, logging is /// disabled. When logging is disabled, no logging events will fire. /// </summary> public static bool Enabled { get { lock (syncRoot) { return _enabled; } } set { lock (syncRoot) { _enabled = value; } } } /////////////////////////////////////////////////////////////////////// /// <summary> /// Log a message to all the registered log event handlers without going /// through the SQLite library. /// </summary> /// <param name="message">The message to be logged.</param> public static void LogMessage( string message ) { LogMessage(null, message); } /////////////////////////////////////////////////////////////////////// /// <summary> /// Log a message to all the registered log event handlers without going /// through the SQLite library. /// </summary> /// <param name="errorCode">The SQLite error code.</param> /// <param name="message">The message to be logged.</param> public static void LogMessage( SQLiteErrorCode errorCode, string message ) { LogMessage((object)errorCode, message); } /////////////////////////////////////////////////////////////////////// /// <summary> /// Log a message to all the registered log event handlers without going /// through the SQLite library. /// </summary> /// <param name="errorCode">The integer error code.</param> /// <param name="message">The message to be logged.</param> public static void LogMessage( int errorCode, string message ) { LogMessage((object)errorCode, message); } /////////////////////////////////////////////////////////////////////// /// <summary> /// Log a message to all the registered log event handlers without going /// through the SQLite library. /// </summary> /// <param name="errorCode"> /// The error code. The type of this object value should be |
︙ | ︙ | |||
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 | } 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. | > > > > > > > > | 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 | } 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. |
︙ | ︙ | |||
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 | } 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) { | > > > | 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 | } 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 !NET_COMPACT_20 if (e == null) return; string message = e.Message; if (message == null) { |
︙ | ︙ | |||
474 475 476 477 478 479 480 481 482 | 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)); } } | > < | 521 522 523 524 525 526 527 528 529 530 531 | 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 | object obj = param.Value; DbType objType = param.DbType; if ((obj != null) && (objType == DbType.Object)) objType = SQLiteConvert.TypeToDbType(obj.GetType()); | < < > > > > > > | 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 | object obj = param.Value; DbType objType = param.DbType; if ((obj != null) && (objType == DbType.Object)) objType = SQLiteConvert.TypeToDbType(obj.GetType()); if ((_flags & SQLiteConnectionFlags.LogPreBind) == SQLiteConnectionFlags.LogPreBind) { IntPtr handle = _sqlite_stmt; SQLiteLog.LogMessage(String.Format( "Binding statement {0} paramter #{1} with database type {2} and raw value {{{3}}}...", handle, index, objType, obj)); } if ((obj == null) || Convert.IsDBNull(obj)) { _sql.Bind_Null(this, _flags, index); return; } if ((_flags & SQLiteConnectionFlags.BindAllAsText) == SQLiteConnectionFlags.BindAllAsText) { _sql.Bind_Text(this, _flags, index, obj.ToString()); return; } switch (objType) { case DbType.Date: case DbType.Time: case DbType.DateTime: // |
︙ | ︙ |
Changes to System.Data.SQLite/System.Data.SQLite.Properties.targets.
︙ | ︙ | |||
81 82 83 84 85 86 87 88 89 90 91 92 93 94 | 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> | > > > > > > > > | 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 | 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 sqlite3_prepare_v2() function when preparing queries? --> <PropertyGroup Condition="'$(UsePrepareV2)' != 'false'"> <DefineConstants>$(DefineConstants);USE_PREPARE_V2</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> |
︙ | ︙ | |||
149 150 151 152 153 154 155 156 157 158 159 160 161 162 | NOTE: Enable extra diagnostics from the custom built interop DLL (see the "SQLite.NET.Settings.targets" file for more information)? --> <PropertyGroup Condition="'$(InteropDebug)' != 'false'"> <DefineConstants>$(DefineConstants);INTEROP_DEBUG</DefineConstants> </PropertyGroup> <!-- NOTE: Enable the logging callback in the custom built interop DLL (see the "SQLite.NET.Settings.targets" file for more information)? --> <PropertyGroup Condition="'$(InteropLog)' != 'false'"> <DefineConstants>$(DefineConstants);INTEROP_LOG</DefineConstants> </PropertyGroup> | > > > > > > > > | 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 | NOTE: Enable extra diagnostics from the custom built interop DLL (see the "SQLite.NET.Settings.targets" file for more information)? --> <PropertyGroup Condition="'$(InteropDebug)' != 'false'"> <DefineConstants>$(DefineConstants);INTEROP_DEBUG</DefineConstants> </PropertyGroup> <!-- NOTE: Disable all use of the sqlite3_close_v2() native API and use the legacy System.Data.SQLite connection closing algorithm instead. --> <PropertyGroup Condition="'$(InteropLegacyClose)' != 'false'"> <DefineConstants>$(DefineConstants);INTEROP_LEGACY_CLOSE</DefineConstants> </PropertyGroup> <!-- NOTE: Enable the logging callback in the custom built interop DLL (see the "SQLite.NET.Settings.targets" file for more information)? --> <PropertyGroup Condition="'$(InteropLog)' != 'false'"> <DefineConstants>$(DefineConstants);INTEROP_LOG</DefineConstants> </PropertyGroup> |
︙ | ︙ |
Changes to System.Data.SQLite/UnsafeNativeMethods.cs.
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; |
︙ | ︙ | |||
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 | /// </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(); ///////////////////////////////////////////////////////////////////////// | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 | /// </summary> /// <param name="fileName"> /// The name of the executable library. /// </param> /// <returns> /// The native module handle upon success -OR- IntPtr.Zero on failure. /// </returns> #if !PLATFORM_COMPACTFRAMEWORK [DllImport("kernel32", #else [DllImport("coredll", #endif CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Auto, #if !PLATFORM_COMPACTFRAMEWORK BestFitMapping = false, ThrowOnUnmappableChar = true, #endif SetLastError = true)] private static extern IntPtr LoadLibrary(string fileName); ///////////////////////////////////////////////////////////////////////// #if PLATFORM_COMPACTFRAMEWORK /// <summary> /// This is the P/Invoke method that wraps the native Win32 GetSystemInfo /// function. See the MSDN documentation for full details on what it /// does. /// </summary> /// <param name="systemInfo"> /// The system information structure to be filled in by the function. /// </param> [DllImport("coredll", CallingConvention = CallingConvention.Winapi)] private static extern void GetSystemInfo(out SYSTEM_INFO systemInfo); ///////////////////////////////////////////////////////////////////////// /// <summary> /// This enumeration contains the possible values for the processor /// architecture field of the system information structure. /// </summary> private enum ProcessorArchitecture : ushort /* COMPAT: Win32. */ { Intel = 0, MIPS = 1, Alpha = 2, PowerPC = 3, SHx = 4, ARM = 5, IA64 = 6, Alpha64 = 7, MSIL = 8, AMD64 = 9, IA32_on_Win64 = 10, Unknown = 0xFFFF } ///////////////////////////////////////////////////////////////////////// /// <summary> /// This structure contains information about the current computer. This /// includes the processor type, page size, memory addresses, etc. /// </summary> [StructLayout(LayoutKind.Sequential)] private struct SYSTEM_INFO { public ProcessorArchitecture wProcessorArchitecture; public ushort wReserved; /* NOT USED */ public uint dwPageSize; /* NOT USED */ public IntPtr lpMinimumApplicationAddress; /* NOT USED */ public IntPtr lpMaximumApplicationAddress; /* NOT USED */ public uint dwActiveProcessorMask; /* NOT USED */ public uint dwNumberOfProcessors; /* NOT USED */ public uint dwProcessorType; /* NOT USED */ public uint dwAllocationGranularity; /* NOT USED */ public ushort wProcessorLevel; /* NOT USED */ public ushort wProcessorRevision; /* NOT USED */ } #endif ///////////////////////////////////////////////////////////////////////// /// <summary> /// This lock is used to protect the static _SQLiteModule and /// processorArchitecturePlatforms fields, below. /// </summary> private static readonly object staticSyncRoot = new object(); ///////////////////////////////////////////////////////////////////////// |
︙ | ︙ | |||
137 138 139 140 141 142 143 | /// 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 // | | | | 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 | /// Attempts to initialize this class by pre-loading the native SQLite /// library for the processor architecture of the current process. /// </summary> internal static void Initialize() { #if !PLATFORM_COMPACTFRAMEWORK // // NOTE: If the "No_PreLoadSQLite" environment variable is set (to // anything), skip all our special code and simply return. // if (Environment.GetEnvironmentVariable("No_PreLoadSQLite") != null) return; #endif lock (staticSyncRoot) { |
︙ | ︙ | |||
169 170 171 172 173 174 175 176 177 178 179 180 181 182 | // // 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); | > | 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 | // // 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"); processorArchitecturePlatforms.Add("ARM", "WinCE"); } // // BUGBUG: What about other application domains? // if (_SQLiteModule == IntPtr.Zero) _SQLiteModule = PreLoadSQLiteDll(null, null); |
︙ | ︙ | |||
200 201 202 203 204 205 206 207 208 209 210 211 212 213 | // is set, use it verbatim for the base directory. // string directory = Environment.GetEnvironmentVariable( "PreLoadSQLite_BaseDirectory"); if (directory != null) return directory; // // NOTE: Otherwise, fallback on using the base directory of the // current application domain. // return AppDomain.CurrentDomain.BaseDirectory; #else | > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 | // is set, use it verbatim for the base directory. // string directory = Environment.GetEnvironmentVariable( "PreLoadSQLite_BaseDirectory"); if (directory != null) return directory; // // NOTE: If the "PreLoadSQLite_UseAssemblyDirectory" environment // variable is set (to anything), attempt to use the directory // containing the currently executing assembly (i.e. // System.Data.SQLite) intsead of the application domain base // directory. // if (Environment.GetEnvironmentVariable( "PreLoadSQLite_UseAssemblyDirectory") != null) { try { Assembly assembly = Assembly.GetExecutingAssembly(); if (assembly != null) { directory = Path.GetDirectoryName(assembly.Location); if (!String.IsNullOrEmpty(directory)) return directory; } } catch { // do nothing. } } // // NOTE: Otherwise, fallback on using the base directory of the // current application domain. // return AppDomain.CurrentDomain.BaseDirectory; #else |
︙ | ︙ | |||
273 274 275 276 277 278 279 | ///////////////////////////////////////////////////////////////////////// /// <summary> /// Queries and returns the processor architecture of the current /// process. /// </summary> /// <returns> /// The processor architecture of the current process -OR- null if it | | < | 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 | ///////////////////////////////////////////////////////////////////////// /// <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. /// </returns> private static string GetProcessorArchitecture() { #if !PLATFORM_COMPACTFRAMEWORK // // NOTE: If the "PreLoadSQLite_ProcessorArchitecture" environment // variable is set, use it verbatim for the current processor |
︙ | ︙ | |||
296 297 298 299 300 301 302 | // // BUGBUG: Will this always be reliable? // return Environment.GetEnvironmentVariable(PROCESSOR_ARCHITECTURE); #else // | > > > > > > > > > > > > | > > > > > | > > > > > > > > > > > > | 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 | // // BUGBUG: Will this always be reliable? // return Environment.GetEnvironmentVariable(PROCESSOR_ARCHITECTURE); #else // // NOTE: On the .NET Compact Framework, attempt to use the native // Win32 API function (via P/Invoke) that can provide us with // the processor architecture. // try { // // NOTE: The output of the GetSystemInfo function will be placed // here. Only the processor architecture field is used by // this method. // SYSTEM_INFO systemInfo; // // NOTE: Query the system information via P/Invoke, thus filling // the structure. // GetSystemInfo(out systemInfo); // // NOTE: Return the processor architecture value as a string. // return systemInfo.wProcessorArchitecture.ToString(); } catch { // do nothing. } // // NOTE: Upon failure, return an empty string. // return String.Empty; #endif } ///////////////////////////////////////////////////////////////////////// /// <summary> |
︙ | ︙ | |||
504 505 506 507 508 509 510 | // // 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). // | | | | | 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 | // // NOTE: On the .NET Compact Framework, the native interop assembly must // be used because it provides several workarounds to .NET Compact // Framework limitations important for proper operation of the core // System.Data.SQLite functionality (e.g. being able to bind // parameters and handle column values of types Int64 and Double). // internal const string SQLITE_DLL = "SQLite.Interop.085.dll"; #elif SQLITE_STANDARD // // NOTE: Otherwise, if the standard SQLite library is enabled, use it. // private const string SQLITE_DLL = "sqlite3"; #elif USE_INTEROP_DLL // // 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); |
︙ | ︙ | |||
639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 | #if !PLATFORM_COMPACTFRAMEWORK [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)] #else [DllImport(SQLITE_DLL)] #endif internal static extern SQLiteErrorCode sqlite3_close(IntPtr db); #if !PLATFORM_COMPACTFRAMEWORK [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)] #else [DllImport(SQLITE_DLL)] #endif internal static extern SQLiteErrorCode sqlite3_close_v2(IntPtr db); /* 3.7.14+ */ #if !PLATFORM_COMPACTFRAMEWORK [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)] #else [DllImport(SQLITE_DLL)] #endif internal static extern SQLiteErrorCode sqlite3_create_function(IntPtr db, byte[] strName, int nArgs, int nType, IntPtr pvUser, SQLiteCallback func, SQLiteCallback fstep, SQLiteFinalCallback ffinal); | > > | 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 | #if !PLATFORM_COMPACTFRAMEWORK [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)] #else [DllImport(SQLITE_DLL)] #endif internal static extern SQLiteErrorCode sqlite3_close(IntPtr db); #if !INTEROP_LEGACY_CLOSE #if !PLATFORM_COMPACTFRAMEWORK [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)] #else [DllImport(SQLITE_DLL)] #endif internal static extern SQLiteErrorCode sqlite3_close_v2(IntPtr db); /* 3.7.14+ */ #endif #if !PLATFORM_COMPACTFRAMEWORK [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)] #else [DllImport(SQLITE_DLL)] #endif internal static extern SQLiteErrorCode sqlite3_create_function(IntPtr db, byte[] strName, int nArgs, int nType, IntPtr pvUser, SQLiteCallback func, SQLiteCallback fstep, SQLiteFinalCallback ffinal); |
︙ | ︙ | |||
771 772 773 774 775 776 777 778 779 780 781 782 783 784 | #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); | > > > > > > > > > | 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 | #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 USE_PREPARE_V2 #if !PLATFORM_COMPACTFRAMEWORK [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)] #else [DllImport(SQLITE_DLL)] #endif internal static extern SQLiteErrorCode sqlite3_prepare_v2(IntPtr db, IntPtr pSql, int nBytes, out IntPtr stmt, out IntPtr ptrRemain); #endif #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); |
︙ | ︙ | |||
794 795 796 797 798 799 800 | [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)] #else [DllImport(SQLITE_DLL)] #endif internal static extern IntPtr sqlite3_value_text16(IntPtr p); #endif | | | 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 | [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 |
︙ | ︙ | |||
1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 | [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 | > > > > > > > | 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 | [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 int sqlite3_column_bytes16(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 |
︙ | ︙ | |||
1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 | #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 | > > > > > > > | 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 | #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)] #else [DllImport(SQLITE_DLL)] #endif internal static extern int sqlite3_value_bytes16(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 |
︙ | ︙ | |||
1361 1362 1363 1364 1365 1366 1367 | [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 | | | 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 | [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); |
︙ | ︙ | |||
1419 1420 1421 1422 1423 1424 1425 | } #if PLATFORM_COMPACTFRAMEWORK internal abstract class CriticalHandle : IDisposable { private bool _isClosed; protected IntPtr handle; | | | 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 | } #if PLATFORM_COMPACTFRAMEWORK internal abstract class CriticalHandle : IDisposable { private bool _isClosed; protected IntPtr handle; protected CriticalHandle(IntPtr invalidHandleValue) { handle = invalidHandleValue; _isClosed = false; } ~CriticalHandle() |
︙ | ︙ |
Changes to Tests/basic.eagle.
︙ | ︙ | |||
310 311 312 313 314 315 316 | } -body { set id [object invoke Interpreter.GetActive NextId] set dataSource [file join [getDatabaseDirectory] $fileName] unset -nocomplain results errors set code [compileCSharpWith [subst { | < | 310 311 312 313 314 315 316 317 318 319 320 321 322 323 | } -body { set id [object invoke Interpreter.GetActive NextId] set dataSource [file join [getDatabaseDirectory] $fileName] unset -nocomplain results errors set code [compileCSharpWith [subst { using System.Data.SQLite; namespace _Dynamic${id} { public static class Test${id} { public static bool TestSetAvRetry( |
︙ | ︙ | |||
419 420 421 422 423 424 425 | INSERT INTO t1 (x) VALUES(1); \ SELECT x FROM t1; \ } unset -nocomplain results errors set code [compileCSharpWith [subst { | < | 418 419 420 421 422 423 424 425 426 427 428 429 430 431 | INSERT INTO t1 (x) VALUES(1); \ SELECT x FROM t1; \ } unset -nocomplain results errors set code [compileCSharpWith [subst { using System.Data.SQLite; namespace _Dynamic${id} { public static class Test${id} { public static void Main() |
︙ | ︙ | |||
477 478 479 480 481 482 483 | INSERT INTO t1 (x) VALUES(1); \ SELECT x FROM t1; \ } unset -nocomplain results errors set code [compileCSharpWith [subst { | < | 475 476 477 478 479 480 481 482 483 484 485 486 487 488 | INSERT INTO t1 (x) VALUES(1); \ SELECT x FROM t1; \ } unset -nocomplain results errors set code [compileCSharpWith [subst { using System.Data.SQLite; namespace _Dynamic${id} { public static class Test${id} { public static void Main() |
︙ | ︙ | |||
933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 | unset -nocomplain results errors set code [compileCSharpWith [subst { using System; using System.Data.SQLite; using System.Reflection; namespace _Dynamic${id} { public static class Test${id} { public static string GetConnectionString( string key, string value, string propertyName ) { SQLiteConnectionStringBuilder builder = | > > > > > > > > > > > > > > > > > > > > | 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 | unset -nocomplain results errors set code [compileCSharpWith [subst { using System; using System.Data.SQLite; using System.Reflection; using System.Text; namespace _Dynamic${id} { public static class Test${id} { private static string ToHexString( byte\[\] array ) { if (array == null) return null; StringBuilder result = new StringBuilder(); int length = array.Length; for (int index = 0; index < length; index++) result.AppendFormat("{0:x2}", array\[index\]); return result.ToString(); } /////////////////////////////////////////////////////////////////////// public static string GetConnectionString( string key, string value, string propertyName ) { SQLiteConnectionStringBuilder builder = |
︙ | ︙ | |||
959 960 961 962 963 964 965 | if (propertyName != null) { propertyValue = typeof(SQLiteConnectionStringBuilder).InvokeMember( propertyName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.GetProperty, null, builder, null); } | | > | 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 | if (propertyName != null) { propertyValue = typeof(SQLiteConnectionStringBuilder).InvokeMember( propertyName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.GetProperty, null, builder, null); } return String.Format("{0}, {1}", (propertyValue is byte\[\]) ? ToHexString((byte\[\])propertyValue) : propertyValue, builder); } /////////////////////////////////////////////////////////////////////// public static void Main() { // do nothing. |
︙ | ︙ | |||
981 982 983 984 985 986 987 | 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" \ | | | | | 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 | if {$code eq "Ok"} then { set keys [list null Version Synchronous UseUTF16Encoding Pooling \ BinaryGUID "Data Source" Uri FullUri "Default Timeout" \ Enlist FailIfMissing "Legacy Format" "Read Only" \ Password "Page Size" "Max Page Count" "Cache Size" \ DateTimeFormat DateTimeKind BaseSchemaName \ "Journal Mode" "Default IsolationLevel" "Foreign Keys" \ Flags SetDefaults ToFullPath HexPassword] set values [list null 3 Normal True False \ True test.db test.db file:test.db 60 \ False True False True \ secret 4096 1024 8192 \ UnixEpoch Utc sqlite_schema \ Memory Serializable False \ Default False False 736563726574] set propertyNames [list null Version SyncMode UseUTF16Encoding Pooling \ BinaryGUID DataSource Uri FullUri DefaultTimeout \ Enlist FailIfMissing LegacyFormat ReadOnly \ Password PageSize MaxPageCount CacheSize \ DateTimeFormat DateTimeKind BaseSchemaName \ JournalMode DefaultIsolationLevel ForeignKeys \ Flags SetDefaults ToFullPath HexPassword] foreach key $keys value $values propertyName $propertyNames { set code [catch { object invoke _Dynamic${id}.Test${id} GetConnectionString \ $key $value $propertyName } result] |
︙ | ︙ | |||
1028 1029 1030 1031 1032 1033 1034 | 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\ | | | 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 | 0 \{True, Read Only=True\} 0 \{secret, Password=secret\} 0 \{4096, Page\ Size=4096\} 0 \{1024, Max Page Count=1024\} 0 \{8192, Cache Size=8192\} 0\ \{UnixEpoch, DateTimeFormat=UnixEpoch\} 0 \{Utc, DateTimeKind=Utc\} 0\ \{sqlite_schema, BaseSchemaName=sqlite_schema\} 0 \{Memory, Journal\ Mode=Memory\} 0 \{Serializable, Default IsolationLevel=Serializable\} 0\ \{False, Foreign Keys=False\} 0 \{(?:Default|LogCallbackException),\ Flags=(?:Default|LogCallbackException)\} 0 \{False, SetDefaults=False\} 0\ \{False, ToFullPath=False\} 0 {736563726574, HexPassword=736563726574}$}} ############################################################################### runTest {test data-1.17 {SQLiteConvert ToDateTime (Julian Day)} -body { set dateTime [object invoke System.Data.SQLite.SQLiteConvert ToDateTime \ 2455928.0 Utc] |
︙ | ︙ | |||
1432 1433 1434 1435 1436 1437 1438 | [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 \ | | | 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 | [object invoke -flags +NonPublic System.Data.SQLite.SQLiteConvert \ TypeNameToDbType "NVARCHAR(1)"] \ [object invoke -flags +NonPublic System.Data.SQLite.SQLiteConvert \ TypeNameToDbType "VARCHAR (1)"] \ [object invoke -flags +NonPublic System.Data.SQLite.SQLiteConvert \ TypeNameToDbType "NVARCHAR (1)"] \ } -constraints {eagle System.Data.SQLite} -result \ {AnsiString String AnsiString String AnsiString String}} ############################################################################### runTest {test data-1.28 {SetMemoryStatus method} -setup { # # NOTE: Make sure that SQLite core library is completely shutdown prior to # starting this test. |
︙ | ︙ | |||
2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 | unset -nocomplain e d c b a x result db fileName } -constraints \ {eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} -match \ regexp -result {^\{0 x System#DBNull#\d+ 1\ \{System\.Reflection\.TargetInvocationException: Exception has been thrown by\ the target of an invocation\. ---> System\.InvalidCastException:.*\}\ System#DBNull#\d+\} \{0 x 1 0 1 1\}$}} ############################################################################### unset -nocomplain systemDataSQLiteDllFile systemDataSQLiteLinqDllFile \ testExeFile testLinqExeFile northwindEfDbFile testLinqOutFile ############################################################################### runSQLiteTestEpilogue runTestEpilogue | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 | unset -nocomplain e d c b a x result db fileName } -constraints \ {eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} -match \ regexp -result {^\{0 x System#DBNull#\d+ 1\ \{System\.Reflection\.TargetInvocationException: Exception has been thrown by\ the target of an invocation\. ---> System\.InvalidCastException:.*\}\ System#DBNull#\d+\} \{0 x 1 0 1 1\}$}} ############################################################################### runTest {test data-1.48 {static SQLiteCommand.Execute method} -setup { unset -nocomplain result sql } -body { set sql(1) { \ CREATE TABLE t1(x); \ INSERT INTO t1 (x) VALUES (NULL); \ SELECT x FROM t1 ORDER BY x; \ } set sql(2) { \ CREATE TABLE t1(x); \ INSERT INTO t1 (x) VALUES (?); \ SELECT x FROM t1 ORDER BY x; \ } set result(1) [object invoke System.Data.SQLite.SQLiteCommand Execute \ "this will not execute" None null] set result(2) [object invoke System.Data.SQLite.SQLiteCommand Execute \ $sql(1) NonQuery null] set result(3) [object invoke System.Data.SQLite.SQLiteCommand Execute \ $sql(1) Scalar null] set result(4) [object invoke System.Data.SQLite.SQLiteCommand Execute \ $sql(1) Reader null] set result(5) [object invoke System.Data.SQLite.SQLiteCommand Execute \ "this will not execute" None null 1] set result(6) [object invoke System.Data.SQLite.SQLiteCommand Execute \ $sql(2) NonQuery null 1] set result(7) [object invoke System.Data.SQLite.SQLiteCommand Execute \ $sql(2) Scalar null 1] set result(8) [object invoke System.Data.SQLite.SQLiteCommand Execute \ $sql(2) Reader null 1] list $result(1) $result(2) $result(3) $result(4) $result(5) $result(6) \ $result(7) $result(8) } -cleanup { unset -nocomplain result sql } -constraints {eagle monoBug28 SQLite System.Data.SQLite} -match regexp \ -result {^\{\} 1 System#DBNull#\d+ System#Data#SQLite#SQLiteDataReader#\d+ \{\}\ 1 1 System#Data#SQLite#SQLiteDataReader#\d+$}} ############################################################################### unset -nocomplain systemDataSQLiteDllFile systemDataSQLiteLinqDllFile \ testExeFile testLinqExeFile northwindEfDbFile testLinqOutFile ############################################################################### runSQLiteTestEpilogue runTestEpilogue |
Changes to Tests/common.eagle.
︙ | ︙ | |||
85 86 87 88 89 90 91 92 93 94 | # NOTE: Use the default test year for the CLR v2.0. # return 2008; # TODO: Good "fallback" default? } } } } proc getBuildConfiguration {} { # | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | | | | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 | # NOTE: Use the default test year for the CLR v2.0. # return 2008; # TODO: Good "fallback" default? } } } } proc getBuildYears {} { # # NOTE: See if the list of test years has been overridden by the user # (e.g. on the command line). # if {[info exists ::test_years] && [llength $::test_years] > 0} then { # # NOTE: Use the specified list of test years. # return $::test_years } else { # # NOTE: Use the default list of test years. # return [list 2005 2008 2010 2012] } } proc getBuildPlatform { native } { if {[info exists ::test_platform] && \ [string length $::test_platform] > 0} then { # # NOTE: Use the specified test platform. If this variable is not set, # the default value will be based on the machine architecture. # return [expr {$native ? $::test_platform : ""}] } elseif {[info exists ::test_machine] && \ [string length $::test_machine] > 0} then { # # NOTE: For native builds, return the platform name corresponding to # the test machine architecture; otherwise, return an empty # string. # return [expr {$native ? [machineToPlatform $::test_machine] : ""}] } elseif {[info exists ::tcl_platform(machine)]} then { # # NOTE: For native builds, return the platform name corresponding to # the machine architecture; otherwise, return an empty string. # return [expr {$native ? \ [machineToPlatform $::tcl_platform(machine)] : ""}] } else { # # NOTE: No machine architecture is available, return an empty string. # return "" } } proc getBuildConfiguration {} { # # NOTE: See if the "configuration" setting has been overridden by the # user (e.g. on the command line). This helps control exactly # which set of binaries we are testing (i.e. those built in the # "Debug" or "Release" build configurations). To override this # value via the 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 typically "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 getBuildConfigurations {} { # # NOTE: See if the list of test configurations has been overridden by # the user (e.g. on the command line). # if {[info exists ::test_configurations] && \ [llength $::test_configurations] > 0} then { # # NOTE: Use the specified list of test configurations. # return $::test_configurations } else { # # NOTE: Use the default list of test configurations. # return [list Debug Release] } } proc getBuildBaseDirectory {} { # # NOTE: Figure out the base directory where all the builds should be # located. This will be the directory that contains the actual # build output directory (e.g. parent of "bin"). # if {[info exists ::build_base_directory] && \ [string length $::build_base_directory] > 0} then { # # NOTE: The location of the build base directory has been overridden; # therefore, use it verbatim. # return $::build_base_directory } elseif {[info exists ::common_directory] && \ [string length $::common_directory] > 0} then { # # NOTE: Next, fallback to the parent directory of the one containing # this file (i.e. "common.eagle"), if available. # return [file dirname $::common_directory] } elseif {[info exists ::path] && \ [string length $::path] > 0} then { # # NOTE: Finally, fallback to the parent directory of the EagleTest # path. The EagleTest package guarantees that this variable # will be set to the directory containing the first file to # execute the [runTestPrologue] script library procedure. # return [file dirname $::path] } else { # # NOTE: No path is available, return an empty string. This point # should not be reached. # return "" } } proc joinBuildDirectory { native path year platform configuration } { # # NOTE: Figure out and then return the fully qualified path to the build # directory based on all the arguments provided by our caller. # if {$native} then { return [file join $path bin $year $platform $configuration] } else { return [file join $path bin $year $configuration bin] } } proc getBuildDirectory {} { # # NOTE: See if the "native" runtime option has been set. If so, use the # directory for the mixed-mode assembly (a.k.a. the native interop # assembly). To enable this option via the command line, enter a # command similar to one of the following (all on one line): |
︙ | ︙ | |||
148 149 150 151 152 153 154 | [string length $::build_directory] > 0} then { # # NOTE: The location of the build directory has been overridden; # therefore, use it verbatim. # return $::build_directory } else { | < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 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 |
︙ | ︙ | |||
216 217 218 219 220 221 222 | # # 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. # | | < < < < < | > > | 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 | # # Note that all of the build commands above will default to using # the latest version of MSBuild available and the "test_year" may # need to be adjusted accordingly to actually run the test suite. # Refer to the comments in [getBuildYear] for more information on # how to set this variable. # set native [hasRuntimeOption native] return [joinBuildDirectory $native [getBuildBaseDirectory] \ [getBuildYear] [getBuildPlatform $native] [getBuildConfiguration]] } } proc getBuildFileName { fileName } { # # NOTE: Returns the specified file name as if it were located in the # build directory, discarding any directory information present |
︙ | ︙ | |||
622 623 624 625 626 627 628 629 630 631 632 633 634 635 | # and the [checkForSQLite] procedure has been called to probe for # the SQLite native library; otherwise, this procedure will simply # always return zero. # return [expr {[haveConstraint System.Data.SQLite] && \ [haveConstraint SQLite]}] } proc checkForSQLite { channel } { tputs $channel "---- checking for core SQLite library... " if {[catch { object invoke -flags +NonPublic System.Data.SQLite.SQLite3 \ SQLiteVersion} version] == 0} then { | > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 | # and the [checkForSQLite] procedure has been called to probe for # the SQLite native library; otherwise, this procedure will simply # always return zero. # return [expr {[haveConstraint System.Data.SQLite] && \ [haveConstraint SQLite]}] } proc checkForSQLiteBuilds { channel } { # # NOTE: Check for every possible valid combination of values used when # locating out the build output directory, showing each available # build variation along the way. # foreach native [list false true] { foreach year [getBuildYears] { foreach configuration [getBuildConfigurations] { tputs $channel [appendArgs \ "---- checking for System.Data.SQLite build \"" [expr \ {$native ? "native/" : ""}] $year / $configuration "\"... "] set fileName [file nativename [file join [joinBuildDirectory \ $native [getBuildBaseDirectory] $year [getBuildPlatform \ $native] $configuration] System.Data.SQLite.dll]] if {[file exists $fileName]} then { tputs $channel yes\n } else { tputs $channel no\n } } } } } proc checkForSQLite { channel } { tputs $channel "---- checking for core SQLite library... " if {[catch { object invoke -flags +NonPublic System.Data.SQLite.SQLite3 \ SQLiteVersion} version] == 0} then { |
︙ | ︙ | |||
822 823 824 825 826 827 828 | {temporary true} {varName db} } { # # NOTE: First, see if our caller has requested an in-memory database. # set isMemory [isMemoryDb $fileName] # | | > | | | 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 | {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 database directory. Each database and related files # 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 |
︙ | ︙ | |||
923 924 925 926 927 928 929 | set flags [combineFlags $flags $::connection_flags] tputs $::test_channel [appendArgs \ "---- combined connection flags are: " $flags \n] } # | | | | | | 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 | set flags [combineFlags $flags $::connection_flags] tputs $::test_channel [appendArgs \ "---- combined connection flags are: " $flags \n] } # # NOTE: If our caller specified some 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 |
︙ | ︙ | |||
962 963 964 965 966 967 968 | # return $db } proc getDbConnection { {varName db} } { # # NOTE: Refer to the specified variable (e.g. "db") in the context of our | | | | 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 | # 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 via the # [setupDb] procedure 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 |
︙ | ︙ | |||
995 996 997 998 999 1000 1001 | $db "\", error: " \n\t $result \n] } } } proc freeDbConnection { {varName connection} } { # | | | | > | | | 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 | $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 \ |
︙ | ︙ | |||
1054 1055 1056 1057 1058 1059 1060 | # if {$collect} then { collectGarbage $::test_channel } # # NOTE: Refer to the specified variable (e.g. "db") in the context of our | | | | | | 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 | # 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 via the # [setupDb] procedure 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: " \ |
︙ | ︙ | |||
1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 | 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. # | > > > > > | 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 | tputs $::test_channel [appendArgs [formatList [lsort \ $defineConstants]] \n] } else { tputs $::test_channel unknown\n } } # # NOTE: Check the available builds of SQLite and System.Data.SQLite. # checkForSQLiteBuilds $::test_channel # # NOTE: Now, we need to know if the SQLite core library is available # (i.e. because the managed-only System.Data.SQLite assembly can # load without it; however, it cannot do anything useful without # it). If we are using the mixed-mode assembly and we already # found it (above), this should always succeed. # |
︙ | ︙ | |||
1751 1752 1753 1754 1755 1756 1757 | # NOTE: Attempt to determine if various compile-time options needed for # test constraints were enabled for the managed assembly. There # are some compile-time options that must also have been enabled # for the interop assembly in order to be effective. For those # options, it will be assumed that it was enabled for the interop # assembly if it was enabled for the managed assembly. # | | | | | > > > | | | | 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 | # NOTE: Attempt to determine if various compile-time options needed for # test constraints were enabled for the managed assembly. There # are some compile-time options that must also have been enabled # for the interop assembly in order to be effective. For those # options, it will be assumed that it was enabled for the interop # assembly if it was enabled for the managed assembly. # foreach defineConstant [list \ CHECK_STATE COUNT_HANDLE DEBUG INTEROP_CODEC INTEROP_DEBUG \ INTEROP_EXTENSION_FUNCTIONS INTEROP_LEGACY_CLOSE INTEROP_LOG \ INTEROP_TEST_EXTENSION NET_20 NET_35 NET_40 NET_45 NET_COMPACT_20 \ PLATFORM_COMPACTFRAMEWORK PRELOAD_NATIVE_LIBRARY RETARGETABLE \ SQLITE_STANDARD THROW_ON_DISPOSED TRACE TRACE_CONNECTION \ TRACE_HANDLE TRACE_PRELOAD TRACE_STATEMENT TRACE_WARNING \ USE_INTEROP_DLL USE_PREPARE_V2 WINDOWS] { # # NOTE: Check if the compile-time option is listed in the list of # "define constants" kept track of by the managed assembly. # checkForSQLiteDefineConstant $::test_channel $defineConstant } # # 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: Try to setup an interrupt callback using the script debugger # that will cancel all SQL queries in progress for all database # connections known to this interpreter. # |
︙ | ︙ | |||
1882 1883 1884 1885 1886 1887 1888 | ############################# END Eagle ONLY ############################## ########################################################################### } # # NOTE: Save the name of the directory containing this file. # | | | | 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 | ############################# 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 } |
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 buildYear.2005 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 buildYear.2005 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 buildYear.2008 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 buildYear.2008 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 buildYear.2010 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 buildYear.2010 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 buildYear.2012 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 buildYear.2012 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.
︙ | ︙ | |||
45 46 47 48 49 50 51 | reportSQLiteResources $test_channel ############################################################################### runTest {test stress-1.1 {multithreaded stress testing} -setup { unset -nocomplain result thread index workload priority noWorkload \ priorities srcDb db fileName compiled options count times logFileName \ | | | | 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | reportSQLiteResources $test_channel ############################################################################### runTest {test stress-1.1 {multithreaded stress testing} -setup { unset -nocomplain result thread index workload priority noWorkload \ priorities srcDb db fileName compiled options count times logFileName \ logListener event timeout connection indicators iterations exitOnFail \ coTaskMem noTrace failures status ############################################################################# proc setupWorkloadMemDb { fileName {varName db} } { # # NOTE: This should be an in-memory database; therefore, skip attempting # to delete the underlying database file as that would not make any |
︙ | ︙ | |||
139 140 141 142 143 144 145 146 147 148 149 150 151 152 | } ############################################################################# proc delayTest { {extra 0} } { after [expr {int((rand() * 1000) + $extra)}] } ############################################################################# proc showTest { indicator } { tputs $::test_channel $indicator append ::indicators $indicator delayTest $::count(2) | > > > > > > > > > | 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 | } ############################################################################# proc delayTest { {extra 0} } { after [expr {int((rand() * 1000) + $extra)}] } ############################################################################# proc waitTest { indicator } { if {![$::event WaitOne $::timeout]} then { error [appendArgs "timeout while starting workload #" \ [expr {[string ordinal $indicator 0] - [string ordinal A 0] + 1}]] } } ############################################################################# proc showTest { indicator } { tputs $::test_channel $indicator append ::indicators $indicator delayTest $::count(2) |
︙ | ︙ | |||
464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 | # logging subsystem is working properly. Second, it places the file # name for the associated database file into the trace log file. # set connection [getDbConnection] $connection LogMessage 0 [appendArgs \ "starting stress test using database \"" $fileName(2) \"...] ############################################################################# # WORKLOAD #1 (A) # ############################################################################# set workload(1) [list \ [list srcFileName dstFileName table count1 count2 count3] { # # NOTE: Workload #1, CREATE TABLE statements. # lappend ::times(1) [lindex [time { initTest A setupWorkloadFileDb $dstFileName for {set index 2} {$index <= $count1} {incr index} { if {[catch { sql execute $db [appendArgs \ "CREATE TABLE IF NOT EXISTS t" \ | > > > > > > > > > > > > > > > | 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 | # logging subsystem is working properly. Second, it places the file # name for the associated database file into the trace log file. # set connection [getDbConnection] $connection LogMessage 0 [appendArgs \ "starting stress test using database \"" $fileName(2) \"...] ############################################################################# set timeout [object invoke -flags +NonPublic \ Eagle._Components.Private.ThreadOps DefaultJoinTimeout] tputs $test_channel [appendArgs \ "---- workloads will start before or timeout after " $timeout \ " millisecond(s)\n"] ############################################################################# set event [object create -alias \ System.Threading.EventWaitHandle false ManualReset] ############################################################################# # WORKLOAD #1 (A) # ############################################################################# set workload(1) [list \ [list srcFileName dstFileName table count1 count2 count3] { # # NOTE: Workload #1, CREATE TABLE statements. # waitTest A lappend ::times(1) [lindex [time { initTest A setupWorkloadFileDb $dstFileName for {set index 2} {$index <= $count1} {incr index} { if {[catch { sql execute $db [appendArgs \ "CREATE TABLE IF NOT EXISTS t" \ |
︙ | ︙ | |||
505 506 507 508 509 510 511 512 513 514 515 516 517 518 | ############################################################################# set workload(2) [list \ [list srcFileName dstFileName table count1 count2 count3] { # # NOTE: Workload #2, DROP TABLE statements. # lappend ::times(2) [lindex [time { initTest B setupWorkloadFileDb $dstFileName for {set index 2} {$index <= $count1} {incr index} { if {[catch { sql execute $db [appendArgs \ "DROP TABLE IF EXISTS t" $index \;] | > | 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 | ############################################################################# set workload(2) [list \ [list srcFileName dstFileName table count1 count2 count3] { # # NOTE: Workload #2, DROP TABLE statements. # waitTest B lappend ::times(2) [lindex [time { initTest B setupWorkloadFileDb $dstFileName for {set index 2} {$index <= $count1} {incr index} { if {[catch { sql execute $db [appendArgs \ "DROP TABLE IF EXISTS t" $index \;] |
︙ | ︙ | |||
535 536 537 538 539 540 541 542 543 544 545 546 547 548 | ############################################################################# set workload(3) [list \ [list srcFileName dstFileName table count1 count2 count3] { # # NOTE: Workload #3, "small" SELECT statements. # lappend ::times(3) [lindex [time { initTest C setupWorkloadFileDb $dstFileName for {set index 1} {$index <= $count1} {incr index} { if {[catch { set reader [sql execute -execute reader \ -format dataReader -alias $db [appendArgs \ | > | 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 | ############################################################################# set workload(3) [list \ [list srcFileName dstFileName table count1 count2 count3] { # # NOTE: Workload #3, "small" SELECT statements. # waitTest C lappend ::times(3) [lindex [time { initTest C setupWorkloadFileDb $dstFileName for {set index 1} {$index <= $count1} {incr index} { if {[catch { set reader [sql execute -execute reader \ -format dataReader -alias $db [appendArgs \ |
︙ | ︙ | |||
572 573 574 575 576 577 578 579 580 581 582 583 584 585 | ############################################################################# set workload(4) [list \ [list srcFileName dstFileName table count1 count2 count3] { # # NOTE: Workload #4, "big" SELECT statements. # lappend ::times(4) [lindex [time { initTest D setupWorkloadFileDb $dstFileName for {set index 1} {$index <= $count1} {incr index} { if {[catch { set reader [sql execute -execute reader \ -format dataReader -alias $db [appendArgs \ | > | 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 | ############################################################################# set workload(4) [list \ [list srcFileName dstFileName table count1 count2 count3] { # # NOTE: Workload #4, "big" SELECT statements. # waitTest D lappend ::times(4) [lindex [time { initTest D setupWorkloadFileDb $dstFileName for {set index 1} {$index <= $count1} {incr index} { if {[catch { set reader [sql execute -execute reader \ -format dataReader -alias $db [appendArgs \ |
︙ | ︙ | |||
609 610 611 612 613 614 615 616 617 618 619 620 621 622 | ############################################################################# set workload(5) [list \ [list srcFileName dstFileName table count1 count2 count3] { # # NOTE: Workload #5, "small" INSERT statements. # lappend ::times(5) [lindex [time { initTest E setupWorkloadFileDb $dstFileName for {set index 1} {$index <= $count1} {incr index} { if {[catch { sql execute $db [appendArgs "INSERT INTO " $table \ "(x, y, z) VALUES('" [format %lX [expr {random()}]] \ | > | 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 | ############################################################################# set workload(5) [list \ [list srcFileName dstFileName table count1 count2 count3] { # # NOTE: Workload #5, "small" INSERT statements. # waitTest E lappend ::times(5) [lindex [time { initTest E setupWorkloadFileDb $dstFileName for {set index 1} {$index <= $count1} {incr index} { if {[catch { sql execute $db [appendArgs "INSERT INTO " $table \ "(x, y, z) VALUES('" [format %lX [expr {random()}]] \ |
︙ | ︙ | |||
641 642 643 644 645 646 647 648 649 650 651 652 653 654 | ############################################################################# set workload(6) [list \ [list srcFileName dstFileName table count1 count2 count3] { # # NOTE: Workload #6, "big" INSERT statements. # lappend ::times(6) [lindex [time { initTest F setupWorkloadFileDb $dstFileName for {set index 1} {$index <= $count1} {incr index} { if {[catch { sql execute $db [appendArgs "INSERT INTO " $table \ "(x, y, z) VALUES('" [format %lX [expr {random()}]] \ | > | 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 | ############################################################################# set workload(6) [list \ [list srcFileName dstFileName table count1 count2 count3] { # # NOTE: Workload #6, "big" INSERT statements. # waitTest F lappend ::times(6) [lindex [time { initTest F setupWorkloadFileDb $dstFileName for {set index 1} {$index <= $count1} {incr index} { if {[catch { sql execute $db [appendArgs "INSERT INTO " $table \ "(x, y, z) VALUES('" [format %lX [expr {random()}]] \ |
︙ | ︙ | |||
672 673 674 675 676 677 678 679 680 681 682 683 684 685 | ############################################################################# set workload(7) [list \ [list srcFileName dstFileName table count1 count2 count3] { # # NOTE: Workload #7, "small" UPDATE statements. # lappend ::times(7) [lindex [time { initTest G setupWorkloadFileDb $dstFileName for {set index 1} {$index <= $count1} {incr index} { if {[catch { sql execute $db [appendArgs "UPDATE " $table \ " SET y = '" [base64 encode -- [expr {randstr($count2)}]] \ | > | 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 | ############################################################################# set workload(7) [list \ [list srcFileName dstFileName table count1 count2 count3] { # # NOTE: Workload #7, "small" UPDATE statements. # waitTest G lappend ::times(7) [lindex [time { initTest G setupWorkloadFileDb $dstFileName for {set index 1} {$index <= $count1} {incr index} { if {[catch { sql execute $db [appendArgs "UPDATE " $table \ " SET y = '" [base64 encode -- [expr {randstr($count2)}]] \ |
︙ | ︙ | |||
703 704 705 706 707 708 709 710 711 712 713 714 715 716 | ############################################################################# set workload(8) [list \ [list srcFileName dstFileName table count1 count2 count3] { # # NOTE: Workload #8, "big" UPDATE statements. # lappend ::times(8) [lindex [time { initTest H setupWorkloadFileDb $dstFileName for {set index 1} {$index <= $count1} {incr index} { if {[catch { sql execute $db [appendArgs "UPDATE " $table \ " SET y = RANDOMBLOB(" $count3 ") WHERE x LIKE '" \ | > | 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 | ############################################################################# set workload(8) [list \ [list srcFileName dstFileName table count1 count2 count3] { # # NOTE: Workload #8, "big" UPDATE statements. # waitTest H lappend ::times(8) [lindex [time { initTest H setupWorkloadFileDb $dstFileName for {set index 1} {$index <= $count1} {incr index} { if {[catch { sql execute $db [appendArgs "UPDATE " $table \ " SET y = RANDOMBLOB(" $count3 ") WHERE x LIKE '" \ |
︙ | ︙ | |||
734 735 736 737 738 739 740 741 742 743 744 745 746 747 | ############################################################################# set workload(9) [list \ [list srcFileName dstFileName table count1 count2 count3] { # # NOTE: Workload #9, "small" DELETE statements. # lappend ::times(9) [lindex [time { initTest I setupWorkloadFileDb $dstFileName for {set index 1} {$index <= $count1} {incr index} { if {[catch { sql execute $db [appendArgs "DELETE FROM " $table \ " WHERE x LIKE '" [format %X $index] "%' AND z = 'small';"] | > | 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 | ############################################################################# set workload(9) [list \ [list srcFileName dstFileName table count1 count2 count3] { # # NOTE: Workload #9, "small" DELETE statements. # waitTest I lappend ::times(9) [lindex [time { initTest I setupWorkloadFileDb $dstFileName for {set index 1} {$index <= $count1} {incr index} { if {[catch { sql execute $db [appendArgs "DELETE FROM " $table \ " WHERE x LIKE '" [format %X $index] "%' AND z = 'small';"] |
︙ | ︙ | |||
764 765 766 767 768 769 770 771 772 773 774 775 776 777 | ############################################################################# set workload(10) [list \ [list srcFileName dstFileName table count1 count2 count3] { # # NOTE: Workload #10, "big" DELETE statements. # lappend ::times(10) [lindex [time { initTest J setupWorkloadFileDb $dstFileName for {set index 1} {$index <= $count1} {incr index} { if {[catch { sql execute $db [appendArgs "DELETE FROM " $table \ " WHERE x LIKE '" [format %X $index] "%' AND z = 'big';"] | > | 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 | ############################################################################# set workload(10) [list \ [list srcFileName dstFileName table count1 count2 count3] { # # NOTE: Workload #10, "big" DELETE statements. # waitTest J lappend ::times(10) [lindex [time { initTest J setupWorkloadFileDb $dstFileName for {set index 1} {$index <= $count1} {incr index} { if {[catch { sql execute $db [appendArgs "DELETE FROM " $table \ " WHERE x LIKE '" [format %X $index] "%' AND z = 'big';"] |
︙ | ︙ | |||
794 795 796 797 798 799 800 801 802 803 804 805 806 807 | ############################################################################# set workload(11) [list \ [list srcFileName dstFileName table count1 count2 count3] { # # NOTE: Workload #11, VACUUM statement. # lappend ::times(11) [lindex [time { initTest K setupWorkloadFileDb $dstFileName for {set index 1} {$index <= $count1} {incr index} { if {[catch { sql execute $db "VACUUM;" showTest K | > | 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 | ############################################################################# set workload(11) [list \ [list srcFileName dstFileName table count1 count2 count3] { # # NOTE: Workload #11, VACUUM statement. # waitTest K lappend ::times(11) [lindex [time { initTest K setupWorkloadFileDb $dstFileName for {set index 1} {$index <= $count1} {incr index} { if {[catch { sql execute $db "VACUUM;" showTest K |
︙ | ︙ | |||
823 824 825 826 827 828 829 830 831 832 833 834 835 836 | ############################################################################# set workload(12) [list \ [list srcFileName dstFileName table count1 count2 count3] { # # NOTE: Workload #12, backup to in-memory database. # lappend ::times(12) [lindex [time { initTest L for {set index 1} {$index <= $count1} {incr index} { if {[string is integer -strict $::compiled(12)]} then { set id $::compiled(12); # NOTE: Already compiled. if {[catch { object invoke _Dynamic${id}.Test${id} BackupAndGetData | > | 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 | ############################################################################# set workload(12) [list \ [list srcFileName dstFileName table count1 count2 count3] { # # NOTE: Workload #12, backup to in-memory database. # waitTest L lappend ::times(12) [lindex [time { initTest L for {set index 1} {$index <= $count1} {incr index} { if {[string is integer -strict $::compiled(12)]} then { set id $::compiled(12); # NOTE: Already compiled. if {[catch { object invoke _Dynamic${id}.Test${id} BackupAndGetData |
︙ | ︙ | |||
905 906 907 908 909 910 911 912 913 914 915 916 917 918 | ############################################################################# set workload(13) [list \ [list srcFileName dstFileName table count1 count2 count3] { # # NOTE: Workload #13, backup from an in-memory database. # lappend ::times(13) [lindex [time { initTest M for {set index 1} {$index <= $count1} {incr index} { if {[string is integer -strict $::compiled(13)]} then { set id $::compiled(13); # NOTE: Already compiled. if {[catch { object invoke _Dynamic${id}.Test${id} BackupAndGetData | > | 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 | ############################################################################# set workload(13) [list \ [list srcFileName dstFileName table count1 count2 count3] { # # NOTE: Workload #13, backup from an in-memory database. # waitTest M lappend ::times(13) [lindex [time { initTest M for {set index 1} {$index <= $count1} {incr index} { if {[string is integer -strict $::compiled(13)]} then { set id $::compiled(13); # NOTE: Already compiled. if {[catch { object invoke _Dynamic${id}.Test${id} BackupAndGetData |
︙ | ︙ | |||
987 988 989 990 991 992 993 994 995 996 997 998 999 1000 | ############################################################################# set workload(14) [list \ [list srcFileName dstFileName table count1 count2 count3] { # # NOTE: Workload #14, PRAGMA integrity check statement. # lappend ::times(14) [lindex [time { initTest N setupWorkloadFileDb $dstFileName for {set index 1} {$index <= $count1} {incr index} { if {[catch { set result [sql execute -execute scalar $db \ "PRAGMA integrity_check;"] | > | 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 | ############################################################################# set workload(14) [list \ [list srcFileName dstFileName table count1 count2 count3] { # # NOTE: Workload #14, PRAGMA integrity check statement. # waitTest N lappend ::times(14) [lindex [time { initTest N setupWorkloadFileDb $dstFileName for {set index 1} {$index <= $count1} {incr index} { if {[catch { set result [sql execute -execute scalar $db \ "PRAGMA integrity_check;"] |
︙ | ︙ | |||
1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 | ############################################################################# set workload(15) [list \ [list srcFileName dstFileName table count1 count2 count3] { # # NOTE: Workload #15, force managed garbage collection # lappend ::times(15) [lindex [time { initTest O for {set index 1} {$index <= $count1} {incr index} { if {[catch { collectGarbage $::test_channel showTest O } error]} then { | > | 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 | ############################################################################# set workload(15) [list \ [list srcFileName dstFileName table count1 count2 count3] { # # NOTE: Workload #15, force managed garbage collection # waitTest O lappend ::times(15) [lindex [time { initTest O for {set index 1} {$index <= $count1} {incr index} { if {[catch { collectGarbage $::test_channel showTest O } error]} then { |
︙ | ︙ | |||
1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 | ############################################################################# set workload(16) [list \ [list srcFileName dstFileName table count1 count2 count3] { # # NOTE: Workload #16, allocate (exclude) some native heap memory # lappend ::times(16) [lindex [time { initTest P set maxSize $::count(5) object invoke GC AddMemoryPressure $maxSize try { for {set index 1} {$index <= $count1} {incr index} { if {[catch { | > | 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 | ############################################################################# set workload(16) [list \ [list srcFileName dstFileName table count1 count2 count3] { # # NOTE: Workload #16, allocate (exclude) some native heap memory # waitTest P lappend ::times(16) [lindex [time { initTest P set maxSize $::count(5) object invoke GC AddMemoryPressure $maxSize try { for {set index 1} {$index <= $count1} {incr index} { if {[catch { |
︙ | ︙ | |||
1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 | ############################################################################# set workload(17) [list \ [list srcFileName dstFileName table count1 count2 count3] { # # NOTE: Workload #17, change the database journal mode # lappend ::times(17) [lindex [time { initTest Q setupWorkloadFileDb $dstFileName for {set index 1} {$index <= $count1} {incr index} { if {[catch { sql execute $db [appendArgs "PRAGMA journal_mode = \"" \ [expr {$index % 2 == 0 ? "delete" : "wal"}] \"\;] | > | 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 | ############################################################################# set workload(17) [list \ [list srcFileName dstFileName table count1 count2 count3] { # # NOTE: Workload #17, change the database journal mode # waitTest Q lappend ::times(17) [lindex [time { initTest Q setupWorkloadFileDb $dstFileName for {set index 1} {$index <= $count1} {incr index} { if {[catch { sql execute $db [appendArgs "PRAGMA journal_mode = \"" \ [expr {$index % 2 == 0 ? "delete" : "wal"}] \"\;] |
︙ | ︙ | |||
1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 | ############################################################################# set workload(18) [list \ [list srcFileName dstFileName table count1 count2 count3] { # # NOTE: Workload #18, execute queries against the in-memory database # lappend ::times(18) [lindex [time { initTest R setupWorkloadMemDb $srcFileName for {set index 1} {$index <= $count1} {incr index} { if {[catch { # # NOTE: Workload #18.3, "small" SELECT statements. | > | 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 | ############################################################################# set workload(18) [list \ [list srcFileName dstFileName table count1 count2 count3] { # # NOTE: Workload #18, execute queries against the in-memory database # waitTest R lappend ::times(18) [lindex [time { initTest R setupWorkloadMemDb $srcFileName for {set index 1} {$index <= $count1} {incr index} { if {[catch { # # NOTE: Workload #18.3, "small" SELECT statements. |
︙ | ︙ | |||
1233 1234 1235 1236 1237 1238 1239 | foreach index(1) [lsort -integer [array names workload]] { if {[lsearch -exact $noWorkload $index(1)] == -1} then { set thread($index(1)) [object create -alias System.Threading.Thread \ [list apply $workload($index(1)) $fileName(1) $fileName(2) t1 \ $count(1) $count(3) $count(4)] 1048576] $thread($index(1)) Name [appendArgs \ | | < | | | > > > > > | 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 | foreach index(1) [lsort -integer [array names workload]] { if {[lsearch -exact $noWorkload $index(1)] == -1} then { set thread($index(1)) [object create -alias System.Threading.Thread \ [list apply $workload($index(1)) $fileName(1) $fileName(2) t1 \ $count(1) $count(3) $count(4)] 1048576] $thread($index(1)) Name [appendArgs \ [file rootname [file tail $fileName(2)]] " #" $index(1)] if {[info exists priority($index(1))]} then { $thread($index(1)) Priority $priority($index(1)) } } } foreach index(1) [array names thread] { $thread($index(1)) Start } $event Set; # GO foreach index(1) [array names thread] { $thread($index(1)) Join } foreach index(1) [array names thread] { if {[info exists thread($index(1))] && \ [cleanupThread $thread($index(1))]} then { unset -nocomplain thread($index(1)) } |
︙ | ︙ | |||
1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 | rename freeMem "" rename useMem "" rename allocMem "" rename failTest "" rename doneTest "" rename showTest "" rename delayTest "" rename initTest "" rename isExpectedError "" rename formatWorkloadTime "" rename formatWorkloadResult "" rename setupWorkloadFileDb "" rename setupWorkloadMemDb "" | > | 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 | rename freeMem "" rename useMem "" rename allocMem "" rename failTest "" rename doneTest "" rename showTest "" rename waitTest "" rename delayTest "" rename initTest "" rename isExpectedError "" rename formatWorkloadTime "" rename formatWorkloadResult "" rename setupWorkloadFileDb "" rename setupWorkloadMemDb "" |
︙ | ︙ | |||
1377 1378 1379 1380 1381 1382 1383 | } rename cleanupLogging "" rename setupLogging "" unset -nocomplain result thread index workload priority noWorkload \ priorities srcDb db fileName compiled options count times logFileName \ | | | | 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 | } rename cleanupLogging "" rename setupLogging "" unset -nocomplain result thread index workload priority noWorkload \ priorities srcDb db fileName compiled options count times logFileName \ logListener event timeout connection indicators iterations exitOnFail \ coTaskMem noTrace failures status } -time true -constraints {eagle monoBug28 command.sql compile.DATA SQLite\ System.Data.SQLite} -result {0}} ############################################################################### # # NOTE: Report after test. |
︙ | ︙ |
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 74 75 76 | 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.Data.SQLite.SQLite3.LoadExtension}\ {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.SQLite3.Prepare}\ {System.Data.SQLite.SQLiteException (0x80004005): SQL logic error or missing\ database, no such function: interopTest}} {1 {EXCEPTION\ System.Data.SQLite.SQLiteException System.Data.SQLite.SQLite3.Prepare}\ {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.SQLite3.Reset}\ {System.Data.SQLite.SQLiteException (0x80004005): SQL logic error or missing\ database, need exactly one argument}}}} ############################################################################### runSQLiteTestEpilogue runTestEpilogue |
Added Tests/tkt-1c456ae75f.eagle.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 | ############################################################################### # # tkt-1c456ae75f.eagle -- # # Written by Joe Mistachkin. # Released to the public domain, use at your own risk! # ############################################################################### package require Eagle package require Eagle.Library package require Eagle.Test runTestPrologue ############################################################################### package require System.Data.SQLite.Test runSQLiteTestPrologue ############################################################################### runTest {test tkt-1c456ae75f-1.1 {unencrypted database, hex password} -setup { setupDb [set fileName tkt-1c456ae75f-1.1.db] } -body { sql execute $db "CREATE TABLE t1(x);" sql execute $db "INSERT INTO t1 (x) VALUES(1);" cleanupDb $fileName db true false false setupDb $fileName "" "" "" "" "HexPassword=3132333435;" true false set result [list] lappend result [catch {sql execute -execute scalar $db \ "SELECT COUNT(*) FROM t1;"} error] $error lappend result [catch {sql execute $db \ "INSERT INTO t1 (x) VALUES(1);"} error] $error cleanupDb $fileName db true false false setupDb $fileName "" "" "" "" "" true false lappend result [catch {sql execute $db \ "INSERT INTO t1 (x) VALUES(1);"} error] $error lappend result [catch {sql execute -execute scalar $db \ "SELECT COUNT(*) FROM t1;"} error] $error set result } -cleanup { cleanupDb $fileName unset -nocomplain error result db fileName } -constraints {eagle defineConstant.System.Data.SQLite.INTEROP_CODEC monoBug28\ command.sql compile.DATA SQLite System.Data.SQLite} -match regexp -result {^1\ \{System\.Data\.SQLite\.SQLiteException \(0x80004005\): file is encrypted or is\ not a database.*?\} 1 \{System\.Data\.SQLite\.SQLiteException \(0x80004005\):\ file is encrypted or is not a database.*?\} 0 1 0 2$}} ############################################################################### runTest {test tkt-1c456ae75f-1.2 {database, hex password} -setup { setupDb [set fileName tkt-1c456ae75f-1.2.db] "" "" "" "" \ "HexPassword=3132333435;" } -body { sql execute $db "CREATE TABLE t1(x);" sql execute $db "INSERT INTO t1 (x) VALUES(1);" cleanupDb $fileName db true false false setupDb $fileName "" "" "" "" "Password=12345;" true false set result [list] lappend result [catch {sql execute -execute scalar $db \ "SELECT COUNT(*) FROM t1;"} error] $error lappend result [catch {sql execute $db \ "INSERT INTO t1 (x) VALUES(1);"} error] $error cleanupDb $fileName db true false false setupDb $fileName "" "" "" "" "HexPassword=3132333435;" true false lappend result [catch {sql execute $db \ "INSERT INTO t1 (x) VALUES(1);"} error] $error lappend result [catch {sql execute -execute scalar $db \ "SELECT COUNT(*) FROM t1;"} error] $error set result } -cleanup { cleanupDb $fileName unset -nocomplain error result db fileName } -constraints {eagle defineConstant.System.Data.SQLite.INTEROP_CODEC monoBug28\ command.sql compile.DATA SQLite System.Data.SQLite} -result {0 1 0 1 0 1 0 3}} ############################################################################### runTest {test tkt-1c456ae75f-1.3 {database, wrong hex password} -setup { setupDb [set fileName tkt-1c456ae75f-1.3.db] "" "" "" "" \ "HexPassword=3132333435;" } -body { sql execute $db "CREATE TABLE t1(x);" sql execute $db "INSERT INTO t1 (x) VALUES(1);" cleanupDb $fileName db true false false setupDb $fileName "" "" "" "" "HexPassword=3132333436;" true false set result [list] lappend result [catch {sql execute -execute scalar $db \ "SELECT COUNT(*) FROM t1;"} error] $error lappend result [catch {sql execute $db \ "INSERT INTO t1 (x) VALUES(1);"} error] $error cleanupDb $fileName db true false false setupDb $fileName "" "" "" "" "HexPassword=3132333435;" true false lappend result [catch {sql execute $db \ "INSERT INTO t1 (x) VALUES(1);"} error] $error lappend result [catch {sql execute -execute scalar $db \ "SELECT COUNT(*) FROM t1;"} error] $error set result } -cleanup { cleanupDb $fileName unset -nocomplain error result db fileName } -constraints {eagle defineConstant.System.Data.SQLite.INTEROP_CODEC monoBug28\ command.sql compile.DATA SQLite System.Data.SQLite} -match regexp -result {^1\ \{System\.Data\.SQLite\.SQLiteException \(0x80004005\): file is encrypted or is\ not a database.*?\} 1 \{System\.Data\.SQLite\.SQLiteException \(0x80004005\):\ file is encrypted or is not a database.*?\} 0 1 0 2$}} ############################################################################### runTest {test tkt-1c456ae75f-1.4 {database, hex password via builder} -setup { setupDb [set fileName tkt-1c456ae75f-1.4.db] "" "" "" "" \ "HexPassword=3132333435;" } -body { sql execute $db "CREATE TABLE t1(x);" sql execute $db "INSERT INTO t1 (x) VALUES(1);" cleanupDb $fileName db true false false set connectionStringBuilder [object create -alias \ System.Data.SQLite.SQLiteConnectionStringBuilder] $connectionStringBuilder DataSource \ [file join [getDatabaseDirectory] $fileName] $connectionStringBuilder HexPassword [list 0x31 0x32 0x33 0x34 0x35] set connection [object create -alias \ System.Data.SQLite.SQLiteConnection \ [$connectionStringBuilder ToString] true] $connection Open; addDbConnection $connection set result [list] lappend result [catch {sql execute -execute scalar $db \ "SELECT COUNT(*) FROM t1;"} error] $error lappend result [catch {sql execute $db \ "INSERT INTO t1 (x) VALUES(1);"} error] $error cleanupDb $fileName db true false false setupDb $fileName "" "" "" "" "Password=\"12345\";" true false lappend result [catch {sql execute $db \ "INSERT INTO t1 (x) VALUES(1);"} error] $error lappend result [catch {sql execute -execute scalar $db \ "SELECT COUNT(*) FROM t1;"} error] $error set result } -cleanup { unset -nocomplain connection cleanupDb $fileName; # NOTE: After object disposal. unset -nocomplain connectionStringBuilder error result db fileName } -constraints {eagle defineConstant.System.Data.SQLite.INTEROP_CODEC monoBug28\ command.sql compile.DATA SQLite System.Data.SQLite} -result {0 1 0 1 0 1 0 3}} ############################################################################### runSQLiteTestEpilogue runTestEpilogue |
Added Tests/tkt-3567020edf.eagle.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | ############################################################################### # # tkt-3567020edf.eagle -- # # Written by Joe Mistachkin. # Released to the public domain, use at your own risk! # ############################################################################### package require Eagle package require Eagle.Library package require Eagle.Test runTestPrologue ############################################################################### package require System.Data.SQLite.Test runSQLiteTestPrologue ############################################################################### runTest {test tkt-3567020edf-1.1 {embedded NUL characters (UTF-8)} -setup { setupDb [set fileName tkt-3567020edf-1.1.db] } -body { sql execute $db "CREATE TABLE t1(x);" sql execute $db "INSERT INTO t1 (x) VALUES(?);" \ [list param1 String one\x00two] sql execute -execute reader -format list $db "SELECT x FROM t1;" } -cleanup { cleanupDb $fileName unset -nocomplain db fileName } -constraints \ {eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} -result \ "one\x00two"} ############################################################################### runTest {test tkt-3567020edf-1.2 {embedded NUL characters (UTF-16)} -setup { setupDb [set fileName tkt-3567020edf-1.2.db] "" "" "" "" \ UseUTF16Encoding=True } -body { sql execute $db "CREATE TABLE t1(x);" sql execute $db "INSERT INTO t1 (x) VALUES(?);" \ [list param1 String one\x00two] sql execute -execute reader -format list $db "SELECT x FROM t1;" } -cleanup { cleanupDb $fileName unset -nocomplain db fileName } -constraints \ {eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} -result \ "one\x00two"} ############################################################################### runSQLiteTestEpilogue runTestEpilogue |
Added Tests/tkt-393d954be0.eagle.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | ############################################################################### # # tkt-393d954be0.eagle -- # # Written by Joe Mistachkin. # Released to the public domain, use at your own risk! # ############################################################################### package require Eagle package require Eagle.Library package require Eagle.Test runTestPrologue ############################################################################### package require System.Data.SQLite.Test runSQLiteTestPrologue ############################################################################### runTest {test tkt-393d954be0-1.1 {custom connection pool} -setup { set nullPool [object create -flags +NonPublic -alias \ System.Data.SQLite.NullConnectionPool true] object invoke System.Data.SQLite.SQLiteConnection ConnectionPool $nullPool setupDb [set fileName tkt-393d954be0-1.1.db] "" "" "" "" "Pooling=True;" } -body { set exists(0) [file exists [file join [getDatabaseDirectory] [file tail \ $fileName]]] cleanupDb $fileName set exists(1) [file exists [file join [getDatabaseDirectory] [file tail \ $fileName]]] set counts null; set openCount 0; set closeCount 0; set totalCount 0 object invoke -flags +NonPublic System.Data.SQLite.SQLiteConnectionPool \ GetCounts $fileName counts openCount closeCount totalCount object invoke -flags +NonPublic System.Data.SQLite.SQLiteConnectionPool \ ClearPool $fileName object invoke -flags +NonPublic System.Data.SQLite.SQLiteConnectionPool \ ClearAllPools list $exists(0) $exists(1) $counts $openCount $closeCount $totalCount \ [object invoke $nullPool ToString] } -cleanup { cleanupDb $fileName catch {object invoke System.Data.SQLite.SQLiteConnection ConnectionPool null} unset -nocomplain db fileName exists counts openCount closeCount totalCount \ nullPool } -constraints {eagle monoBug28 buildConfiguration.Debug command.sql\ compile.DATA SQLite System.Data.SQLite} -match regexp -result [string map \ [list \n \r\n] {^True False \{\} 0 0 0\ \{Remove\(".*?\\tkt-393d954be0-1\.1\.db",\ 100, 0\) Add\(".*?\\tkt-393d954be0-1\.1\.db", -?\d+, 0\) GetCounts\("tkt-393d954be0-1\.1\.db", , 0, 0, 0\) ClearPool\("tkt-393d954be0-1\.1\.db"\) ClearAllPools\(\) \}$}]} ############################################################################### runSQLiteTestEpilogue runTestEpilogue |
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-ae5267b863.eagle.
︙ | ︙ | |||
143 144 145 146 147 148 149 | object invoke _Dynamic${id}.Test${id} Main } result] : [set result ""]}] $result } -cleanup { cleanupDb $fileName unset -nocomplain result code results errors sql dataSource id db fileName } -constraints [fixConstraints {eagle monoBug28 command.sql compile.DATA\ | | > | | 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 | object invoke _Dynamic${id}.Test${id} Main } result] : [set result ""]}] $result } -cleanup { cleanupDb $fileName unset -nocomplain result code results errors sql dataSource id db fileName } -constraints [fixConstraints {eagle monoBug28 command.sql compile.DATA\ SQLite System.Data.SQLite !mda\ !defineConstant.System.Data.SQLite.INTEROP_LEGACY_CLOSE}] -match regexp \ -result {^Ok System#CodeDom#Compiler#CompilerResults#\d+ \{\} 0 \{\}$}} ############################################################################### runSQLiteTestEpilogue runTestEpilogue |
Added Tests/tkt-c010fa6584.eagle.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 | ############################################################################### # # tkt-c010fa6584.eagle -- # # Written by Joe Mistachkin. # Released to the public domain, use at your own risk! # ############################################################################### package require Eagle package require Eagle.Library package require Eagle.Test runTestPrologue ############################################################################### package require System.Data.SQLite.Test runSQLiteTestPrologue ############################################################################### runTest {test tkt-c010fa6584-1.1 {column "integral" type handling} -setup { setupDb [set fileName tkt-c010fa6584-1.1.db] } -body { # # NOTE: Create a database table with all the integral type names that are # recognized by System.Data.SQLite. Subsequently, each column will # be tested against a list of values that meet and/or exceed the # bounds for the underlying primitive integral CLR type. # sql execute $db { CREATE TABLE t1( a00 SYSNAME, -- This is the 'payload' column name. a01, -- String a02 TEXT, -- String a03 BIGINT, -- Int64 a04 BIGUINT, -- UInt64 a05 COUNTER, -- Int64 a06 IDENTITY, -- Int64 a07 INT, -- Int32 a08 INT8, -- SByte a09 INT16, -- Int16 a10 INT32, -- Int32 a11 INT64, -- Int64 a12 INTEGER, -- Int64 a13 INTEGER8, -- SByte a14 INTEGER16, -- Int16 a15 INTEGER32, -- Int32 a16 INTEGER64, -- Int64 a17 LONG, -- Int64 a18 SMALLINT, -- Int16 a19 SMALLUINT, -- UInt16 a20 TINYINT, -- Byte a21 TINYSINT, -- SByte a22 UINT, -- UInt32 a23 UINT8, -- Byte a24 UINT16, -- UInt16 a25 UINT32, -- UInt32 a26 UINT64, -- UInt64 a27 ULONG, -- UInt64 a28 UNSIGNEDINTEGER, -- UInt32 a29 UNSIGNEDINTEGER8, -- Byte a30 UNSIGNEDINTEGER16, -- UInt16 a31 UNSIGNEDINTEGER32, -- UInt32 a32 UNSIGNEDINTEGER64 -- UInt64 ); } # # NOTE: These are the numeric values being tested against all the types in # the database table defined above. This list includes values that # are out-of-bounds for each primitive integral type. # set values [list \ -9223372036854775809 -9223372036854775808 \ -2147483649 -2147483648 \ -32769 -32768 \ -129 -128 \ -1 0 1 \ 127 128 \ 255 256 \ 32767 32768 \ 65535 65536 \ 2147483647 2147483648 \ 4294967295 4294967296 \ 9223372036854775807 9223372036854775808 \ 18446744073709551615 18446744073709551616] for {set index 1} {$index <= 32} {incr index} { set name [appendArgs a [format %02d $index]] foreach value $values { sql execute $db [subst { INSERT INTO t1 (a00, $name) VALUES('$name', $value); }] } } set results [list] for {set index 1} {$index <= 32} {incr index} { set name [appendArgs a [format %02d $index]] set count [sql execute -execute scalar $db [subst { SELECT COUNT(*) FROM t1 WHERE a00 = '$name'; }]] for {set offset 0} {$offset < $count} {incr offset} { set code [catch { sql execute -execute scalar $db [subst { SELECT $name FROM t1 WHERE a00 = '$name' LIMIT 1 OFFSET $offset; }] } result] set match [expr {$result eq [lindex $values $offset]}] lappend results [list \ $name $offset $match [lindex $values $offset] \ $code [expr {$code == 0 ? $result : $errorCode}]] } } set results } -cleanup { cleanupDb $fileName unset -nocomplain match result code offset count results value name index \ values db fileName } -constraints \ {eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} -result \ {{a01 0 False -9223372036854775809 0 -9.22337203685478E+18} {a01 1 True\ -9223372036854775808 0 -9223372036854775808} {a01 2 True -2147483649 0\ -2147483649} {a01 3 True -2147483648 0 -2147483648} {a01 4 True -32769 0\ -32769} {a01 5 True -32768 0 -32768} {a01 6 True -129 0 -129} {a01 7 True -128\ 0 -128} {a01 8 True -1 0 -1} {a01 9 True 0 0 0} {a01 10 True 1 0 1} {a01 11\ True 127 0 127} {a01 12 True 128 0 128} {a01 13 True 255 0 255} {a01 14 True\ 256 0 256} {a01 15 True 32767 0 32767} {a01 16 True 32768 0 32768} {a01 17 True\ 65535 0 65535} {a01 18 True 65536 0 65536} {a01 19 True 2147483647 0\ 2147483647} {a01 20 True 2147483648 0 2147483648} {a01 21 True 4294967295 0\ 4294967295} {a01 22 True 4294967296 0 4294967296} {a01 23 True\ 9223372036854775807 0 9223372036854775807} {a01 24 False 9223372036854775808 0\ 9.22337203685478E+18} {a01 25 False 18446744073709551615 0\ 1.84467440737096E+19} {a01 26 False 18446744073709551616 0\ 1.84467440737096E+19} {a02 0 False -9223372036854775809 0\ -9.22337203685478e+18} {a02 1 True -9223372036854775808 0 -9223372036854775808}\ {a02 2 True -2147483649 0 -2147483649} {a02 3 True -2147483648 0 -2147483648}\ {a02 4 True -32769 0 -32769} {a02 5 True -32768 0 -32768} {a02 6 True -129 0\ -129} {a02 7 True -128 0 -128} {a02 8 True -1 0 -1} {a02 9 True 0 0 0} {a02 10\ True 1 0 1} {a02 11 True 127 0 127} {a02 12 True 128 0 128} {a02 13 True 255 0\ 255} {a02 14 True 256 0 256} {a02 15 True 32767 0 32767} {a02 16 True 32768 0\ 32768} {a02 17 True 65535 0 65535} {a02 18 True 65536 0 65536} {a02 19 True\ 2147483647 0 2147483647} {a02 20 True 2147483648 0 2147483648} {a02 21 True\ 4294967295 0 4294967295} {a02 22 True 4294967296 0 4294967296} {a02 23 True\ 9223372036854775807 0 9223372036854775807} {a02 24 False 9223372036854775808 0\ 9.22337203685478e+18} {a02 25 False 18446744073709551615 0\ 1.84467440737096e+19} {a02 26 False 18446744073709551616 0\ 1.84467440737096e+19} {a03 0 False -9223372036854775809 0 -9223372036854775808}\ {a03 1 True -9223372036854775808 0 -9223372036854775808} {a03 2 True\ -2147483649 0 -2147483649} {a03 3 True -2147483648 0 -2147483648} {a03 4 True\ -32769 0 -32769} {a03 5 True -32768 0 -32768} {a03 6 True -129 0 -129} {a03 7\ True -128 0 -128} {a03 8 True -1 0 -1} {a03 9 True 0 0 0} {a03 10 True 1 0 1}\ {a03 11 True 127 0 127} {a03 12 True 128 0 128} {a03 13 True 255 0 255} {a03 14\ True 256 0 256} {a03 15 True 32767 0 32767} {a03 16 True 32768 0 32768} {a03 17\ True 65535 0 65535} {a03 18 True 65536 0 65536} {a03 19 True 2147483647 0\ 2147483647} {a03 20 True 2147483648 0 2147483648} {a03 21 True 4294967295 0\ 4294967295} {a03 22 True 4294967296 0 4294967296} {a03 23 True\ 9223372036854775807 0 9223372036854775807} {a03 24 False 9223372036854775808 0\ -9223372036854775808} {a03 25 False 18446744073709551615 0\ -9223372036854775808} {a03 26 False 18446744073709551616 0\ -9223372036854775808} {a04 0 False -9223372036854775809 0 9223372036854775808}\ {a04 1 False -9223372036854775808 0 9223372036854775808} {a04 2 False\ -2147483649 0 18446744071562067967} {a04 3 False -2147483648 0\ 18446744071562067968} {a04 4 False -32769 0 18446744073709518847} {a04 5 False\ -32768 0 18446744073709518848} {a04 6 False -129 0 18446744073709551487} {a04 7\ False -128 0 18446744073709551488} {a04 8 False -1 0 18446744073709551615} {a04\ 9 True 0 0 0} {a04 10 True 1 0 1} {a04 11 True 127 0 127} {a04 12 True 128 0\ 128} {a04 13 True 255 0 255} {a04 14 True 256 0 256} {a04 15 True 32767 0\ 32767} {a04 16 True 32768 0 32768} {a04 17 True 65535 0 65535} {a04 18 True\ 65536 0 65536} {a04 19 True 2147483647 0 2147483647} {a04 20 True 2147483648 0\ 2147483648} {a04 21 True 4294967295 0 4294967295} {a04 22 True 4294967296 0\ 4294967296} {a04 23 True 9223372036854775807 0 9223372036854775807} {a04 24\ True 9223372036854775808 0 9223372036854775808} {a04 25 False\ 18446744073709551615 0 9223372036854775808} {a04 26 False 18446744073709551616\ 0 9223372036854775808} {a05 0 False -9223372036854775809 0\ -9223372036854775808} {a05 1 True -9223372036854775808 0 -9223372036854775808}\ {a05 2 True -2147483649 0 -2147483649} {a05 3 True -2147483648 0 -2147483648}\ {a05 4 True -32769 0 -32769} {a05 5 True -32768 0 -32768} {a05 6 True -129 0\ -129} {a05 7 True -128 0 -128} {a05 8 True -1 0 -1} {a05 9 True 0 0 0} {a05 10\ True 1 0 1} {a05 11 True 127 0 127} {a05 12 True 128 0 128} {a05 13 True 255 0\ 255} {a05 14 True 256 0 256} {a05 15 True 32767 0 32767} {a05 16 True 32768 0\ 32768} {a05 17 True 65535 0 65535} {a05 18 True 65536 0 65536} {a05 19 True\ 2147483647 0 2147483647} {a05 20 True 2147483648 0 2147483648} {a05 21 True\ 4294967295 0 4294967295} {a05 22 True 4294967296 0 4294967296} {a05 23 True\ 9223372036854775807 0 9223372036854775807} {a05 24 False 9223372036854775808 0\ -9223372036854775808} {a05 25 False 18446744073709551615 0\ -9223372036854775808} {a05 26 False 18446744073709551616 0\ -9223372036854775808} {a06 0 False -9223372036854775809 0 -9223372036854775808}\ {a06 1 True -9223372036854775808 0 -9223372036854775808} {a06 2 True\ -2147483649 0 -2147483649} {a06 3 True -2147483648 0 -2147483648} {a06 4 True\ -32769 0 -32769} {a06 5 True -32768 0 -32768} {a06 6 True -129 0 -129} {a06 7\ True -128 0 -128} {a06 8 True -1 0 -1} {a06 9 True 0 0 0} {a06 10 True 1 0 1}\ {a06 11 True 127 0 127} {a06 12 True 128 0 128} {a06 13 True 255 0 255} {a06 14\ True 256 0 256} {a06 15 True 32767 0 32767} {a06 16 True 32768 0 32768} {a06 17\ True 65535 0 65535} {a06 18 True 65536 0 65536} {a06 19 True 2147483647 0\ 2147483647} {a06 20 True 2147483648 0 2147483648} {a06 21 True 4294967295 0\ 4294967295} {a06 22 True 4294967296 0 4294967296} {a06 23 True\ 9223372036854775807 0 9223372036854775807} {a06 24 False 9223372036854775808 0\ -9223372036854775808} {a06 25 False 18446744073709551615 0\ -9223372036854775808} {a06 26 False 18446744073709551616 0\ -9223372036854775808} {a07 0 False -9223372036854775809 0 0} {a07 1 False\ -9223372036854775808 0 0} {a07 2 False -2147483649 0 2147483647} {a07 3 True\ -2147483648 0 -2147483648} {a07 4 True -32769 0 -32769} {a07 5 True -32768 0\ -32768} {a07 6 True -129 0 -129} {a07 7 True -128 0 -128} {a07 8 True -1 0 -1}\ {a07 9 True 0 0 0} {a07 10 True 1 0 1} {a07 11 True 127 0 127} {a07 12 True 128\ 0 128} {a07 13 True 255 0 255} {a07 14 True 256 0 256} {a07 15 True 32767 0\ 32767} {a07 16 True 32768 0 32768} {a07 17 True 65535 0 65535} {a07 18 True\ 65536 0 65536} {a07 19 True 2147483647 0 2147483647} {a07 20 False 2147483648 0\ -2147483648} {a07 21 False 4294967295 0 -1} {a07 22 False 4294967296 0 0} {a07\ 23 False 9223372036854775807 0 -1} {a07 24 False 9223372036854775808 0 0} {a07\ 25 False 18446744073709551615 0 0} {a07 26 False 18446744073709551616 0 0} {a08\ 0 False -9223372036854775809 0 0} {a08 1 False -9223372036854775808 0 0} {a08 2\ False -2147483649 0 -1} {a08 3 False -2147483648 0 0} {a08 4 False -32769 0 -1}\ {a08 5 False -32768 0 0} {a08 6 False -129 0 127} {a08 7 True -128 0 -128} {a08\ 8 True -1 0 -1} {a08 9 True 0 0 0} {a08 10 True 1 0 1} {a08 11 True 127 0 127}\ {a08 12 False 128 0 -128} {a08 13 False 255 0 -1} {a08 14 False 256 0 0} {a08\ 15 False 32767 0 -1} {a08 16 False 32768 0 0} {a08 17 False 65535 0 -1} {a08 18\ False 65536 0 0} {a08 19 False 2147483647 0 -1} {a08 20 False 2147483648 0 0}\ {a08 21 False 4294967295 0 -1} {a08 22 False 4294967296 0 0} {a08 23 False\ 9223372036854775807 0 -1} {a08 24 False 9223372036854775808 0 0} {a08 25 False\ 18446744073709551615 0 0} {a08 26 False 18446744073709551616 0 0} {a09 0 False\ -9223372036854775809 0 0} {a09 1 False -9223372036854775808 0 0} {a09 2 False\ -2147483649 0 -1} {a09 3 False -2147483648 0 0} {a09 4 False -32769 0 32767}\ {a09 5 True -32768 0 -32768} {a09 6 True -129 0 -129} {a09 7 True -128 0 -128}\ {a09 8 True -1 0 -1} {a09 9 True 0 0 0} {a09 10 True 1 0 1} {a09 11 True 127 0\ 127} {a09 12 True 128 0 128} {a09 13 True 255 0 255} {a09 14 True 256 0 256}\ {a09 15 True 32767 0 32767} {a09 16 False 32768 0 -32768} {a09 17 False 65535 0\ -1} {a09 18 False 65536 0 0} {a09 19 False 2147483647 0 -1} {a09 20 False\ 2147483648 0 0} {a09 21 False 4294967295 0 -1} {a09 22 False 4294967296 0 0}\ {a09 23 False 9223372036854775807 0 -1} {a09 24 False 9223372036854775808 0 0}\ {a09 25 False 18446744073709551615 0 0} {a09 26 False 18446744073709551616 0 0}\ {a10 0 False -9223372036854775809 0 0} {a10 1 False -9223372036854775808 0 0}\ {a10 2 False -2147483649 0 2147483647} {a10 3 True -2147483648 0 -2147483648}\ {a10 4 True -32769 0 -32769} {a10 5 True -32768 0 -32768} {a10 6 True -129 0\ -129} {a10 7 True -128 0 -128} {a10 8 True -1 0 -1} {a10 9 True 0 0 0} {a10 10\ True 1 0 1} {a10 11 True 127 0 127} {a10 12 True 128 0 128} {a10 13 True 255 0\ 255} {a10 14 True 256 0 256} {a10 15 True 32767 0 32767} {a10 16 True 32768 0\ 32768} {a10 17 True 65535 0 65535} {a10 18 True 65536 0 65536} {a10 19 True\ 2147483647 0 2147483647} {a10 20 False 2147483648 0 -2147483648} {a10 21 False\ 4294967295 0 -1} {a10 22 False 4294967296 0 0} {a10 23 False\ 9223372036854775807 0 -1} {a10 24 False 9223372036854775808 0 0} {a10 25 False\ 18446744073709551615 0 0} {a10 26 False 18446744073709551616 0 0} {a11 0 False\ -9223372036854775809 0 -9223372036854775808} {a11 1 True -9223372036854775808 0\ -9223372036854775808} {a11 2 True -2147483649 0 -2147483649} {a11 3 True\ -2147483648 0 -2147483648} {a11 4 True -32769 0 -32769} {a11 5 True -32768 0\ -32768} {a11 6 True -129 0 -129} {a11 7 True -128 0 -128} {a11 8 True -1 0 -1}\ {a11 9 True 0 0 0} {a11 10 True 1 0 1} {a11 11 True 127 0 127} {a11 12 True 128\ 0 128} {a11 13 True 255 0 255} {a11 14 True 256 0 256} {a11 15 True 32767 0\ 32767} {a11 16 True 32768 0 32768} {a11 17 True 65535 0 65535} {a11 18 True\ 65536 0 65536} {a11 19 True 2147483647 0 2147483647} {a11 20 True 2147483648 0\ 2147483648} {a11 21 True 4294967295 0 4294967295} {a11 22 True 4294967296 0\ 4294967296} {a11 23 True 9223372036854775807 0 9223372036854775807} {a11 24\ False 9223372036854775808 0 -9223372036854775808} {a11 25 False\ 18446744073709551615 0 -9223372036854775808} {a11 26 False 18446744073709551616\ 0 -9223372036854775808} {a12 0 False -9223372036854775809 0\ -9223372036854775808} {a12 1 True -9223372036854775808 0 -9223372036854775808}\ {a12 2 True -2147483649 0 -2147483649} {a12 3 True -2147483648 0 -2147483648}\ {a12 4 True -32769 0 -32769} {a12 5 True -32768 0 -32768} {a12 6 True -129 0\ -129} {a12 7 True -128 0 -128} {a12 8 True -1 0 -1} {a12 9 True 0 0 0} {a12 10\ True 1 0 1} {a12 11 True 127 0 127} {a12 12 True 128 0 128} {a12 13 True 255 0\ 255} {a12 14 True 256 0 256} {a12 15 True 32767 0 32767} {a12 16 True 32768 0\ 32768} {a12 17 True 65535 0 65535} {a12 18 True 65536 0 65536} {a12 19 True\ 2147483647 0 2147483647} {a12 20 True 2147483648 0 2147483648} {a12 21 True\ 4294967295 0 4294967295} {a12 22 True 4294967296 0 4294967296} {a12 23 True\ 9223372036854775807 0 9223372036854775807} {a12 24 False 9223372036854775808 0\ -9223372036854775808} {a12 25 False 18446744073709551615 0\ -9223372036854775808} {a12 26 False 18446744073709551616 0\ -9223372036854775808} {a13 0 False -9223372036854775809 0 0} {a13 1 False\ -9223372036854775808 0 0} {a13 2 False -2147483649 0 -1} {a13 3 False\ -2147483648 0 0} {a13 4 False -32769 0 -1} {a13 5 False -32768 0 0} {a13 6\ False -129 0 127} {a13 7 True -128 0 -128} {a13 8 True -1 0 -1} {a13 9 True 0 0\ 0} {a13 10 True 1 0 1} {a13 11 True 127 0 127} {a13 12 False 128 0 -128} {a13\ 13 False 255 0 -1} {a13 14 False 256 0 0} {a13 15 False 32767 0 -1} {a13 16\ False 32768 0 0} {a13 17 False 65535 0 -1} {a13 18 False 65536 0 0} {a13 19\ False 2147483647 0 -1} {a13 20 False 2147483648 0 0} {a13 21 False 4294967295 0\ -1} {a13 22 False 4294967296 0 0} {a13 23 False 9223372036854775807 0 -1} {a13\ 24 False 9223372036854775808 0 0} {a13 25 False 18446744073709551615 0 0} {a13\ 26 False 18446744073709551616 0 0} {a14 0 False -9223372036854775809 0 0} {a14\ 1 False -9223372036854775808 0 0} {a14 2 False -2147483649 0 -1} {a14 3 False\ -2147483648 0 0} {a14 4 False -32769 0 32767} {a14 5 True -32768 0 -32768} {a14\ 6 True -129 0 -129} {a14 7 True -128 0 -128} {a14 8 True -1 0 -1} {a14 9 True 0\ 0 0} {a14 10 True 1 0 1} {a14 11 True 127 0 127} {a14 12 True 128 0 128} {a14\ 13 True 255 0 255} {a14 14 True 256 0 256} {a14 15 True 32767 0 32767} {a14 16\ False 32768 0 -32768} {a14 17 False 65535 0 -1} {a14 18 False 65536 0 0} {a14\ 19 False 2147483647 0 -1} {a14 20 False 2147483648 0 0} {a14 21 False\ 4294967295 0 -1} {a14 22 False 4294967296 0 0} {a14 23 False\ 9223372036854775807 0 -1} {a14 24 False 9223372036854775808 0 0} {a14 25 False\ 18446744073709551615 0 0} {a14 26 False 18446744073709551616 0 0} {a15 0 False\ -9223372036854775809 0 0} {a15 1 False -9223372036854775808 0 0} {a15 2 False\ -2147483649 0 2147483647} {a15 3 True -2147483648 0 -2147483648} {a15 4 True\ -32769 0 -32769} {a15 5 True -32768 0 -32768} {a15 6 True -129 0 -129} {a15 7\ True -128 0 -128} {a15 8 True -1 0 -1} {a15 9 True 0 0 0} {a15 10 True 1 0 1}\ {a15 11 True 127 0 127} {a15 12 True 128 0 128} {a15 13 True 255 0 255} {a15 14\ True 256 0 256} {a15 15 True 32767 0 32767} {a15 16 True 32768 0 32768} {a15 17\ True 65535 0 65535} {a15 18 True 65536 0 65536} {a15 19 True 2147483647 0\ 2147483647} {a15 20 False 2147483648 0 -2147483648} {a15 21 False 4294967295 0\ -1} {a15 22 False 4294967296 0 0} {a15 23 False 9223372036854775807 0 -1} {a15\ 24 False 9223372036854775808 0 0} {a15 25 False 18446744073709551615 0 0} {a15\ 26 False 18446744073709551616 0 0} {a16 0 False -9223372036854775809 0\ -9223372036854775808} {a16 1 True -9223372036854775808 0 -9223372036854775808}\ {a16 2 True -2147483649 0 -2147483649} {a16 3 True -2147483648 0 -2147483648}\ {a16 4 True -32769 0 -32769} {a16 5 True -32768 0 -32768} {a16 6 True -129 0\ -129} {a16 7 True -128 0 -128} {a16 8 True -1 0 -1} {a16 9 True 0 0 0} {a16 10\ True 1 0 1} {a16 11 True 127 0 127} {a16 12 True 128 0 128} {a16 13 True 255 0\ 255} {a16 14 True 256 0 256} {a16 15 True 32767 0 32767} {a16 16 True 32768 0\ 32768} {a16 17 True 65535 0 65535} {a16 18 True 65536 0 65536} {a16 19 True\ 2147483647 0 2147483647} {a16 20 True 2147483648 0 2147483648} {a16 21 True\ 4294967295 0 4294967295} {a16 22 True 4294967296 0 4294967296} {a16 23 True\ 9223372036854775807 0 9223372036854775807} {a16 24 False 9223372036854775808 0\ -9223372036854775808} {a16 25 False 18446744073709551615 0\ -9223372036854775808} {a16 26 False 18446744073709551616 0\ -9223372036854775808} {a17 0 False -9223372036854775809 0 -9223372036854775808}\ {a17 1 True -9223372036854775808 0 -9223372036854775808} {a17 2 True\ -2147483649 0 -2147483649} {a17 3 True -2147483648 0 -2147483648} {a17 4 True\ -32769 0 -32769} {a17 5 True -32768 0 -32768} {a17 6 True -129 0 -129} {a17 7\ True -128 0 -128} {a17 8 True -1 0 -1} {a17 9 True 0 0 0} {a17 10 True 1 0 1}\ {a17 11 True 127 0 127} {a17 12 True 128 0 128} {a17 13 True 255 0 255} {a17 14\ True 256 0 256} {a17 15 True 32767 0 32767} {a17 16 True 32768 0 32768} {a17 17\ True 65535 0 65535} {a17 18 True 65536 0 65536} {a17 19 True 2147483647 0\ 2147483647} {a17 20 True 2147483648 0 2147483648} {a17 21 True 4294967295 0\ 4294967295} {a17 22 True 4294967296 0 4294967296} {a17 23 True\ 9223372036854775807 0 9223372036854775807} {a17 24 False 9223372036854775808 0\ -9223372036854775808} {a17 25 False 18446744073709551615 0\ -9223372036854775808} {a17 26 False 18446744073709551616 0\ -9223372036854775808} {a18 0 False -9223372036854775809 0 0} {a18 1 False\ -9223372036854775808 0 0} {a18 2 False -2147483649 0 -1} {a18 3 False\ -2147483648 0 0} {a18 4 False -32769 0 32767} {a18 5 True -32768 0 -32768} {a18\ 6 True -129 0 -129} {a18 7 True -128 0 -128} {a18 8 True -1 0 -1} {a18 9 True 0\ 0 0} {a18 10 True 1 0 1} {a18 11 True 127 0 127} {a18 12 True 128 0 128} {a18\ 13 True 255 0 255} {a18 14 True 256 0 256} {a18 15 True 32767 0 32767} {a18 16\ False 32768 0 -32768} {a18 17 False 65535 0 -1} {a18 18 False 65536 0 0} {a18\ 19 False 2147483647 0 -1} {a18 20 False 2147483648 0 0} {a18 21 False\ 4294967295 0 -1} {a18 22 False 4294967296 0 0} {a18 23 False\ 9223372036854775807 0 -1} {a18 24 False 9223372036854775808 0 0} {a18 25 False\ 18446744073709551615 0 0} {a18 26 False 18446744073709551616 0 0} {a19 0 False\ -9223372036854775809 0 0} {a19 1 False -9223372036854775808 0 0} {a19 2 False\ -2147483649 0 65535} {a19 3 False -2147483648 0 0} {a19 4 False -32769 0 32767}\ {a19 5 False -32768 0 32768} {a19 6 False -129 0 65407} {a19 7 False -128 0\ 65408} {a19 8 False -1 0 65535} {a19 9 True 0 0 0} {a19 10 True 1 0 1} {a19 11\ True 127 0 127} {a19 12 True 128 0 128} {a19 13 True 255 0 255} {a19 14 True\ 256 0 256} {a19 15 True 32767 0 32767} {a19 16 True 32768 0 32768} {a19 17 True\ 65535 0 65535} {a19 18 False 65536 0 0} {a19 19 False 2147483647 0 65535} {a19\ 20 False 2147483648 0 0} {a19 21 False 4294967295 0 65535} {a19 22 False\ 4294967296 0 0} {a19 23 False 9223372036854775807 0 65535} {a19 24 False\ 9223372036854775808 0 0} {a19 25 False 18446744073709551615 0 0} {a19 26 False\ 18446744073709551616 0 0} {a20 0 False -9223372036854775809 0 0} {a20 1 False\ -9223372036854775808 0 0} {a20 2 False -2147483649 0 255} {a20 3 False\ -2147483648 0 0} {a20 4 False -32769 0 255} {a20 5 False -32768 0 0} {a20 6\ False -129 0 127} {a20 7 False -128 0 128} {a20 8 False -1 0 255} {a20 9 True 0\ 0 0} {a20 10 True 1 0 1} {a20 11 True 127 0 127} {a20 12 True 128 0 128} {a20\ 13 True 255 0 255} {a20 14 False 256 0 0} {a20 15 False 32767 0 255} {a20 16\ False 32768 0 0} {a20 17 False 65535 0 255} {a20 18 False 65536 0 0} {a20 19\ False 2147483647 0 255} {a20 20 False 2147483648 0 0} {a20 21 False 4294967295\ 0 255} {a20 22 False 4294967296 0 0} {a20 23 False 9223372036854775807 0 255}\ {a20 24 False 9223372036854775808 0 0} {a20 25 False 18446744073709551615 0 0}\ {a20 26 False 18446744073709551616 0 0} {a21 0 False -9223372036854775809 0 0}\ {a21 1 False -9223372036854775808 0 0} {a21 2 False -2147483649 0 -1} {a21 3\ False -2147483648 0 0} {a21 4 False -32769 0 -1} {a21 5 False -32768 0 0} {a21\ 6 False -129 0 127} {a21 7 True -128 0 -128} {a21 8 True -1 0 -1} {a21 9 True 0\ 0 0} {a21 10 True 1 0 1} {a21 11 True 127 0 127} {a21 12 False 128 0 -128} {a21\ 13 False 255 0 -1} {a21 14 False 256 0 0} {a21 15 False 32767 0 -1} {a21 16\ False 32768 0 0} {a21 17 False 65535 0 -1} {a21 18 False 65536 0 0} {a21 19\ False 2147483647 0 -1} {a21 20 False 2147483648 0 0} {a21 21 False 4294967295 0\ -1} {a21 22 False 4294967296 0 0} {a21 23 False 9223372036854775807 0 -1} {a21\ 24 False 9223372036854775808 0 0} {a21 25 False 18446744073709551615 0 0} {a21\ 26 False 18446744073709551616 0 0} {a22 0 False -9223372036854775809 0 0} {a22\ 1 False -9223372036854775808 0 0} {a22 2 False -2147483649 0 2147483647} {a22 3\ False -2147483648 0 2147483648} {a22 4 False -32769 0 4294934527} {a22 5 False\ -32768 0 4294934528} {a22 6 False -129 0 4294967167} {a22 7 False -128 0\ 4294967168} {a22 8 False -1 0 4294967295} {a22 9 True 0 0 0} {a22 10 True 1 0\ 1} {a22 11 True 127 0 127} {a22 12 True 128 0 128} {a22 13 True 255 0 255} {a22\ 14 True 256 0 256} {a22 15 True 32767 0 32767} {a22 16 True 32768 0 32768} {a22\ 17 True 65535 0 65535} {a22 18 True 65536 0 65536} {a22 19 True 2147483647 0\ 2147483647} {a22 20 True 2147483648 0 2147483648} {a22 21 True 4294967295 0\ 4294967295} {a22 22 False 4294967296 0 0} {a22 23 False 9223372036854775807 0\ 4294967295} {a22 24 False 9223372036854775808 0 0} {a22 25 False\ 18446744073709551615 0 0} {a22 26 False 18446744073709551616 0 0} {a23 0 False\ -9223372036854775809 0 0} {a23 1 False -9223372036854775808 0 0} {a23 2 False\ -2147483649 0 255} {a23 3 False -2147483648 0 0} {a23 4 False -32769 0 255}\ {a23 5 False -32768 0 0} {a23 6 False -129 0 127} {a23 7 False -128 0 128} {a23\ 8 False -1 0 255} {a23 9 True 0 0 0} {a23 10 True 1 0 1} {a23 11 True 127 0\ 127} {a23 12 True 128 0 128} {a23 13 True 255 0 255} {a23 14 False 256 0 0}\ {a23 15 False 32767 0 255} {a23 16 False 32768 0 0} {a23 17 False 65535 0 255}\ {a23 18 False 65536 0 0} {a23 19 False 2147483647 0 255} {a23 20 False\ 2147483648 0 0} {a23 21 False 4294967295 0 255} {a23 22 False 4294967296 0 0}\ {a23 23 False 9223372036854775807 0 255} {a23 24 False 9223372036854775808 0 0}\ {a23 25 False 18446744073709551615 0 0} {a23 26 False 18446744073709551616 0 0}\ {a24 0 False -9223372036854775809 0 0} {a24 1 False -9223372036854775808 0 0}\ {a24 2 False -2147483649 0 65535} {a24 3 False -2147483648 0 0} {a24 4 False\ -32769 0 32767} {a24 5 False -32768 0 32768} {a24 6 False -129 0 65407} {a24 7\ False -128 0 65408} {a24 8 False -1 0 65535} {a24 9 True 0 0 0} {a24 10 True 1\ 0 1} {a24 11 True 127 0 127} {a24 12 True 128 0 128} {a24 13 True 255 0 255}\ {a24 14 True 256 0 256} {a24 15 True 32767 0 32767} {a24 16 True 32768 0 32768}\ {a24 17 True 65535 0 65535} {a24 18 False 65536 0 0} {a24 19 False 2147483647 0\ 65535} {a24 20 False 2147483648 0 0} {a24 21 False 4294967295 0 65535} {a24 22\ False 4294967296 0 0} {a24 23 False 9223372036854775807 0 65535} {a24 24 False\ 9223372036854775808 0 0} {a24 25 False 18446744073709551615 0 0} {a24 26 False\ 18446744073709551616 0 0} {a25 0 False -9223372036854775809 0 0} {a25 1 False\ -9223372036854775808 0 0} {a25 2 False -2147483649 0 2147483647} {a25 3 False\ -2147483648 0 2147483648} {a25 4 False -32769 0 4294934527} {a25 5 False -32768\ 0 4294934528} {a25 6 False -129 0 4294967167} {a25 7 False -128 0 4294967168}\ {a25 8 False -1 0 4294967295} {a25 9 True 0 0 0} {a25 10 True 1 0 1} {a25 11\ True 127 0 127} {a25 12 True 128 0 128} {a25 13 True 255 0 255} {a25 14 True\ 256 0 256} {a25 15 True 32767 0 32767} {a25 16 True 32768 0 32768} {a25 17 True\ 65535 0 65535} {a25 18 True 65536 0 65536} {a25 19 True 2147483647 0\ 2147483647} {a25 20 True 2147483648 0 2147483648} {a25 21 True 4294967295 0\ 4294967295} {a25 22 False 4294967296 0 0} {a25 23 False 9223372036854775807 0\ 4294967295} {a25 24 False 9223372036854775808 0 0} {a25 25 False\ 18446744073709551615 0 0} {a25 26 False 18446744073709551616 0 0} {a26 0 False\ -9223372036854775809 0 9223372036854775808} {a26 1 False -9223372036854775808 0\ 9223372036854775808} {a26 2 False -2147483649 0 18446744071562067967} {a26 3\ False -2147483648 0 18446744071562067968} {a26 4 False -32769 0\ 18446744073709518847} {a26 5 False -32768 0 18446744073709518848} {a26 6 False\ -129 0 18446744073709551487} {a26 7 False -128 0 18446744073709551488} {a26 8\ False -1 0 18446744073709551615} {a26 9 True 0 0 0} {a26 10 True 1 0 1} {a26 11\ True 127 0 127} {a26 12 True 128 0 128} {a26 13 True 255 0 255} {a26 14 True\ 256 0 256} {a26 15 True 32767 0 32767} {a26 16 True 32768 0 32768} {a26 17 True\ 65535 0 65535} {a26 18 True 65536 0 65536} {a26 19 True 2147483647 0\ 2147483647} {a26 20 True 2147483648 0 2147483648} {a26 21 True 4294967295 0\ 4294967295} {a26 22 True 4294967296 0 4294967296} {a26 23 True\ 9223372036854775807 0 9223372036854775807} {a26 24 True 9223372036854775808 0\ 9223372036854775808} {a26 25 False 18446744073709551615 0 9223372036854775808}\ {a26 26 False 18446744073709551616 0 9223372036854775808} {a27 0 False\ -9223372036854775809 0 9223372036854775808} {a27 1 False -9223372036854775808 0\ 9223372036854775808} {a27 2 False -2147483649 0 18446744071562067967} {a27 3\ False -2147483648 0 18446744071562067968} {a27 4 False -32769 0\ 18446744073709518847} {a27 5 False -32768 0 18446744073709518848} {a27 6 False\ -129 0 18446744073709551487} {a27 7 False -128 0 18446744073709551488} {a27 8\ False -1 0 18446744073709551615} {a27 9 True 0 0 0} {a27 10 True 1 0 1} {a27 11\ True 127 0 127} {a27 12 True 128 0 128} {a27 13 True 255 0 255} {a27 14 True\ 256 0 256} {a27 15 True 32767 0 32767} {a27 16 True 32768 0 32768} {a27 17 True\ 65535 0 65535} {a27 18 True 65536 0 65536} {a27 19 True 2147483647 0\ 2147483647} {a27 20 True 2147483648 0 2147483648} {a27 21 True 4294967295 0\ 4294967295} {a27 22 True 4294967296 0 4294967296} {a27 23 True\ 9223372036854775807 0 9223372036854775807} {a27 24 True 9223372036854775808 0\ 9223372036854775808} {a27 25 False 18446744073709551615 0 9223372036854775808}\ {a27 26 False 18446744073709551616 0 9223372036854775808} {a28 0 False\ -9223372036854775809 0 9223372036854775808} {a28 1 False -9223372036854775808 0\ 9223372036854775808} {a28 2 False -2147483649 0 18446744071562067967} {a28 3\ False -2147483648 0 18446744071562067968} {a28 4 False -32769 0\ 18446744073709518847} {a28 5 False -32768 0 18446744073709518848} {a28 6 False\ -129 0 18446744073709551487} {a28 7 False -128 0 18446744073709551488} {a28 8\ False -1 0 18446744073709551615} {a28 9 True 0 0 0} {a28 10 True 1 0 1} {a28 11\ True 127 0 127} {a28 12 True 128 0 128} {a28 13 True 255 0 255} {a28 14 True\ 256 0 256} {a28 15 True 32767 0 32767} {a28 16 True 32768 0 32768} {a28 17 True\ 65535 0 65535} {a28 18 True 65536 0 65536} {a28 19 True 2147483647 0\ 2147483647} {a28 20 True 2147483648 0 2147483648} {a28 21 True 4294967295 0\ 4294967295} {a28 22 True 4294967296 0 4294967296} {a28 23 True\ 9223372036854775807 0 9223372036854775807} {a28 24 True 9223372036854775808 0\ 9223372036854775808} {a28 25 False 18446744073709551615 0 9223372036854775808}\ {a28 26 False 18446744073709551616 0 9223372036854775808} {a29 0 False\ -9223372036854775809 0 0} {a29 1 False -9223372036854775808 0 0} {a29 2 False\ -2147483649 0 255} {a29 3 False -2147483648 0 0} {a29 4 False -32769 0 255}\ {a29 5 False -32768 0 0} {a29 6 False -129 0 127} {a29 7 False -128 0 128} {a29\ 8 False -1 0 255} {a29 9 True 0 0 0} {a29 10 True 1 0 1} {a29 11 True 127 0\ 127} {a29 12 True 128 0 128} {a29 13 True 255 0 255} {a29 14 False 256 0 0}\ {a29 15 False 32767 0 255} {a29 16 False 32768 0 0} {a29 17 False 65535 0 255}\ {a29 18 False 65536 0 0} {a29 19 False 2147483647 0 255} {a29 20 False\ 2147483648 0 0} {a29 21 False 4294967295 0 255} {a29 22 False 4294967296 0 0}\ {a29 23 False 9223372036854775807 0 255} {a29 24 False 9223372036854775808 0 0}\ {a29 25 False 18446744073709551615 0 0} {a29 26 False 18446744073709551616 0 0}\ {a30 0 False -9223372036854775809 0 0} {a30 1 False -9223372036854775808 0 0}\ {a30 2 False -2147483649 0 65535} {a30 3 False -2147483648 0 0} {a30 4 False\ -32769 0 32767} {a30 5 False -32768 0 32768} {a30 6 False -129 0 65407} {a30 7\ False -128 0 65408} {a30 8 False -1 0 65535} {a30 9 True 0 0 0} {a30 10 True 1\ 0 1} {a30 11 True 127 0 127} {a30 12 True 128 0 128} {a30 13 True 255 0 255}\ {a30 14 True 256 0 256} {a30 15 True 32767 0 32767} {a30 16 True 32768 0 32768}\ {a30 17 True 65535 0 65535} {a30 18 False 65536 0 0} {a30 19 False 2147483647 0\ 65535} {a30 20 False 2147483648 0 0} {a30 21 False 4294967295 0 65535} {a30 22\ False 4294967296 0 0} {a30 23 False 9223372036854775807 0 65535} {a30 24 False\ 9223372036854775808 0 0} {a30 25 False 18446744073709551615 0 0} {a30 26 False\ 18446744073709551616 0 0} {a31 0 False -9223372036854775809 0 0} {a31 1 False\ -9223372036854775808 0 0} {a31 2 False -2147483649 0 2147483647} {a31 3 False\ -2147483648 0 2147483648} {a31 4 False -32769 0 4294934527} {a31 5 False -32768\ 0 4294934528} {a31 6 False -129 0 4294967167} {a31 7 False -128 0 4294967168}\ {a31 8 False -1 0 4294967295} {a31 9 True 0 0 0} {a31 10 True 1 0 1} {a31 11\ True 127 0 127} {a31 12 True 128 0 128} {a31 13 True 255 0 255} {a31 14 True\ 256 0 256} {a31 15 True 32767 0 32767} {a31 16 True 32768 0 32768} {a31 17 True\ 65535 0 65535} {a31 18 True 65536 0 65536} {a31 19 True 2147483647 0\ 2147483647} {a31 20 True 2147483648 0 2147483648} {a31 21 True 4294967295 0\ 4294967295} {a31 22 False 4294967296 0 0} {a31 23 False 9223372036854775807 0\ 4294967295} {a31 24 False 9223372036854775808 0 0} {a31 25 False\ 18446744073709551615 0 0} {a31 26 False 18446744073709551616 0 0} {a32 0 False\ -9223372036854775809 0 9223372036854775808} {a32 1 False -9223372036854775808 0\ 9223372036854775808} {a32 2 False -2147483649 0 18446744071562067967} {a32 3\ False -2147483648 0 18446744071562067968} {a32 4 False -32769 0\ 18446744073709518847} {a32 5 False -32768 0 18446744073709518848} {a32 6 False\ -129 0 18446744073709551487} {a32 7 False -128 0 18446744073709551488} {a32 8\ False -1 0 18446744073709551615} {a32 9 True 0 0 0} {a32 10 True 1 0 1} {a32 11\ True 127 0 127} {a32 12 True 128 0 128} {a32 13 True 255 0 255} {a32 14 True\ 256 0 256} {a32 15 True 32767 0 32767} {a32 16 True 32768 0 32768} {a32 17 True\ 65535 0 65535} {a32 18 True 65536 0 65536} {a32 19 True 2147483647 0\ 2147483647} {a32 20 True 2147483648 0 2147483648} {a32 21 True 4294967295 0\ 4294967295} {a32 22 True 4294967296 0 4294967296} {a32 23 True\ 9223372036854775807 0 9223372036854775807} {a32 24 True 9223372036854775808 0\ 9223372036854775808} {a32 25 False 18446744073709551615 0 9223372036854775808}\ {a32 26 False 18446744073709551616 0 9223372036854775808}}} ############################################################################### runTest {test tkt-c010fa6584-1.2 {UInt32 parameter} -setup { setupDb [set fileName tkt-c010fa6584-1.2.db] } -body { sql execute $db "CREATE TABLE t1(x UINT32);" sql execute $db "INSERT INTO t1 (x) VALUES(?);" \ [list param1 UInt32 0xFFFFFFFF] sql execute -execute scalar $db "SELECT x FROM t1;" } -cleanup { cleanupDb $fileName unset -nocomplain db fileName } -constraints \ {eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} -result \ {4294967295}} ############################################################################### runTest {test tkt-c010fa6584-1.3 {UInt32 parameter (Int64)} -setup { setupDb [set fileName tkt-c010fa6584-1.3.db] } -body { sql execute $db "CREATE TABLE t1(x INTEGER);" sql execute $db "INSERT INTO t1 (x) VALUES(?);" \ [list param1 UInt32 0xFFFFFFFF] sql execute -execute scalar $db "SELECT x FROM t1;" } -cleanup { cleanupDb $fileName unset -nocomplain db fileName } -constraints \ {eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} -result \ {-1}} ############################################################################### runTest {test tkt-c010fa6584-1.4 {UInt32 parameter (Int64) w/flag} -setup { setupDb [set fileName tkt-c010fa6584-1.4.db] "" "" "" BindUInt32AsInt64 } -body { sql execute $db "CREATE TABLE t1(x INTEGER);" sql execute $db "INSERT INTO t1 (x) VALUES(?);" \ [list param1 UInt32 0xFFFFFFFF] sql execute -execute scalar $db "SELECT x FROM t1;" } -cleanup { cleanupDb $fileName unset -nocomplain db fileName } -constraints \ {eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} -result \ {4294967295}} ############################################################################### runSQLiteTestEpilogue runTestEpilogue |
Added Tests/tkt-e06c4caff3.eagle.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 | ############################################################################### # # tkt-e06c4caff3.eagle -- # # Written by Joe Mistachkin. # Released to the public domain, use at your own risk! # ############################################################################### package require Eagle package require Eagle.Library package require Eagle.Test runTestPrologue ############################################################################### package require System.Data.SQLite.Test runSQLiteTestPrologue ############################################################################### runTest {test tkt-e06c4caff3-1.1 {NaN to NULL constraint failure} -setup { setupDb [set fileName tkt-e06c4caff3-1.1.db] } -body { sql execute $db "CREATE TABLE t1(x REAL NOT NULL);" sql execute $db "INSERT INTO t1 (x) VALUES(?);" \ [list param1 Double [set NaN [object invoke Double NaN]]] } -cleanup { cleanupDb $fileName unset -nocomplain NaN db fileName } -constraints \ {eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} \ -returnCodes 1 -match regexp -result [string map [list \n \r\n]\ {^System\.Data\.SQLite\.SQLiteException \(0x80004005\): constraint failed t1\.x may not be NULL .*$}]} ############################################################################### runTest {test tkt-e06c4caff3-1.2 {NaN to NULL} -setup { setupDb [set fileName tkt-e06c4caff3-1.2.db] } -body { sql execute $db "CREATE TABLE t1(x REAL);" sql execute $db "INSERT INTO t1 (x) VALUES(?);" \ [list param1 Double [set NaN [object invoke Double NaN]]] sql execute -execute reader -format list $db "SELECT x FROM t1;" } -cleanup { cleanupDb $fileName unset -nocomplain NaN db fileName } -constraints \ {eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} \ -result {}} ############################################################################### runTest {test tkt-e06c4caff3-1.3 {NaN w/BindAllAsText} -setup { setupDb [set fileName tkt-e06c4caff3-1.3.db] "" "" "" BindAllAsText } -body { sql execute $db "CREATE TABLE t1(x REAL NOT NULL);" list [sql execute $db "INSERT INTO t1 (x) VALUES(?);" \ [list param1 Double [set NaN [object invoke Double NaN]]]] \ [sql execute -execute reader -format list $db "SELECT x FROM t1;"] } -cleanup { cleanupDb $fileName unset -nocomplain NaN db fileName } -constraints \ {eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} -result \ {1 0}} ############################################################################### runTest {test tkt-e06c4caff3-1.4 {NaN w/BindAllAsText & GetAllAsText} -setup { setupDb [set fileName tkt-e06c4caff3-1.4.db] "" "" "" BindAndGetAllAsText } -body { sql execute $db "CREATE TABLE t1(x REAL NOT NULL);" list [sql execute $db "INSERT INTO t1 (x) VALUES(?);" \ [list param1 Double [set NaN [object invoke Double NaN]]]] \ [sql execute -execute reader -format list $db "SELECT x FROM t1;"] } -cleanup { cleanupDb $fileName unset -nocomplain NaN db fileName } -constraints \ {eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} -result \ {1 NaN}} ############################################################################### runSQLiteTestEpilogue runTestEpilogue |
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) 85; # NOTE: Incremented with each release. set version(revision) 0 ############################################################################### # ********************* END VOLATILE VERSION INFORMATION ********************** ############################################################################### # |
︙ | ︙ | |||
173 174 175 176 177 178 179 180 181 182 183 184 185 186 | [appendArgs <version> [string map [list . \\.] $version(full)] \ </version>] \ [appendArgs <version> [string map [list . \\.] $version(full)] \ </version>] \ [appendArgs <version> [string map [list . \\.] $version(full)] \ </version>] \ [appendArgs <version> [string map [list . \\.] $version(full)] \ </version>] \ [appendArgs Version= [string map [list . \\.] $version(full)] ,] \ [appendArgs "\; [format %03d $version(build)] "\;] \ [appendArgs AssemblyVersion\\(\" [string map [list . \\.] \ $version(full)] \"\\)] \ [appendArgs AssemblyFileVersion\\(\" [string map [list . \\.] \ $version(full)] \"\\)] \ | > > | 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 | [appendArgs <version> [string map [list . \\.] $version(full)] \ </version>] \ [appendArgs <version> [string map [list . \\.] $version(full)] \ </version>] \ [appendArgs <version> [string map [list . \\.] $version(full)] \ </version>] \ [appendArgs <version> [string map [list . \\.] $version(full)] \ </version>] \ [appendArgs <version> [string map [list . \\.] $version(full)] \ </version>] \ [appendArgs Version= [string map [list . \\.] $version(full)] ,] \ [appendArgs "\; [format %03d $version(build)] "\;] \ [appendArgs AssemblyVersion\\(\" [string map [list . \\.] \ $version(full)] \"\\)] \ [appendArgs AssemblyFileVersion\\(\" [string map [list . \\.] \ $version(full)] \"\\)] \ |
︙ | ︙ | |||
239 240 241 242 243 244 245 246 247 248 249 250 251 252 | $version(full)] \"\\)] \ [appendArgs AssemblyFileVersion\\(\" [string map [list . \\.] \ $version(full)] \"\\)]] set fileNames [list \ readme.htm \ SQLite.nuspec \ SQLite.MSIL.nuspec \ SQLite.x64.nuspec \ SQLite.x86.nuspec \ [file join Doc Extra dbfactorysupport.html] \ [file join Doc Extra welcome.html] \ [file join Membership Properties AssemblyInfo.cs] \ [file join Membership Properties AssemblyInfo.cs] \ | > | 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 | $version(full)] \"\\)] \ [appendArgs AssemblyFileVersion\\(\" [string map [list . \\.] \ $version(full)] \"\\)]] set fileNames [list \ readme.htm \ SQLite.nuspec \ SQLite.Beta.nuspec \ SQLite.MSIL.nuspec \ SQLite.x64.nuspec \ SQLite.x86.nuspec \ [file join Doc Extra dbfactorysupport.html] \ [file join Doc Extra welcome.html] \ [file join Membership Properties AssemblyInfo.cs] \ [file join Membership Properties AssemblyInfo.cs] \ |
︙ | ︙ |
Changes to 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.85.0 March XX, 2013 <font color="red">(release scheduled)</font><br /> Using <a href="http://www.sqlite.org/src/info/66d5f2b767">SQLite 3.7.16</a><br /> Originally written by Robert Simpson<br /> Released to the public domain, use at your own risk!<br /> Official provider website: <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/2012. 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.85.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. |
︙ | ︙ | |||
182 183 184 185 186 187 188 189 190 191 192 193 194 195 | at the sqlite.org website. Several additional pieces are compiled on top of it to extend its functionality, but the core engine's source is not changed.</p> <p> </p> <h2><b>Version History</b></h2> <p> <b>1.0.84.0 - January 9, 2013</b> </p> <ul> <li>Updated to <a href="http://www.sqlite.org/releaselog/3_7_15_2.html">SQLite 3.7.15.2</a>.</li> <li>Explicitly dispose of all SQLiteCommand objects managed by the DbDataAdapter class. Fix for [6434e23a0f].</li> <li>Add Cancel method to the SQLiteConnection class to interrupt a long running query.</li> | > > > > > > > > > > > > > > > > > > > > > > > > > | 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 | at the sqlite.org website. Several additional pieces are compiled on top of it to extend its functionality, but the core engine's source is not changed.</p> <p> </p> <h2><b>Version History</b></h2> <p> <b>1.0.85.0 - March XX, 2013 <font color="red">(release scheduled)</font></b> </p> <ul> <li>Updated to <a href="http://www.sqlite.org/src/info/66d5f2b767">SQLite 3.7.16</a>.</li> <li>Properly handle embedded NUL characters in parameter and column values. Fix for [3567020edf].</li> <li>Make use of the sqlite3_prepare_v2 function when applicable.</li> <li>Check for a valid row in the SQLiteDataReader.GetValue method.</li> <li>Implement processor architecture detection when running on the .NET Compact Framework (via P/Invoke).</li> <li>Support automated testing when running on the .NET Compact Framework 2.0.</li> <li>Skip checking loaded assemblies for types tagged with the SQLiteFunction attribute when the No_SQLiteFunctions environment variable is set. Pursuant to [e4c8121f7b].</li> <li>Add HexPassword connection string property to work around the inability to include a literal semicolon in a connection string property value. Pursuant to [1c456ae75f].</li> <li>Add static Execute method to the SQLiteCommand class.</li> <li>Support custom connection pool implementations by adding the ISQLiteConnectionPool interface, the static SQLiteConnection.ConnectionPool property, and the static CreateHandle method in addition to modifying the SQLiteConnectionPool class. Pursuant to [393d954be0].</li> <li>Add public constructor to the SQLiteDataAdapter class that allows passing the parseViaFramework parameter to the SQLiteConnection constructor.</li> <li>When built with the CHECK_STATE compile-time option, skip throwing exceptions from the SQLiteDataReader class when the object is being disposed.</li> <li>Support automatic value conversions for columns with a declared type of BIGUINT, INTEGER8, INTEGER16, INTEGER32, INTEGER64, SMALLUINT, TINYSINT, UNSIGNEDINTEGER, UNSIGNEDINTEGER8, UNSIGNEDINTEGER16, UNSIGNEDINTEGER32, UNSIGNEDINTEGER64, INT8, INT16, INT32, INT64, UINT, UINT8, UINT16, UINT32, UINT64, or ULONG.</li> <li>Add BindUInt32AsInt64 connection flag to force binding of UInt32 values as Int64 instead. Pursuant to [c010fa6584].</li> <li>Add BindAllAsText and GetAllAsText connection flags to force binding and returning of all values as text.</li> <li>Remove AUTOINCREMENT from the column type name map. <b>** Potentially Incompatible Change **</b></li> <li>Avoid throwing overflow exceptions from the SQLite3.GetValue method for integral column types. Partial fix for [c010fa6584]. <b>** Potentially Incompatible Change **</b></li> <li>Use the legacy connection closing algorithm when built with the INTEROP_LEGACY_CLOSE compile-time option.</li> <li>Support using the directory containing the primary managed-only assembly as the basis for native library pre-loading.</li> <li>Still further enhancements to the build and test automation.</li> </ul> <p> <b>1.0.84.0 - January 9, 2013</b> </p> <ul> <li>Updated to <a href="http://www.sqlite.org/releaselog/3_7_15_2.html">SQLite 3.7.15.2</a>.</li> <li>Explicitly dispose of all SQLiteCommand objects managed by the DbDataAdapter class. Fix for [6434e23a0f].</li> <li>Add Cancel method to the SQLiteConnection class to interrupt a long running query.</li> |
︙ | ︙ |
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.85.0")] [assembly: AssemblyFileVersion("1.0.85.0")] |
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.85.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139" /> </DbProviderFactories> </system.data> </configuration> |
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.85.0")] // [assembly: AssemblyFileVersion("1.0.85.0")] |
Changes to testce/Program.cs.
︙ | ︙ | |||
30 31 32 33 34 35 36 | 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) | > | > | 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | bool autoClose = false; int exitCode = 2; /* INCOMPLETE */ Assembly assembly = Assembly.GetExecutingAssembly(); AssemblyName assemblyName = assembly.GetName(); string directory = Path.GetDirectoryName(assemblyName.CodeBase); if (args.Length > 0) { try { autoClose = bool.Parse(args[0]); } catch { } } try { File.Delete(directory + "\\test.db"); } catch { } SQLiteFunction.RegisterFunction(typeof(TestFunc)); SQLiteFunction.RegisterFunction(typeof(MyCount)); SQLiteFunction.RegisterFunction(typeof(MySequence)); |
︙ | ︙ |
Changes to testlinq/2008/App.config.
1 2 3 4 5 | <?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.85.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139" /> </DbProviderFactories> </system.data> <connectionStrings> <add name="northwindEFEntities" connectionString="metadata=res://*/NorthwindModel2008.csdl|res://*/NorthwindModel2008.ssdl|res://*/NorthwindModel2008.msl;provider=System.Data.SQLite;provider connection string="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.85.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139" /> </DbProviderFactories> </system.data> <connectionStrings> <add name="northwindEFEntities" connectionString="metadata=res://*/NorthwindModel2010.csdl|res://*/NorthwindModel2010.ssdl|res://*/NorthwindModel2010.msl;provider=System.Data.SQLite;provider connection string="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.85.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139" /> </DbProviderFactories> </system.data> <connectionStrings> <add name="northwindEFEntities" connectionString="metadata=res://*/NorthwindModel2012.csdl|res://*/NorthwindModel2012.ssdl|res://*/NorthwindModel2012.msl;provider=System.Data.SQLite;provider connection string="data source=.\northwindEF.db"" providerName="System.Data.EntityClient" /> </connectionStrings> </configuration> |
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.85.0")] [assembly: AssemblyFileVersion("1.0.85.0")] |
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.85.0")] [assembly: AssemblyFileVersion("1.0.85.0")] |
Changes to www/build.wiki.
︙ | ︙ | |||
120 121 122 123 124 125 126 127 128 129 130 131 132 133 | <li> Make sure the version information is correct for System.Data.SQLite in the following files: <ul> <li><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> | > | 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 | <li> Make sure the version information is correct for System.Data.SQLite in the following files: <ul> <li><root>\readme.htm</li> <li><root>\SQLite.nuspec</li> <li><root>\SQLite.Beta.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/downloads.wiki.
︙ | ︙ | |||
547 548 549 550 551 552 553 | (7.82 MiB) </td> <td width="5"></td> <td valign="top"> This setup package features the mixed-mode assembly and will install all the necessary runtime components and dependencies for the x86 version of the System.Data.SQLite 1.0.84.0 (3.7.15.2) package. The Visual C++ 2012 | | | | 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 | (7.82 MiB) </td> <td width="5"></td> <td valign="top"> This setup package features the mixed-mode assembly and will install all the necessary runtime components and dependencies for the x86 version of the System.Data.SQLite 1.0.84.0 (3.7.15.2) package. The Visual C++ 2012 RTM runtime for x86 is included. The .NET Framework 4.5 is required. <br /> <big><b>This setup package is capable of installing the design-time components for Visual Studio 2012.</b></big> <br /> (sha1: 6954e6ee073a5965fbac99408e485bf68c1d35cf) </td> </tr> <tr> <td width="10"> </td> <td width="30%" valign="top" align="right"> <a href="/downloads/1.0.84.0/sqlite-netFx45-setup-x86-2012-1.0.84.0.exe">sqlite-netFx45-setup-x86-2012-1.0.84.0.exe</a> <br /> (7.85 MiB) </td> <td width="5"></td> <td valign="top"> This setup package will install all the necessary runtime components and dependencies for the x86 version of the System.Data.SQLite 1.0.84.0 (3.7.15.2) package. The Visual C++ 2012 RTM runtime for x86 is included. The .NET Framework 4.5 is required. <br /> (sha1: 6406842a3d916f2977f75ab5c6975debc232ce76) </td> </tr> <tr> |
︙ | ︙ | |||
592 593 594 595 596 597 598 | (8.45 MiB) </td> <td width="5"></td> <td valign="top"> This setup package features the mixed-mode assembly and will install all the necessary runtime components and dependencies for the x64 version of the System.Data.SQLite 1.0.84.0 (3.7.15.2) package. The Visual C++ 2012 | | | | 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 | (8.45 MiB) </td> <td width="5"></td> <td valign="top"> This setup package features the mixed-mode assembly and will install all the necessary runtime components and dependencies for the x64 version of the System.Data.SQLite 1.0.84.0 (3.7.15.2) package. The Visual C++ 2012 RTM runtime for x64 is included. The .NET Framework 4.5 is required. <br /> (sha1: 4ee62f74e45fd40ccaecbfe685fb6d08792c0cde) </td> </tr> <tr> <td width="10"> </td> <td width="30%" valign="top" align="right"> <a href="/downloads/1.0.84.0/sqlite-netFx45-setup-x64-2012-1.0.84.0.exe">sqlite-netFx45-setup-x64-2012-1.0.84.0.exe</a> <br /> (8.50 MiB) </td> <td width="5"></td> <td valign="top"> This setup package will install all the necessary runtime components and dependencies for the x64 version of the System.Data.SQLite 1.0.84.0 (3.7.15.2) package. The Visual C++ 2012 RTM runtime for x64 is included. The .NET Framework 4.5 is required. <br /> (sha1: 0e24f71a7f2bcdb74bbd7afd807dafeafc64a81e) </td> </tr> <tr> |
︙ | ︙ | |||
879 880 881 882 883 884 885 | <br /> (1.66 MiB) </td> <td width="5"></td> <td valign="top"> This binary package features the mixed-mode assembly and contains all the binaries for the x86 version of the System.Data.SQLite 1.0.84.0 | | | | 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 | <br /> (1.66 MiB) </td> <td width="5"></td> <td valign="top"> This binary package features the mixed-mode assembly and contains all the binaries for the x86 version of the System.Data.SQLite 1.0.84.0 (3.7.15.2) package. The Visual C++ 2012 RTM runtime for x86 and the .NET Framework 4.5 are required. <br /> (sha1: 0dc8d3533375f8589c85d29d3270912666ef61e4) </td> </tr> <tr> <td width="10"> </td> <td width="30%" valign="top" align="right"> <a href="/downloads/1.0.84.0/sqlite-netFx45-binary-Win32-2012-1.0.84.0.zip">sqlite-netFx45-binary-Win32-2012-1.0.84.0.zip</a> <br /> (1.70 MiB) </td> <td width="5"></td> <td valign="top"> This binary package contains all the binaries for the x86 version of the System.Data.SQLite 1.0.84.0 (3.7.15.2) package. The Visual C++ 2012 RTM runtime for x86 and the .NET Framework 4.5 are required. <br /> (sha1: 1d88fdb25802d6b6ad34d7fa2da2da7003a49e53) </td> </tr> <tr> |
︙ | ︙ | |||
920 921 922 923 924 925 926 | <br /> (1.69 MiB) </td> <td width="5"></td> <td valign="top"> This binary package features the mixed-mode assembly and contains all the binaries for the x64 version of the System.Data.SQLite 1.0.84.0 | | | | 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 | <br /> (1.69 MiB) </td> <td width="5"></td> <td valign="top"> This binary package features the mixed-mode assembly and contains all the binaries for the x64 version of the System.Data.SQLite 1.0.84.0 (3.7.15.2) package. The Visual C++ 2012 RTM runtime for x64 and the .NET Framework 4.5 are required. <br /> (sha1: 33e865f0214fef3def4de4f18462832f9788ade4) </td> </tr> <tr> <td width="10"> </td> <td width="30%" valign="top" align="right"> <a href="/downloads/1.0.84.0/sqlite-netFx45-binary-x64-2012-1.0.84.0.zip">sqlite-netFx45-binary-x64-2012-1.0.84.0.zip</a> <br /> (1.75 MiB) </td> <td width="5"></td> <td valign="top"> This binary package contains all the binaries for the x64 version of the System.Data.SQLite 1.0.84.0 (3.7.15.2) package. The Visual C++ 2012 RTM runtime for x64 and the .NET Framework 4.5 are required. <br /> (sha1: a3970b48c78ecbf9fb92553d52f2af5cbfe01e25) </td> </tr> <tr> |
︙ | ︙ | |||
1213 1214 1215 1216 1217 1218 1219 | <br /> (1.98 MiB) </td> <td width="5"></td> <td valign="top"> This binary package features the mixed-mode assembly and contains all the binaries for the x86 version of the System.Data.SQLite 1.0.84.0 | | | | 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 | <br /> (1.98 MiB) </td> <td width="5"></td> <td valign="top"> This binary package features the mixed-mode assembly and contains all the binaries for the x86 version of the System.Data.SQLite 1.0.84.0 (3.7.15.2) package. The Visual C++ 2012 RTM runtime for x86 is statically linked. The .NET Framework 4.5 is required. <br /> (sha1: 24a13024db3ef732cde9f128b43dcb0a9802dcdd) </td> </tr> <tr> <td width="10"> </td> <td width="30%" valign="top" align="right"> <a href="/downloads/1.0.84.0/sqlite-netFx45-static-binary-Win32-2012-1.0.84.0.zip">sqlite-netFx45-static-binary-Win32-2012-1.0.84.0.zip</a> <br /> (2.03 MiB) </td> <td width="5"></td> <td valign="top"> This binary package contains all the binaries for the x86 version of the System.Data.SQLite 1.0.84.0 (3.7.15.2) package. The Visual C++ 2012 RTM runtime for x86 is statically linked. The .NET Framework 4.5 is required. <br /> (sha1: 40f7633bbe527802f13cb653dc13354d871e4bb7) </td> </tr> |
︙ | ︙ | |||
1255 1256 1257 1258 1259 1260 1261 | <br /> (1.94 MiB) </td> <td width="5"></td> <td valign="top"> This binary package features the mixed-mode assembly and contains all the binaries for the x64 version of the System.Data.SQLite 1.0.84.0 | | | | 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 | <br /> (1.94 MiB) </td> <td width="5"></td> <td valign="top"> This binary package features the mixed-mode assembly and contains all the binaries for the x64 version of the System.Data.SQLite 1.0.84.0 (3.7.15.2) package. The Visual C++ 2012 RTM runtime for x64 is statically linked. The .NET Framework 4.5 is required. <br /> (sha1: b41daf0cd84393651a8a68a6149dbd0193cdd838) </td> </tr> <tr> <td width="10"> </td> <td width="30%" valign="top" align="right"> <a href="/downloads/1.0.84.0/sqlite-netFx45-static-binary-x64-2012-1.0.84.0.zip">sqlite-netFx45-static-binary-x64-2012-1.0.84.0.zip</a> <br /> (2.01 MiB) </td> <td width="5"></td> <td valign="top"> This binary package contains all the binaries for the x64 version of the System.Data.SQLite 1.0.84.0 (3.7.15.2) package. The Visual C++ 2012 RTM runtime for x64 is statically linked. The .NET Framework 4.5 is required. <br /> (sha1: 3516de01e430fbcda5625b8b52b76efd0a260875) </td> </tr> |
︙ | ︙ |
Changes to www/faq.wiki.
︙ | ︙ | |||
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> | > > > > > > | 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 | <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> <br> <li> <a href="#q21">Is this behavior a bug? <b>-OR-</b> Is there a quick way to view the various lists of tickets for the System.Data.SQLite project? </a> </li> </ol> <hr> <a name="q1"></a> <p> <b>(1) When will the next version of System.Data.SQLite be released?</b> </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> | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 | 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> <hr> <a name="q21"></a> <p> <b>(21) Is this behavior a bug? -OR- Is there a quick way to view the various lists of tickets for the System.Data.SQLite project?</b> </p> <p> If any behavior is observed that appears to be a bug, it may be reported via the <a href="/index.html/doc/trunk/www/support.wiki">sqlite-users</a> public mailing list or by filing a <a href="/index.html/tktnew">ticket</a>. Prior to taking one of these steps, it is always prudent to check the various lists of previously filed tickets to see if the behavior being observed has already been reported and possibly fixed in a subsequent release. <ol> <li><a href="/index.html/rptview?rn=6"> The list of tickets actively being worked on. </a></li> <li><a href="/index.html/rptview?rn=2"> The list of tickets currently open. </a></li> <li><a href="/index.html/rptview?rn=4"> The list of tickets fixed and then closed. </a></li> <li><a href="/index.html/rptview?rn=7"> The list of tickets closed without needing a fix. </a></li> </ol> </p> |
Changes to www/news.wiki.
1 2 3 4 5 6 7 8 | <title>News</title> <b>Version History</b> <p> <b>1.0.84.0 - January 9, 2013</b> </p> <ul> | > > > > > > > > > > > > > > > > > > > > > > > > > | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | <title>News</title> <b>Version History</b> <p> <b>1.0.85.0 - March XX, 2013 <font color="red">(release scheduled)</font></b> </p> <ul> <li>Updated to [http://www.sqlite.org/src/info/66d5f2b767|SQLite 3.7.16].</li> <li>Properly handle embedded NUL characters in parameter and column values. Fix for [3567020edf].</li> <li>Make use of the sqlite3_prepare_v2 function when applicable.</li> <li>Check for a valid row in the SQLiteDataReader.GetValue method.</li> <li>Implement processor architecture detection when running on the .NET Compact Framework (via P/Invoke).</li> <li>Support automated testing when running on the .NET Compact Framework 2.0.</li> <li>Skip checking loaded assemblies for types tagged with the SQLiteFunction attribute when the No_SQLiteFunctions environment variable is set. Pursuant to [e4c8121f7b].</li> <li>Add HexPassword connection string property to work around the inability to include a literal semicolon in a connection string property value. Pursuant to [1c456ae75f].</li> <li>Add static Execute method to the SQLiteCommand class.</li> <li>Support custom connection pool implementations by adding the ISQLiteConnectionPool interface, the static SQLiteConnection.ConnectionPool property, and the static CreateHandle method in addition to modifying the SQLiteConnectionPool class. Pursuant to [393d954be0].</li> <li>Add public constructor to the SQLiteDataAdapter class that allows passing the parseViaFramework parameter to the SQLiteConnection constructor.</li> <li>When built with the CHECK_STATE compile-time option, skip throwing exceptions from the SQLiteDataReader class when the object is being disposed.</li> <li>Support automatic value conversions for columns with a declared type of BIGUINT, INTEGER8, INTEGER16, INTEGER32, INTEGER64, SMALLUINT, TINYSINT, UNSIGNEDINTEGER, UNSIGNEDINTEGER8, UNSIGNEDINTEGER16, UNSIGNEDINTEGER32, UNSIGNEDINTEGER64, INT8, INT16, INT32, INT64, UINT, UINT8, UINT16, UINT32, UINT64, or ULONG.</li> <li>Add BindUInt32AsInt64 connection flag to force binding of UInt32 values as Int64 instead. Pursuant to [c010fa6584].</li> <li>Add BindAllAsText and GetAllAsText connection flags to force binding and returning of all values as text.</li> <li>Remove AUTOINCREMENT from the column type name map. <b>** Potentially Incompatible Change **</b></li> <li>Avoid throwing overflow exceptions from the SQLite3.GetValue method for integral column types. Partial fix for [c010fa6584]. <b>** Potentially Incompatible Change **</b></li> <li>Use the legacy connection closing algorithm when built with the INTEROP_LEGACY_CLOSE compile-time option.</li> <li>Support using the directory containing the primary managed-only assembly as the basis for native library pre-loading.</li> <li>Still further enhancements to the build and test automation.</li> </ul> <p> <b>1.0.84.0 - January 9, 2013</b> </p> <ul> <li>Updated to [http://www.sqlite.org/releaselog/3_7_15_2.html|SQLite 3.7.15.2].</li> <li>Explicitly dispose of all SQLiteCommand objects managed by the DbDataAdapter class. Fix for [6434e23a0f].</li> <li>Add Cancel method to the SQLiteConnection class to interrupt a long running query.</li> <li>Improve thread safety of the SQLiteLog.LogMessage method.</li> </ul> <p> <b>1.0.83.0 - December 29, 2012</b> </p> |
︙ | ︙ |
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 performed in the order specified. </p> <a name="assumptions"></a> <h2>Assumptions & Prerequisites</h2> <p> The string "<b><root></b>" represents the directory where the local working copy of the source tree (a.k.a. the working check-out directory) for the System.Data.SQLite project is to reside. This should be a completely empty directory. </p> <p> The string "<b><repositories></b>" represents the directory where the local clone of the repository for the System.Data.SQLite project (and potentially other projects) is to reside. </p> <a name="fossil"></a> <h2>Obtain & Install Fossil Itself</h2> <p> The [http://www.fossil-scm.org | Fossil] open-source [http://en.wikipedia.org/wiki/Distributed_revision_control | distributed version control] system is a computer program that must be installed on your machine before you use it. Fortunately, installing Fossil is very easy. Fossil consists of a single executable file that you simply download and run. For convenience, the Fossil |
︙ | ︙ | |||
51 52 53 54 55 56 57 | 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> Please note that the repository itself uses an [http://www.fossil-scm.org/index.html/doc/trunk/www/fileformat.wiki | enduring file format] stored in a single [http://www.fossil-scm.org/index.html/doc/trunk/www/tech_overview.wiki | SQLite database file] with a particular schema. </li> <li> |
︙ | ︙ | |||
84 85 86 87 88 89 90 | 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 the working copy is located: <b>fossil [http://www.fossil-scm.org/index.html/help/update | update]</b> </li> </ol> |