From 50420545fc572f1ac633d38ed36c90f5be253aca Mon Sep 17 00:00:00 2001 From: mistachkin Date: Thu, 20 Jun 2013 18:53:33 +0000 Subject: [PATCH 001/101] VSIX tooling changes to support Visual Studio 2013. FossilOrigin-Name: c5954c58c043fed24471fa184048e4ea0b5ba1d6 --- manifest | 21 ++++++++++++--------- manifest.uuid | 2 +- tool/build-all-msvc.bat | 19 ++++++++++++++++--- tool/mkvsix.tcl | 14 ++++++++++++++ tool/win/sqlite.vsix | Bin 32816 -> 32819 bytes 5 files changed, 43 insertions(+), 13 deletions(-) diff --git a/manifest b/manifest index 4b1070228c..1d5979a7b6 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Disable\sposix_fallocate()\sfor\sall\ssystems,\sall\sthe\stime,\sunless\sthe\nHAVE_POSIX_FALLOCATE\scompile-time\smacro\sis\ssupplied. -D 2013-06-20T14:07:37.671 +C VSIX\stooling\schanges\sto\ssupport\sVisual\sStudio\s2013. +D 2013-06-20T18:53:33.003 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5e41da95d92656a5004b03d3576e8b226858a28e F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -1048,7 +1048,7 @@ F test/wherelimit.test 5e9fd41e79bb2b2d588ed999d641d9c965619b31 F test/win32lock.test 7a6bd73a5dcdee39b5bb93e92395e1773a194361 F test/zeroblob.test caaecfb4f908f7bc086ed238668049f96774d688 F test/zerodamage.test 209d7ed441f44cc5299e4ebffbef06fd5aabfefd -F tool/build-all-msvc.bat c55f64ca200308fb5fa5c1ee751ea95a13977b5a x +F tool/build-all-msvc.bat 38623a30fd58288fda5cc7f7df2682aaab75c9d5 x F tool/build-shell.sh 950f47c6174f1eea171319438b93ba67ff5bf367 F tool/checkSpacing.c 810e51703529a204fc4e1eb060e9ab663e3c06d2 F tool/diffdb.c 7524b1b5df217c20cd0431f6789851a4e0cb191b @@ -1067,7 +1067,7 @@ F tool/mksqlite3c-noext.tcl 8bce31074e4cbe631bb7676526a048335f4c9f02 F tool/mksqlite3c.tcl a61fe62a2895ca6458c463fccf1211ca1c000fcf F tool/mksqlite3h.tcl ba24038056f51fde07c0079c41885ab85e2cff12 F tool/mksqlite3internalh.tcl 3dca7bb5374cee003379b8cbac73714f610ef795 -F tool/mkvsix.tcl 0be7f7a591f1e83f9199cb82911b66668ca484c9 +F tool/mkvsix.tcl b28d7e1dbce2e69ff2cf2043ff363b08939f3178 F tool/offsets.c fe4262fdfa378e8f5499a42136d17bf3b98f6091 F tool/omittest.tcl 4665982e95a6e5c1bd806cf7bc3dea95be422d77 F tool/opcodeDoc.awk b3a2a3d5d3075b8bd90b7afe24283efdd586659c @@ -1092,8 +1092,11 @@ F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06 F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 -F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac -P 2b2ade92788be623af6f57e37d98994be2cec142 -R 4c8df645fee7190a620dee659859568b -U drh -Z 4cfe85260540c90b4ee0898bd7491d71 +F tool/win/sqlite.vsix ff59777ec70801730169ae1b576f4fd0f320c30a +P b674462243138fcee192ef05d434665e30c681c4 +R c7ac56de3bf31222ff450ec13703ae2c +T *branch * vsix2013 +T *sym-vsix2013 * +T -sym-trunk * +U mistachkin +Z 23c3e117a2a1cdf9be8d5e81d565dca9 diff --git a/manifest.uuid b/manifest.uuid index 225d72de72..5172b8e972 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -b674462243138fcee192ef05d434665e30c681c4 \ No newline at end of file +c5954c58c043fed24471fa184048e4ea0b5ba1d6 \ No newline at end of file diff --git a/tool/build-all-msvc.bat b/tool/build-all-msvc.bat index c433435779..ed05f959fe 100755 --- a/tool/build-all-msvc.bat +++ b/tool/build-all-msvc.bat @@ -203,8 +203,8 @@ SET TOOLPATH=%gawk.exe_PATH%;%tclsh85.exe_PATH% %_VECHO% ToolPath = '%TOOLPATH%' REM -REM NOTE: Check for MSVC 2012 because the Windows SDK directory handling is -REM slightly different for that version. +REM NOTE: Check for MSVC 2012/2013 because the Windows SDK directory handling +REM is slightly different for those versions. REM IF "%VisualStudioVersion%" == "11.0" ( REM @@ -214,6 +214,14 @@ IF "%VisualStudioVersion%" == "11.0" ( IF NOT DEFINED NSDKLIBPATH ( SET SET_NSDKLIBPATH=1 ) +) ELSE IF "%VisualStudioVersion%" == "12.0" ( + REM + REM NOTE: If the Windows SDK library path has already been set, do not set + REM it to something else later on. + REM + IF NOT DEFINED NSDKLIBPATH ( + SET SET_NSDKLIBPATH=1 + ) ) ELSE ( CALL :fn_UnsetVariable SET_NSDKLIBPATH ) @@ -351,7 +359,12 @@ FOR %%P IN (%PLATFORMS%) DO ( CALL :fn_AppendVariable NSDKLIBPATH \lib\x86 ) ELSE IF DEFINED WindowsSdkDir ( CALL :fn_CopyVariable WindowsSdkDir NSDKLIBPATH - CALL :fn_AppendVariable NSDKLIBPATH \lib\win8\um\x86 + + IF "%VisualStudioVersion%" == "12.0" ( + CALL :fn_AppendVariable NSDKLIBPATH \lib\winv6.3\um\x86 + ) ELSE ( + CALL :fn_AppendVariable NSDKLIBPATH \lib\win8\um\x86 + ) ) ) diff --git a/tool/mkvsix.tcl b/tool/mkvsix.tcl index e9f1f818da..2de4d77bae 100644 --- a/tool/mkvsix.tcl +++ b/tool/mkvsix.tcl @@ -255,14 +255,28 @@ if {[string equal -nocase $packageFlavor WinRT]} then { set shortName SQLite.WinRT set displayName "SQLite for Windows Runtime" set targetPlatformIdentifier Windows + set targetPlatformVersion v8.0 + set minVsVersion 11.0 set extraSdkPath "" set extraFileListAttributes [appendArgs \ "\r\n " {AppliesTo="WindowsAppContainer"} \ "\r\n " {DependsOn="Microsoft.VCLibs, version=11.0"}] +} elseif {[string equal -nocase $packageFlavor WinRT81]} then { + set shortName SQLite.WinRT81 + set displayName "SQLite for Windows Runtime (Windows 8.1)" + set targetPlatformIdentifier Windows + set targetPlatformVersion v8.1 + set minVsVersion 12.0 + set extraSdkPath "" + set extraFileListAttributes [appendArgs \ + "\r\n " {AppliesTo="WindowsAppContainer"} \ + "\r\n " {DependsOn="Microsoft.VCLibs, version=12.0"}] } elseif {[string equal -nocase $packageFlavor WP80]} then { set shortName SQLite.WP80 set displayName "SQLite for Windows Phone" set targetPlatformIdentifier "Windows Phone" + set targetPlatformVersion v8.0 + set minVsVersion 11.0 set extraSdkPath "\\..\\$targetPlatformIdentifier" set extraFileListAttributes "" } else { diff --git a/tool/win/sqlite.vsix b/tool/win/sqlite.vsix index 93eefac2dbbd9da8a901fc215cc94629002b5723..99c7f35f4e19a2df1aa08392fc86089bba993eca 100644 GIT binary patch delta 977 zcmV;?11|iqfC96C0X1LYu9ZYDEG70KSvM0xo|zI0g!ID1tRbwxqih#h}=< ztyPvhiTPX6cOMnSN!B(OTm1bFB)v6Pg_+u>up78VOvq+61DBniKSnkM;~!@ae0~KpFaU)V zoFnB559Ra~-Xf7Q^^~L|EN>U8#C$iO)oPXcKbnh9t*b?83!gUB>P);3+IRc|H8SSC zCG;l}x#*&8EgpYcW#G|wY=pytuh|6o6gOaxn8 zWO1~~0o{0#T5qQb*IGaDz?m!L7MQ@aupMvgt+sQiBN5(&%%rQ4wj>zu`Sf*7+#p-0 zH{TM7E)({ztZO50DupiagHG69--aD=iat0paKN;D4jlN8jZys}A;s=Gj=PDfYwwZb zZS@k&HXWXBaU!W1CVcFlpp>7S1H?XICf+<%tosMECI#She^Xu5LVEjd_22*i089Y@ z01p5F08>OuO<`_nW@U49E_iKhRgg_f!$1&*?}h${W$D#KZ=zjGK?{Nvq0ozZh{>cG z*)L~jO-1tG-H^t%dwbxSecze+VsEtg1`6n`l2_TK6ktnNq1`DNxxToTVsST}%vY%4 z2?I|jBE5SIe_j_q&xHXcXTQ}EJ2@CHTmsxYYkz0f$~Q)}%A9&PQEY?%E`p0{nA zg)fZ^nWJ4kYG}8c?a;FS$0QC1?h?bEsTdnBnF&84L+FO-P4qtHhIQ18Uc+H9DEUC- zNS;|xEval$e#wy_Ij^4%t(c|#xOQav_CdVezRUh91^F17;19C}d*1>L!d%oso2{2> zMFIc-zLW8NHwQZqnM>tu&XX^GI{_t=YkpY)Vw1&wTmdMPB7Z&~Q(e?Tdi!qm-~a#s zOaTA@4*(Bv|YVu(wy?PTKzXm4Rt_0tSx-a!y4Gqk4v!|;1 zC;bcia#!7TH29LX5y&pUBqL5!YcEN!A>vzOWiDHy_fQ4TsiYL zT`?vuxLGeZC9l_5b@|Rr7f0=&Wvbd?dBt+IN3I@ynrigx2cyDlf#k*>>yxJ+H<@_f zJG4VWExlfUo!PYa8y8+*(#-!V)TZjG?5nJo-7;!R&daB9`b_6mjrA>?ac19LPqiJL zswQ@ZXEvwY;l`q}8SIRr6$TvJ zw>Y>v?D}LG6#sDHoOOqylcw#OWf-;WQJE&U)Z6Eq| z`32THC+BQgJhAKl6!SUtoqIRkUvekD`^)?-S3}jBZp>UZEo{=Y$H(-~t>|_7VzsU0 zUh$ec8qy(^e8OeJQCBhd*)kWlCWmC1`|b#Pb&&r~aqHVjLNlH&`zl?%`V3R3 z%Awg4EN^vHxHoy8U#>6xjkoIcn`hZf7gJyT^-i9BVs_9Z-aik7w_V?!XuCYjaz4}I z^rOW$zSqy(9=zY%Ze#x69iLY0D(kbj=c9hG=JutRWy?-{HTZb^-A>QHpNkq^2&X+d zyZK3JJ>zCo)(0i^uACu`dK;4*?=UbhI5ILY@B`^!7jNIhyv(%J;u5`z+?>z}j^2kI z1X|y>{%cQtan&V%QSZ_PtOvUSUbxyGNx9UMQ+DlUWbnj)<=d}>SZ`;)Kl^*yvdy{a zXVtwF%2;Dko+n%gjhTE~L}07sZWiO+lKsoLH~nyMJgz+X*|etm?N6^K-%Mnj{Qj5! zy9W+7oYyyAa=kgxwrFAM#s60(vA&Nz%(`XOKdtk>_nkk~u6nd5buz!i&aYXuIWx1C zrS1sTY>z4qUATRPL>c>Ot*ZHl4jDzM=6}2{%e6x|u~C@o_0Eu7uC*pyYR`VoJvr0U z%1e4$UcBXu>950Y>{pU^n*4*6F~FOdW%9myiOnk2htc!bms)dn2K!grq}H9CY*c5> zs5UvTE|M{M@`<__M$O5p^>!|p!KVTYKoC#>;y;xbfyo7yU|?WmkYG5#s2Vg2X!P=W QYev?|kL$hIxNAUK0b~Zrvj6}9 From 9894742beb7633046581777862e62f2ae9e63fdf Mon Sep 17 00:00:00 2001 From: mistachkin Date: Thu, 20 Jun 2013 19:07:58 +0000 Subject: [PATCH 002/101] Use the target platorm version in the VS props file as well. FossilOrigin-Name: ce5a8cc1cf663546ebdce08bef7d957ed4d341c6 --- manifest | 15 ++++++--------- manifest.uuid | 2 +- tool/win/sqlite.vsix | Bin 32819 -> 32825 bytes 3 files changed, 7 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index 1d5979a7b6..ddd91a5c6e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C VSIX\stooling\schanges\sto\ssupport\sVisual\sStudio\s2013. -D 2013-06-20T18:53:33.003 +C Use\sthe\starget\splatorm\sversion\sin\sthe\sVS\sprops\sfile\sas\swell. +D 2013-06-20T19:07:58.086 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5e41da95d92656a5004b03d3576e8b226858a28e F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -1092,11 +1092,8 @@ F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06 F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 -F tool/win/sqlite.vsix ff59777ec70801730169ae1b576f4fd0f320c30a -P b674462243138fcee192ef05d434665e30c681c4 -R c7ac56de3bf31222ff450ec13703ae2c -T *branch * vsix2013 -T *sym-vsix2013 * -T -sym-trunk * +F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff +P c5954c58c043fed24471fa184048e4ea0b5ba1d6 +R 7752ef9980936689becf7e3beb7b8742 U mistachkin -Z 23c3e117a2a1cdf9be8d5e81d565dca9 +Z 3aee8dea98fb53abe6ab78ab5ec0f41a diff --git a/manifest.uuid b/manifest.uuid index 5172b8e972..5e6ac03230 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -c5954c58c043fed24471fa184048e4ea0b5ba1d6 \ No newline at end of file +ce5a8cc1cf663546ebdce08bef7d957ed4d341c6 \ No newline at end of file diff --git a/tool/win/sqlite.vsix b/tool/win/sqlite.vsix index 99c7f35f4e19a2df1aa08392fc86089bba993eca..ac4afb3f4bc2aa7c4419376732e5a7b3910d1070 100644 GIT binary patch delta 560 zcmV-00?+-kfC9OI0+6*4=U~)A;p3DiwE+MChXeosG?9TSk?;+F#Z*me+dvS#7y2KB zaB&2!)@?4OkrYbQme3N69eUc!S{g}P?}xfOa&1EYdsZ7cc0kD`gxqHK&CYvocBJHd zD@CvYW4Tso_%WV^0jNTkT-9mVVfEp2c%Hp|lgy3&0|f@IT-h{i5Zf<=*rEZ+Y%FXzLs*l}$+ZWnK8@zH&{k6?~VGfqp>Y7WS^g>Ii)dLrlUP0$L#hDXzq%lg!QMNbn zi?0kbyH_>gc*mY2^2na!+A~JIsX_B#YRC?z4$rl005Ipa6>QgQ$d2{A4-R?~^4OKf zcj6L3=1_4w<#*2mhoP#qkA3#FyjxEua%e%7?!)I`Gy7L?gwt5?)!Dm~@giq$9N06F zfvOM31tnzor?~hQP)h>@li__Bv&aIOdJX4b)I#Colqa21!F y%6&TlvXcgWX8|jdZhlz-Xp_i(TmdeVC4XE30eX{ze_sI(ljDC%1{8b%0000%Fbp67 delta 551 zcmV+?0@(ezfC96C0+6*4K!;aB{6X)(uK@r6UjzUEG?9TSk?;+Fy;Mz4+dvS#SL%OQ zS*e1h)|-|KDz;ID+X{gYN;vLiV~_16`(bv+Ara!gvo=NvlHr2jHnVU1-kaI+#wQyk z$r`K^Mkm3~XciFAxhaIMlAy)%$5C*Se*F?(S#tw95?`)e64Z#zZ%SQWgW@hyBDcnw z5~JKGTEH5lX~0r{<(93G1^qRf9R{9;5Kq)0xczTU+w@1>AWbQQMHz%cSC$u z2<&}L+2r5_7*0u&km)o?Gg!7&Ovf1B%idFeti&87a0gyw4#>3#S4Gj$0u7TY(ENTGEgli<1G@n->Qx{2*`MNR?YPXK0bTeXT7XO4trQ4{krd10ZwKQ=zP)kaS&0r(T{vzi zro&s|<43cy0=0S#K!;aB{6X)(uK@r6Uz2owRR3>QF4txLr004C813CZz From 463f348f2ca660446da64b9abe842da22f59e432 Mon Sep 17 00:00:00 2001 From: mistachkin Date: Fri, 21 Jun 2013 07:54:39 +0000 Subject: [PATCH 003/101] Update comments and package flavor error message. FossilOrigin-Name: 9d1b96182af08a73de9dd0327965b96a6d48ac11 --- manifest | 12 ++++++------ manifest.uuid | 2 +- tool/mkvsix.tcl | 14 +++++++------- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/manifest b/manifest index ddd91a5c6e..dd4ae69898 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Use\sthe\starget\splatorm\sversion\sin\sthe\sVS\sprops\sfile\sas\swell. -D 2013-06-20T19:07:58.086 +C Update\scomments\sand\spackage\sflavor\serror\smessage. +D 2013-06-21T07:54:39.197 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5e41da95d92656a5004b03d3576e8b226858a28e F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -1067,7 +1067,7 @@ F tool/mksqlite3c-noext.tcl 8bce31074e4cbe631bb7676526a048335f4c9f02 F tool/mksqlite3c.tcl a61fe62a2895ca6458c463fccf1211ca1c000fcf F tool/mksqlite3h.tcl ba24038056f51fde07c0079c41885ab85e2cff12 F tool/mksqlite3internalh.tcl 3dca7bb5374cee003379b8cbac73714f610ef795 -F tool/mkvsix.tcl b28d7e1dbce2e69ff2cf2043ff363b08939f3178 +F tool/mkvsix.tcl f3312df26fd9938a27fa0a845ec96bea84b0c16b F tool/offsets.c fe4262fdfa378e8f5499a42136d17bf3b98f6091 F tool/omittest.tcl 4665982e95a6e5c1bd806cf7bc3dea95be422d77 F tool/opcodeDoc.awk b3a2a3d5d3075b8bd90b7afe24283efdd586659c @@ -1093,7 +1093,7 @@ F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P c5954c58c043fed24471fa184048e4ea0b5ba1d6 -R 7752ef9980936689becf7e3beb7b8742 +P ce5a8cc1cf663546ebdce08bef7d957ed4d341c6 +R 94b717d64d889391ffc6225632038588 U mistachkin -Z 3aee8dea98fb53abe6ab78ab5ec0f41a +Z 99783f3b22c024a372aa90c126538916 diff --git a/manifest.uuid b/manifest.uuid index 5e6ac03230..64464643dd 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -ce5a8cc1cf663546ebdce08bef7d957ed4d341c6 \ No newline at end of file +9d1b96182af08a73de9dd0327965b96a6d48ac11 \ No newline at end of file diff --git a/tool/mkvsix.tcl b/tool/mkvsix.tcl index 2de4d77bae..77ec4b15c6 100644 --- a/tool/mkvsix.tcl +++ b/tool/mkvsix.tcl @@ -65,12 +65,12 @@ # argument is optional and if present must contain the name of the directory # containing the root of the source tree for SQLite. The third argument is # optional and if present must contain the flavor the VSIX package to build. -# Currently, the only supported package flavors are "WinRT" and "WP80". The -# fourth argument is optional and if present must be a string containing a list -# of platforms to include in the VSIX package. The format of the platform list -# string is "platform1,platform2,platform3". Typically, when on Windows, this -# script is executed using commands similar to the following from a normal -# Windows command prompt: +# Currently, the only supported package flavors are "WinRT", "WinRT81", and +# "WP80". The fourth argument is optional and if present must be a string +# containing a list of platforms to include in the VSIX package. The format +# of the platform list string is "platform1,platform2,platform3". Typically, +# when on Windows, this script is executed using commands similar to the +# following from a normal Windows command prompt: # # CD /D C:\dev\sqlite\core # tclsh85 tool\mkvsix.tcl C:\Temp @@ -280,7 +280,7 @@ if {[string equal -nocase $packageFlavor WinRT]} then { set extraSdkPath "\\..\\$targetPlatformIdentifier" set extraFileListAttributes "" } else { - fail "unsupported package flavor, must be \"WinRT\" or \"WP80\"" + fail "unsupported package flavor, must be \"WinRT\", \"WinRT81\", or \"WP80\"" } if {$argc >= 4} then { From da5b1cd4464caa8433a82084dbfd19e0329c0e2a Mon Sep 17 00:00:00 2001 From: mistachkin Date: Wed, 10 Jul 2013 19:39:02 +0000 Subject: [PATCH 004/101] More changes to support MSVC 18. FossilOrigin-Name: 29c458e2c21f7c8db727fe8dbd4d154918b53a4e --- Makefile.msc | 9 +++++++++ manifest | 12 ++++++------ manifest.uuid | 2 +- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/Makefile.msc b/Makefile.msc index 206f1680d4..95dc01cb69 100644 --- a/Makefile.msc +++ b/Makefile.msc @@ -445,6 +445,15 @@ LTLIBOPTS = /MACHINE:$(PLATFORM) # !IF $(FOR_WINRT)!=0 LTLINKOPTS = $(LTLINKOPTS) /APPCONTAINER +!IF $(_MSC_VER)==1800 +!IF "$(PLATFORM)"=="x86" +LTLINKOPTS = $(LTLINKOPTS) "/LIBPATH:$(VCINSTALLDIR)\store" +!ELSEIF "$(PLATFORM)"=="x64" +LTLINKOPTS = $(LTLINKOPTS) "/LIBPATH:$(VCINSTALLDIR)\store\amd64" +!ELSEIF "$(PLATFORM)"=="arm" +LTLINKOPTS = $(LTLINKOPTS) "/LIBPATH:$(VCINSTALLDIR)\store\arm" +!ENDIF +!ENDIF !ENDIF # If either debugging or symbols are enabled, enable PDBs. diff --git a/manifest b/manifest index dd4ae69898..1685f222b7 100644 --- a/manifest +++ b/manifest @@ -1,9 +1,9 @@ -C Update\scomments\sand\spackage\sflavor\serror\smessage. -D 2013-06-21T07:54:39.197 +C More\schanges\sto\ssupport\sMSVC\s18. +D 2013-07-10T19:39:02.664 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5e41da95d92656a5004b03d3576e8b226858a28e F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 -F Makefile.msc 7d226394826f060f232c0a02a468e8651819b7c2 +F Makefile.msc 751c3d495c159a15e46a35e523e02f5ae1dffeeb F Makefile.vxworks db21ed42a01d5740e656b16f92cb5d8d5e5dd315 F README cd04a36fbc7ea56932a4052d7d0b7f09f27c33d6 F VERSION 05c7bd63b96f31cfdef5c766ed91307ac121f5aa @@ -1093,7 +1093,7 @@ F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P ce5a8cc1cf663546ebdce08bef7d957ed4d341c6 -R 94b717d64d889391ffc6225632038588 +P 9d1b96182af08a73de9dd0327965b96a6d48ac11 +R dce12cbb8dc011a7157a4fc9c756a0b9 U mistachkin -Z 99783f3b22c024a372aa90c126538916 +Z b25307feb6067015ecfaf839e3826c1b diff --git a/manifest.uuid b/manifest.uuid index 64464643dd..d8a4992d74 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -9d1b96182af08a73de9dd0327965b96a6d48ac11 \ No newline at end of file +29c458e2c21f7c8db727fe8dbd4d154918b53a4e \ No newline at end of file From 6cdc63d4e395009af781353d05896e1599499d51 Mon Sep 17 00:00:00 2001 From: mistachkin Date: Wed, 10 Jul 2013 19:53:49 +0000 Subject: [PATCH 005/101] Use the VisualStudioVersion variable instead of _MSC_VER. FossilOrigin-Name: 603e9db817d457e59e329ad55ac3f1e567759b32 --- Makefile.msc | 2 +- manifest | 12 ++++++------ manifest.uuid | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Makefile.msc b/Makefile.msc index 95dc01cb69..9b0b17732e 100644 --- a/Makefile.msc +++ b/Makefile.msc @@ -445,7 +445,7 @@ LTLIBOPTS = /MACHINE:$(PLATFORM) # !IF $(FOR_WINRT)!=0 LTLINKOPTS = $(LTLINKOPTS) /APPCONTAINER -!IF $(_MSC_VER)==1800 +!IF "$(VisualStudioVersion)"=="12.0" !IF "$(PLATFORM)"=="x86" LTLINKOPTS = $(LTLINKOPTS) "/LIBPATH:$(VCINSTALLDIR)\store" !ELSEIF "$(PLATFORM)"=="x64" diff --git a/manifest b/manifest index 1685f222b7..815508a92f 100644 --- a/manifest +++ b/manifest @@ -1,9 +1,9 @@ -C More\schanges\sto\ssupport\sMSVC\s18. -D 2013-07-10T19:39:02.664 +C Use\sthe\sVisualStudioVersion\svariable\sinstead\sof\s_MSC_VER. +D 2013-07-10T19:53:49.176 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5e41da95d92656a5004b03d3576e8b226858a28e F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 -F Makefile.msc 751c3d495c159a15e46a35e523e02f5ae1dffeeb +F Makefile.msc 2c391a8c3e3e941df2670499225e56a2665b6743 F Makefile.vxworks db21ed42a01d5740e656b16f92cb5d8d5e5dd315 F README cd04a36fbc7ea56932a4052d7d0b7f09f27c33d6 F VERSION 05c7bd63b96f31cfdef5c766ed91307ac121f5aa @@ -1093,7 +1093,7 @@ F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P 9d1b96182af08a73de9dd0327965b96a6d48ac11 -R dce12cbb8dc011a7157a4fc9c756a0b9 +P 29c458e2c21f7c8db727fe8dbd4d154918b53a4e +R 1fc16d780ab429b1ac8777f58708e855 U mistachkin -Z b25307feb6067015ecfaf839e3826c1b +Z c5cda1e51e4d22d5432eaa97bb145bf4 diff --git a/manifest.uuid b/manifest.uuid index d8a4992d74..65cf1538bc 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -29c458e2c21f7c8db727fe8dbd4d154918b53a4e \ No newline at end of file +603e9db817d457e59e329ad55ac3f1e567759b32 \ No newline at end of file From 4eaa1295c9408fe4eb15ffd898a85b071dba7935 Mon Sep 17 00:00:00 2001 From: mistachkin Date: Wed, 10 Jul 2013 21:33:25 +0000 Subject: [PATCH 006/101] More corrects to VS 2013 integration. FossilOrigin-Name: 7a8b0e362b529d54231453046f22e90e651ecdc5 --- Makefile.msc | 10 ++++++---- manifest | 12 ++++++------ manifest.uuid | 2 +- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/Makefile.msc b/Makefile.msc index 9b0b17732e..8e77e14a76 100644 --- a/Makefile.msc +++ b/Makefile.msc @@ -447,11 +447,13 @@ LTLIBOPTS = /MACHINE:$(PLATFORM) LTLINKOPTS = $(LTLINKOPTS) /APPCONTAINER !IF "$(VisualStudioVersion)"=="12.0" !IF "$(PLATFORM)"=="x86" -LTLINKOPTS = $(LTLINKOPTS) "/LIBPATH:$(VCINSTALLDIR)\store" +LTLINKOPTS = $(LTLINKOPTS) "/LIBPATH:$(VCINSTALLDIR)\lib\store" !ELSEIF "$(PLATFORM)"=="x64" -LTLINKOPTS = $(LTLINKOPTS) "/LIBPATH:$(VCINSTALLDIR)\store\amd64" -!ELSEIF "$(PLATFORM)"=="arm" -LTLINKOPTS = $(LTLINKOPTS) "/LIBPATH:$(VCINSTALLDIR)\store\arm" +LTLINKOPTS = $(LTLINKOPTS) "/LIBPATH:$(VCINSTALLDIR)\lib\store\amd64" +!ELSEIF "$(PLATFORM)"=="ARM" +LTLINKOPTS = $(LTLINKOPTS) "/LIBPATH:$(VCINSTALLDIR)\lib\store\arm" +!ELSE +LTLINKOPTS = $(LTLINKOPTS) "/LIBPATH:$(VCINSTALLDIR)\lib\store" !ENDIF !ENDIF !ENDIF diff --git a/manifest b/manifest index 815508a92f..1183d08667 100644 --- a/manifest +++ b/manifest @@ -1,9 +1,9 @@ -C Use\sthe\sVisualStudioVersion\svariable\sinstead\sof\s_MSC_VER. -D 2013-07-10T19:53:49.176 +C More\scorrects\sto\sVS\s2013\sintegration. +D 2013-07-10T21:33:25.856 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5e41da95d92656a5004b03d3576e8b226858a28e F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 -F Makefile.msc 2c391a8c3e3e941df2670499225e56a2665b6743 +F Makefile.msc d45c66f73ed79474d5c3df44a48a9f06cdfd942f F Makefile.vxworks db21ed42a01d5740e656b16f92cb5d8d5e5dd315 F README cd04a36fbc7ea56932a4052d7d0b7f09f27c33d6 F VERSION 05c7bd63b96f31cfdef5c766ed91307ac121f5aa @@ -1093,7 +1093,7 @@ F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P 29c458e2c21f7c8db727fe8dbd4d154918b53a4e -R 1fc16d780ab429b1ac8777f58708e855 +P 603e9db817d457e59e329ad55ac3f1e567759b32 +R f9815c19281fc25d64f0e7d7244efa66 U mistachkin -Z c5cda1e51e4d22d5432eaa97bb145bf4 +Z fdae0f9dfe136531de23272d34a5b71e diff --git a/manifest.uuid b/manifest.uuid index 65cf1538bc..30c1bd2520 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -603e9db817d457e59e329ad55ac3f1e567759b32 \ No newline at end of file +7a8b0e362b529d54231453046f22e90e651ecdc5 \ No newline at end of file From 60bdad7f54afcab0c0ae61c3be432c5c9427ef5c Mon Sep 17 00:00:00 2001 From: mistachkin Date: Thu, 11 Jul 2013 03:09:45 +0000 Subject: [PATCH 007/101] Environment variable names in nmake must be in all uppercase. FossilOrigin-Name: 0328e873f2f98ac0aed93ec07ba7e14228cc10e0 --- Makefile.msc | 2 +- manifest | 12 ++++++------ manifest.uuid | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Makefile.msc b/Makefile.msc index 8e77e14a76..f2aa94644c 100644 --- a/Makefile.msc +++ b/Makefile.msc @@ -445,7 +445,7 @@ LTLIBOPTS = /MACHINE:$(PLATFORM) # !IF $(FOR_WINRT)!=0 LTLINKOPTS = $(LTLINKOPTS) /APPCONTAINER -!IF "$(VisualStudioVersion)"=="12.0" +!IF "$(VISUALSTUDIOVERSION)"=="12.0" !IF "$(PLATFORM)"=="x86" LTLINKOPTS = $(LTLINKOPTS) "/LIBPATH:$(VCINSTALLDIR)\lib\store" !ELSEIF "$(PLATFORM)"=="x64" diff --git a/manifest b/manifest index 1183d08667..3f096864ca 100644 --- a/manifest +++ b/manifest @@ -1,9 +1,9 @@ -C More\scorrects\sto\sVS\s2013\sintegration. -D 2013-07-10T21:33:25.856 +C Environment\svariable\snames\sin\snmake\smust\sbe\sin\sall\suppercase. +D 2013-07-11T03:09:45.896 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5e41da95d92656a5004b03d3576e8b226858a28e F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 -F Makefile.msc d45c66f73ed79474d5c3df44a48a9f06cdfd942f +F Makefile.msc 1b432129f87a6a4258f9b9e01ba5ccda0b19851a F Makefile.vxworks db21ed42a01d5740e656b16f92cb5d8d5e5dd315 F README cd04a36fbc7ea56932a4052d7d0b7f09f27c33d6 F VERSION 05c7bd63b96f31cfdef5c766ed91307ac121f5aa @@ -1093,7 +1093,7 @@ F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P 603e9db817d457e59e329ad55ac3f1e567759b32 -R f9815c19281fc25d64f0e7d7244efa66 +P 7a8b0e362b529d54231453046f22e90e651ecdc5 +R ff249db1b0f16f46ad7ee4ebeeb16b40 U mistachkin -Z fdae0f9dfe136531de23272d34a5b71e +Z 80027817d1c05a21c407e2d8f86e9a15 diff --git a/manifest.uuid b/manifest.uuid index 30c1bd2520..aaeecb4f34 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -7a8b0e362b529d54231453046f22e90e651ecdc5 \ No newline at end of file +0328e873f2f98ac0aed93ec07ba7e14228cc10e0 \ No newline at end of file From b13af4c5dd7a0c9be0e7f2b9b0b57936167938ed Mon Sep 17 00:00:00 2001 From: dan Date: Tue, 3 Sep 2013 14:43:12 +0000 Subject: [PATCH 008/101] Fix another problem in stat4 sample selection. FossilOrigin-Name: d59f580904e6e7e90fc0a692a3dd4eeff5942479 --- manifest | 16 ++++----- manifest.uuid | 2 +- src/analyze.c | 90 ++++++++++++++++++++++++++++------------------ test/analyze9.test | 35 +++++++++++++++++- 4 files changed, 98 insertions(+), 45 deletions(-) diff --git a/manifest b/manifest index 99db51e4ea..680f65071a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Make\ssure\sthe\somit-noop-left-join\soptimization\sis\snot\sapplied\sif\scolumns\nof\sthe\sLEFT\sJOIN\sare\sused\sin\sthe\sORDER\sBY\sclause.\s\s\nTicket\s[be84e357c035] -D 2013-09-03T14:03:47.008 +C Fix\sanother\sproblem\sin\sstat4\ssample\sselection. +D 2013-09-03T14:43:12.842 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5e41da95d92656a5004b03d3576e8b226858a28e F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -157,7 +157,7 @@ F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a F src/alter.c 2af0330bb1b601af7a7789bf7229675fd772a083 -F src/analyze.c 66903e3e5a36eee728c0dc1d574e8cb16059210f +F src/analyze.c 51e6e5d56aaee93465a530d8f9e7a9b69cf9702c F src/attach.c fea00cab11c854646a27641a263f5876569a51f9 F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34 F src/backup.c 2f1987981139bd2f6d8c728d64bf09fb387443c3 @@ -308,7 +308,7 @@ F test/analyze5.test 765c4e284aa69ca172772aa940946f55629bc8c4 F test/analyze6.test 19151da2c4e918905d2081b74ac5c4d47fc850ab F test/analyze7.test bb1409afc9e8629e414387ef048b8e0e3e0bdc4f F test/analyze8.test 093d15c1c888eed5034304a98c992f7360130b88 -F test/analyze9.test 3b23fc97bcc0f4b5629aacdd8e1aa267114dcc79 +F test/analyze9.test 4a48461d71a7b4a958570c580495a97e842e2700 F test/analyzeA.test 1a5c40079894847976d983ca39c707aaa44b6944 F test/async.test 1d0e056ba1bb9729283a0f22718d3a25e82c277b F test/async2.test c0a9bd20816d7d6a2ceca7b8c03d3d69c28ffb8b @@ -1109,7 +1109,7 @@ F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 F tool/wherecosttest.c f407dc4c79786982a475261866a161cd007947ae F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac -P f7079b5365dd6cd8324a4fb23605e81476122ed6 -R ef683c5e75a524283b39e51db1610c55 -U drh -Z 7e7396aa706179eb8731d96e0b228672 +P 0303d6bc7112e6f810ae1bd75cafc5ffc51f5212 +R ae0a46263eba3c1ef0a78f34bdb8ef01 +U dan +Z 3daa1eef98d5cdbb101dd3c2f83cf235 diff --git a/manifest.uuid b/manifest.uuid index 4af698a9c6..549d7b88f6 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -0303d6bc7112e6f810ae1bd75cafc5ffc51f5212 \ No newline at end of file +d59f580904e6e7e90fc0a692a3dd4eeff5942479 \ No newline at end of file diff --git a/src/analyze.c b/src/analyze.c index 89dc84f2c1..99a0a2fd8b 100644 --- a/src/analyze.c +++ b/src/analyze.c @@ -383,24 +383,63 @@ static const FuncDef statInitFuncdef = { 0 /* pDestructor */ }; +#ifdef SQLITE_ENABLE_STAT4 +/* +** pNew and pOld are both candidate non-periodic samples selected for +** the same column (pNew->iCol==pOld->iCol). Ignoring this column and +** considering only any trailing columns and the sample hash value, this +** function returns true if sample pNew is to be preferred over pOld. +** In other words, if we assume that the cardinalities of the selected +** column for pNew and pOld are equal, is pNew to be preferred over pOld. +** +** This function assumes that for each argument sample, the contents of +** the anEq[] array from pSample->anEq[pSample->iCol+1] onwards are valid. +*/ +static int sampleIsBetterPost( + Stat4Accum *pAccum, + Stat4Sample *pNew, + Stat4Sample *pOld +){ + int nCol = pAccum->nCol; + int i; + assert( pNew->iCol==pOld->iCol ); + for(i=pNew->iCol+1; ianEq[i]>pOld->anEq[i] ) return 1; + if( pNew->anEq[i]anEq[i] ) return 0; + } + if( pNew->iHash>pOld->iHash ) return 1; + return 0; +} +#endif + #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 /* ** Return true if pNew is to be preferred over pOld. +** +** This function assumes that for each argument sample, the contents of +** the anEq[] array from pSample->anEq[pSample->iCol] onwards are valid. */ -static int sampleIsBetter(Stat4Sample *pNew, Stat4Sample *pOld){ +static int sampleIsBetter( + Stat4Accum *pAccum, + Stat4Sample *pNew, + Stat4Sample *pOld +){ tRowcnt nEqNew = pNew->anEq[pNew->iCol]; tRowcnt nEqOld = pOld->anEq[pOld->iCol]; assert( pOld->isPSample==0 && pNew->isPSample==0 ); assert( IsStat4 || (pNew->iCol==0 && pOld->iCol==0) ); - if( (nEqNew>nEqOld) - || (nEqNew==nEqOld && pNew->iColiCol) - || (nEqNew==nEqOld && pNew->iCol==pOld->iCol && pNew->iHash>pOld->iHash) - ){ - return 1; + if( (nEqNew>nEqOld) ) return 1; +#ifdef SQLITE_ENABLE_STAT4 + if( nEqNew==nEqOld ){ + if( pNew->iColiCol ) return 1; + return (pNew->iCol==pOld->iCol && sampleIsBetterPost(pAccum, pNew, pOld)); } return 0; +#else + return (nEqNew==nEqOld && pNew->iHash>pOld->iHash); +#endif } /* @@ -423,8 +462,6 @@ void sampleCopy(Stat4Accum *p, Stat4Sample *pTo, Stat4Sample *pFrom){ static void sampleInsert(Stat4Accum *p, Stat4Sample *pNew, int nEqZero){ Stat4Sample *pSample; int i; - i64 iSeq; - int iPos; assert( IsStat4 || nEqZero==0 ); @@ -441,8 +478,9 @@ static void sampleInsert(Stat4Accum *p, Stat4Sample *pNew, int nEqZero){ Stat4Sample *pOld = &p->a[i]; if( pOld->anEq[pNew->iCol]==0 ){ if( pOld->isPSample ) return; - assert( sampleIsBetter(pNew, pOld) ); - if( pUpgrade==0 || sampleIsBetter(pOld, pUpgrade) ){ + assert( pOld->iCol>pNew->iCol ); + assert( sampleIsBetter(p, pNew, pOld) ); + if( pUpgrade==0 || sampleIsBetter(p, pOld, pUpgrade) ){ pUpgrade = pOld; } } @@ -481,25 +519,6 @@ static void sampleInsert(Stat4Accum *p, Stat4Sample *pNew, int nEqZero){ sampleCopy(p, pSample, pNew); p->nSample++; -#if 0 - iSeq = pNew->anLt[p->nCol-1]; - for(iPos=p->nSample; iPos>0; iPos--){ - if( iSeq>p->a[iPos-1].anLt[p->nCol-1] ) break; - } - - if( iPos!=p->nSample ){ - Stat4Sample *pEnd = &p->a[p->nSample]; - tRowcnt *anEq = pEnd->anEq; - tRowcnt *anLt = pEnd->anLt; - tRowcnt *anDLt = pEnd->anDLt; - memmove(&p->a[iPos], &p->a[iPos+1], (p->nSample-iPos)*sizeof(p->a[0])); - pSample->anEq = anEq; - pSample->anDLt = anDLt; - pSample->anLt = anLt; - } -#endif - - /* Zero the first nEqZero entries in the anEq[] array. */ memset(pSample->anEq, 0, sizeof(tRowcnt)*nEqZero); @@ -508,7 +527,7 @@ static void sampleInsert(Stat4Accum *p, Stat4Sample *pNew, int nEqZero){ int iMin = -1; for(i=0; imxSample; i++){ if( p->a[i].isPSample ) continue; - if( iMin<0 || sampleIsBetter(&p->a[iMin], &p->a[i]) ){ + if( iMin<0 || sampleIsBetter(p, &p->a[iMin], &p->a[i]) ){ iMin = i; } } @@ -532,9 +551,8 @@ static void samplePushPrevious(Stat4Accum *p, int iChng){ ** into IndexSample.a[] at this point. */ for(i=(p->nCol-2); i>=iChng; i--){ Stat4Sample *pBest = &p->aBest[i]; - if( p->nSamplemxSample - || sampleIsBetter(pBest, &p->a[p->iMin]) - ){ + pBest->anEq[i] = p->current.anEq[i]; + if( p->nSamplemxSample || sampleIsBetter(p, pBest, &p->a[p->iMin]) ){ sampleInsert(p, pBest, i); } } @@ -561,7 +579,9 @@ static void samplePushPrevious(Stat4Accum *p, int iChng){ }else /* Or if it is a non-periodic sample. Add it in this case too. */ - if( p->nSamplemxSample || sampleIsBetter(&p->current, &p->a[p->iMin]) ){ + if( p->nSamplemxSample + || sampleIsBetter(p, &p->current, &p->a[p->iMin]) + ){ sampleInsert(p, &p->current, 0); } } @@ -635,7 +655,7 @@ static void statPush( /* Update the aBest[] array. */ for(i=0; i<(p->nCol-1); i++){ p->current.iCol = i; - if( i>=iChng || sampleIsBetter(&p->current, &p->aBest[i]) ){ + if( i>=iChng || sampleIsBetterPost(p, &p->current, &p->aBest[i]) ){ sampleCopy(p, &p->aBest[i], &p->current); } } diff --git a/test/analyze9.test b/test/analyze9.test index 777e462fdb..604f340bf5 100644 --- a/test/analyze9.test +++ b/test/analyze9.test @@ -244,7 +244,7 @@ do_execsql_test 4.3 { FROM sqlite_stat4 ORDER BY rowid DESC LIMIT 2; } { - {2 1 1 1} {295 296 296} {120 122 125} {201 4} + {2 1 1 1} {295 295 295} {120 121 124} {201 3} {5 3 1 1} {290 290 292} {119 119 121} {200 1} } @@ -916,5 +916,38 @@ ifcapable auth { } {1 {not authorized}} } +#------------------------------------------------------------------------- +# +reset_db +proc r {args} { expr rand() } +db func r r +db func lrange lrange +do_test 20.1 { + execsql { + CREATE TABLE t1(a,b,c,d); + CREATE INDEX i1 ON t1(a,b,c,d); + } + for {set i 0} {$i < 16} {incr i} { + execsql { + INSERT INTO t1 VALUES($i, r(), r(), r()); + INSERT INTO t1 VALUES($i, $i, r(), r()); + INSERT INTO t1 VALUES($i, $i, $i, r()); + INSERT INTO t1 VALUES($i, $i, $i, $i); + INSERT INTO t1 VALUES($i, $i, $i, $i); + INSERT INTO t1 VALUES($i, $i, $i, r()); + INSERT INTO t1 VALUES($i, $i, r(), r()); + INSERT INTO t1 VALUES($i, r(), r(), r()); + } + } +} {} +do_execsql_test 20.2 { ANALYZE } +for {set i 0} {$i<16} {incr i} { + set val "$i $i $i $i" + do_execsql_test 20.3.$i { + SELECT count(*) FROM sqlite_stat4 + WHERE lrange(test_decode(sample), 0, 3)=$val + } {1} +} + finish_test From fbc38de9803be5f5bcc89cc4795d1692091a5577 Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 3 Sep 2013 19:26:22 +0000 Subject: [PATCH 009/101] Harden the STAT4 logic in where.c against OOM faults. FossilOrigin-Name: 91d2cfbc95c34c0040deb69106bb9f895abb94c0 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/where.c | 5 ++++- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 680f65071a..0a72bf87ba 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sanother\sproblem\sin\sstat4\ssample\sselection. -D 2013-09-03T14:43:12.842 +C Harden\sthe\sSTAT4\slogic\sin\swhere.c\sagainst\sOOM\sfaults. +D 2013-09-03T19:26:22.132 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5e41da95d92656a5004b03d3576e8b226858a28e F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -290,7 +290,7 @@ F src/vtab.c 165ce0e797c2cd23badb104c9f2ae9042d6d942c F src/wal.c 7dc3966ef98b74422267e7e6e46e07ff6c6eb1b4 F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4 F src/walker.c 4fa43583d0a84b48f93b1e88f11adf2065be4e73 -F src/where.c 99477e9dd4d4d33be32115b4fbd18b6f033d045a +F src/where.c 1fe091c69412b9eddae05e160260781394b41631 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 F test/aggnested.test 45c0201e28045ad38a530b5a144b73cd4aa2cfd6 @@ -1109,7 +1109,7 @@ F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 F tool/wherecosttest.c f407dc4c79786982a475261866a161cd007947ae F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac -P 0303d6bc7112e6f810ae1bd75cafc5ffc51f5212 -R ae0a46263eba3c1ef0a78f34bdb8ef01 -U dan -Z 3daa1eef98d5cdbb101dd3c2f83cf235 +P d59f580904e6e7e90fc0a692a3dd4eeff5942479 +R fe3c8072a3f0ead6396100d646dd55b5 +U drh +Z 4e9e05f19356d6ec8498cc0ab2084861 diff --git a/manifest.uuid b/manifest.uuid index 549d7b88f6..fc2add064f 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d59f580904e6e7e90fc0a692a3dd4eeff5942479 \ No newline at end of file +91d2cfbc95c34c0040deb69106bb9f895abb94c0 \ No newline at end of file diff --git a/src/where.c b/src/where.c index b633dfd574..d08db48e08 100644 --- a/src/where.c +++ b/src/where.c @@ -2421,12 +2421,15 @@ static void whereKeyStats( tRowcnt *aStat /* OUT: stats written here */ ){ IndexSample *aSample = pIdx->aSample; - int iCol = pRec->nField-1; /* Index of required stats in anEq[] etc. */ + int iCol; /* Index of required stats in anEq[] etc. */ int iMin = 0; /* Smallest sample not yet tested */ int i = pIdx->nSample; /* Smallest sample larger than or equal to pRec */ int iTest; /* Next sample to test */ int res; /* Result of comparison operation */ + assert( pRec!=0 || pParse->db->mallocFailed ); + if( pRec==0 ) return; + iCol = pRec->nField - 1; assert( pIdx->nSample>0 ); assert( pRec->nField>0 && iColnSampleCol ); do{ From 30f07042dfa4166d20e8ac1cbbc35465cc8d5f5e Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 4 Sep 2013 02:07:38 +0000 Subject: [PATCH 010/101] Conditionally exclude code from analyze.c that is not used by STAT3. FossilOrigin-Name: a48948a170056dfb87541dd5eb2773094dec6f8a --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/analyze.c | 2 ++ 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/manifest b/manifest index 0a72bf87ba..3fb45c08e5 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Harden\sthe\sSTAT4\slogic\sin\swhere.c\sagainst\sOOM\sfaults. -D 2013-09-03T19:26:22.132 +C Conditionally\sexclude\scode\sfrom\sanalyze.c\sthat\sis\snot\sused\sby\sSTAT3. +D 2013-09-04T02:07:38.666 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5e41da95d92656a5004b03d3576e8b226858a28e F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -157,7 +157,7 @@ F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a F src/alter.c 2af0330bb1b601af7a7789bf7229675fd772a083 -F src/analyze.c 51e6e5d56aaee93465a530d8f9e7a9b69cf9702c +F src/analyze.c a492484869888fe5faf6f154e83cd1a8cb02d7ea F src/attach.c fea00cab11c854646a27641a263f5876569a51f9 F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34 F src/backup.c 2f1987981139bd2f6d8c728d64bf09fb387443c3 @@ -1109,7 +1109,7 @@ F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 F tool/wherecosttest.c f407dc4c79786982a475261866a161cd007947ae F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac -P d59f580904e6e7e90fc0a692a3dd4eeff5942479 -R fe3c8072a3f0ead6396100d646dd55b5 +P 91d2cfbc95c34c0040deb69106bb9f895abb94c0 +R de4c0b4db329755c881b794576ecab1d U drh -Z 4e9e05f19356d6ec8498cc0ab2084861 +Z 4998967182f8bfcd840ee000c0017287 diff --git a/manifest.uuid b/manifest.uuid index fc2add064f..12b5cd65ce 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -91d2cfbc95c34c0040deb69106bb9f895abb94c0 \ No newline at end of file +a48948a170056dfb87541dd5eb2773094dec6f8a \ No newline at end of file diff --git a/src/analyze.c b/src/analyze.c index 99a0a2fd8b..4091e5b6e6 100644 --- a/src/analyze.c +++ b/src/analyze.c @@ -465,6 +465,7 @@ static void sampleInsert(Stat4Accum *p, Stat4Sample *pNew, int nEqZero){ assert( IsStat4 || nEqZero==0 ); +#ifdef SQLITE_ENABLE_STAT4 if( pNew->isPSample==0 ){ Stat4Sample *pUpgrade = 0; assert( pNew->anEq[pNew->iCol]>0 ); @@ -491,6 +492,7 @@ static void sampleInsert(Stat4Accum *p, Stat4Sample *pNew, int nEqZero){ goto find_new_min; } } +#endif /* If necessary, remove sample iMin to make room for the new sample. */ if( p->nSample>=p->mxSample ){ From c2cfb5152508063bceecafddbb152f366a646853 Mon Sep 17 00:00:00 2001 From: mistachkin Date: Wed, 4 Sep 2013 04:04:08 +0000 Subject: [PATCH 011/101] Fix out-of-order variable declaration. Fix harmless compiler warning. FossilOrigin-Name: 8df95bb0b3f72222cf262174247a467c234f9939 --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- src/analyze.c | 2 ++ src/where.c | 10 +++++----- 4 files changed, 16 insertions(+), 14 deletions(-) diff --git a/manifest b/manifest index 3fb45c08e5..c3d18e94f2 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Conditionally\sexclude\scode\sfrom\sanalyze.c\sthat\sis\snot\sused\sby\sSTAT3. -D 2013-09-04T02:07:38.666 +C Fix\sout-of-order\svariable\sdeclaration.\s\sFix\sharmless\scompiler\swarning. +D 2013-09-04T04:04:08.155 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5e41da95d92656a5004b03d3576e8b226858a28e F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -157,7 +157,7 @@ F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a F src/alter.c 2af0330bb1b601af7a7789bf7229675fd772a083 -F src/analyze.c a492484869888fe5faf6f154e83cd1a8cb02d7ea +F src/analyze.c 3f1c87b00c52e49caa0a190528503fda8f26fc3a F src/attach.c fea00cab11c854646a27641a263f5876569a51f9 F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34 F src/backup.c 2f1987981139bd2f6d8c728d64bf09fb387443c3 @@ -290,7 +290,7 @@ F src/vtab.c 165ce0e797c2cd23badb104c9f2ae9042d6d942c F src/wal.c 7dc3966ef98b74422267e7e6e46e07ff6c6eb1b4 F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4 F src/walker.c 4fa43583d0a84b48f93b1e88f11adf2065be4e73 -F src/where.c 1fe091c69412b9eddae05e160260781394b41631 +F src/where.c 95a351c94ecc9d6b4fa7f0e251ab480335b83ab8 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 F test/aggnested.test 45c0201e28045ad38a530b5a144b73cd4aa2cfd6 @@ -1109,7 +1109,7 @@ F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 F tool/wherecosttest.c f407dc4c79786982a475261866a161cd007947ae F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac -P 91d2cfbc95c34c0040deb69106bb9f895abb94c0 -R de4c0b4db329755c881b794576ecab1d -U drh -Z 4998967182f8bfcd840ee000c0017287 +P a48948a170056dfb87541dd5eb2773094dec6f8a +R 8eb1f582f1bc97c17449e31bd6792386 +U mistachkin +Z 0184d76aee144da494741e51191a6949 diff --git a/manifest.uuid b/manifest.uuid index 12b5cd65ce..923771a84d 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -a48948a170056dfb87541dd5eb2773094dec6f8a \ No newline at end of file +8df95bb0b3f72222cf262174247a467c234f9939 \ No newline at end of file diff --git a/src/analyze.c b/src/analyze.c index 4091e5b6e6..64dae669f2 100644 --- a/src/analyze.c +++ b/src/analyze.c @@ -524,7 +524,9 @@ static void sampleInsert(Stat4Accum *p, Stat4Sample *pNew, int nEqZero){ /* Zero the first nEqZero entries in the anEq[] array. */ memset(pSample->anEq, 0, sizeof(tRowcnt)*nEqZero); +#ifdef SQLITE_ENABLE_STAT4 find_new_min: +#endif if( p->nSample>=p->mxSample ){ int iMin = -1; for(i=0; imxSample; i++){ diff --git a/src/where.c b/src/where.c index d08db48e08..13786160b6 100644 --- a/src/where.c +++ b/src/where.c @@ -2557,11 +2557,6 @@ static int whereRangeScanEst( UnpackedRecord *pRec = pBuilder->pRec; tRowcnt a[2]; u8 aff; - if( nEq==p->nColumn ){ - aff = SQLITE_AFF_INTEGER; - }else{ - aff = p->pTable->aCol[p->aiColumn[nEq]].affinity; - } /* Variable iLower will be set to the estimate of the number of rows in ** the index that are less than the lower bound of the range query. The @@ -2583,6 +2578,11 @@ static int whereRangeScanEst( tRowcnt iLower; tRowcnt iUpper; + if( nEq==p->nColumn ){ + aff = SQLITE_AFF_INTEGER; + }else{ + aff = p->pTable->aCol[p->aiColumn[nEq]].affinity; + } /* Determine iLower and iUpper using ($P) only. */ if( nEq==0 ){ iLower = 0; From 2b1a64a120ef31f3f7aa51fb2f075fed48beb744 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 4 Sep 2013 15:15:10 +0000 Subject: [PATCH 012/101] The sqlite3Stat4ProbeSetValue() routine should always return results using the database encoding. FossilOrigin-Name: eb21663271369c3862bc8fd800f76d568c8579fe --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/vdbemem.c | 11 ++++++----- 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/manifest b/manifest index c3d18e94f2..8b0abdb3ff 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sout-of-order\svariable\sdeclaration.\s\sFix\sharmless\scompiler\swarning. -D 2013-09-04T04:04:08.155 +C The\ssqlite3Stat4ProbeSetValue()\sroutine\sshould\salways\sreturn\sresults\susing\nthe\sdatabase\sencoding. +D 2013-09-04T15:15:10.328 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5e41da95d92656a5004b03d3576e8b226858a28e F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -283,7 +283,7 @@ F src/vdbeInt.h cbe71b8b36d8b3bba5709cc3f436c7e3b47b7b08 F src/vdbeapi.c 96b24b946cf21894f63d9393e821baa2f0a80979 F src/vdbeaux.c c7fe2695e256dbf254113c4fe90d3ec9aabe3bbe F src/vdbeblob.c 5dc79627775bd9a9b494dd956e26297946417d69 -F src/vdbemem.c 75ad7fd8f068a8baaba1cf3a84714ef7d3b7a2b8 +F src/vdbemem.c 817ce21ab4ca57f902619bb8fef3f8a51bbd0ed8 F src/vdbesort.c 3937e06b2a0e354500e17dc206ef4c35770a5017 F src/vdbetrace.c e7ec40e1999ff3c6414424365d5941178966dcbc F src/vtab.c 165ce0e797c2cd23badb104c9f2ae9042d6d942c @@ -1109,7 +1109,7 @@ F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 F tool/wherecosttest.c f407dc4c79786982a475261866a161cd007947ae F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac -P a48948a170056dfb87541dd5eb2773094dec6f8a -R 8eb1f582f1bc97c17449e31bd6792386 -U mistachkin -Z 0184d76aee144da494741e51191a6949 +P 8df95bb0b3f72222cf262174247a467c234f9939 +R b944ffe32b90c0165476ae59b14b7022 +U drh +Z 60caa6bea3811d3575717487293d6e9c diff --git a/manifest.uuid b/manifest.uuid index 923771a84d..264edfda1a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -8df95bb0b3f72222cf262174247a467c234f9939 \ No newline at end of file +eb21663271369c3862bc8fd800f76d568c8579fe \ No newline at end of file diff --git a/src/vdbemem.c b/src/vdbemem.c index dbdfc53074..95a8798712 100644 --- a/src/vdbemem.c +++ b/src/vdbemem.c @@ -1304,6 +1304,8 @@ int sqlite3Stat4ProbeSetValue( ){ int rc = SQLITE_OK; sqlite3_value *pVal = 0; + sqlite3 *db = pParse->db; + struct ValueNewStat4Ctx alloc; alloc.pParse = pParse; @@ -1315,7 +1317,7 @@ int sqlite3Stat4ProbeSetValue( pExpr = sqlite3ExprSkipCollate(pExpr); if( !pExpr ){ - pVal = valueNew(pParse->db, &alloc); + pVal = valueNew(db, &alloc); if( pVal ){ sqlite3VdbeMemSetNull((Mem*)pVal); *pbOk = 1; @@ -1327,11 +1329,11 @@ int sqlite3Stat4ProbeSetValue( int iBindVar = pExpr->iColumn; sqlite3VdbeSetVarmask(pParse->pVdbe, iBindVar); if( (v = pParse->pReprepare)!=0 ){ - pVal = valueNew(pParse->db, &alloc); + pVal = valueNew(db, &alloc); if( pVal ){ rc = sqlite3VdbeMemCopy((Mem*)pVal, &v->aVar[iBindVar-1]); if( rc==SQLITE_OK ){ - sqlite3ValueApplyAffinity(pVal, affinity, SQLITE_UTF8); + sqlite3ValueApplyAffinity(pVal, affinity, ENC(db)); } pVal->db = pParse->db; *pbOk = 1; @@ -1341,12 +1343,11 @@ int sqlite3Stat4ProbeSetValue( *pbOk = 0; } }else{ - sqlite3 *db = pParse->db; rc = valueFromExpr(db, pExpr, ENC(db), affinity, &pVal, &alloc); *pbOk = (pVal!=0); } - assert( pVal==0 || pVal->db==pParse->db ); + assert( pVal==0 || pVal->db==db ); return rc; } From 55a1b3087539c62577fb23e2a82623c71fb892bc Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 4 Sep 2013 16:08:50 +0000 Subject: [PATCH 013/101] Fix a bug in the command-line shell for ".mode insert" on UTF16 databases with BLOB values. FossilOrigin-Name: d8fdc7821808e2bfa048144ee3015b745232dc30 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/shell.c | 10 +++++++--- test/shell1.test | 12 ++++++++++++ 4 files changed, 27 insertions(+), 11 deletions(-) diff --git a/manifest b/manifest index 8b0abdb3ff..dbbeaf3f64 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C The\ssqlite3Stat4ProbeSetValue()\sroutine\sshould\salways\sreturn\sresults\susing\nthe\sdatabase\sencoding. -D 2013-09-04T15:15:10.328 +C Fix\sa\sbug\sin\sthe\scommand-line\sshell\sfor\s".mode\sinsert"\son\sUTF16\sdatabases\nwith\sBLOB\svalues. +D 2013-09-04T16:08:50.014 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5e41da95d92656a5004b03d3576e8b226858a28e F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -217,7 +217,7 @@ F src/random.c 0b2dbc37fdfbfa6bd455b091dfcef5bdb32dba68 F src/resolve.c 9d53899cc6e1f4ec0b4632d07e97d57827bf63b9 F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0 F src/select.c 8b148eb851f384412aea57091659d14b369918ca -F src/shell.c dbe064d404bb497acd8a44c066cd6b8460a71236 +F src/shell.c d920a891ca09b8bd262cced7fb0ab9d723f7a747 F src/sqlite.h.in ec40aa958a270416fb04b4f72210357bf163d2c5 F src/sqlite3.rc fea433eb0a59f4c9393c8e6d76a6e2596b1fe0c0 F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc @@ -780,7 +780,7 @@ F test/shared9.test 5f2a8f79b4d6c7d107a01ffa1ed05ae7e6333e21 F test/sharedA.test 0cdf1a76dfa00e6beee66af5b534b1e8df2720f5 F test/shared_err.test 0079c05c97d88cfa03989b7c20a8b266983087aa F test/sharedlock.test 927a4b6da11978c82b857dbdb20a932aad732123 -F test/shell1.test 928547277d385038c696428e9d791cbbad098974 +F test/shell1.test 474ed53bb461c4ba9b6468d3a74e86eb8ee0d9d0 F test/shell2.test 037d6ad16e873354195d30bb2dc4b5321788154a F test/shell3.test 9196c42772d575685e722c92b4b39053c6ebba59 F test/shell4.test aa4eef8118b412d1a01477a53426ece169ea86a9 @@ -1109,7 +1109,7 @@ F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 F tool/wherecosttest.c f407dc4c79786982a475261866a161cd007947ae F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac -P 8df95bb0b3f72222cf262174247a467c234f9939 -R b944ffe32b90c0165476ae59b14b7022 +P eb21663271369c3862bc8fd800f76d568c8579fe +R ded2cb0c19eb56b367f2fc24300a6779 U drh -Z 60caa6bea3811d3575717487293d6e9c +Z 14271c216b0039f50adca506335fce27 diff --git a/manifest.uuid b/manifest.uuid index 264edfda1a..0a4d9d90f9 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -eb21663271369c3862bc8fd800f76d568c8579fe \ No newline at end of file +d8fdc7821808e2bfa048144ee3015b745232dc30 \ No newline at end of file diff --git a/src/shell.c b/src/shell.c index 915952cfbe..ccdb157a80 100644 --- a/src/shell.c +++ b/src/shell.c @@ -1194,7 +1194,7 @@ static int shell_exec( char **azCols = (char **)pData; /* Names of result columns */ char **azVals = &azCols[nCol]; /* Results */ int *aiTypes = (int *)&azVals[nCol]; /* Result types */ - int i; + int i, x; assert(sizeof(int) <= sizeof(char *)); /* save off ptrs to column names */ for(i=0; imode==MODE_Insert ){ + azVals[i] = ""; + }else{ + azVals[i] = (char*)sqlite3_column_text(pStmt, i); + } if( !azVals[i] && (aiTypes[i]!=SQLITE_NULL) ){ rc = SQLITE_NOMEM; break; /* from for */ diff --git a/test/shell1.test b/test/shell1.test index 25fb330de0..562f10e65a 100644 --- a/test/shell1.test +++ b/test/shell1.test @@ -722,7 +722,11 @@ do_test shell1-3-31.1 { # Test the output of the ".dump" command # do_test shell1-4.1 { + db close + forcedelete test.db + sqlite3 db test.db db eval { + PRAGMA encoding=UTF16; CREATE TABLE t1(x); INSERT INTO t1 VALUES(null), (''), (1), (2.25), ('hello'), (x'807f'); } @@ -752,6 +756,14 @@ INSERT INTO t1 VALUES(X'807f');}} # Test the output of ".mode tcl" # do_test shell1-4.3 { + db close + forcedelete test.db + sqlite3 db test.db + db eval { + PRAGMA encoding=UTF8; + CREATE TABLE t1(x); + INSERT INTO t1 VALUES(null), (''), (1), (2.25), ('hello'), (x'807f'); + } catchcmd test.db ".mode tcl\nselect * from t1;" } {0 {"" "" From af0d8bcf4b5d9242389c561159c333ebf8ae1199 Mon Sep 17 00:00:00 2001 From: dan Date: Wed, 4 Sep 2013 16:38:42 +0000 Subject: [PATCH 014/101] Add tests to improve coverage when SQLITE_ENABLE_STAT3 is defined. FossilOrigin-Name: f929e9b41f2f69b086be3dd48fe557adbba7ae5c --- manifest | 17 +- manifest.uuid | 2 +- test/analyzeB.test | 683 +++++++++++++++++++++++++++++++++++++++++ test/mallocA.test | 18 ++ test/permutations.test | 2 +- 5 files changed, 712 insertions(+), 10 deletions(-) create mode 100644 test/analyzeB.test diff --git a/manifest b/manifest index dbbeaf3f64..3f42052729 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\sbug\sin\sthe\scommand-line\sshell\sfor\s".mode\sinsert"\son\sUTF16\sdatabases\nwith\sBLOB\svalues. -D 2013-09-04T16:08:50.014 +C Add\stests\sto\simprove\scoverage\swhen\sSQLITE_ENABLE_STAT3\sis\sdefined. +D 2013-09-04T16:38:42.308 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5e41da95d92656a5004b03d3576e8b226858a28e F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -310,6 +310,7 @@ F test/analyze7.test bb1409afc9e8629e414387ef048b8e0e3e0bdc4f F test/analyze8.test 093d15c1c888eed5034304a98c992f7360130b88 F test/analyze9.test 4a48461d71a7b4a958570c580495a97e842e2700 F test/analyzeA.test 1a5c40079894847976d983ca39c707aaa44b6944 +F test/analyzeB.test 8bf35ee0a548aea831bf56762cb8e7fdb1db083d F test/async.test 1d0e056ba1bb9729283a0f22718d3a25e82c277b F test/async2.test c0a9bd20816d7d6a2ceca7b8c03d3d69c28ffb8b F test/async3.test d73a062002376d7edc1fe3edff493edbec1fc2f7 @@ -651,7 +652,7 @@ F test/malloc6.test 2f039d9821927eacae43e1831f815e157659a151 F test/malloc7.test 7c68a32942858bc715284856c5507446bba88c3a F test/malloc8.test 9b7a3f8cb9cf0b12fff566e80a980b1767bd961d F test/malloc9.test 2307c6ee3703b0a21391f3ea92388b4b73f9105e -F test/mallocA.test 71e4b57e640c017cf2833e51fe6e8e43e8575b73 +F test/mallocA.test 1ba0367fb5434e7bc2fa4afcb30b14174d91b160 F test/mallocAll.test 98f1be74bc9f49a858bc4f361fc58e26486798be F test/mallocB.test bc475ab850cda896142ab935bbfbc74c24e51ed6 F test/mallocC.test 3dffe16532f109293ce1ccecd0c31dca55ef08c4 @@ -716,7 +717,7 @@ F test/pagesize.test 1dd51367e752e742f58e861e65ed7390603827a0 F test/pcache.test b09104b03160aca0d968d99e8cd2c5b1921a993d F test/pcache2.test a83efe2dec0d392f814bfc998def1d1833942025 F test/percentile.test b98fc868d71eb5619d42a1702e9ab91718cbed54 -F test/permutations.test 47f8c1d3d72ea46863426dcedb1e368f4b6ed70b +F test/permutations.test 9cd3bba6f1e8658442d0dcfcef6c2e5efd131bdc F test/pragma.test 5e7de6c32a5d764f09437d2025f07e4917b9e178 F test/pragma2.test 224f0381f9411a78ae685cac24c13656a62021b7 F test/printf.test ec9870c4dce8686a37818e0bf1aba6e6a1863552 @@ -1109,7 +1110,7 @@ F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 F tool/wherecosttest.c f407dc4c79786982a475261866a161cd007947ae F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac -P eb21663271369c3862bc8fd800f76d568c8579fe -R ded2cb0c19eb56b367f2fc24300a6779 -U drh -Z 14271c216b0039f50adca506335fce27 +P d8fdc7821808e2bfa048144ee3015b745232dc30 +R 1b8932f1781f5719312a95a87cdda18d +U dan +Z 67321bf0786d50805840f21a47eb7fad diff --git a/manifest.uuid b/manifest.uuid index 0a4d9d90f9..0550529fea 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d8fdc7821808e2bfa048144ee3015b745232dc30 \ No newline at end of file +f929e9b41f2f69b086be3dd48fe557adbba7ae5c \ No newline at end of file diff --git a/test/analyzeB.test b/test/analyzeB.test new file mode 100644 index 0000000000..2a78c18b3d --- /dev/null +++ b/test/analyzeB.test @@ -0,0 +1,683 @@ +# 2013 August 3 +# +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. +# +#*********************************************************************** +# +# This file contains automated tests used to verify that the sqlite_stat3 +# functionality is working. The tests in this file are based on a subset +# of the sqlite_stat4 tests in analyze9.test. +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl +set testprefix analyzeB + +ifcapable !stat3 { + finish_test + return +} + +do_execsql_test 1.0 { + CREATE TABLE t1(a TEXT, b TEXT); + INSERT INTO t1 VALUES('(0)', '(0)'); + INSERT INTO t1 VALUES('(1)', '(1)'); + INSERT INTO t1 VALUES('(2)', '(2)'); + INSERT INTO t1 VALUES('(3)', '(3)'); + INSERT INTO t1 VALUES('(4)', '(4)'); + CREATE INDEX i1 ON t1(a, b); +} {} + + +do_execsql_test 1.1 { + ANALYZE; +} {} + +do_execsql_test 1.2 { + SELECT tbl,idx,nEq,nLt,nDLt,quote(sample) FROM sqlite_stat3; +} { + t1 i1 1 0 0 '(0)' + t1 i1 1 1 1 '(1)' + t1 i1 1 2 2 '(2)' + t1 i1 1 3 3 '(3)' + t1 i1 1 4 4 '(4)' +} + +if {[permutation] != "utf16"} { + do_execsql_test 1.3 { + SELECT tbl,idx,nEq,nLt,nDLt,quote(sample) FROM sqlite_stat3; + } { + t1 i1 1 0 0 '(0)' + t1 i1 1 1 1 '(1)' + t1 i1 1 2 2 '(2)' + t1 i1 1 3 3 '(3)' + t1 i1 1 4 4 '(4)' + } +} + + +#------------------------------------------------------------------------- +# This is really just to test SQL user function "test_decode". +# +reset_db +do_execsql_test 2.1 { + CREATE TABLE t1(a, b, c); + INSERT INTO t1(a) VALUES('some text'); + INSERT INTO t1(a) VALUES(14); + INSERT INTO t1(a) VALUES(NULL); + INSERT INTO t1(a) VALUES(22.0); + INSERT INTO t1(a) VALUES(x'656667'); + CREATE INDEX i1 ON t1(a, b, c); + ANALYZE; + SELECT quote(sample) FROM sqlite_stat3; +} { + NULL 14 22.0 {'some text'} X'656667' +} + +#------------------------------------------------------------------------- +# +reset_db +do_execsql_test 3.1 { + CREATE TABLE t2(a, b); + CREATE INDEX i2 ON t2(a, b); + BEGIN; +} + +do_test 3.2 { + for {set i 0} {$i < 1000} {incr i} { + set a [expr $i / 10] + set b [expr int(rand() * 15.0)] + execsql { INSERT INTO t2 VALUES($a, $b) } + } + execsql COMMIT +} {} + +db func lindex lindex + +# Each value of "a" occurs exactly 10 times in the table. +# +do_execsql_test 3.3.1 { + SELECT count(*) FROM t2 GROUP BY a; +} [lrange [string repeat "10 " 100] 0 99] + +# The first element in the "nEq" list of all samples should therefore be 10. +# +do_execsql_test 3.3.2 { + ANALYZE; + SELECT nEq FROM sqlite_stat3; +} [lrange [string repeat "10 " 100] 0 23] + +#------------------------------------------------------------------------- +# +do_execsql_test 3.4 { + DROP TABLE IF EXISTS t1; + CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c); + INSERT INTO t1 VALUES(1, 1, 'one-a'); + INSERT INTO t1 VALUES(11, 1, 'one-b'); + INSERT INTO t1 VALUES(21, 1, 'one-c'); + INSERT INTO t1 VALUES(31, 1, 'one-d'); + INSERT INTO t1 VALUES(41, 1, 'one-e'); + INSERT INTO t1 VALUES(51, 1, 'one-f'); + INSERT INTO t1 VALUES(61, 1, 'one-g'); + INSERT INTO t1 VALUES(71, 1, 'one-h'); + INSERT INTO t1 VALUES(81, 1, 'one-i'); + INSERT INTO t1 VALUES(91, 1, 'one-j'); + INSERT INTO t1 SELECT a+1,2,'two' || substr(c,4) FROM t1; + INSERT INTO t1 SELECT a+2,3,'three'||substr(c,4) FROM t1 WHERE c GLOB 'one-*'; + INSERT INTO t1 SELECT a+3,4,'four'||substr(c,4) FROM t1 WHERE c GLOB 'one-*'; + INSERT INTO t1 SELECT a+4,5,'five'||substr(c,4) FROM t1 WHERE c GLOB 'one-*'; + INSERT INTO t1 SELECT a+5,6,'six'||substr(c,4) FROM t1 WHERE c GLOB 'one-*'; + CREATE INDEX t1b ON t1(b); + ANALYZE; + SELECT c FROM t1 WHERE b=3 AND a BETWEEN 30 AND 60; +} {three-d three-e three-f} + + +#------------------------------------------------------------------------- +# These tests verify that the sample selection for stat3 appears to be +# working as designed. +# + +reset_db +db func lindex lindex +db func lrange lrange + +do_execsql_test 4.0 { + DROP TABLE IF EXISTS t1; + CREATE TABLE t1(a, b, c); + CREATE INDEX i1 ON t1(c, b, a); +} + + +proc insert_filler_rows_n {iStart args} { + set A(-ncopy) 1 + set A(-nval) 1 + + foreach {k v} $args { + if {[info exists A($k)]==0} { error "no such option: $k" } + set A($k) $v + } + if {[llength $args] % 2} { + error "option requires an argument: [lindex $args end]" + } + + for {set i 0} {$i < $A(-nval)} {incr i} { + set iVal [expr $iStart+$i] + for {set j 0} {$j < $A(-ncopy)} {incr j} { + execsql { INSERT INTO t1 VALUES($iVal, $iVal, $iVal) } + } + } +} + +do_test 4.1 { + execsql { BEGIN } + insert_filler_rows_n 0 -ncopy 10 -nval 19 + insert_filler_rows_n 20 -ncopy 1 -nval 100 + + execsql { + INSERT INTO t1(c, b, a) VALUES(200, 1, 'a'); + INSERT INTO t1(c, b, a) VALUES(200, 1, 'b'); + INSERT INTO t1(c, b, a) VALUES(200, 1, 'c'); + + INSERT INTO t1(c, b, a) VALUES(200, 2, 'e'); + INSERT INTO t1(c, b, a) VALUES(200, 2, 'f'); + + INSERT INTO t1(c, b, a) VALUES(201, 3, 'g'); + INSERT INTO t1(c, b, a) VALUES(201, 4, 'h'); + + ANALYZE; + SELECT count(*) FROM sqlite_stat3; + SELECT count(*) FROM t1; + } +} {24 297} + +do_execsql_test 4.2 { + SELECT neq, nlt, ndlt, sample FROM sqlite_stat3 ORDER BY rowid LIMIT 16; +} { + 10 0 0 0 + 10 10 1 1 + 10 20 2 2 + 10 30 3 3 + 10 40 4 4 + 10 50 5 5 + 10 60 6 6 + 10 70 7 7 + 10 80 8 8 + 10 90 9 9 + 10 100 10 10 + 10 110 11 11 + 10 120 12 12 + 10 130 13 13 + 10 140 14 14 + 10 150 15 15 +} + +do_execsql_test 4.3 { + SELECT neq, nlt, ndlt, sample FROM sqlite_stat3 + ORDER BY rowid DESC LIMIT 2; +} { + 2 295 120 201 + 5 290 119 200 +} + +do_execsql_test 4.4 { SELECT count(DISTINCT c) FROM t1 WHERE c<201 } 120 +do_execsql_test 4.5 { SELECT count(DISTINCT c) FROM t1 WHERE c<200 } 119 + +reset_db +do_test 4.7 { + execsql { + BEGIN; + CREATE TABLE t1(o,t INTEGER PRIMARY KEY); + CREATE INDEX i1 ON t1(o); + } + for {set i 0} {$i<10000} {incr i [expr (($i<1000)?1:10)]} { + execsql { INSERT INTO t1 VALUES('x', $i) } + } + execsql { + COMMIT; + ANALYZE; + SELECT count(*) FROM sqlite_stat3; + } +} {1} +do_execsql_test 4.8 { + SELECT sample FROM sqlite_stat3; +} {x} + + +#------------------------------------------------------------------------- +# The following would cause a crash at one point. +# +reset_db +do_execsql_test 5.1 { + PRAGMA encoding = 'utf-16'; + CREATE TABLE t0(v); + ANALYZE; +} + +#------------------------------------------------------------------------- +# This was also crashing (corrupt sqlite_stat3 table). +# +reset_db +do_execsql_test 6.1 { + CREATE TABLE t1(a, b); + CREATE INDEX i1 ON t1(a); + CREATE INDEX i2 ON t1(b); + INSERT INTO t1 VALUES(1, 1); + INSERT INTO t1 VALUES(2, 2); + INSERT INTO t1 VALUES(3, 3); + INSERT INTO t1 VALUES(4, 4); + INSERT INTO t1 VALUES(5, 5); + ANALYZE; + PRAGMA writable_schema = 1; + CREATE TEMP TABLE x1 AS + SELECT tbl,idx,neq,nlt,ndlt,sample FROM sqlite_stat3 + ORDER BY (rowid%5), rowid; + DELETE FROM sqlite_stat3; + INSERT INTO sqlite_stat3 SELECT * FROM x1; + PRAGMA writable_schema = 0; + ANALYZE sqlite_master; +} +do_execsql_test 6.2 { + SELECT * FROM t1 WHERE a = 'abc'; +} + +#------------------------------------------------------------------------- +# The following tests experiment with adding corrupted records to the +# 'sample' column of the sqlite_stat3 table. +# +reset_db +sqlite3_db_config_lookaside db 0 0 0 + +do_execsql_test 7.1 { + CREATE TABLE t1(a, b); + CREATE INDEX i1 ON t1(a, b); + INSERT INTO t1 VALUES(1, 1); + INSERT INTO t1 VALUES(2, 2); + INSERT INTO t1 VALUES(3, 3); + INSERT INTO t1 VALUES(4, 4); + INSERT INTO t1 VALUES(5, 5); + ANALYZE; + UPDATE sqlite_stat3 SET sample = X'' WHERE rowid = 1; + ANALYZE sqlite_master; +} + +do_execsql_test 7.2 { + UPDATE sqlite_stat3 SET sample = X'FFFF'; + ANALYZE sqlite_master; + SELECT * FROM t1 WHERE a = 1; +} {1 1} + +do_execsql_test 7.3 { + ANALYZE; + UPDATE sqlite_stat3 SET neq = '0 0 0'; + ANALYZE sqlite_master; + SELECT * FROM t1 WHERE a = 1; +} {1 1} + +do_execsql_test 7.4 { + ANALYZE; + UPDATE sqlite_stat3 SET ndlt = '0 0 0'; + ANALYZE sqlite_master; + SELECT * FROM t1 WHERE a = 3; +} {3 3} + +do_execsql_test 7.5 { + ANALYZE; + UPDATE sqlite_stat3 SET nlt = '0 0 0'; + ANALYZE sqlite_master; + SELECT * FROM t1 WHERE a = 5; +} {5 5} + +#------------------------------------------------------------------------- +# +reset_db +do_execsql_test 8.1 { + CREATE TABLE t1(x TEXT); + CREATE INDEX i1 ON t1(x); + INSERT INTO t1 VALUES('1'); + INSERT INTO t1 VALUES('2'); + INSERT INTO t1 VALUES('3'); + INSERT INTO t1 VALUES('4'); + ANALYZE; +} +do_execsql_test 8.2 { + SELECT * FROM t1 WHERE x = 3; +} {3} + +#------------------------------------------------------------------------- +# +reset_db +do_execsql_test 9.1 { + CREATE TABLE t1(a, b, c, d, e); + CREATE INDEX i1 ON t1(a, b, c, d); + CREATE INDEX i2 ON t1(e); +} +do_test 9.2 { + execsql BEGIN; + for {set i 0} {$i < 100} {incr i} { + execsql "INSERT INTO t1 VALUES('x', 'y', 'z', $i, [expr $i/2])" + } + for {set i 0} {$i < 20} {incr i} { + execsql "INSERT INTO t1 VALUES('x', 'y', 'z', 101, $i)" + } + for {set i 102} {$i < 200} {incr i} { + execsql "INSERT INTO t1 VALUES('x', 'y', 'z', $i, [expr $i/2])" + } + execsql COMMIT + execsql ANALYZE +} {} + +do_eqp_test 9.3.1 { + SELECT * FROM t1 WHERE a='x' AND b='y' AND c='z' AND d=101 AND e=5; +} {/t1 USING INDEX i1/} +do_eqp_test 9.3.2 { + SELECT * FROM t1 WHERE a='x' AND b='y' AND c='z' AND d=99 AND e=5; +} {/t1 USING INDEX i1/} + +set value_d [expr 101] +do_eqp_test 9.4.1 { + SELECT * FROM t1 WHERE a='x' AND b='y' AND c='z' AND d=$value_d AND e=5 +} {/t1 USING INDEX i1/} +set value_d [expr 99] +do_eqp_test 9.4.2 { + SELECT * FROM t1 WHERE a='x' AND b='y' AND c='z' AND d=$value_d AND e=5 +} {/t1 USING INDEX i1/} + +#------------------------------------------------------------------------- +# Check that the planner takes stat3 data into account when considering +# "IS NULL" and "IS NOT NULL" constraints. +# +do_execsql_test 10.1.1 { + DROP TABLE IF EXISTS t3; + CREATE TABLE t3(a, b); + CREATE INDEX t3a ON t3(a); + CREATE INDEX t3b ON t3(b); +} +do_test 10.1.2 { + for {set i 1} {$i < 100} {incr i} { + if {$i>90} { set a $i } else { set a NULL } + set b [expr $i % 5] + execsql "INSERT INTO t3 VALUES($a, $b)" + } + execsql ANALYZE +} {} +do_eqp_test 10.1.3 { + SELECT * FROM t3 WHERE a IS NULL AND b = 2 +} {/t3 USING INDEX t3b/} +do_eqp_test 10.1.4 { + SELECT * FROM t3 WHERE a IS NOT NULL AND b = 2 +} {/t3 USING INDEX t3a/} + +#------------------------------------------------------------------------- +# Check that stat3 data is used correctly with non-default collation +# sequences. +# +foreach {tn schema} { + 1 { + CREATE TABLE t4(a COLLATE nocase, b); + CREATE INDEX t4a ON t4(a); + CREATE INDEX t4b ON t4(b); + } + 2 { + CREATE TABLE t4(a, b); + CREATE INDEX t4a ON t4(a COLLATE nocase); + CREATE INDEX t4b ON t4(b); + } +} { + drop_all_tables + do_test 11.$tn.1 { execsql $schema } {} + + do_test 11.$tn.2 { + for {set i 0} {$i < 100} {incr i} { + if { ($i % 10)==0 } { set a ABC } else { set a DEF } + set b [expr $i % 5] + execsql { INSERT INTO t4 VALUES($a, $b) } + } + execsql ANALYZE + } {} + + do_eqp_test 11.$tn.3 { + SELECT * FROM t4 WHERE a = 'def' AND b = 3; + } {/t4 USING INDEX t4b/} + + if {$tn==1} { + set sql "SELECT * FROM t4 WHERE a = 'abc' AND b = 3;" + do_eqp_test 11.$tn.4 $sql {/t4 USING INDEX t4a/} + } else { + + set sql "SELECT * FROM t4 WHERE a = 'abc' COLLATE nocase AND b = 3;" + do_eqp_test 11.$tn.5 $sql {/t4 USING INDEX t4a/} + + set sql "SELECT * FROM t4 WHERE a COLLATE nocase = 'abc' AND b = 3;" + do_eqp_test 11.$tn.6 $sql {/t4 USING INDEX t4a/} + } +} + +#------------------------------------------------------------------------- +# Test that nothing untoward happens if the stat3 table contains entries +# for indexes that do not exist. Or NULL values in the idx column. +# Or NULL values in any of the other columns. +# +drop_all_tables +do_execsql_test 15.1 { + CREATE TABLE x1(a, b, UNIQUE(a, b)); + INSERT INTO x1 VALUES(1, 2); + INSERT INTO x1 VALUES(3, 4); + INSERT INTO x1 VALUES(5, 6); + ANALYZE; + INSERT INTO sqlite_stat3 VALUES(NULL, NULL, NULL, NULL, NULL, NULL); +} +db close +sqlite3 db test.db +do_execsql_test 15.2 { SELECT * FROM x1 } {1 2 3 4 5 6} + +do_execsql_test 15.3 { + INSERT INTO sqlite_stat3 VALUES(42, 42, 42, 42, 42, 42); +} +db close +sqlite3 db test.db +do_execsql_test 15.4 { SELECT * FROM x1 } {1 2 3 4 5 6} + +do_execsql_test 15.5 { + UPDATE sqlite_stat1 SET stat = NULL; +} +db close +sqlite3 db test.db +do_execsql_test 15.6 { SELECT * FROM x1 } {1 2 3 4 5 6} + +do_execsql_test 15.7 { + ANALYZE; + UPDATE sqlite_stat1 SET tbl = 'no such tbl'; +} +db close +sqlite3 db test.db +do_execsql_test 15.8 { SELECT * FROM x1 } {1 2 3 4 5 6} + +do_execsql_test 15.9 { + ANALYZE; + UPDATE sqlite_stat3 SET neq = NULL, nlt=NULL, ndlt=NULL; +} +db close +sqlite3 db test.db +do_execsql_test 15.10 { SELECT * FROM x1 } {1 2 3 4 5 6} + +# This is just for coverage.... +do_execsql_test 15.11 { + ANALYZE; + UPDATE sqlite_stat1 SET stat = stat || ' unordered'; +} +db close +sqlite3 db test.db +do_execsql_test 15.12 { SELECT * FROM x1 } {1 2 3 4 5 6} + +#------------------------------------------------------------------------- +# Test that allocations used for sqlite_stat3 samples are included in +# the quantity returned by SQLITE_DBSTATUS_SCHEMA_USED. +# +set one [string repeat x 1000] +set two [string repeat x 2000] +do_test 16.1 { + reset_db + execsql { + CREATE TABLE t1(a, UNIQUE(a)); + INSERT INTO t1 VALUES($one); + ANALYZE; + } + set nByte [lindex [sqlite3_db_status db SCHEMA_USED 0] 1] + + reset_db + execsql { + CREATE TABLE t1(a, UNIQUE(a)); + INSERT INTO t1 VALUES($two); + ANALYZE; + } + set nByte2 [lindex [sqlite3_db_status db SCHEMA_USED 0] 1] + + expr {$nByte2 > $nByte+950 && $nByte2 < $nByte+1050} +} {1} + +#------------------------------------------------------------------------- +# Test that stat3 data may be used with partial indexes. +# +do_test 17.1 { + reset_db + execsql { + CREATE TABLE t1(a, b, c, d); + CREATE INDEX i1 ON t1(a, b) WHERE d IS NOT NULL; + INSERT INTO t1 VALUES(-1, -1, -1, NULL); + INSERT INTO t1 SELECT 2*a,2*b,2*c,d FROM t1; + INSERT INTO t1 SELECT 2*a,2*b,2*c,d FROM t1; + INSERT INTO t1 SELECT 2*a,2*b,2*c,d FROM t1; + INSERT INTO t1 SELECT 2*a,2*b,2*c,d FROM t1; + INSERT INTO t1 SELECT 2*a,2*b,2*c,d FROM t1; + INSERT INTO t1 SELECT 2*a,2*b,2*c,d FROM t1; + } + + for {set i 0} {$i < 32} {incr i} { + execsql { INSERT INTO t1 VALUES($i%2, $b, $i/2, 'abc') } + } + execsql {ANALYZE main.t1} +} {} + +do_catchsql_test 17.1.2 { + ANALYZE temp.t1; +} {1 {no such table: temp.t1}} + +do_eqp_test 17.2 { + SELECT * FROM t1 WHERE d IS NOT NULL AND a=0; +} {/USING INDEX i1/} +do_eqp_test 17.3 { + SELECT * FROM t1 WHERE d IS NOT NULL AND a=0; +} {/USING INDEX i1/} + +do_execsql_test 17.4 { + CREATE INDEX i2 ON t1(c) WHERE d IS NOT NULL; + ANALYZE main.i2; +} +do_eqp_test 17.5 { + SELECT * FROM t1 WHERE d IS NOT NULL AND a=0; +} {/USING INDEX i1/} +do_eqp_test 17.6 { + SELECT * FROM t1 WHERE d IS NOT NULL AND a=0 AND b=0 AND c=10; +} {/USING INDEX i2/} + +#------------------------------------------------------------------------- +# +do_test 18.1 { + reset_db + execsql { + CREATE TABLE t1(a, b); + CREATE INDEX i1 ON t1(a, b); + } + for {set i 0} {$i < 9} {incr i} { + execsql { + INSERT INTO t1 VALUES($i, 0); + INSERT INTO t1 VALUES($i, 0); + INSERT INTO t1 VALUES($i, 0); + INSERT INTO t1 VALUES($i, 0); + INSERT INTO t1 VALUES($i, 0); + INSERT INTO t1 VALUES($i, 0); + INSERT INTO t1 VALUES($i, 0); + INSERT INTO t1 VALUES($i, 0); + INSERT INTO t1 VALUES($i, 0); + INSERT INTO t1 VALUES($i, 0); + INSERT INTO t1 VALUES($i, 0); + INSERT INTO t1 VALUES($i, 0); + INSERT INTO t1 VALUES($i, 0); + INSERT INTO t1 VALUES($i, 0); + INSERT INTO t1 VALUES($i, 0); + } + } + execsql ANALYZE + execsql { SELECT count(*) FROM sqlite_stat3 } +} {9} + +#------------------------------------------------------------------------- +# For coverage. +# +ifcapable view { + do_test 19.1 { + reset_db + execsql { + CREATE TABLE t1(x, y); + CREATE INDEX i1 ON t1(x, y); + CREATE VIEW v1 AS SELECT * FROM t1; + ANALYZE; + } + } {} +} +ifcapable auth { + proc authproc {op args} { + if {$op == "SQLITE_ANALYZE"} { return "SQLITE_DENY" } + return "SQLITE_OK" + } + do_test 19.2 { + reset_db + db auth authproc + execsql { + CREATE TABLE t1(x, y); + CREATE VIEW v1 AS SELECT * FROM t1; + } + catchsql ANALYZE + } {1 {not authorized}} +} + +#------------------------------------------------------------------------- +# +reset_db +proc r {args} { expr rand() } +db func r r +db func lrange lrange +do_test 20.1 { + execsql { + CREATE TABLE t1(a,b,c,d); + CREATE INDEX i1 ON t1(a,b,c,d); + } + for {set i 0} {$i < 16} {incr i} { + execsql { + INSERT INTO t1 VALUES($i, r(), r(), r()); + INSERT INTO t1 VALUES($i, $i, r(), r()); + INSERT INTO t1 VALUES($i, $i, $i, r()); + INSERT INTO t1 VALUES($i, $i, $i, $i); + INSERT INTO t1 VALUES($i, $i, $i, $i); + INSERT INTO t1 VALUES($i, $i, $i, r()); + INSERT INTO t1 VALUES($i, $i, r(), r()); + INSERT INTO t1 VALUES($i, r(), r(), r()); + } + } +} {} +do_execsql_test 20.2 { ANALYZE } +for {set i 0} {$i<16} {incr i} { + set val $i + do_execsql_test 20.3.$i { + SELECT count(*) FROM sqlite_stat3 WHERE sample=$val + } {1} +} + +finish_test + diff --git a/test/mallocA.test b/test/mallocA.test index 1e05723e13..61e88a61e7 100644 --- a/test/mallocA.test +++ b/test/mallocA.test @@ -97,6 +97,24 @@ do_faultsim_test 6.2 -faults oom* -body { } -test { faultsim_test_result [list 0 {1 2}] } +ifcapable stat3 { + do_test 6.3-prep { + execsql { + PRAGMA writable_schema = 1; + CREATE TABLE sqlite_stat4 AS + SELECT tbl, idx, neq, nlt, ndlt, sqlite_record(sample) AS sample + FROM sqlite_stat3; + } + } {} + do_faultsim_test 6.3 -faults oom* -body { + execsql { + ANALYZE sqlite_master; + SELECT rowid FROM t1 WHERE a='abc' AND b<'y'; + } + } -test { + faultsim_test_result [list 0 {1 2}] + } +} # Ensure that no file descriptors were leaked. do_test malloc-99.X { diff --git a/test/permutations.test b/test/permutations.test index b9033932d8..47c4665cdd 100644 --- a/test/permutations.test +++ b/test/permutations.test @@ -316,7 +316,7 @@ test_suite "coverage-analyze" -description { } -files { analyze3.test analyze4.test analyze5.test analyze6.test analyze7.test analyze8.test analyze9.test analyzeA.test - analyze.test mallocA.test + analyze.test analyzeB.test mallocA.test } From 74dade2155f4111617d93598bb1e1782f17a1d58 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 4 Sep 2013 18:14:53 +0000 Subject: [PATCH 015/101] Rearrange the order of conditions in an "if" statement to facilitate testing. FossilOrigin-Name: 8462fb43c275a70db59c4339650225deeadeef00 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/where.c | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index 3f42052729..e283ebdf5d 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\stests\sto\simprove\scoverage\swhen\sSQLITE_ENABLE_STAT3\sis\sdefined. -D 2013-09-04T16:38:42.308 +C Rearrange\sthe\sorder\sof\sconditions\sin\san\s"if"\sstatement\sto\sfacilitate\stesting. +D 2013-09-04T18:14:53.187 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5e41da95d92656a5004b03d3576e8b226858a28e F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -290,7 +290,7 @@ F src/vtab.c 165ce0e797c2cd23badb104c9f2ae9042d6d942c F src/wal.c 7dc3966ef98b74422267e7e6e46e07ff6c6eb1b4 F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4 F src/walker.c 4fa43583d0a84b48f93b1e88f11adf2065be4e73 -F src/where.c 95a351c94ecc9d6b4fa7f0e251ab480335b83ab8 +F src/where.c 613993bd44f43a5d78f1e0068f3d7197f3133990 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 F test/aggnested.test 45c0201e28045ad38a530b5a144b73cd4aa2cfd6 @@ -1110,7 +1110,7 @@ F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 F tool/wherecosttest.c f407dc4c79786982a475261866a161cd007947ae F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac -P d8fdc7821808e2bfa048144ee3015b745232dc30 -R 1b8932f1781f5719312a95a87cdda18d -U dan -Z 67321bf0786d50805840f21a47eb7fad +P f929e9b41f2f69b086be3dd48fe557adbba7ae5c +R cc5fb62c722092188f8662d393b9b48e +U drh +Z 3d3da6aaad5a89de084de232785827d1 diff --git a/manifest.uuid b/manifest.uuid index 0550529fea..05fd8fd0c5 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -f929e9b41f2f69b086be3dd48fe557adbba7ae5c \ No newline at end of file +8462fb43c275a70db59c4339650225deeadeef00 \ No newline at end of file diff --git a/src/where.c b/src/where.c index 13786160b6..0f6cffb042 100644 --- a/src/where.c +++ b/src/where.c @@ -2549,9 +2549,9 @@ static int whereRangeScanEst( Index *p = pBuilder->pNew->u.btree.pIndex; int nEq = pBuilder->pNew->u.btree.nEq; - if( nEq==pBuilder->nRecValid + if( p->nSample>0 + && nEq==pBuilder->nRecValid && nEqnSampleCol - && p->nSample && OptimizationEnabled(pParse->db, SQLITE_Stat3) ){ UnpackedRecord *pRec = pBuilder->pRec; From 8ff2d9561afc23db75500c1ed9fafe6ceef53e0b Mon Sep 17 00:00:00 2001 From: dan Date: Thu, 5 Sep 2013 18:40:29 +0000 Subject: [PATCH 016/101] When preparing an UPDATE statement, avoid generating VDBE code for those foreign key related actions and constraint checks that may be seen to be unnecessary by considering the subset of table columns potentially modified by the UPDATE. FossilOrigin-Name: e940b5de49baa1d6a4cf859fbbc0e0df86ac5dbf --- manifest | 25 ++++----- manifest.uuid | 2 +- src/delete.c | 4 +- src/fkey.c | 112 ++++++++++++++++++++++++++++++++--------- src/insert.c | 2 +- src/sqliteInt.h | 10 ++-- src/update.c | 6 +-- test/fkey7.test | 54 ++++++++++++++++++++ test/permutations.test | 2 +- 9 files changed, 169 insertions(+), 48 deletions(-) create mode 100644 test/fkey7.test diff --git a/manifest b/manifest index e283ebdf5d..60cf6a27a2 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Rearrange\sthe\sorder\sof\sconditions\sin\san\s"if"\sstatement\sto\sfacilitate\stesting. -D 2013-09-04T18:14:53.187 +C When\spreparing\san\sUPDATE\sstatement,\savoid\sgenerating\sVDBE\scode\sfor\sthose\sforeign\skey\srelated\sactions\sand\sconstraint\schecks\sthat\smay\sbe\sseen\sto\sbe\sunnecessary\sby\sconsidering\sthe\ssubset\sof\stable\scolumns\spotentially\smodified\sby\sthe\sUPDATE. +D 2013-09-05T18:40:29.445 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5e41da95d92656a5004b03d3576e8b226858a28e F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -171,16 +171,16 @@ F src/callback.c d7e46f40c3cf53c43550b7da7a1d0479910b62cc F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac F src/ctime.c ea4b7f3623a0fcb1146e7f245d7410033e86859c F src/date.c 067a81c9942c497aafd2c260e13add8a7d0c7dd4 -F src/delete.c 2317c814866d9aa71fea16b3faf4fdd4d6a49b94 +F src/delete.c 2dc64ca360b7d7da481183ea920a813a0c203c97 F src/expr.c 4d89bd03a04fcdb5ff71d86b4e0cc7d3230797b8 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb -F src/fkey.c 914a6bbd987d857c41ac9d244efa6641f36faadb +F src/fkey.c be866cd8c4fa6cae98ba33109578fd1a3311ee5b F src/func.c 5b064acd303b3e74f019ab551d423ff6cace4023 F src/global.c 5caf4deab621abb45b4c607aad1bd21c20aac759 F src/hash.c ac3470bbf1ca4ae4e306a8ecb0fdf1731810ffe4 F src/hash.h 8890a25af81fb85a9ad7790d32eedab4b994da22 F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08 -F src/insert.c a66bcdc956145369c1a876709f47f69476973e15 +F src/insert.c a271771db927873c850da8928d6ee9fc058fb9fe F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d F src/legacy.c 0df0b1550b9cc1f58229644735e317ac89131f12 F src/lempar.c cdf0a000315332fc9b50b62f3b5e22e080a0952b @@ -221,7 +221,7 @@ F src/shell.c d920a891ca09b8bd262cced7fb0ab9d723f7a747 F src/sqlite.h.in ec40aa958a270416fb04b4f72210357bf163d2c5 F src/sqlite3.rc fea433eb0a59f4c9393c8e6d76a6e2596b1fe0c0 F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc -F src/sqliteInt.h 600086a5082e2291b0aeeefcfbb546f2bbda67b2 +F src/sqliteInt.h a083fc4effb15c15946a36919793c311bc247b57 F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158 F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e @@ -273,7 +273,7 @@ F src/test_vfstrace.c 34b544e80ba7fb77be15395a609c669df2e660a2 F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9 F src/tokenize.c 70061085a51f2f4fc15ece94f32c03bcb78e63b2 F src/trigger.c 5c0ea9b8755e7c5e1a700f3e27ac4f8d92dd221e -F src/update.c 7d9d38e4f341ada7d79035ea969cdefb8b9014d1 +F src/update.c f5182157f5d0d0a97bc5f5e3c9bdba0dfbe08f08 F src/utf.c 6fc6c88d50448c469c5c196acf21617a24f90269 F src/util.c f566b5138099a2df8533b190d0dcc74b7dfbe0c9 F src/vacuum.c d9c5759f4c5a438bb43c2086f72c5d2edabc36c8 @@ -462,6 +462,7 @@ F test/fkey3.test 5ec899d12b13bcf1e9ef40eff7fb692fdb91392e F test/fkey4.test 86446017011273aad8f9a99c1a65019e7bd9ca9d F test/fkey5.test 0bf64f2d19ad80433ca0b24edbf604a18b353d5f F test/fkey6.test c555f7fc45d842cc84b0d3ff93951ce2b8c25fc8 +F test/fkey7.test e31d0e71a41c1d29349a16448d6c420e2c53a8fc F test/fkey_malloc.test bb74c9cb8f8fceed03b58f8a7ef2df98520bbd51 F test/format4.test 1f0cac8ff3895e9359ed87e41aaabee982a812eb F test/fts-9fd058691.test 78b887e30ae6816df0e1fed6259de4b5a64ad33c @@ -717,7 +718,7 @@ F test/pagesize.test 1dd51367e752e742f58e861e65ed7390603827a0 F test/pcache.test b09104b03160aca0d968d99e8cd2c5b1921a993d F test/pcache2.test a83efe2dec0d392f814bfc998def1d1833942025 F test/percentile.test b98fc868d71eb5619d42a1702e9ab91718cbed54 -F test/permutations.test 9cd3bba6f1e8658442d0dcfcef6c2e5efd131bdc +F test/permutations.test 72f4f8881d388163ddbbeec0a6ed812e863ea2e6 F test/pragma.test 5e7de6c32a5d764f09437d2025f07e4917b9e178 F test/pragma2.test 224f0381f9411a78ae685cac24c13656a62021b7 F test/printf.test ec9870c4dce8686a37818e0bf1aba6e6a1863552 @@ -1110,7 +1111,7 @@ F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 F tool/wherecosttest.c f407dc4c79786982a475261866a161cd007947ae F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac -P f929e9b41f2f69b086be3dd48fe557adbba7ae5c -R cc5fb62c722092188f8662d393b9b48e -U drh -Z 3d3da6aaad5a89de084de232785827d1 +P 8462fb43c275a70db59c4339650225deeadeef00 +R d3b1cfd48ce8f1b63476cb1b87cb1fe9 +U dan +Z ebec4296d6724df2f506ca7d4f2e487f diff --git a/manifest.uuid b/manifest.uuid index 05fd8fd0c5..1ea65c845e 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -8462fb43c275a70db59c4339650225deeadeef00 \ No newline at end of file +e940b5de49baa1d6a4cf859fbbc0e0df86ac5dbf \ No newline at end of file diff --git a/src/delete.c b/src/delete.c index af64afc65c..50a35cd165 100644 --- a/src/delete.c +++ b/src/delete.c @@ -536,7 +536,7 @@ void sqlite3GenerateRowDelete( /* Do FK processing. This call checks that any FK constraints that ** refer to this table (i.e. constraints attached to other tables) ** are not violated by deleting this row. */ - sqlite3FkCheck(pParse, pTab, iOld, 0); + sqlite3FkCheck(pParse, pTab, iOld, 0, 0, 0); } /* Delete the index and table entries. Skip this step if pTab is really @@ -553,7 +553,7 @@ void sqlite3GenerateRowDelete( /* Do any ON CASCADE, SET NULL or SET DEFAULT operations required to ** handle rows (possibly in other tables) that refer via a foreign key ** to the row just deleted. */ - sqlite3FkActions(pParse, pTab, 0, iOld); + sqlite3FkActions(pParse, pTab, 0, iOld, 0, 0); /* Invoke AFTER DELETE trigger programs. */ sqlite3CodeRowTrigger(pParse, pTrigger, diff --git a/src/fkey.c b/src/fkey.c index bb59c656f6..1947c2ee20 100644 --- a/src/fkey.c +++ b/src/fkey.c @@ -682,6 +682,70 @@ void sqlite3FkDropTable(Parse *pParse, SrcList *pName, Table *pTab){ } } + +/* +** The second argument points to an FKey object representing a foreign key +** for which pTab is the child table. An UPDATE statement against pTab +** is currently being processed. For each column of the table that is +** actually updated, the corresponding element in the aChange[] array +** is zero or greater (if a column is unmodified the corresponding element +** is set to -1). If the rowid column is modified by the UPDATE statement +** the bChngRowid argument is non-zero. +** +** This function returns true if any of the columns that are part of the +** child key for FK constraint *p are modified. +*/ +static int fkChildIsModified( + Table *pTab, /* Table being updated */ + FKey *p, /* Foreign key for which pTab is the child */ + int *aChange, /* Array indicating modified columns */ + int bChngRowid /* True if rowid is modified by this update */ +){ + int i; + for(i=0; inCol; i++){ + int iChildKey = p->aCol[i].iFrom; + if( aChange[iChildKey]>=0 ) return 1; + if( iChildKey==pTab->iPKey && bChngRowid ) return 1; + } + return 0; +} + +/* +** The second argument points to an FKey object representing a foreign key +** for which pTab is the parent table. An UPDATE statement against pTab +** is currently being processed. For each column of the table that is +** actually updated, the corresponding element in the aChange[] array +** is zero or greater (if a column is unmodified the corresponding element +** is set to -1). If the rowid column is modified by the UPDATE statement +** the bChngRowid argument is non-zero. +** +** This function returns true if any of the columns that are part of the +** parent key for FK constraint *p are modified. +*/ +static int fkParentIsModified( + Table *pTab, + FKey *p, + int *aChange, + int bChngRowid +){ + int i; + for(i=0; inCol; i++){ + char *zKey = p->aCol[i].zCol; + int iKey; + for(iKey=0; iKeynCol; iKey++){ + if( aChange[iKey]>=0 || (iKey==pTab->iPKey && bChngRowid) ){ + Column *pCol = &pTab->aCol[iKey]; + if( zKey ){ + if( 0==sqlite3StrICmp(pCol->zName, zKey) ) return 1; + }else if( pCol->colFlags & COLFLAG_PRIMKEY ){ + return 1; + } + } + } + } + return 0; +} + /* ** This function is called when inserting, deleting or updating a row of ** table pTab to generate VDBE code to perform foreign key constraint @@ -706,7 +770,9 @@ void sqlite3FkCheck( Parse *pParse, /* Parse context */ Table *pTab, /* Row is being deleted from this table */ int regOld, /* Previous row data is stored here */ - int regNew /* New row data is stored here */ + int regNew, /* New row data is stored here */ + int *aChange, /* Array indicating UPDATEd columns (or 0) */ + int bChngRowid /* True if rowid is UPDATEd */ ){ sqlite3 *db = pParse->db; /* Database handle */ FKey *pFKey; /* Used to iterate through FKs */ @@ -734,6 +800,13 @@ void sqlite3FkCheck( int i; int isIgnore = 0; + if( aChange + && sqlite3_stricmp(pTab->zName, pFKey->zTo)!=0 + && fkChildIsModified(pTab, pFKey, aChange, bChngRowid)==0 + ){ + continue; + } + /* Find the parent table of this foreign key. Also find a unique index ** on the parent key columns in the parent table. If either of these ** schema items cannot be located, set an error in pParse and return @@ -816,6 +889,10 @@ void sqlite3FkCheck( SrcList *pSrc; int *aiCol = 0; + if( aChange && fkParentIsModified(pTab, pFKey, aChange, bChngRowid)==0 ){ + continue; + } + if( !pFKey->isDeferred && !(db->flags & SQLITE_DeferFKs) && !pParse->pToplevel && !pParse->isMultiWrite ){ @@ -889,6 +966,7 @@ u32 sqlite3FkOldmask( return mask; } + /* ** This function is called before generating code to update or delete a ** row contained in table pTab. If the operation is a DELETE, then @@ -918,32 +996,16 @@ int sqlite3FkRequired( }else{ /* This is an UPDATE. Foreign key processing is only required if the ** operation modifies one or more child or parent key columns. */ - int i; FKey *p; /* Check if any child key columns are being modified. */ for(p=pTab->pFKey; p; p=p->pNextFrom){ - for(i=0; inCol; i++){ - int iChildKey = p->aCol[i].iFrom; - if( aChange[iChildKey]>=0 ) return 1; - if( iChildKey==pTab->iPKey && chngRowid ) return 1; - } + if( fkChildIsModified(pTab, p, aChange, chngRowid) ) return 1; } /* Check if any parent key columns are being modified. */ for(p=sqlite3FkReferences(pTab); p; p=p->pNextTo){ - for(i=0; inCol; i++){ - char *zKey = p->aCol[i].zCol; - int iKey; - for(iKey=0; iKeynCol; iKey++){ - Column *pCol = &pTab->aCol[iKey]; - if( (zKey ? !sqlite3StrICmp(pCol->zName, zKey) - : (pCol->colFlags & COLFLAG_PRIMKEY)!=0) ){ - if( aChange[iKey]>=0 ) return 1; - if( iKey==pTab->iPKey && chngRowid ) return 1; - } - } - } + if( fkParentIsModified(pTab, p, aChange, chngRowid) ) return 1; } } } @@ -1169,7 +1231,9 @@ void sqlite3FkActions( Parse *pParse, /* Parse context */ Table *pTab, /* Table being updated or deleted from */ ExprList *pChanges, /* Change-list for UPDATE, NULL for DELETE */ - int regOld /* Address of array containing old row */ + int regOld, /* Address of array containing old row */ + int *aChange, /* Array indicating UPDATEd columns (or 0) */ + int bChngRowid /* True if rowid is UPDATEd */ ){ /* If foreign-key support is enabled, iterate through all FKs that ** refer to table pTab. If there is an action associated with the FK @@ -1178,9 +1242,11 @@ void sqlite3FkActions( if( pParse->db->flags&SQLITE_ForeignKeys ){ FKey *pFKey; /* Iterator variable */ for(pFKey = sqlite3FkReferences(pTab); pFKey; pFKey=pFKey->pNextTo){ - Trigger *pAction = fkActionTrigger(pParse, pTab, pFKey, pChanges); - if( pAction ){ - sqlite3CodeRowTriggerDirect(pParse, pAction, pTab, regOld, OE_Abort, 0); + if( aChange==0 || fkParentIsModified(pTab, pFKey, aChange, bChngRowid) ){ + Trigger *pAct = fkActionTrigger(pParse, pTab, pFKey, pChanges); + if( pAct ){ + sqlite3CodeRowTriggerDirect(pParse, pAct, pTab, regOld, OE_Abort, 0); + } } } } diff --git a/src/insert.c b/src/insert.c index 1c2cabb938..32cfb83fa8 100644 --- a/src/insert.c +++ b/src/insert.c @@ -1031,7 +1031,7 @@ void sqlite3Insert( sqlite3GenerateConstraintChecks(pParse, pTab, baseCur, regIns, aRegIdx, keyColumn>=0, 0, onError, endOfLoop, &isReplace ); - sqlite3FkCheck(pParse, pTab, 0, regIns); + sqlite3FkCheck(pParse, pTab, 0, regIns, 0, 0); sqlite3CompleteInsertion( pParse, pTab, baseCur, regIns, aRegIdx, 0, appendFlag, isReplace==0 ); diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 49264238b8..d74903fda1 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -3209,18 +3209,18 @@ const char *sqlite3JournalModename(int); ** provided (enforcement of FK constraints requires the triggers sub-system). */ #if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER) - void sqlite3FkCheck(Parse*, Table*, int, int); + void sqlite3FkCheck(Parse*, Table*, int, int, int*, int); void sqlite3FkDropTable(Parse*, SrcList *, Table*); - void sqlite3FkActions(Parse*, Table*, ExprList*, int); + void sqlite3FkActions(Parse*, Table*, ExprList*, int, int*, int); int sqlite3FkRequired(Parse*, Table*, int*, int); u32 sqlite3FkOldmask(Parse*, Table*); FKey *sqlite3FkReferences(Table *); #else - #define sqlite3FkActions(a,b,c,d) + #define sqlite3FkActions(a,b,c,d,e,f) #define sqlite3FkCheck(a,b,c,d) #define sqlite3FkDropTable(a,b,c) - #define sqlite3FkOldmask(a,b) 0 - #define sqlite3FkRequired(a,b,c,d) 0 + #define sqlite3FkOldmask(a,b) 0 + #define sqlite3FkRequired(a,b,c,d,e,f) 0 #endif #ifndef SQLITE_OMIT_FOREIGN_KEY void sqlite3FkDelete(sqlite3 *, Table*); diff --git a/src/update.c b/src/update.c index 5077f64e35..0f760a4609 100644 --- a/src/update.c +++ b/src/update.c @@ -488,7 +488,7 @@ void sqlite3Update( /* Do FK constraint checks. */ if( hasFK ){ - sqlite3FkCheck(pParse, pTab, regOldRowid, 0); + sqlite3FkCheck(pParse, pTab, regOldRowid, 0, aXRef, chngRowid); } /* Delete the index entries associated with the current record. */ @@ -502,7 +502,7 @@ void sqlite3Update( sqlite3VdbeJumpHere(v, j1); if( hasFK ){ - sqlite3FkCheck(pParse, pTab, 0, regNewRowid); + sqlite3FkCheck(pParse, pTab, 0, regNewRowid, aXRef, chngRowid); } /* Insert the new index entries and the new record. */ @@ -512,7 +512,7 @@ void sqlite3Update( ** handle rows (possibly in other tables) that refer via a foreign key ** to the row just updated. */ if( hasFK ){ - sqlite3FkActions(pParse, pTab, pChanges, regOldRowid); + sqlite3FkActions(pParse, pTab, pChanges, regOldRowid, aXRef, chngRowid); } } diff --git a/test/fkey7.test b/test/fkey7.test new file mode 100644 index 0000000000..c2682edbe5 --- /dev/null +++ b/test/fkey7.test @@ -0,0 +1,54 @@ +# 2001 September 15 +# +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. +# +#*********************************************************************** +# This file implements regression tests for SQLite library. +# +# This file implements tests for foreign keys. +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl +set testprefix fkey7 + +ifcapable {!foreignkey} { + finish_test + return +} + +do_execsql_test 1.1 { + PRAGMA foreign_keys = 1; + + CREATE TABLE s1(a PRIMARY KEY, b); + CREATE TABLE par(a, b REFERENCES s1, c UNIQUE, PRIMARY KEY(a)); + + CREATE TABLE c1(a, b REFERENCES par); + CREATE TABLE c2(a, b REFERENCES par); + CREATE TABLE c3(a, b REFERENCES par(c)); +} + +proc auth {op tbl args} { + if {$op == "SQLITE_READ"} { set ::tbls($tbl) 1 } + return "SQLITE_OK" +} +db auth auth +db cache size 0 +proc do_tblsread_test {tn sql tbllist} { + array unset ::tbls + uplevel [list execsql $sql] + uplevel [list do_test $tn {lsort [array names ::tbls]} $tbllist] +} + +do_tblsread_test 1.2 { UPDATE par SET b=? WHERE a=? } {par s1} +do_tblsread_test 1.3 { UPDATE par SET a=? WHERE b=? } {c1 c2 par} +do_tblsread_test 1.4 { UPDATE par SET c=? WHERE b=? } {c3 par} +do_tblsread_test 1.5 { UPDATE par SET a=?,b=?,c=? WHERE b=? } {c1 c2 c3 par s1} + + +finish_test diff --git a/test/permutations.test b/test/permutations.test index 47c4665cdd..7468b89673 100644 --- a/test/permutations.test +++ b/test/permutations.test @@ -509,7 +509,7 @@ test_suite "utf16" -description { } -files { alter.test alter3.test analyze.test analyze3.test analyze4.test analyze5.test analyze6.test - analyze7.test analyze8.test analyze9.test analyzeA.test + analyze7.test analyze8.test analyze9.test analyzeA.test analyzeB.test auth.test bind.test blob.test capi2.test capi3.test collate1.test collate2.test collate3.test collate4.test collate5.test collate6.test conflict.test date.test delete.test expr.test fkey1.test func.test From 0d31dc37ac2a659fca1058c16928a29ccaca3ab4 Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 6 Sep 2013 00:40:59 +0000 Subject: [PATCH 017/101] Make sure the destination WhereLoop is left in a sane state when an OOM fault occurs inside of whereLoopXfer(). FossilOrigin-Name: a99a53b81e29c9514b85318bea028d1667e5f760 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/where.c | 5 ++++- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 60cf6a27a2..f9d32711c6 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C When\spreparing\san\sUPDATE\sstatement,\savoid\sgenerating\sVDBE\scode\sfor\sthose\sforeign\skey\srelated\sactions\sand\sconstraint\schecks\sthat\smay\sbe\sseen\sto\sbe\sunnecessary\sby\sconsidering\sthe\ssubset\sof\stable\scolumns\spotentially\smodified\sby\sthe\sUPDATE. -D 2013-09-05T18:40:29.445 +C Make\ssure\sthe\sdestination\sWhereLoop\sis\sleft\sin\sa\ssane\sstate\swhen\san\nOOM\sfault\soccurs\sinside\sof\swhereLoopXfer(). +D 2013-09-06T00:40:59.250 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5e41da95d92656a5004b03d3576e8b226858a28e F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -290,7 +290,7 @@ F src/vtab.c 165ce0e797c2cd23badb104c9f2ae9042d6d942c F src/wal.c 7dc3966ef98b74422267e7e6e46e07ff6c6eb1b4 F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4 F src/walker.c 4fa43583d0a84b48f93b1e88f11adf2065be4e73 -F src/where.c 613993bd44f43a5d78f1e0068f3d7197f3133990 +F src/where.c 06c249a5137575ecf4d527e5a1dadb1087e4375c F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 F test/aggnested.test 45c0201e28045ad38a530b5a144b73cd4aa2cfd6 @@ -1111,7 +1111,7 @@ F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 F tool/wherecosttest.c f407dc4c79786982a475261866a161cd007947ae F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac -P 8462fb43c275a70db59c4339650225deeadeef00 -R d3b1cfd48ce8f1b63476cb1b87cb1fe9 -U dan -Z ebec4296d6724df2f506ca7d4f2e487f +P e940b5de49baa1d6a4cf859fbbc0e0df86ac5dbf +R 27c19be948fb041fa8a271cfce7ac00b +U drh +Z 37cec8f35623233f7042fbd6abda9820 diff --git a/manifest.uuid b/manifest.uuid index 1ea65c845e..dd8735e5d7 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -e940b5de49baa1d6a4cf859fbbc0e0df86ac5dbf \ No newline at end of file +a99a53b81e29c9514b85318bea028d1667e5f760 \ No newline at end of file diff --git a/src/where.c b/src/where.c index 0f6cffb042..3c8a1eaac6 100644 --- a/src/where.c +++ b/src/where.c @@ -4068,8 +4068,11 @@ static int whereLoopResize(sqlite3 *db, WhereLoop *p, int n){ ** Transfer content from the second pLoop into the first. */ static int whereLoopXfer(sqlite3 *db, WhereLoop *pTo, WhereLoop *pFrom){ - if( whereLoopResize(db, pTo, pFrom->nLTerm) ) return SQLITE_NOMEM; whereLoopClearUnion(db, pTo); + if( whereLoopResize(db, pTo, pFrom->nLTerm) ){ + memset(&pTo->u, 0, sizeof(pTo->u)); + return SQLITE_NOMEM; + } memcpy(pTo, pFrom, WHERE_LOOP_XFER_SZ); memcpy(pTo->aLTerm, pFrom->aLTerm, pTo->nLTerm*sizeof(pTo->aLTerm[0])); if( pFrom->wsFlags & WHERE_VIRTUALTABLE ){ From d36e1041120280adfc9612d8f6e4ade318b3ffa0 Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 6 Sep 2013 13:10:12 +0000 Subject: [PATCH 018/101] Combine the FuncDef.iPrefEnc and FuncDef.flags fields into a single new FuncDef.funcFlags field. FossilOrigin-Name: 97b10e66e98e84755aa577f8da017bf1aea2056c --- manifest | 32 ++++++++++++++++---------------- manifest.uuid | 2 +- src/analyze.c | 9 +++------ src/attach.c | 6 ++---- src/callback.c | 6 +++--- src/expr.c | 13 +++++++------ src/func.c | 8 ++++---- src/main.c | 4 ++-- src/select.c | 4 ++-- src/sqliteInt.h | 31 ++++++++++++++++--------------- src/vdbe.c | 4 ++-- src/vdbeaux.c | 2 +- src/vtab.c | 2 +- 13 files changed, 60 insertions(+), 63 deletions(-) diff --git a/manifest b/manifest index f9d32711c6..91047af181 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Make\ssure\sthe\sdestination\sWhereLoop\sis\sleft\sin\sa\ssane\sstate\swhen\san\nOOM\sfault\soccurs\sinside\sof\swhereLoopXfer(). -D 2013-09-06T00:40:59.250 +C Combine\sthe\sFuncDef.iPrefEnc\sand\sFuncDef.flags\sfields\sinto\sa\ssingle\nnew\sFuncDef.funcFlags\sfield. +D 2013-09-06T13:10:12.385 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5e41da95d92656a5004b03d3576e8b226858a28e F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -157,8 +157,8 @@ F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a F src/alter.c 2af0330bb1b601af7a7789bf7229675fd772a083 -F src/analyze.c 3f1c87b00c52e49caa0a190528503fda8f26fc3a -F src/attach.c fea00cab11c854646a27641a263f5876569a51f9 +F src/analyze.c 7da9d6a0d04a3662d110a28f4a7e7b73a6171e75 +F src/attach.c eeb8d9d2c791caa0a54a835170ea898e96c2802d F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34 F src/backup.c 2f1987981139bd2f6d8c728d64bf09fb387443c3 F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb @@ -167,15 +167,15 @@ F src/btree.c b9b57df546df2636294bfb21a986f5707b417df2 F src/btree.h bfe0e8c5759b4ec77b0d18390064a6ef3cdffaaf F src/btreeInt.h 51cf220a9b9223354770883e93a859dc377aa27f F src/build.c f63e8929c7f89c0074fbc74929bc946ea117b2f8 -F src/callback.c d7e46f40c3cf53c43550b7da7a1d0479910b62cc +F src/callback.c f99a8957ba2adf369645fac0db09ad8adcf1caa2 F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac F src/ctime.c ea4b7f3623a0fcb1146e7f245d7410033e86859c F src/date.c 067a81c9942c497aafd2c260e13add8a7d0c7dd4 F src/delete.c 2dc64ca360b7d7da481183ea920a813a0c203c97 -F src/expr.c 4d89bd03a04fcdb5ff71d86b4e0cc7d3230797b8 +F src/expr.c 33ae44812d25799000dbcfd54bb2142b30cdd049 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fkey.c be866cd8c4fa6cae98ba33109578fd1a3311ee5b -F src/func.c 5b064acd303b3e74f019ab551d423ff6cace4023 +F src/func.c 7650d35651bb0ca903d24f4e5e944bfdaac9f152 F src/global.c 5caf4deab621abb45b4c607aad1bd21c20aac759 F src/hash.c ac3470bbf1ca4ae4e306a8ecb0fdf1731810ffe4 F src/hash.h 8890a25af81fb85a9ad7790d32eedab4b994da22 @@ -185,7 +185,7 @@ F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d F src/legacy.c 0df0b1550b9cc1f58229644735e317ac89131f12 F src/lempar.c cdf0a000315332fc9b50b62f3b5e22e080a0952b F src/loadext.c 867c7b330b740c6c917af9956b13b81d0a048303 -F src/main.c c4c781b06faa2ce4040c32a75fd931a07ba7054e +F src/main.c 35931467ec026b05babb279cb8a573e62f6fe1a3 F src/malloc.c fe085aa851b666b7c375c1ff957643dc20a04bf6 F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c 437c7c4af964895d4650f29881df63535caaa1fa @@ -216,12 +216,12 @@ F src/printf.c da9119eb31a187a4b99f60aa4a225141c0ebb74b F src/random.c 0b2dbc37fdfbfa6bd455b091dfcef5bdb32dba68 F src/resolve.c 9d53899cc6e1f4ec0b4632d07e97d57827bf63b9 F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0 -F src/select.c 8b148eb851f384412aea57091659d14b369918ca +F src/select.c 9239586282bd146ec5843a2cde7d54cd7816cf78 F src/shell.c d920a891ca09b8bd262cced7fb0ab9d723f7a747 F src/sqlite.h.in ec40aa958a270416fb04b4f72210357bf163d2c5 F src/sqlite3.rc fea433eb0a59f4c9393c8e6d76a6e2596b1fe0c0 F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc -F src/sqliteInt.h a083fc4effb15c15946a36919793c311bc247b57 +F src/sqliteInt.h 32e959dba9899360ce4ae3cd6cc77b4a8df277e8 F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158 F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e @@ -277,16 +277,16 @@ F src/update.c f5182157f5d0d0a97bc5f5e3c9bdba0dfbe08f08 F src/utf.c 6fc6c88d50448c469c5c196acf21617a24f90269 F src/util.c f566b5138099a2df8533b190d0dcc74b7dfbe0c9 F src/vacuum.c d9c5759f4c5a438bb43c2086f72c5d2edabc36c8 -F src/vdbe.c 2b1cd2c7e3d74e6aa99ce2f538bfdd07a00dc2f1 +F src/vdbe.c a393a94c0d77b86c7c4ad2cfb43ec4ba278d9596 F src/vdbe.h 4f554b5627f26710c4c36d919110a3fc611ca5c4 F src/vdbeInt.h cbe71b8b36d8b3bba5709cc3f436c7e3b47b7b08 F src/vdbeapi.c 96b24b946cf21894f63d9393e821baa2f0a80979 -F src/vdbeaux.c c7fe2695e256dbf254113c4fe90d3ec9aabe3bbe +F src/vdbeaux.c 88beca92f2ed0bbe2c6f87946d0e999a6807ea1b F src/vdbeblob.c 5dc79627775bd9a9b494dd956e26297946417d69 F src/vdbemem.c 817ce21ab4ca57f902619bb8fef3f8a51bbd0ed8 F src/vdbesort.c 3937e06b2a0e354500e17dc206ef4c35770a5017 F src/vdbetrace.c e7ec40e1999ff3c6414424365d5941178966dcbc -F src/vtab.c 165ce0e797c2cd23badb104c9f2ae9042d6d942c +F src/vtab.c 5a423b042eb1402ef77697d03d6a67378d97bc8d F src/wal.c 7dc3966ef98b74422267e7e6e46e07ff6c6eb1b4 F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4 F src/walker.c 4fa43583d0a84b48f93b1e88f11adf2065be4e73 @@ -1111,7 +1111,7 @@ F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 F tool/wherecosttest.c f407dc4c79786982a475261866a161cd007947ae F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac -P e940b5de49baa1d6a4cf859fbbc0e0df86ac5dbf -R 27c19be948fb041fa8a271cfce7ac00b +P a99a53b81e29c9514b85318bea028d1667e5f760 +R 8c10a6011eb52c6098e833ca515e6c77 U drh -Z 37cec8f35623233f7042fbd6abda9820 +Z c7e49c79214a66374f550dcdb7a70012 diff --git a/manifest.uuid b/manifest.uuid index dd8735e5d7..dbc304a491 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -a99a53b81e29c9514b85318bea028d1667e5f760 \ No newline at end of file +97b10e66e98e84755aa577f8da017bf1aea2056c \ No newline at end of file diff --git a/src/analyze.c b/src/analyze.c index 64dae669f2..42c81fd659 100644 --- a/src/analyze.c +++ b/src/analyze.c @@ -371,8 +371,7 @@ static void statInit( } static const FuncDef statInitFuncdef = { 1+IsStat34, /* nArg */ - SQLITE_UTF8, /* iPrefEnc */ - 0, /* flags */ + SQLITE_UTF8, /* funcFlags */ 0, /* pUserData */ 0, /* pNext */ statInit, /* xFunc */ @@ -668,8 +667,7 @@ static void statPush( } static const FuncDef statPushFuncdef = { 2+IsStat34, /* nArg */ - SQLITE_UTF8, /* iPrefEnc */ - 0, /* flags */ + SQLITE_UTF8, /* funcFlags */ 0, /* pUserData */ 0, /* pNext */ statPush, /* xFunc */ @@ -804,8 +802,7 @@ static void statGet( } static const FuncDef statGetFuncdef = { 1+IsStat34, /* nArg */ - SQLITE_UTF8, /* iPrefEnc */ - 0, /* flags */ + SQLITE_UTF8, /* funcFlags */ 0, /* pUserData */ 0, /* pNext */ statGet, /* xFunc */ diff --git a/src/attach.c b/src/attach.c index ce95ea702e..6d965ace65 100644 --- a/src/attach.c +++ b/src/attach.c @@ -379,8 +379,7 @@ attach_end: void sqlite3Detach(Parse *pParse, Expr *pDbname){ static const FuncDef detach_func = { 1, /* nArg */ - SQLITE_UTF8, /* iPrefEnc */ - 0, /* flags */ + SQLITE_UTF8, /* funcFlags */ 0, /* pUserData */ 0, /* pNext */ detachFunc, /* xFunc */ @@ -401,8 +400,7 @@ void sqlite3Detach(Parse *pParse, Expr *pDbname){ void sqlite3Attach(Parse *pParse, Expr *p, Expr *pDbname, Expr *pKey){ static const FuncDef attach_func = { 3, /* nArg */ - SQLITE_UTF8, /* iPrefEnc */ - 0, /* flags */ + SQLITE_UTF8, /* funcFlags */ 0, /* pUserData */ 0, /* pNext */ attachFunc, /* xFunc */ diff --git a/src/callback.c b/src/callback.c index d40c65cb92..66fa490894 100644 --- a/src/callback.c +++ b/src/callback.c @@ -270,9 +270,9 @@ static int matchQuality( } /* Bonus points if the text encoding matches */ - if( enc==p->iPrefEnc ){ + if( enc==(p->funcFlags & SQLITE_FUNC_ENCMASK) ){ match += 2; /* Exact encoding match */ - }else if( (enc & p->iPrefEnc & 2)!=0 ){ + }else if( (enc & p->funcFlags & 2)!=0 ){ match += 1; /* Both are UTF16, but with different byte orders */ } @@ -406,7 +406,7 @@ FuncDef *sqlite3FindFunction( (pBest = sqlite3DbMallocZero(db, sizeof(*pBest)+nName+1))!=0 ){ pBest->zName = (char *)&pBest[1]; pBest->nArg = (u16)nArg; - pBest->iPrefEnc = enc; + pBest->funcFlags = enc; memcpy(pBest->zName, zName, nName); pBest->zName[nName] = 0; sqlite3FuncDefInsert(&db->aFunc, pBest); diff --git a/src/expr.c b/src/expr.c index aa6f275438..6587ee1f78 100644 --- a/src/expr.c +++ b/src/expr.c @@ -2634,7 +2634,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ ** IFNULL() functions. This avoids unnecessary evalation of ** arguments past the first non-NULL argument. */ - if( pDef->flags & SQLITE_FUNC_COALESCE ){ + if( pDef->funcFlags & SQLITE_FUNC_COALESCE ){ int endCoalesce = sqlite3VdbeMakeLabel(v); assert( nFarg>=2 ); sqlite3ExprCode(pParse, pFarg->a[0].pExpr, target); @@ -2658,7 +2658,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ ** or OPFLAG_TYPEOFARG respectively, to avoid unnecessary data ** loading. */ - if( (pDef->flags & (SQLITE_FUNC_LENGTH|SQLITE_FUNC_TYPEOF))!=0 ){ + if( (pDef->funcFlags & (SQLITE_FUNC_LENGTH|SQLITE_FUNC_TYPEOF))!=0 ){ u8 exprOp; assert( nFarg==1 ); assert( pFarg->a[0].pExpr!=0 ); @@ -2666,8 +2666,9 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ if( exprOp==TK_COLUMN || exprOp==TK_AGG_COLUMN ){ assert( SQLITE_FUNC_LENGTH==OPFLAG_LENGTHARG ); assert( SQLITE_FUNC_TYPEOF==OPFLAG_TYPEOFARG ); - testcase( pDef->flags==SQLITE_FUNC_LENGTH ); - pFarg->a[0].pExpr->op2 = pDef->flags; + testcase( (pDef->funcFlags&~SQLITE_FUNC_ENCMASK) + ==SQLITE_FUNC_LENGTH ); + pFarg->a[0].pExpr->op2 = pDef->funcFlags&~SQLITE_FUNC_ENCMASK; } } @@ -2700,11 +2701,11 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ if( i<32 && sqlite3ExprIsConstant(pFarg->a[i].pExpr) ){ constMask |= (1<flags & SQLITE_FUNC_NEEDCOLL)!=0 && !pColl ){ + if( (pDef->funcFlags & SQLITE_FUNC_NEEDCOLL)!=0 && !pColl ){ pColl = sqlite3ExprCollSeq(pParse, pFarg->a[i].pExpr); } } - if( pDef->flags & SQLITE_FUNC_NEEDCOLL ){ + if( pDef->funcFlags & SQLITE_FUNC_NEEDCOLL ){ if( !pColl ) pColl = db->pDfltColl; sqlite3VdbeAddOp4(v, OP_CollSeq, 0, 0, 0, (char *)pColl, P4_COLLSEQ); } diff --git a/src/func.c b/src/func.c index 07c5069fcb..64e33640b0 100644 --- a/src/func.c +++ b/src/func.c @@ -1554,7 +1554,7 @@ static void setLikeOptFlag(sqlite3 *db, const char *zName, u8 flagVal){ pDef = sqlite3FindFunction(db, zName, sqlite3Strlen30(zName), 2, SQLITE_UTF8, 0); if( ALWAYS(pDef) ){ - pDef->flags = flagVal; + pDef->funcFlags |= flagVal; } } @@ -1598,7 +1598,7 @@ int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, int *pIsNocase, char *aWc){ pDef = sqlite3FindFunction(db, pExpr->u.zToken, sqlite3Strlen30(pExpr->u.zToken), 2, SQLITE_UTF8, 0); - if( NEVER(pDef==0) || (pDef->flags & SQLITE_FUNC_LIKE)==0 ){ + if( NEVER(pDef==0) || (pDef->funcFlags & SQLITE_FUNC_LIKE)==0 ){ return 0; } @@ -1610,7 +1610,7 @@ int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, int *pIsNocase, char *aWc){ assert( (char*)&likeInfoAlt == (char*)&likeInfoAlt.matchAll ); assert( &((char*)&likeInfoAlt)[1] == (char*)&likeInfoAlt.matchOne ); assert( &((char*)&likeInfoAlt)[2] == (char*)&likeInfoAlt.matchSet ); - *pIsNocase = (pDef->flags & SQLITE_FUNC_CASE)==0; + *pIsNocase = (pDef->funcFlags & SQLITE_FUNC_CASE)==0; return 1; } @@ -1689,7 +1689,7 @@ void sqlite3RegisterGlobalFunctions(void){ AGGREGATE(total, 1, 0, 0, sumStep, totalFinalize ), AGGREGATE(avg, 1, 0, 0, sumStep, avgFinalize ), /* AGGREGATE(count, 0, 0, 0, countStep, countFinalize ), */ - {0,SQLITE_UTF8,SQLITE_FUNC_COUNT,0,0,0,countStep,countFinalize,"count",0,0}, + {0,SQLITE_UTF8|SQLITE_FUNC_COUNT,0,0,0,countStep,countFinalize,"count",0,0}, AGGREGATE(count, 1, 0, 0, countStep, countFinalize ), AGGREGATE(group_concat, 1, 0, 0, groupConcatStep, groupConcatFinalize), AGGREGATE(group_concat, 2, 0, 0, groupConcatStep, groupConcatFinalize), diff --git a/src/main.c b/src/main.c index 4697009666..407de0e4da 100644 --- a/src/main.c +++ b/src/main.c @@ -1406,7 +1406,7 @@ int sqlite3CreateFunc( ** operation to continue but invalidate all precompiled statements. */ p = sqlite3FindFunction(db, zFunctionName, nName, nArg, (u8)enc, 0); - if( p && p->iPrefEnc==enc && p->nArg==nArg ){ + if( p && (p->funcFlags & SQLITE_FUNC_ENCMASK)==enc && p->nArg==nArg ){ if( db->nVdbeActive ){ sqlite3Error(db, SQLITE_BUSY, "unable to delete/modify user-function due to active statements"); @@ -1431,7 +1431,7 @@ int sqlite3CreateFunc( pDestructor->nRef++; } p->pDestructor = pDestructor; - p->flags = 0; + p->funcFlags &= SQLITE_FUNC_ENCMASK; p->xFunc = xFunc; p->xStep = xStep; p->xFinalize = xFinal; diff --git a/src/select.c b/src/select.c index 83fcf7ed40..6e409e73a5 100644 --- a/src/select.c +++ b/src/select.c @@ -3228,7 +3228,7 @@ static Table *isSimpleCount(Select *p, AggInfo *pAggInfo){ if( IsVirtual(pTab) ) return 0; if( pExpr->op!=TK_AGG_FUNCTION ) return 0; if( NEVER(pAggInfo->nFunc==0) ) return 0; - if( (pAggInfo->aFunc[0].pFunc->flags&SQLITE_FUNC_COUNT)==0 ) return 0; + if( (pAggInfo->aFunc[0].pFunc->funcFlags&SQLITE_FUNC_COUNT)==0 ) return 0; if( pExpr->flags&EP_Distinct ) return 0; return pTab; @@ -3825,7 +3825,7 @@ static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){ assert( nArg==1 ); codeDistinct(pParse, pF->iDistinct, addrNext, 1, regAgg); } - if( pF->pFunc->flags & SQLITE_FUNC_NEEDCOLL ){ + if( pF->pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL ){ CollSeq *pColl = 0; struct ExprList_item *pItem; int j; diff --git a/src/sqliteInt.h b/src/sqliteInt.h index d74903fda1..6b3fbe8518 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -1065,8 +1065,7 @@ struct sqlite3 { */ struct FuncDef { i16 nArg; /* Number of arguments. -1 means unlimited */ - u8 iPrefEnc; /* Preferred text encoding (SQLITE_UTF8, 16LE, 16BE) */ - u8 flags; /* Some combination of SQLITE_FUNC_* */ + u16 funcFlags; /* Some combination of SQLITE_FUNC_* */ void *pUserData; /* User data parameter */ FuncDef *pNext; /* Next function with same name */ void (*xFunc)(sqlite3_context*,int,sqlite3_value**); /* Regular function */ @@ -1102,14 +1101,16 @@ struct FuncDestructor { ** values must correspond to OPFLAG_LENGTHARG and OPFLAG_TYPEOFARG. There ** are assert() statements in the code to verify this. */ -#define SQLITE_FUNC_LIKE 0x01 /* Candidate for the LIKE optimization */ -#define SQLITE_FUNC_CASE 0x02 /* Case-sensitive LIKE-type function */ -#define SQLITE_FUNC_EPHEM 0x04 /* Ephemeral. Delete with VDBE */ -#define SQLITE_FUNC_NEEDCOLL 0x08 /* sqlite3GetFuncCollSeq() might be called */ -#define SQLITE_FUNC_COUNT 0x10 /* Built-in count(*) aggregate */ -#define SQLITE_FUNC_COALESCE 0x20 /* Built-in coalesce() or ifnull() function */ -#define SQLITE_FUNC_LENGTH 0x40 /* Built-in length() function */ -#define SQLITE_FUNC_TYPEOF 0x80 /* Built-in typeof() function */ +#define SQLITE_FUNC_ENCMASK 0x003 /* SQLITE_UTF8, SQLITE_UTF16BE or UTF16LE */ +#define SQLITE_FUNC_LIKE 0x004 /* Candidate for the LIKE optimization */ +#define SQLITE_FUNC_CASE 0x008 /* Case-sensitive LIKE-type function */ +#define SQLITE_FUNC_EPHEM 0x010 /* Ephemeral. Delete with VDBE */ +#define SQLITE_FUNC_NEEDCOLL 0x020 /* sqlite3GetFuncCollSeq() might be called */ +#define SQLITE_FUNC_LENGTH 0x040 /* Built-in length() function */ +#define SQLITE_FUNC_TYPEOF 0x080 /* Built-in typeof() function */ +#define SQLITE_FUNC_COUNT 0x100 /* Built-in count(*) aggregate */ +#define SQLITE_FUNC_COALESCE 0x200 /* Built-in coalesce() or ifnull() */ +#define SQLITE_FUNC_UNLIKELY 0x400 /* Built-in unlikely() function */ /* ** The following three macros, FUNCTION(), LIKEFUNC() and AGGREGATE() are @@ -1137,18 +1138,18 @@ struct FuncDestructor { ** parameter. */ #define FUNCTION(zName, nArg, iArg, bNC, xFunc) \ - {nArg, SQLITE_UTF8, (bNC*SQLITE_FUNC_NEEDCOLL), \ + {nArg, SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \ SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, #zName, 0, 0} #define FUNCTION2(zName, nArg, iArg, bNC, xFunc, extraFlags) \ - {nArg, SQLITE_UTF8, (bNC*SQLITE_FUNC_NEEDCOLL)|extraFlags, \ + {nArg, SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL)|extraFlags, \ SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, #zName, 0, 0} #define STR_FUNCTION(zName, nArg, pArg, bNC, xFunc) \ - {nArg, SQLITE_UTF8, bNC*SQLITE_FUNC_NEEDCOLL, \ + {nArg, SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \ pArg, 0, xFunc, 0, 0, #zName, 0, 0} #define LIKEFUNC(zName, nArg, arg, flags) \ - {nArg, SQLITE_UTF8, flags, (void *)arg, 0, likeFunc, 0, 0, #zName, 0, 0} + {nArg, SQLITE_UTF8|flags, (void *)arg, 0, likeFunc, 0, 0, #zName, 0, 0} #define AGGREGATE(zName, nArg, arg, nc, xStep, xFinal) \ - {nArg, SQLITE_UTF8, nc*SQLITE_FUNC_NEEDCOLL, \ + {nArg, SQLITE_UTF8|(nc*SQLITE_FUNC_NEEDCOLL), \ SQLITE_INT_TO_PTR(arg), 0, 0, xStep,xFinal,#zName,0,0} /* diff --git a/src/vdbe.c b/src/vdbe.c index 9f8bcb2168..70d06eb31f 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -1437,7 +1437,7 @@ case OP_Function: { MemSetTypeFlag(&ctx.s, MEM_Null); ctx.fErrorOrAux = 0; - if( ctx.pFunc->flags & SQLITE_FUNC_NEEDCOLL ){ + if( ctx.pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL ){ assert( pOp>aOp ); assert( pOp[-1].p4type==P4_COLLSEQ ); assert( pOp[-1].opcode==OP_CollSeq ); @@ -5437,7 +5437,7 @@ case OP_AggStep: { ctx.isError = 0; ctx.pColl = 0; ctx.skipFlag = 0; - if( ctx.pFunc->flags & SQLITE_FUNC_NEEDCOLL ){ + if( ctx.pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL ){ assert( pOp>p->aOp ); assert( pOp[-1].p4type==P4_COLLSEQ ); assert( pOp[-1].opcode==OP_CollSeq ); diff --git a/src/vdbeaux.c b/src/vdbeaux.c index ec071606a2..bb67c6da30 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -604,7 +604,7 @@ void sqlite3VdbeJumpHere(Vdbe *p, int addr){ ** the FuncDef is not ephermal, then do nothing. */ static void freeEphemeralFunction(sqlite3 *db, FuncDef *pDef){ - if( ALWAYS(pDef) && (pDef->flags & SQLITE_FUNC_EPHEM)!=0 ){ + if( ALWAYS(pDef) && (pDef->funcFlags & SQLITE_FUNC_EPHEM)!=0 ){ sqlite3DbFree(db, pDef); } } diff --git a/src/vtab.c b/src/vtab.c index 357a6dba2a..195aa68b25 100644 --- a/src/vtab.c +++ b/src/vtab.c @@ -1013,7 +1013,7 @@ FuncDef *sqlite3VtabOverloadFunction( memcpy(pNew->zName, pDef->zName, sqlite3Strlen30(pDef->zName)+1); pNew->xFunc = xFunc; pNew->pUserData = pArg; - pNew->flags |= SQLITE_FUNC_EPHEM; + pNew->funcFlags |= SQLITE_FUNC_EPHEM; return pNew; } From cca9f3d291179e8126f29622f1a5c43105d1a045 Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 6 Sep 2013 15:23:29 +0000 Subject: [PATCH 019/101] Initial implementation of the unlikely() SQL function used as a hint to the query planner. FossilOrigin-Name: 036fc37a034093a4c6fc190633bd41c2b7230d77 --- manifest | 25 +++++++++++++---------- manifest.uuid | 2 +- src/expr.c | 20 +++++++++++++++++-- src/func.c | 20 ++++++++++--------- src/resolve.c | 25 +++++++++++++++++++++++ src/sqliteInt.h | 5 +++-- src/where.c | 50 +++++++++++++++++++++++++++++++++++++++++----- test/analyze9.test | 2 +- 8 files changed, 118 insertions(+), 31 deletions(-) diff --git a/manifest b/manifest index 91047af181..c355e4ffe5 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Combine\sthe\sFuncDef.iPrefEnc\sand\sFuncDef.flags\sfields\sinto\sa\ssingle\nnew\sFuncDef.funcFlags\sfield. -D 2013-09-06T13:10:12.385 +C Initial\simplementation\sof\sthe\sunlikely()\sSQL\sfunction\sused\sas\sa\shint\sto\nthe\squery\splanner. +D 2013-09-06T15:23:29.191 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5e41da95d92656a5004b03d3576e8b226858a28e F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -172,10 +172,10 @@ F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac F src/ctime.c ea4b7f3623a0fcb1146e7f245d7410033e86859c F src/date.c 067a81c9942c497aafd2c260e13add8a7d0c7dd4 F src/delete.c 2dc64ca360b7d7da481183ea920a813a0c203c97 -F src/expr.c 33ae44812d25799000dbcfd54bb2142b30cdd049 +F src/expr.c d0ed048b3b3c97fddbcccb8df43cc39b89e682c2 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fkey.c be866cd8c4fa6cae98ba33109578fd1a3311ee5b -F src/func.c 7650d35651bb0ca903d24f4e5e944bfdaac9f152 +F src/func.c a297b1f3cf48dd483f5453b7155bc5e8f4ca1fc2 F src/global.c 5caf4deab621abb45b4c607aad1bd21c20aac759 F src/hash.c ac3470bbf1ca4ae4e306a8ecb0fdf1731810ffe4 F src/hash.h 8890a25af81fb85a9ad7790d32eedab4b994da22 @@ -214,14 +214,14 @@ F src/pragma.c 3aa3d8c8623b7b71c5b1bfb72dcc31fb0c25665f F src/prepare.c fa6988589f39af8504a61731614cd4f6ae71554f F src/printf.c da9119eb31a187a4b99f60aa4a225141c0ebb74b F src/random.c 0b2dbc37fdfbfa6bd455b091dfcef5bdb32dba68 -F src/resolve.c 9d53899cc6e1f4ec0b4632d07e97d57827bf63b9 +F src/resolve.c 748618c3df7f37f2cd33c8834770b1e34f9b1185 F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0 F src/select.c 9239586282bd146ec5843a2cde7d54cd7816cf78 F src/shell.c d920a891ca09b8bd262cced7fb0ab9d723f7a747 F src/sqlite.h.in ec40aa958a270416fb04b4f72210357bf163d2c5 F src/sqlite3.rc fea433eb0a59f4c9393c8e6d76a6e2596b1fe0c0 F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc -F src/sqliteInt.h 32e959dba9899360ce4ae3cd6cc77b4a8df277e8 +F src/sqliteInt.h fd9005fab1cd063f5c4e76a2120efc080b43750a F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158 F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e @@ -290,7 +290,7 @@ F src/vtab.c 5a423b042eb1402ef77697d03d6a67378d97bc8d F src/wal.c 7dc3966ef98b74422267e7e6e46e07ff6c6eb1b4 F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4 F src/walker.c 4fa43583d0a84b48f93b1e88f11adf2065be4e73 -F src/where.c 06c249a5137575ecf4d527e5a1dadb1087e4375c +F src/where.c c9f8ae51797bebfbfa49b9e5bede6fc142b44262 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 F test/aggnested.test 45c0201e28045ad38a530b5a144b73cd4aa2cfd6 @@ -308,7 +308,7 @@ F test/analyze5.test 765c4e284aa69ca172772aa940946f55629bc8c4 F test/analyze6.test 19151da2c4e918905d2081b74ac5c4d47fc850ab F test/analyze7.test bb1409afc9e8629e414387ef048b8e0e3e0bdc4f F test/analyze8.test 093d15c1c888eed5034304a98c992f7360130b88 -F test/analyze9.test 4a48461d71a7b4a958570c580495a97e842e2700 +F test/analyze9.test e688c7289d3d33b7185e2c2afcac6a9f095563a3 F test/analyzeA.test 1a5c40079894847976d983ca39c707aaa44b6944 F test/analyzeB.test 8bf35ee0a548aea831bf56762cb8e7fdb1db083d F test/async.test 1d0e056ba1bb9729283a0f22718d3a25e82c277b @@ -1111,7 +1111,10 @@ F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 F tool/wherecosttest.c f407dc4c79786982a475261866a161cd007947ae F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac -P a99a53b81e29c9514b85318bea028d1667e5f760 -R 8c10a6011eb52c6098e833ca515e6c77 +P 97b10e66e98e84755aa577f8da017bf1aea2056c +R fcd7cd29a90a12a870cace66939b8877 +T *branch * unlikely-func +T *sym-unlikely-func * +T -sym-trunk * U drh -Z c7e49c79214a66374f550dcdb7a70012 +Z 2a30cee668099b5c8e0e2b447ac67feb diff --git a/manifest.uuid b/manifest.uuid index dbc304a491..b43b68fee1 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -97b10e66e98e84755aa577f8da017bf1aea2056c \ No newline at end of file +036fc37a034093a4c6fc190633bd41c2b7230d77 \ No newline at end of file diff --git a/src/expr.c b/src/expr.c index 6587ee1f78..ece0293840 100644 --- a/src/expr.c +++ b/src/expr.c @@ -89,8 +89,16 @@ Expr *sqlite3ExprAddCollateString(Parse *pParse, Expr *pExpr, const char *zC){ ** an expression. */ Expr *sqlite3ExprSkipCollate(Expr *pExpr){ - while( pExpr && (pExpr->op==TK_COLLATE || pExpr->op==TK_AS) ){ - pExpr = pExpr->pLeft; + while( pExpr ){ + if( pExpr->op==TK_COLLATE || pExpr->op==TK_AS ){ + pExpr = pExpr->pLeft; + }else if( ExprHasAnyProperty(pExpr, EP_Hint) ){ + assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); + assert( pExpr->x.pList->nExpr>0 ); + pExpr = pExpr->x.pList->a[0].pExpr; + }else{ + break; + } } return pExpr; } @@ -2649,6 +2657,14 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ break; } + /* The UNLIKELY() function is a no-op. The result is the value + ** of the first argument. + */ + if( pDef->funcFlags & SQLITE_FUNC_UNLIKELY ){ + assert( nFarg>=1 ); + sqlite3ExprCode(pParse, pFarg->a[0].pExpr, target); + break; + } if( pFarg ){ r1 = sqlite3GetTempRange(pParse, nFarg); diff --git a/src/func.c b/src/func.c index 64e33640b0..26cbfbfb03 100644 --- a/src/func.c +++ b/src/func.c @@ -418,14 +418,14 @@ static void lowerFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ } /* -** The COALESCE() and IFNULL() functions are implemented as VDBE code so -** that unused argument values do not have to be computed. However, we -** still need some kind of function implementation for this routines in -** the function table. That function implementation will never be called -** so it doesn't matter what the implementation is. We might as well use -** the "version()" function as a substitute. +** Some functions like COALESCE() and IFNULL() and UNLIKELY() are implemented +** as VDBE code so that unused argument values do not have to be computed. +** However, we still need some kind of function implementation for this +** routines in the function table. The noopFunc macro provides this. +** noopFunc will never be called so it doesn't matter what the implementation +** is. We might as well use the "version()" function as a substitute. */ -#define ifnullFunc versionFunc /* Substitute function - never called */ +#define noopFunc versionFunc /* Substitute function - never called */ /* ** Implementation of random(). Return a random integer. @@ -1659,9 +1659,11 @@ void sqlite3RegisterGlobalFunctions(void){ FUNCTION(lower, 1, 0, 0, lowerFunc ), FUNCTION(coalesce, 1, 0, 0, 0 ), FUNCTION(coalesce, 0, 0, 0, 0 ), - FUNCTION2(coalesce, -1, 0, 0, ifnullFunc, SQLITE_FUNC_COALESCE), + FUNCTION2(coalesce, -1, 0, 0, noopFunc, SQLITE_FUNC_COALESCE), FUNCTION(hex, 1, 0, 0, hexFunc ), - FUNCTION2(ifnull, 2, 0, 0, ifnullFunc, SQLITE_FUNC_COALESCE), + FUNCTION2(ifnull, 2, 0, 0, noopFunc, SQLITE_FUNC_COALESCE), + FUNCTION2(unlikely, 1, 0, 0, noopFunc, SQLITE_FUNC_UNLIKELY), + FUNCTION2(unlikely, 2, 0, 0, noopFunc, SQLITE_FUNC_UNLIKELY), FUNCTION(random, 0, 0, 0, randomFunc ), FUNCTION(randomblob, 1, 0, 0, randomBlob ), FUNCTION(nullif, 2, 0, 1, nullifFunc ), diff --git a/src/resolve.c b/src/resolve.c index 43a3870e23..cb86a83ee0 100644 --- a/src/resolve.c +++ b/src/resolve.c @@ -570,6 +570,18 @@ static void notValidCheckConstraint( # define notValidCheckConstraint(P,N,M) #endif +/* +** Expression p should encode a floating point value between 1.0 and 0.0. +** Return 1024 times this value. Or return -1 if p is not a floating point +** value between 1.0 and 0.0. +*/ +static int exprProbability(Expr *p){ + double r = -1.0; + if( p->op!=TK_FLOAT ) return -1; + sqlite3AtoF(p->u.zToken, &r, sqlite3Strlen30(p->u.zToken), SQLITE_UTF8); + if( r<0.0 || r>1.0 ) return -1; + return (int)(r*1000.0); +} /* ** This routine is callback for sqlite3WalkExpr(). @@ -683,6 +695,19 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ } }else{ is_agg = pDef->xFunc==0; + if( pDef->funcFlags & SQLITE_FUNC_UNLIKELY ){ + ExprSetProperty(pExpr, EP_Hint); + if( n==2 ){ + pExpr->iTable = exprProbability(pList->a[1].pExpr); + if( pExpr->iTable<0 ){ + sqlite3ErrorMsg(pParse, "second parameter to unlikely() must be " + "between 0.0 and 1.0"); + pNC->nErr++; + } + }else{ + pExpr->iTable = 100; + } + } } #ifndef SQLITE_OMIT_AUTHORIZATION if( pDef ){ diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 6b3fbe8518..d8ed4eb04e 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -1752,7 +1752,8 @@ struct Expr { #endif int iTable; /* TK_COLUMN: cursor number of table holding column ** TK_REGISTER: register number - ** TK_TRIGGER: 1 -> new, 0 -> old */ + ** TK_TRIGGER: 1 -> new, 0 -> old + ** EP_Hint: 1000 times likelihood */ ynVar iColumn; /* TK_COLUMN: column index. -1 for rowid. ** TK_VARIABLE: variable number (always >= 1). */ i16 iAgg; /* Which entry in pAggInfo->aCol[] or ->aFunc[] */ @@ -1780,7 +1781,7 @@ struct Expr { #define EP_FixedDest 0x0200 /* Result needed in a specific register */ #define EP_IntValue 0x0400 /* Integer value contained in u.iValue */ #define EP_xIsSelect 0x0800 /* x.pSelect is valid (otherwise x.pList is) */ -#define EP_Hint 0x1000 /* Not used */ +#define EP_Hint 0x1000 /* The UNLIKELY() SQL function */ #define EP_Reduced 0x2000 /* Expr struct is EXPR_REDUCEDSIZE bytes only */ #define EP_TokenOnly 0x4000 /* Expr struct is EXPR_TOKENONLYSIZE bytes only */ #define EP_Static 0x8000 /* Held in memory not obtained from malloc() */ diff --git a/src/where.c b/src/where.c index 3c8a1eaac6..a9905769a4 100644 --- a/src/where.c +++ b/src/where.c @@ -52,12 +52,13 @@ typedef struct WhereOrSet WhereOrSet; ** Cost X is tracked as 10*log2(X) stored in a 16-bit integer. The ** maximum cost for ordinary tables is 64*(2**63) which becomes 6900. ** (Virtual tables can return a larger cost, but let's assume they do not.) -** So all costs can be stored in a 16-bit unsigned integer without risk +** So all costs can be stored in a 16-bit integer without risk ** of overflow. ** ** Costs are estimates, so no effort is made to compute 10*log2(X) exactly. -** Instead, a close estimate is used. Any value of X<=1 is stored as 0. -** X=2 is 10. X=3 is 16. X=1000 is 99. etc. +** Instead, a close estimate is used. Any value of X=1 is stored as 0. +** X=2 is 10. X=3 is 16. X=1000 is 99. etc. Negative values are allowed. +** A WhereCost of -10 means 0.5. WhereCost of -20 means 0.25. And so forth. ** ** The tool/wherecosttest.c source file implements a command-line program ** that will convert WhereCosts to integers, convert integers to WhereCosts @@ -65,7 +66,7 @@ typedef struct WhereOrSet WhereOrSet; ** command-line program is a useful utility to have around when working with ** this module. */ -typedef unsigned short int WhereCost; +typedef short int WhereCost; /* ** This object contains information needed to implement a single nested @@ -268,6 +269,7 @@ struct WhereTerm { WhereOrInfo *pOrInfo; /* Extra information if (eOperator & WO_OR)!=0 */ WhereAndInfo *pAndInfo; /* Extra information if (eOperator& WO_AND)!=0 */ } u; + WhereCost truthProb; /* Probability of truth for this expression */ u16 eOperator; /* A WO_xx value describing */ u8 wtFlags; /* TERM_xxx bit flags. See below */ u8 nChild; /* Number of children that must disable us */ @@ -642,6 +644,9 @@ static void whereClauseClear(WhereClause *pWC){ } } +/* Forward declaration */ +static WhereCost whereCost(tRowcnt x); + /* ** Add a single new WhereTerm entry to the WhereClause object pWC. ** The new WhereTerm object is constructed from Expr p and with wtFlags. @@ -683,6 +688,11 @@ static int whereClauseInsert(WhereClause *pWC, Expr *p, u8 wtFlags){ pWC->nSlot = sqlite3DbMallocSize(db, pWC->a)/sizeof(pWC->a[0]); } pTerm = &pWC->a[idx = pWC->nTerm++]; + if( p && ExprHasAnyProperty(p, EP_Hint) ){ + pTerm->truthProb = whereCost(p->iTable) - 99; + }else{ + pTerm->truthProb = -1; + } pTerm->pExpr = sqlite3ExprSkipCollate(p); pTerm->wtFlags = wtFlags; pTerm->pWC = pWC; @@ -4257,6 +4267,32 @@ whereLoopInsert_noop: return SQLITE_OK; } +/* +** Adjust the WhereLoop.nOut value downward to account for terms of the +** WHERE clause that reference the loop but which are not used by an +** index. +** +** In the current implementation, the first extra WHERE clause term reduces +** the number of output rows by a factor of 10 and each additional term +** reduces the number of output rows by sqrt(2). +*/ +static void whereLoopOutputAdjust(WhereClause *pWC, WhereLoop *pLoop, int iCur){ + WhereTerm *pTerm; + Bitmask notAllowed = ~(pLoop->prereq|pLoop->maskSelf); + int x = 0; + int i; + for(i=pWC->nTerm, pTerm=pWC->a; i>0; i--, pTerm++){ + if( (pTerm->wtFlags & TERM_VIRTUAL)!=0 ) continue; + if( (pTerm->prereqAll & pLoop->maskSelf)==0 ) continue; + if( (pTerm->prereqAll & notAllowed)!=0 ) continue; + x += pTerm->truthProb; + } + for(i=pLoop->nLTerm-1; i>=0; i--){ + x -= pLoop->aLTerm[i]->truthProb; + } + if( x<0 ) pLoop->nOut += x; +} + /* ** We have so far matched pBuilder->pNew->u.btree.nEq terms of the index pIndex. ** Try to match one more. @@ -4423,7 +4459,7 @@ static int whereLoopAddBtreeIndex( } /* Step cost for each output row */ pNew->rRun = whereCostAdd(pNew->rRun, pNew->nOut); - /* TBD: Adjust nOut for additional constraints */ + whereLoopOutputAdjust(pBuilder->pWC, pNew, pSrc->iCursor); rc = whereLoopInsert(pBuilder, pNew); if( (pNew->wsFlags & WHERE_TOP_LIMIT)==0 && pNew->u.btree.nEq<(pProbe->nColumn + (pProbe->zName!=0)) @@ -4627,7 +4663,9 @@ static int whereLoopAddBtree( ** index scans so that a covering index scan will be favored over ** a table scan. */ pNew->rRun = whereCostAdd(rSize,rLogSize) + 16; + whereLoopOutputAdjust(pWC, pNew, pSrc->iCursor); rc = whereLoopInsert(pBuilder, pNew); + pNew->nOut = rSize; if( rc ) break; }else{ Bitmask m = pSrc->colUsed & ~columnsInIndex(pProbe); @@ -4659,7 +4697,9 @@ static int whereLoopAddBtree( ** which we will simplify to just N*log2(N) */ pNew->rRun = rSize + rLogSize; } + whereLoopOutputAdjust(pWC, pNew, pSrc->iCursor); rc = whereLoopInsert(pBuilder, pNew); + pNew->nOut = rSize; if( rc ) break; } } diff --git a/test/analyze9.test b/test/analyze9.test index 604f340bf5..42bf3d5088 100644 --- a/test/analyze9.test +++ b/test/analyze9.test @@ -805,6 +805,7 @@ do_test 16.1 { ANALYZE; } set nByte2 [lindex [sqlite3_db_status db SCHEMA_USED 0] 1] +puts "$nByte $nByte2" expr {$nByte2 > $nByte+950 && $nByte2 < $nByte+1050} } {1} @@ -950,4 +951,3 @@ for {set i 0} {$i<16} {incr i} { } finish_test - From fde1e6bc376be6b667d7e634f0102dccb0cf3f98 Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 6 Sep 2013 17:45:42 +0000 Subject: [PATCH 020/101] Enhance the plan solver to take into account the number of output rows when computing the set of paths to retain for the next cycle. FossilOrigin-Name: 1a46a7242313da96420985fa52e1de3f84533e5b --- manifest | 17 ++++++-------- manifest.uuid | 2 +- src/resolve.c | 2 +- src/where.c | 61 +++++++++++++++++++++++++++++++-------------------- 4 files changed, 46 insertions(+), 36 deletions(-) diff --git a/manifest b/manifest index c355e4ffe5..af8be5bcd5 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Initial\simplementation\sof\sthe\sunlikely()\sSQL\sfunction\sused\sas\sa\shint\sto\nthe\squery\splanner. -D 2013-09-06T15:23:29.191 +C Enhance\sthe\splan\ssolver\sto\stake\sinto\saccount\sthe\snumber\sof\soutput\srows\swhen\ncomputing\sthe\sset\sof\spaths\sto\sretain\sfor\sthe\snext\scycle. +D 2013-09-06T17:45:42.446 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5e41da95d92656a5004b03d3576e8b226858a28e F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -214,7 +214,7 @@ F src/pragma.c 3aa3d8c8623b7b71c5b1bfb72dcc31fb0c25665f F src/prepare.c fa6988589f39af8504a61731614cd4f6ae71554f F src/printf.c da9119eb31a187a4b99f60aa4a225141c0ebb74b F src/random.c 0b2dbc37fdfbfa6bd455b091dfcef5bdb32dba68 -F src/resolve.c 748618c3df7f37f2cd33c8834770b1e34f9b1185 +F src/resolve.c 8a2b6b9a6487e6e5a23b8de571131ccce62a1ce0 F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0 F src/select.c 9239586282bd146ec5843a2cde7d54cd7816cf78 F src/shell.c d920a891ca09b8bd262cced7fb0ab9d723f7a747 @@ -290,7 +290,7 @@ F src/vtab.c 5a423b042eb1402ef77697d03d6a67378d97bc8d F src/wal.c 7dc3966ef98b74422267e7e6e46e07ff6c6eb1b4 F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4 F src/walker.c 4fa43583d0a84b48f93b1e88f11adf2065be4e73 -F src/where.c c9f8ae51797bebfbfa49b9e5bede6fc142b44262 +F src/where.c ce16c689b9a199ffffd63745405214912e941e6f F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 F test/aggnested.test 45c0201e28045ad38a530b5a144b73cd4aa2cfd6 @@ -1111,10 +1111,7 @@ F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 F tool/wherecosttest.c f407dc4c79786982a475261866a161cd007947ae F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac -P 97b10e66e98e84755aa577f8da017bf1aea2056c -R fcd7cd29a90a12a870cace66939b8877 -T *branch * unlikely-func -T *sym-unlikely-func * -T -sym-trunk * +P 036fc37a034093a4c6fc190633bd41c2b7230d77 +R 3890bf7553bc1077426fb2f0e0259279 U drh -Z 2a30cee668099b5c8e0e2b447ac67feb +Z 80a7432df4b498524e527dd8f32c240f diff --git a/manifest.uuid b/manifest.uuid index b43b68fee1..b05ebc1a75 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -036fc37a034093a4c6fc190633bd41c2b7230d77 \ No newline at end of file +1a46a7242313da96420985fa52e1de3f84533e5b \ No newline at end of file diff --git a/src/resolve.c b/src/resolve.c index cb86a83ee0..ec6fe90716 100644 --- a/src/resolve.c +++ b/src/resolve.c @@ -705,7 +705,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ pNC->nErr++; } }else{ - pExpr->iTable = 100; + pExpr->iTable = 75; } } } diff --git a/src/where.c b/src/where.c index a9905769a4..e4485ac7d4 100644 --- a/src/where.c +++ b/src/where.c @@ -5306,9 +5306,12 @@ static int wherePathSolver(WhereInfo *pWInfo, WhereCost nRowEst){ sqlite3 *db; /* The database connection */ int iLoop; /* Loop counter over the terms of the join */ int ii, jj; /* Loop counters */ - WhereCost rCost; /* Cost of a path */ - WhereCost mxCost = 0; /* Maximum cost of a set of paths */ - WhereCost rSortCost; /* Cost to do a sort */ + int mxI = 0; /* Index of next entry to replace */ + WhereCost rCost; /* Cost of a path */ + WhereCost nOut; /* Number of outputs */ + WhereCost mxCost = 0; /* Maximum cost of a set of paths */ + WhereCost mxOut = 0; /* Maximum nOut value on the set of paths */ + WhereCost rSortCost; /* Cost to do a sort */ int nTo, nFrom; /* Number of valid entries in aTo[] and aFrom[] */ WherePath *aFrom; /* All nFrom paths at the previous level */ WherePath *aTo; /* The nTo best paths at the current level */ @@ -5377,6 +5380,7 @@ static int wherePathSolver(WhereInfo *pWInfo, WhereCost nRowEst){ ** Compute its cost */ rCost = whereCostAdd(pWLoop->rSetup,pWLoop->rRun + pFrom->nRow); rCost = whereCostAdd(rCost, pFrom->rCost); + nOut = pFrom->nRow + pWLoop->nOut; maskNew = pFrom->maskLoop | pWLoop->maskSelf; if( !isOrderedValid ){ switch( wherePathSatisfiesOrderBy(pWInfo, @@ -5399,17 +5403,23 @@ static int wherePathSolver(WhereInfo *pWInfo, WhereCost nRowEst){ } /* Check to see if pWLoop should be added to the mxChoice best so far */ for(jj=0, pTo=aTo; jjmaskLoop==maskNew && pTo->isOrderedValid==isOrderedValid ){ + if( pTo->maskLoop==maskNew + && pTo->isOrderedValid==isOrderedValid + && ((pTo->rCost<=rCost && pTo->nRow<=nOut) || + (pTo->rCost>=rCost && pTo->nRow>=nOut)) + ){ testcase( jj==nTo-1 ); break; } } if( jj>=nTo ){ - if( nTo>=mxChoice && rCost>=mxCost ){ + if( nTo>=mxChoice + && (rCost>mxCost || (rCost==mxCost && nOut>=mxOut)) + ){ #ifdef WHERETRACE_ENABLED if( sqlite3WhereTrace&0x4 ){ - sqlite3DebugPrintf("Skip %s cost=%3d order=%c\n", - wherePathName(pFrom, iLoop, pWLoop), rCost, + sqlite3DebugPrintf("Skip %s cost=%-3d,%3d order=%c\n", + wherePathName(pFrom, iLoop, pWLoop), rCost, nOut, isOrderedValid ? (isOrdered ? 'Y' : 'N') : '?'); } #endif @@ -5421,26 +5431,26 @@ static int wherePathSolver(WhereInfo *pWInfo, WhereCost nRowEst){ jj = nTo++; }else{ /* New path replaces the prior worst to keep count below mxChoice */ - for(jj=nTo-1; aTo[jj].rCost0); } + jj = mxI; } pTo = &aTo[jj]; #ifdef WHERETRACE_ENABLED if( sqlite3WhereTrace&0x4 ){ - sqlite3DebugPrintf("New %s cost=%-3d order=%c\n", - wherePathName(pFrom, iLoop, pWLoop), rCost, + sqlite3DebugPrintf("New %s cost=%-3d,%3d order=%c\n", + wherePathName(pFrom, iLoop, pWLoop), rCost, nOut, isOrderedValid ? (isOrdered ? 'Y' : 'N') : '?'); } #endif }else{ - if( pTo->rCost<=rCost ){ + if( pTo->rCost<=rCost && pTo->nRow<=nOut ){ #ifdef WHERETRACE_ENABLED if( sqlite3WhereTrace&0x4 ){ sqlite3DebugPrintf( - "Skip %s cost=%-3d order=%c", - wherePathName(pFrom, iLoop, pWLoop), rCost, + "Skip %s cost=%-3d,%3d order=%c", + wherePathName(pFrom, iLoop, pWLoop), rCost, nOut, isOrderedValid ? (isOrdered ? 'Y' : 'N') : '?'); - sqlite3DebugPrintf(" vs %s cost=%-3d order=%c\n", - wherePathName(pTo, iLoop+1, 0), pTo->rCost, + sqlite3DebugPrintf(" vs %s cost=%-3d,%d order=%c\n", + wherePathName(pTo, iLoop+1, 0), pTo->rCost, pTo->nRow, pTo->isOrderedValid ? (pTo->isOrdered ? 'Y' : 'N') : '?'); } #endif @@ -5452,11 +5462,11 @@ static int wherePathSolver(WhereInfo *pWInfo, WhereCost nRowEst){ #ifdef WHERETRACE_ENABLED if( sqlite3WhereTrace&0x4 ){ sqlite3DebugPrintf( - "Update %s cost=%-3d order=%c", - wherePathName(pFrom, iLoop, pWLoop), rCost, + "Update %s cost=%-3d,%3d order=%c", + wherePathName(pFrom, iLoop, pWLoop), rCost, nOut, isOrderedValid ? (isOrdered ? 'Y' : 'N') : '?'); - sqlite3DebugPrintf(" was %s cost=%-3d order=%c\n", - wherePathName(pTo, iLoop+1, 0), pTo->rCost, + sqlite3DebugPrintf(" was %s cost=%-3d,%3d order=%c\n", + wherePathName(pTo, iLoop+1, 0), pTo->rCost, pTo->nRow, pTo->isOrderedValid ? (pTo->isOrdered ? 'Y' : 'N') : '?'); } #endif @@ -5464,16 +5474,22 @@ static int wherePathSolver(WhereInfo *pWInfo, WhereCost nRowEst){ /* pWLoop is a winner. Add it to the set of best so far */ pTo->maskLoop = pFrom->maskLoop | pWLoop->maskSelf; pTo->revLoop = revMask; - pTo->nRow = pFrom->nRow + pWLoop->nOut; + pTo->nRow = nOut; pTo->rCost = rCost; pTo->isOrderedValid = isOrderedValid; pTo->isOrdered = isOrdered; memcpy(pTo->aLoop, pFrom->aLoop, sizeof(WhereLoop*)*iLoop); pTo->aLoop[iLoop] = pWLoop; if( nTo>=mxChoice ){ + mxI = 0; mxCost = aTo[0].rCost; + mxOut = aTo[0].nRow; for(jj=1, pTo=&aTo[1]; jjrCost>mxCost ) mxCost = pTo->rCost; + if( pTo->rCost>mxCost || (pTo->rCost==mxCost && pTo->nRow>mxOut) ){ + mxCost = pTo->rCost; + mxOut = pTo->nRow; + mxI = jj; + } } } } @@ -5510,12 +5526,9 @@ static int wherePathSolver(WhereInfo *pWInfo, WhereCost nRowEst){ /* Find the lowest cost path. pFrom will be left pointing to that path */ pFrom = aFrom; - assert( nFrom==1 ); -#if 0 /* The following is needed if nFrom is ever more than 1 */ for(ii=1; iirCost>aFrom[ii].rCost ) pFrom = &aFrom[ii]; } -#endif assert( pWInfo->nLevel==nLoop ); /* Load the lowest cost path into pWInfo */ for(iLoop=0; iLoop Date: Sat, 7 Sep 2013 00:29:06 +0000 Subject: [PATCH 021/101] Continuing refinements of the logic to take WHERE clause terms not used for indexing into account when computing the number of output rows from each table. FossilOrigin-Name: b65dc53415f42d8402d0ec7f4bedf59d7b39b486 --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- src/resolve.c | 2 +- src/sqliteInt.h | 1 + src/where.c | 16 +++++++++++----- 5 files changed, 22 insertions(+), 15 deletions(-) diff --git a/manifest b/manifest index af8be5bcd5..55164884ee 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Enhance\sthe\splan\ssolver\sto\stake\sinto\saccount\sthe\snumber\sof\soutput\srows\swhen\ncomputing\sthe\sset\sof\spaths\sto\sretain\sfor\sthe\snext\scycle. -D 2013-09-06T17:45:42.446 +C Continuing\srefinements\sof\sthe\slogic\sto\stake\sWHERE\sclause\sterms\snot\sused\sfor\nindexing\sinto\saccount\swhen\scomputing\sthe\snumber\sof\soutput\srows\sfrom\seach\ntable. +D 2013-09-07T00:29:06.736 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5e41da95d92656a5004b03d3576e8b226858a28e F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -214,14 +214,14 @@ F src/pragma.c 3aa3d8c8623b7b71c5b1bfb72dcc31fb0c25665f F src/prepare.c fa6988589f39af8504a61731614cd4f6ae71554f F src/printf.c da9119eb31a187a4b99f60aa4a225141c0ebb74b F src/random.c 0b2dbc37fdfbfa6bd455b091dfcef5bdb32dba68 -F src/resolve.c 8a2b6b9a6487e6e5a23b8de571131ccce62a1ce0 +F src/resolve.c 594725ba98cbe0e7de9da75c9915dc589d92bcd4 F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0 F src/select.c 9239586282bd146ec5843a2cde7d54cd7816cf78 F src/shell.c d920a891ca09b8bd262cced7fb0ab9d723f7a747 F src/sqlite.h.in ec40aa958a270416fb04b4f72210357bf163d2c5 F src/sqlite3.rc fea433eb0a59f4c9393c8e6d76a6e2596b1fe0c0 F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc -F src/sqliteInt.h fd9005fab1cd063f5c4e76a2120efc080b43750a +F src/sqliteInt.h ac21b3aeb0251a4096a21a0750277f5701adfe0c F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158 F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e @@ -290,7 +290,7 @@ F src/vtab.c 5a423b042eb1402ef77697d03d6a67378d97bc8d F src/wal.c 7dc3966ef98b74422267e7e6e46e07ff6c6eb1b4 F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4 F src/walker.c 4fa43583d0a84b48f93b1e88f11adf2065be4e73 -F src/where.c ce16c689b9a199ffffd63745405214912e941e6f +F src/where.c 613cfc35baebc4aa10b54c15e31745327b057232 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 F test/aggnested.test 45c0201e28045ad38a530b5a144b73cd4aa2cfd6 @@ -1111,7 +1111,7 @@ F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 F tool/wherecosttest.c f407dc4c79786982a475261866a161cd007947ae F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac -P 036fc37a034093a4c6fc190633bd41c2b7230d77 -R 3890bf7553bc1077426fb2f0e0259279 +P 1a46a7242313da96420985fa52e1de3f84533e5b +R eafbf9bd5dba867073722599ec249697 U drh -Z 80a7432df4b498524e527dd8f32c240f +Z 0382b063215f6bbc8f334bae45df8ffd diff --git a/manifest.uuid b/manifest.uuid index b05ebc1a75..24110c517f 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -1a46a7242313da96420985fa52e1de3f84533e5b \ No newline at end of file +b65dc53415f42d8402d0ec7f4bedf59d7b39b486 \ No newline at end of file diff --git a/src/resolve.c b/src/resolve.c index ec6fe90716..ab318be8e2 100644 --- a/src/resolve.c +++ b/src/resolve.c @@ -705,7 +705,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ pNC->nErr++; } }else{ - pExpr->iTable = 75; + pExpr->iTable = 75; /* TUNING: Default 2nd arg to unlikely() is 0.075 */ } } } diff --git a/src/sqliteInt.h b/src/sqliteInt.h index d8ed4eb04e..268fef36fe 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -1032,6 +1032,7 @@ struct sqlite3 { #define SQLITE_Transitive 0x0200 /* Transitive constraints */ #define SQLITE_OmitNoopJoin 0x0400 /* Omit unused tables in joins */ #define SQLITE_Stat3 0x0800 /* Use the SQLITE_STAT3 table */ +#define SQLITE_AdjustOutEst 0x1000 /* Adjust output estimates using WHERE */ #define SQLITE_AllOpts 0xffff /* All optimizations */ /* diff --git a/src/where.c b/src/where.c index e4485ac7d4..ded80e23c3 100644 --- a/src/where.c +++ b/src/where.c @@ -688,7 +688,9 @@ static int whereClauseInsert(WhereClause *pWC, Expr *p, u8 wtFlags){ pWC->nSlot = sqlite3DbMallocSize(db, pWC->a)/sizeof(pWC->a[0]); } pTerm = &pWC->a[idx = pWC->nTerm++]; - if( p && ExprHasAnyProperty(p, EP_Hint) ){ + if( wtFlags & TERM_VIRTUAL ){ + pTerm->truthProb = 0; + }else if( p && ExprHasAnyProperty(p, EP_Hint) ){ pTerm->truthProb = whereCost(p->iTable) - 99; }else{ pTerm->truthProb = -1; @@ -4198,9 +4200,9 @@ static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){ assert( p->rSetup==pTemplate->rSetup ); if( p->prereq==pTemplate->prereq && p->nLTermnLTerm - && (p->wsFlags & WHERE_INDEXED)!=0 - && (pTemplate->wsFlags & WHERE_INDEXED)!=0 - && p->u.btree.pIndex==pTemplate->u.btree.pIndex + && (p->wsFlags & pTemplate->wsFlags & WHERE_INDEXED)!=0 + && (p->u.btree.pIndex==pTemplate->u.btree.pIndex + || p->u.btree.pIndex->nColumn>=pTemplate->u.btree.pIndex->nColumn) ){ /* Overwrite an existing WhereLoop with an similar one that uses ** more terms of the index */ @@ -4215,12 +4217,12 @@ static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){ if( (p->prereq & pTemplate->prereq)==pTemplate->prereq && p->rRun>=pTemplate->rRun && p->nOut>=pTemplate->nOut - && ALWAYS(p->rSetup>=pTemplate->rSetup) /* See SETUP-INVARIANT above */ ){ /* Overwrite an existing WhereLoop with a better one: one that is ** better at one of (1) dependencies, (2) setup-cost, (3) run-cost ** or (4) number of output rows, and is no worse in any of those ** categories. */ + assert( p->rSetup>=pTemplate->rSetup ); /* SETUP-INVARIANT above */ pNext = p->pNextLoop; break; } @@ -4281,6 +4283,10 @@ static void whereLoopOutputAdjust(WhereClause *pWC, WhereLoop *pLoop, int iCur){ Bitmask notAllowed = ~(pLoop->prereq|pLoop->maskSelf); int x = 0; int i; + + if( !OptimizationEnabled(pWC->pWInfo->pParse->db, SQLITE_AdjustOutEst) ){ + return; + } for(i=pWC->nTerm, pTerm=pWC->a; i>0; i--, pTerm++){ if( (pTerm->wtFlags & TERM_VIRTUAL)!=0 ) continue; if( (pTerm->prereqAll & pLoop->maskSelf)==0 ) continue; From 0259bc3da21f41adb2492d39898e0b98388bb561 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 9 Sep 2013 19:37:46 +0000 Subject: [PATCH 022/101] Make sure that the transitive constraint optimization does not cause WHERE clause terms to be disabled prematurely. We are unable to find a test case that fails because of this, but it seems prudent to make this preventative change nevertheless. FossilOrigin-Name: d6e361d7fb8013d616af91ef2c10038c97d1be5f --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/where.c | 13 +++++++------ 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/manifest b/manifest index 91047af181..ed617d0854 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Combine\sthe\sFuncDef.iPrefEnc\sand\sFuncDef.flags\sfields\sinto\sa\ssingle\nnew\sFuncDef.funcFlags\sfield. -D 2013-09-06T13:10:12.385 +C Make\ssure\sthat\sthe\stransitive\sconstraint\soptimization\sdoes\snot\scause\nWHERE\sclause\sterms\sto\sbe\sdisabled\sprematurely.\s\sWe\sare\sunable\sto\sfind\sa\stest\ncase\sthat\sfails\sbecause\sof\sthis,\sbut\sit\sseems\sprudent\sto\smake\sthis\npreventative\schange\snevertheless. +D 2013-09-09T19:37:46.167 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5e41da95d92656a5004b03d3576e8b226858a28e F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -290,7 +290,7 @@ F src/vtab.c 5a423b042eb1402ef77697d03d6a67378d97bc8d F src/wal.c 7dc3966ef98b74422267e7e6e46e07ff6c6eb1b4 F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4 F src/walker.c 4fa43583d0a84b48f93b1e88f11adf2065be4e73 -F src/where.c 06c249a5137575ecf4d527e5a1dadb1087e4375c +F src/where.c b5d59b899b85aa03800905ecdc0a17565d51a6ab F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 F test/aggnested.test 45c0201e28045ad38a530b5a144b73cd4aa2cfd6 @@ -1111,7 +1111,7 @@ F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 F tool/wherecosttest.c f407dc4c79786982a475261866a161cd007947ae F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac -P a99a53b81e29c9514b85318bea028d1667e5f760 -R 8c10a6011eb52c6098e833ca515e6c77 +P 97b10e66e98e84755aa577f8da017bf1aea2056c +R 73b0244a1b138f6550e626804843b7d8 U drh -Z c7e49c79214a66374f550dcdb7a70012 +Z 85372a45ca54a00c15dc226dffaae301 diff --git a/manifest.uuid b/manifest.uuid index dbc304a491..0e91f78a00 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -97b10e66e98e84755aa577f8da017bf1aea2056c \ No newline at end of file +d6e361d7fb8013d616af91ef2c10038c97d1be5f \ No newline at end of file diff --git a/src/where.c b/src/where.c index 3c8a1eaac6..fb097d2af4 100644 --- a/src/where.c +++ b/src/where.c @@ -106,6 +106,7 @@ struct WhereLevel { Index *pCovidx; /* Possible covering index for WHERE_MULTI_OR */ } u; struct WhereLoop *pWLoop; /* The selected WhereLoop object */ + Bitmask notReady; /* FROM entries not usable at this level */ }; /* @@ -2799,6 +2800,7 @@ static void disableTerm(WhereLevel *pLevel, WhereTerm *pTerm){ if( pTerm && (pTerm->wtFlags & TERM_CODED)==0 && (pLevel->iLeftJoin==0 || ExprHasProperty(pTerm->pExpr, EP_FromJoin)) + && (pLevel->notReady & pTerm->prereqAll)==0 ){ pTerm->wtFlags |= TERM_CODED; if( pTerm->iParent>=0 ){ @@ -3224,7 +3226,6 @@ static Bitmask codeOneLoopStart( int addrCont; /* Jump here to continue with next cycle */ int iRowidReg = 0; /* Rowid is stored in this register, if not zero */ int iReleaseReg = 0; /* Temp register to free before returning */ - Bitmask newNotReady; /* Return value */ pParse = pWInfo->pParse; v = pParse->pVdbe; @@ -3234,6 +3235,7 @@ static Bitmask codeOneLoopStart( pLoop = pLevel->pWLoop; pTabItem = &pWInfo->pTabList->a[pLevel->iFrom]; iCur = pTabItem->iCursor; + pLevel->notReady = notReady & ~getMask(&pWInfo->sMaskSet, iCur); bRev = (pWInfo->revMask>>iLevel)&1; omitTable = (pLoop->wsFlags & WHERE_IDX_ONLY)!=0 && (pWInfo->wctrlFlags & WHERE_FORCE_TABLE)==0; @@ -3886,7 +3888,6 @@ static Bitmask codeOneLoopStart( pLevel->p2 = 1 + sqlite3VdbeAddOp2(v, aStart[bRev], iCur, addrBrk); pLevel->p5 = SQLITE_STMTSTATUS_FULLSCAN_STEP; } - newNotReady = notReady & ~getMask(&pWInfo->sMaskSet, iCur); /* Insert code to test every subexpression that can be completely ** computed using the current set of tables. @@ -3896,7 +3897,7 @@ static Bitmask codeOneLoopStart( testcase( pTerm->wtFlags & TERM_VIRTUAL ); testcase( pTerm->wtFlags & TERM_CODED ); if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue; - if( (pTerm->prereqAll & newNotReady)!=0 ){ + if( (pTerm->prereqAll & pLevel->notReady)!=0 ){ testcase( pWInfo->untestedTerms==0 && (pWInfo->wctrlFlags & WHERE_ONETABLE_ONLY)!=0 ); pWInfo->untestedTerms = 1; @@ -3928,7 +3929,7 @@ static Bitmask codeOneLoopStart( if( pLevel->iLeftJoin ) continue; pE = pTerm->pExpr; assert( !ExprHasProperty(pE, EP_FromJoin) ); - assert( (pTerm->prereqRight & newNotReady)!=0 ); + assert( (pTerm->prereqRight & pLevel->notReady)!=0 ); pAlt = findTerm(pWC, iCur, pTerm->u.leftColumn, notReady, WO_EQ|WO_IN, 0); if( pAlt==0 ) continue; if( pAlt->wtFlags & (TERM_CODED) ) continue; @@ -3956,7 +3957,7 @@ static Bitmask codeOneLoopStart( testcase( pTerm->wtFlags & TERM_VIRTUAL ); testcase( pTerm->wtFlags & TERM_CODED ); if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue; - if( (pTerm->prereqAll & newNotReady)!=0 ){ + if( (pTerm->prereqAll & pLevel->notReady)!=0 ){ assert( pWInfo->untestedTerms ); continue; } @@ -3967,7 +3968,7 @@ static Bitmask codeOneLoopStart( } sqlite3ReleaseTempReg(pParse, iReleaseReg); - return newNotReady; + return pLevel->notReady; } #ifdef WHERETRACE_ENABLED From 1d2b3c1f8a5499c3ccb26938d8ffa856ac10aa51 Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 10 Sep 2013 01:41:25 +0000 Subject: [PATCH 023/101] Deterministically initialize the PRNG used as a tie-breaker in the ANALYZE command, so that the analysis is always the same given the same database. This simplifies testing. FossilOrigin-Name: 48ed8b565b84c8fa7898c2f9817c01f7e9c9182e --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/analyze.c | 2 +- test/analyze9.test | 7 +++---- 4 files changed, 12 insertions(+), 13 deletions(-) diff --git a/manifest b/manifest index ed617d0854..11dfa9b55b 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Make\ssure\sthat\sthe\stransitive\sconstraint\soptimization\sdoes\snot\scause\nWHERE\sclause\sterms\sto\sbe\sdisabled\sprematurely.\s\sWe\sare\sunable\sto\sfind\sa\stest\ncase\sthat\sfails\sbecause\sof\sthis,\sbut\sit\sseems\sprudent\sto\smake\sthis\npreventative\schange\snevertheless. -D 2013-09-09T19:37:46.167 +C Deterministically\sinitialize\sthe\sPRNG\sused\sas\sa\stie-breaker\sin\sthe\sANALYZE\ncommand,\sso\sthat\sthe\sanalysis\sis\salways\sthe\ssame\sgiven\sthe\ssame\sdatabase.\nThis\ssimplifies\stesting. +D 2013-09-10T01:41:25.676 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5e41da95d92656a5004b03d3576e8b226858a28e F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -157,7 +157,7 @@ F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a F src/alter.c 2af0330bb1b601af7a7789bf7229675fd772a083 -F src/analyze.c 7da9d6a0d04a3662d110a28f4a7e7b73a6171e75 +F src/analyze.c d322972af09e3f8debb45f420dfe3ded142b108b F src/attach.c eeb8d9d2c791caa0a54a835170ea898e96c2802d F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34 F src/backup.c 2f1987981139bd2f6d8c728d64bf09fb387443c3 @@ -308,7 +308,7 @@ F test/analyze5.test 765c4e284aa69ca172772aa940946f55629bc8c4 F test/analyze6.test 19151da2c4e918905d2081b74ac5c4d47fc850ab F test/analyze7.test bb1409afc9e8629e414387ef048b8e0e3e0bdc4f F test/analyze8.test 093d15c1c888eed5034304a98c992f7360130b88 -F test/analyze9.test 4a48461d71a7b4a958570c580495a97e842e2700 +F test/analyze9.test ed70f0c10502f6bcd6e1ec347edc3c0e114f4b53 F test/analyzeA.test 1a5c40079894847976d983ca39c707aaa44b6944 F test/analyzeB.test 8bf35ee0a548aea831bf56762cb8e7fdb1db083d F test/async.test 1d0e056ba1bb9729283a0f22718d3a25e82c277b @@ -1111,7 +1111,7 @@ F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 F tool/wherecosttest.c f407dc4c79786982a475261866a161cd007947ae F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac -P 97b10e66e98e84755aa577f8da017bf1aea2056c -R 73b0244a1b138f6550e626804843b7d8 +P d6e361d7fb8013d616af91ef2c10038c97d1be5f +R f0dc49c77588220f9d25d9d712edfe4a U drh -Z 85372a45ca54a00c15dc226dffaae301 +Z e68c71d629e67be96bb05aa541d1ef71 diff --git a/manifest.uuid b/manifest.uuid index 0e91f78a00..b31980649d 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d6e361d7fb8013d616af91ef2c10038c97d1be5f \ No newline at end of file +48ed8b565b84c8fa7898c2f9817c01f7e9c9182e \ No newline at end of file diff --git a/src/analyze.c b/src/analyze.c index 42c81fd659..474d80d1b8 100644 --- a/src/analyze.c +++ b/src/analyze.c @@ -347,7 +347,7 @@ static void statInit( p->mxSample = mxSample; p->nPSample = (tRowcnt)(sqlite3_value_int64(argv[1])/(mxSample/3+1) + 1); p->current.anLt = &p->current.anEq[nColUp]; - sqlite3_randomness(sizeof(p->iPrn), &p->iPrn); + p->iPrn = nCol*0x689e962d ^ sqlite3_value_int(argv[1])*0xd0944565; /* Set up the Stat4Accum.a[] and aBest[] arrays */ p->a = (struct Stat4Sample*)&p->current.anLt[nColUp]; diff --git a/test/analyze9.test b/test/analyze9.test index 604f340bf5..250de200b7 100644 --- a/test/analyze9.test +++ b/test/analyze9.test @@ -244,8 +244,8 @@ do_execsql_test 4.3 { FROM sqlite_stat4 ORDER BY rowid DESC LIMIT 2; } { - {2 1 1 1} {295 295 295} {120 121 124} {201 3} - {5 3 1 1} {290 290 292} {119 119 121} {200 1} + {2 1 1 1} {295 296 296} {120 122 125} {201 4} + {5 3 1 1} {290 290 290} {119 119 119} {200 1} } do_execsql_test 4.4 { SELECT count(DISTINCT c) FROM t1 WHERE c<201 } 120 @@ -806,7 +806,7 @@ do_test 16.1 { } set nByte2 [lindex [sqlite3_db_status db SCHEMA_USED 0] 1] - expr {$nByte2 > $nByte+950 && $nByte2 < $nByte+1050} + expr {$nByte2 > $nByte+900 && $nByte2 < $nByte+1050} } {1} #------------------------------------------------------------------------- @@ -950,4 +950,3 @@ for {set i 0} {$i<16} {incr i} { } finish_test - From abfa6d52edd9e6d37fed8c231cfb4f4e966320e5 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 11 Sep 2013 03:53:22 +0000 Subject: [PATCH 024/101] Tweaks to the index selection logic. FossilOrigin-Name: 52d52688644f635a50a60ff17b160f3affa8fa6c --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- src/resolve.c | 2 +- src/where.c | 16 +++++++++++----- test/analyze9.test | 3 +-- 5 files changed, 22 insertions(+), 17 deletions(-) diff --git a/manifest b/manifest index 7a9888a7f6..c6dcacea09 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\strunk\sfixes\sinto\sthe\sunlikely-func\sbranch. -D 2013-09-10T01:53:18.529 +C Tweaks\sto\sthe\sindex\sselection\slogic. +D 2013-09-11T03:53:22.579 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5e41da95d92656a5004b03d3576e8b226858a28e F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -214,7 +214,7 @@ F src/pragma.c 3aa3d8c8623b7b71c5b1bfb72dcc31fb0c25665f F src/prepare.c fa6988589f39af8504a61731614cd4f6ae71554f F src/printf.c da9119eb31a187a4b99f60aa4a225141c0ebb74b F src/random.c 0b2dbc37fdfbfa6bd455b091dfcef5bdb32dba68 -F src/resolve.c 594725ba98cbe0e7de9da75c9915dc589d92bcd4 +F src/resolve.c 140c25a1aa91c460dee74a1b9e6aa5af5c98cbea F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0 F src/select.c 9239586282bd146ec5843a2cde7d54cd7816cf78 F src/shell.c d920a891ca09b8bd262cced7fb0ab9d723f7a747 @@ -290,7 +290,7 @@ F src/vtab.c 5a423b042eb1402ef77697d03d6a67378d97bc8d F src/wal.c 7dc3966ef98b74422267e7e6e46e07ff6c6eb1b4 F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4 F src/walker.c 4fa43583d0a84b48f93b1e88f11adf2065be4e73 -F src/where.c 05cf31505dd514d1e27075ae5ef23a23a3462231 +F src/where.c 6b9e2bc47dd1225d690a9c770f157693519b7391 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 F test/aggnested.test 45c0201e28045ad38a530b5a144b73cd4aa2cfd6 @@ -308,7 +308,7 @@ F test/analyze5.test 765c4e284aa69ca172772aa940946f55629bc8c4 F test/analyze6.test 19151da2c4e918905d2081b74ac5c4d47fc850ab F test/analyze7.test bb1409afc9e8629e414387ef048b8e0e3e0bdc4f F test/analyze8.test 093d15c1c888eed5034304a98c992f7360130b88 -F test/analyze9.test a2c83301160d4d367d4cedfa503fc0b20556c723 +F test/analyze9.test 1b9b7e9a096d1536f03d9ad7b72f638ef5669347 F test/analyzeA.test 1a5c40079894847976d983ca39c707aaa44b6944 F test/analyzeB.test 8bf35ee0a548aea831bf56762cb8e7fdb1db083d F test/async.test 1d0e056ba1bb9729283a0f22718d3a25e82c277b @@ -1111,7 +1111,7 @@ F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 F tool/wherecosttest.c f407dc4c79786982a475261866a161cd007947ae F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac -P b65dc53415f42d8402d0ec7f4bedf59d7b39b486 48ed8b565b84c8fa7898c2f9817c01f7e9c9182e -R 57c422fa5d2c71518d0f8dca5acd5405 +P a51d751553b14aa26912c516f60727551deb8e60 +R de20fadcbd5549c633507180f3bc907b U drh -Z b21635cdf1a77e86e14dc5bd6f2adf83 +Z c7a8a684bdbfede4a4651eea6f5c0b26 diff --git a/manifest.uuid b/manifest.uuid index d4288fff6f..2a7636c690 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -a51d751553b14aa26912c516f60727551deb8e60 \ No newline at end of file +52d52688644f635a50a60ff17b160f3affa8fa6c \ No newline at end of file diff --git a/src/resolve.c b/src/resolve.c index ab318be8e2..40acc91bc3 100644 --- a/src/resolve.c +++ b/src/resolve.c @@ -705,7 +705,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ pNC->nErr++; } }else{ - pExpr->iTable = 75; /* TUNING: Default 2nd arg to unlikely() is 0.075 */ + pExpr->iTable = 62; /* TUNING: Default 2nd arg to unlikely() is 0.0625 */ } } } diff --git a/src/where.c b/src/where.c index b50851d378..f2ecb76409 100644 --- a/src/where.c +++ b/src/where.c @@ -2557,6 +2557,7 @@ static int whereRangeScanEst( ){ int rc = SQLITE_OK; int nOut = (int)*pnOut; + WhereCost nNew; #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 Index *p = pBuilder->pNew->u.btree.pIndex; @@ -2619,6 +2620,7 @@ static int whereRangeScanEst( whereKeyStats(pParse, p, pRec, 0, a); iNew = a[0] + ((pLower->eOperator & WO_GT) ? a[1] : 0); if( iNew>iLower ) iLower = iNew; + nOut--; } } @@ -2633,12 +2635,12 @@ static int whereRangeScanEst( whereKeyStats(pParse, p, pRec, 1, a); iNew = a[0] + ((pUpper->eOperator & WO_LE) ? a[1] : 0); if( iNewpRec = pRec; if( rc==SQLITE_OK ){ - WhereCost nNew; if( iUpper>iLower ){ nNew = whereCost(iUpper - iLower); }else{ @@ -2660,13 +2662,17 @@ static int whereRangeScanEst( assert( pLower || pUpper ); /* TUNING: Each inequality constraint reduces the search space 4-fold. ** A BETWEEN operator, therefore, reduces the search space 16-fold */ + nNew = nOut; if( pLower && (pLower->wtFlags & TERM_VNULL)==0 ){ - nOut -= 20; assert( 20==whereCost(4) ); + nNew -= 20; assert( 20==whereCost(4) ); + nOut--; } if( pUpper ){ - nOut -= 20; assert( 20==whereCost(4) ); + nNew -= 20; assert( 20==whereCost(4) ); + nOut--; } - if( nOut<10 ) nOut = 10; + if( nNew<10 ) nNew = 10; + if( nNewnLTermnLTerm && (p->wsFlags & pTemplate->wsFlags & WHERE_INDEXED)!=0 && (p->u.btree.pIndex==pTemplate->u.btree.pIndex - || p->u.btree.pIndex->nColumn>=pTemplate->u.btree.pIndex->nColumn) + || pTemplate->rRun+p->nLTerm<=p->rRun+pTemplate->nLTerm) ){ /* Overwrite an existing WhereLoop with an similar one that uses ** more terms of the index */ diff --git a/test/analyze9.test b/test/analyze9.test index 17ef36c475..aaf0ba3bb0 100644 --- a/test/analyze9.test +++ b/test/analyze9.test @@ -805,7 +805,6 @@ do_test 16.1 { ANALYZE; } set nByte2 [lindex [sqlite3_db_status db SCHEMA_USED 0] 1] -puts "$nByte $nByte2" expr {$nByte2 > $nByte+900 && $nByte2 < $nByte+1050} } {1} @@ -846,7 +845,7 @@ do_eqp_test 17.3 { } {/USING INDEX i1/} do_execsql_test 17.4 { - CREATE INDEX i2 ON t1(c); + CREATE INDEX i2 ON t1(c, d); ANALYZE main.i2; } do_eqp_test 17.5 { From aae0f9e462a4b49fbd641e4ecb90a992fca91f45 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 11 Sep 2013 11:38:58 +0000 Subject: [PATCH 025/101] Change the name of the two-argument unlikely() function to likelihood(). Add test cases. FossilOrigin-Name: 29a359b8d7f90e6fa2b28ce2a112284fd3870494 --- manifest | 15 ++++---- manifest.uuid | 2 +- src/func.c | 2 +- src/resolve.c | 4 +-- test/whereG.test | 93 ++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 105 insertions(+), 11 deletions(-) create mode 100644 test/whereG.test diff --git a/manifest b/manifest index c6dcacea09..022df6e646 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Tweaks\sto\sthe\sindex\sselection\slogic. -D 2013-09-11T03:53:22.579 +C Change\sthe\sname\sof\sthe\stwo-argument\sunlikely()\sfunction\sto\slikelihood().\nAdd\stest\scases. +D 2013-09-11T11:38:58.186 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5e41da95d92656a5004b03d3576e8b226858a28e F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -175,7 +175,7 @@ F src/delete.c 2dc64ca360b7d7da481183ea920a813a0c203c97 F src/expr.c d0ed048b3b3c97fddbcccb8df43cc39b89e682c2 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fkey.c be866cd8c4fa6cae98ba33109578fd1a3311ee5b -F src/func.c a297b1f3cf48dd483f5453b7155bc5e8f4ca1fc2 +F src/func.c 0aca17c8bc750fad4856e6098ed5e2597b641a75 F src/global.c 5caf4deab621abb45b4c607aad1bd21c20aac759 F src/hash.c ac3470bbf1ca4ae4e306a8ecb0fdf1731810ffe4 F src/hash.h 8890a25af81fb85a9ad7790d32eedab4b994da22 @@ -214,7 +214,7 @@ F src/pragma.c 3aa3d8c8623b7b71c5b1bfb72dcc31fb0c25665f F src/prepare.c fa6988589f39af8504a61731614cd4f6ae71554f F src/printf.c da9119eb31a187a4b99f60aa4a225141c0ebb74b F src/random.c 0b2dbc37fdfbfa6bd455b091dfcef5bdb32dba68 -F src/resolve.c 140c25a1aa91c460dee74a1b9e6aa5af5c98cbea +F src/resolve.c fde5b5c5be70edb1994e5fbef86f0e08fd267333 F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0 F src/select.c 9239586282bd146ec5843a2cde7d54cd7816cf78 F src/shell.c d920a891ca09b8bd262cced7fb0ab9d723f7a747 @@ -1059,6 +1059,7 @@ F test/whereC.test d6f4ecd4fa2d9429681a5b22a25d2bda8e86ab8a F test/whereD.test 6c2feb79ef1f68381b07f39017fe5f9b96da8d62 F test/whereE.test b3a055eef928c992b0a33198a7b8dc10eea5ad2f F test/whereF.test 5b2ba0dbe8074aa13e416b37c753991f0a2492d7 +F test/whereG.test fa2da659bd2c88314774dc5ff7c297c027eb92ba F test/wherelimit.test 5e9fd41e79bb2b2d588ed999d641d9c965619b31 F test/wild001.test bca33f499866f04c24510d74baf1e578d4e44b1c F test/win32lock.test 7a6bd73a5dcdee39b5bb93e92395e1773a194361 @@ -1111,7 +1112,7 @@ F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 F tool/wherecosttest.c f407dc4c79786982a475261866a161cd007947ae F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac -P a51d751553b14aa26912c516f60727551deb8e60 -R de20fadcbd5549c633507180f3bc907b +P 52d52688644f635a50a60ff17b160f3affa8fa6c +R 31254cf1d66f852ba95ac31e1e5bad22 U drh -Z c7a8a684bdbfede4a4651eea6f5c0b26 +Z 703ec90474ce0af750c28f3450c33fc9 diff --git a/manifest.uuid b/manifest.uuid index 2a7636c690..9111f5c25b 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -52d52688644f635a50a60ff17b160f3affa8fa6c \ No newline at end of file +29a359b8d7f90e6fa2b28ce2a112284fd3870494 \ No newline at end of file diff --git a/src/func.c b/src/func.c index 26cbfbfb03..ae79451110 100644 --- a/src/func.c +++ b/src/func.c @@ -1663,7 +1663,7 @@ void sqlite3RegisterGlobalFunctions(void){ FUNCTION(hex, 1, 0, 0, hexFunc ), FUNCTION2(ifnull, 2, 0, 0, noopFunc, SQLITE_FUNC_COALESCE), FUNCTION2(unlikely, 1, 0, 0, noopFunc, SQLITE_FUNC_UNLIKELY), - FUNCTION2(unlikely, 2, 0, 0, noopFunc, SQLITE_FUNC_UNLIKELY), + FUNCTION2(likelihood, 2, 0, 0, noopFunc, SQLITE_FUNC_UNLIKELY), FUNCTION(random, 0, 0, 0, randomFunc ), FUNCTION(randomblob, 1, 0, 0, randomBlob ), FUNCTION(nullif, 2, 0, 1, nullifFunc ), diff --git a/src/resolve.c b/src/resolve.c index 40acc91bc3..5f238e1027 100644 --- a/src/resolve.c +++ b/src/resolve.c @@ -700,8 +700,8 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ if( n==2 ){ pExpr->iTable = exprProbability(pList->a[1].pExpr); if( pExpr->iTable<0 ){ - sqlite3ErrorMsg(pParse, "second parameter to unlikely() must be " - "between 0.0 and 1.0"); + sqlite3ErrorMsg(pParse, "second argument to likelihood() must be a " + "constant between 0.0 and 1.0"); pNC->nErr++; } }else{ diff --git a/test/whereG.test b/test/whereG.test new file mode 100644 index 0000000000..257a410aae --- /dev/null +++ b/test/whereG.test @@ -0,0 +1,93 @@ +# 2013-09-05 +# +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. +# +#*********************************************************************** +# +# Test cases for query planning decisions and the unlikely() and +# likelihood() functions. + +set testdir [file dirname $argv0] +source $testdir/tester.tcl + +do_execsql_test whereG-1.0 { + CREATE TABLE composer( + cid INTEGER PRIMARY KEY, + cname TEXT + ); + CREATE TABLE album( + aid INTEGER PRIMARY KEY, + aname TEXT + ); + CREATE TABLE track( + tid INTEGER PRIMARY KEY, + cid INTEGER REFERENCES composer, + aid INTEGER REFERENCES album, + title TEXT + ); + CREATE INDEX track_i1 ON track(cid); + CREATE INDEX track_i2 ON track(aid); +} {} +do_eqp_test whereG-1.1 { + SELECT DISTINCT aname + FROM album, composer, track + WHERE unlikely(cname LIKE '%bach%') + AND composer.cid=track.cid + AND album.aid=track.aid; +} {/.*composer.*track.*album.*/} +do_eqp_test whereG-1.2 { + SELECT DISTINCT aname + FROM album, composer, track + WHERE likelihood(cname LIKE '%bach%', 0.5) + AND composer.cid=track.cid + AND album.aid=track.aid; +} {/.*track.*composer.*album.*/} +do_eqp_test whereG-1.3 { + SELECT DISTINCT aname + FROM album, composer, track + WHERE cname LIKE '%bach%' + AND composer.cid=track.cid + AND album.aid=track.aid; +} {/.*track.*composer.*album.*/} +do_eqp_test whereG-1.4 { + SELECT DISTINCT aname + FROM album, composer, track + WHERE cname LIKE '%bach%' + AND unlikely(composer.cid=track.cid) + AND unlikely(album.aid=track.aid); +} {/.*track.*composer.*album.*/} + +do_test whereG-2.1 { + catchsql { + SELECT DISTINCT aname + FROM album, composer, track + WHERE likelihood(cname LIKE '%bach%', -0.01) + AND composer.cid=track.cid + AND album.aid=track.aid; + } +} {1 {second argument to likelihood() must be a constant between 0.0 and 1.0}} +do_test whereG-2.2 { + catchsql { + SELECT DISTINCT aname + FROM album, composer, track + WHERE likelihood(cname LIKE '%bach%', 1.01) + AND composer.cid=track.cid + AND album.aid=track.aid; + } +} {1 {second argument to likelihood() must be a constant between 0.0 and 1.0}} +do_test whereG-2.3 { + catchsql { + SELECT DISTINCT aname + FROM album, composer, track + WHERE likelihood(cname LIKE '%bach%', track.cid) + AND composer.cid=track.cid + AND album.aid=track.aid; + } +} {1 {second argument to likelihood() must be a constant between 0.0 and 1.0}} + +finish_test From 09328c00d69172d93b3c7d53525fc06e78464dbc Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 11 Sep 2013 14:34:58 +0000 Subject: [PATCH 026/101] Additional unlikely() test cases. Logic tweaks to support test coverage. FossilOrigin-Name: 5d00cce74a7aefaf30022ae971ab1e0451e0ad6e --- manifest | 16 ++++++------ manifest.uuid | 2 +- src/resolve.c | 3 ++- src/where.c | 2 +- test/whereG.test | 63 +++++++++++++++++++++++++++++++++++++++++++++--- 5 files changed, 72 insertions(+), 14 deletions(-) diff --git a/manifest b/manifest index 022df6e646..9e53d5e7f4 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Change\sthe\sname\sof\sthe\stwo-argument\sunlikely()\sfunction\sto\slikelihood().\nAdd\stest\scases. -D 2013-09-11T11:38:58.186 +C Additional\sunlikely()\stest\scases.\s\sLogic\stweaks\sto\ssupport\stest\scoverage. +D 2013-09-11T14:34:58.423 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5e41da95d92656a5004b03d3576e8b226858a28e F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -214,7 +214,7 @@ F src/pragma.c 3aa3d8c8623b7b71c5b1bfb72dcc31fb0c25665f F src/prepare.c fa6988589f39af8504a61731614cd4f6ae71554f F src/printf.c da9119eb31a187a4b99f60aa4a225141c0ebb74b F src/random.c 0b2dbc37fdfbfa6bd455b091dfcef5bdb32dba68 -F src/resolve.c fde5b5c5be70edb1994e5fbef86f0e08fd267333 +F src/resolve.c 0e5b31ef428a76782c6ea8244d820f94f55c8110 F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0 F src/select.c 9239586282bd146ec5843a2cde7d54cd7816cf78 F src/shell.c d920a891ca09b8bd262cced7fb0ab9d723f7a747 @@ -290,7 +290,7 @@ F src/vtab.c 5a423b042eb1402ef77697d03d6a67378d97bc8d F src/wal.c 7dc3966ef98b74422267e7e6e46e07ff6c6eb1b4 F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4 F src/walker.c 4fa43583d0a84b48f93b1e88f11adf2065be4e73 -F src/where.c 6b9e2bc47dd1225d690a9c770f157693519b7391 +F src/where.c 74beca71522c95dde151a379cef6badb168a49de F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 F test/aggnested.test 45c0201e28045ad38a530b5a144b73cd4aa2cfd6 @@ -1059,7 +1059,7 @@ F test/whereC.test d6f4ecd4fa2d9429681a5b22a25d2bda8e86ab8a F test/whereD.test 6c2feb79ef1f68381b07f39017fe5f9b96da8d62 F test/whereE.test b3a055eef928c992b0a33198a7b8dc10eea5ad2f F test/whereF.test 5b2ba0dbe8074aa13e416b37c753991f0a2492d7 -F test/whereG.test fa2da659bd2c88314774dc5ff7c297c027eb92ba +F test/whereG.test 5e6954236069469b939d3e0ccaf09dc38dc8320b F test/wherelimit.test 5e9fd41e79bb2b2d588ed999d641d9c965619b31 F test/wild001.test bca33f499866f04c24510d74baf1e578d4e44b1c F test/win32lock.test 7a6bd73a5dcdee39b5bb93e92395e1773a194361 @@ -1112,7 +1112,7 @@ F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 F tool/wherecosttest.c f407dc4c79786982a475261866a161cd007947ae F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac -P 52d52688644f635a50a60ff17b160f3affa8fa6c -R 31254cf1d66f852ba95ac31e1e5bad22 +P 29a359b8d7f90e6fa2b28ce2a112284fd3870494 +R 93dee01cdf95f7285a0f10ba394514d9 U drh -Z 703ec90474ce0af750c28f3450c33fc9 +Z 1aa243de8c46c2869ae531db3feb1a86 diff --git a/manifest.uuid b/manifest.uuid index 9111f5c25b..a7dc88fb9b 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -29a359b8d7f90e6fa2b28ce2a112284fd3870494 \ No newline at end of file +5d00cce74a7aefaf30022ae971ab1e0451e0ad6e \ No newline at end of file diff --git a/src/resolve.c b/src/resolve.c index 5f238e1027..0abd61d399 100644 --- a/src/resolve.c +++ b/src/resolve.c @@ -579,7 +579,8 @@ static int exprProbability(Expr *p){ double r = -1.0; if( p->op!=TK_FLOAT ) return -1; sqlite3AtoF(p->u.zToken, &r, sqlite3Strlen30(p->u.zToken), SQLITE_UTF8); - if( r<0.0 || r>1.0 ) return -1; + assert( r>=0.0 ); + if( r>1.0 ) return -1; return (int)(r*1000.0); } diff --git a/src/where.c b/src/where.c index f2ecb76409..540ab075e6 100644 --- a/src/where.c +++ b/src/where.c @@ -691,7 +691,7 @@ static int whereClauseInsert(WhereClause *pWC, Expr *p, u8 wtFlags){ pTerm = &pWC->a[idx = pWC->nTerm++]; if( wtFlags & TERM_VIRTUAL ){ pTerm->truthProb = 0; - }else if( p && ExprHasAnyProperty(p, EP_Hint) ){ + }else if( ALWAYS(p) && ExprHasAnyProperty(p, EP_Hint) ){ pTerm->truthProb = whereCost(p->iTable) - 99; }else{ pTerm->truthProb = -1; diff --git a/test/whereG.test b/test/whereG.test index 257a410aae..38dfeb07bc 100644 --- a/test/whereG.test +++ b/test/whereG.test @@ -32,6 +32,32 @@ do_execsql_test whereG-1.0 { ); CREATE INDEX track_i1 ON track(cid); CREATE INDEX track_i2 ON track(aid); + INSERT INTO composer VALUES(1, 'W. A. Mozart'); + INSERT INTO composer VALUES(2, 'Beethoven'); + INSERT INTO composer VALUES(3, 'Thomas Tallis'); + INSERT INTO composer VALUES(4, 'Joseph Hayden'); + INSERT INTO composer VALUES(5, 'Thomas Weelkes'); + INSERT INTO composer VALUES(6, 'J. S. Bach'); + INSERT INTO composer VALUES(7, 'Orlando Gibbons'); + INSERT INTO composer VALUES(8, 'Josquin des Prés'); + INSERT INTO composer VALUES(9, 'Byrd'); + INSERT INTO composer VALUES(10, 'Francis Poulenc'); + INSERT INTO composer VALUES(11, 'Mendelsshon'); + INSERT INTO composer VALUES(12, 'Zoltán Kodály'); + INSERT INTO composer VALUES(13, 'Handel'); + INSERT INTO album VALUES(100, 'Kodály: Missa Brevis'); + INSERT INTO album VALUES(101, 'Messiah'); + INSERT INTO album VALUES(102, 'Missa Brevis in D-, K.65'); + INSERT INTO album VALUES(103, 'The complete English anthems'); + INSERT INTO album VALUES(104, 'Mass in B Minor, BWV 232'); + INSERT INTO track VALUES(10005, 12, 100, 'Sanctus'); + INSERT INTO track VALUES(10007, 12, 100, 'Agnus Dei'); + INSERT INTO track VALUES(10115, 13, 101, 'Surely He Hath Borne Our Griefs'); + INSERT INTO track VALUES(10129, 13, 101, 'Since By Man Came Death'); + INSERT INTO track VALUES(10206, 1, 102, 'Agnus Dei'); + INSERT INTO track VALUES(10301, 3, 103, 'If Ye Love Me'); + INSERT INTO track VALUES(10402, 6, 104, 'Domine Deus'); + INSERT INTO track VALUES(10403, 6, 104, 'Qui tollis'); } {} do_eqp_test whereG-1.1 { SELECT DISTINCT aname @@ -40,27 +66,58 @@ do_eqp_test whereG-1.1 { AND composer.cid=track.cid AND album.aid=track.aid; } {/.*composer.*track.*album.*/} -do_eqp_test whereG-1.2 { +do_execsql_test whereG-1.2 { + SELECT DISTINCT aname + FROM album, composer, track + WHERE unlikely(cname LIKE '%bach%') + AND composer.cid=track.cid + AND album.aid=track.aid; +} {{Mass in B Minor, BWV 232}} + +do_eqp_test whereG-1.3 { SELECT DISTINCT aname FROM album, composer, track WHERE likelihood(cname LIKE '%bach%', 0.5) AND composer.cid=track.cid AND album.aid=track.aid; } {/.*track.*composer.*album.*/} -do_eqp_test whereG-1.3 { +do_execsql_test whereG-1.4 { + SELECT DISTINCT aname + FROM album, composer, track + WHERE likelihood(cname LIKE '%bach%', 0.5) + AND composer.cid=track.cid + AND album.aid=track.aid; +} {{Mass in B Minor, BWV 232}} + +do_eqp_test whereG-1.5 { SELECT DISTINCT aname FROM album, composer, track WHERE cname LIKE '%bach%' AND composer.cid=track.cid AND album.aid=track.aid; } {/.*track.*composer.*album.*/} -do_eqp_test whereG-1.4 { +do_execsql_test whereG-1.6 { + SELECT DISTINCT aname + FROM album, composer, track + WHERE cname LIKE '%bach%' + AND composer.cid=track.cid + AND album.aid=track.aid; +} {{Mass in B Minor, BWV 232}} + +do_eqp_test whereG-1.7 { SELECT DISTINCT aname FROM album, composer, track WHERE cname LIKE '%bach%' AND unlikely(composer.cid=track.cid) AND unlikely(album.aid=track.aid); } {/.*track.*composer.*album.*/} +do_execsql_test whereG-1.8 { + SELECT DISTINCT aname + FROM album, composer, track + WHERE cname LIKE '%bach%' + AND unlikely(composer.cid=track.cid) + AND unlikely(album.aid=track.aid); +} {{Mass in B Minor, BWV 232}} do_test whereG-2.1 { catchsql { From 89a75397e02236e262c196490e7fbc01c75cdf81 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 11 Sep 2013 14:57:11 +0000 Subject: [PATCH 027/101] Add test cases to cover TPC-H Q8. FossilOrigin-Name: eb5cef8351d12c0f8550dac96ee7a6e495975b5a --- manifest | 11 +-- manifest.uuid | 2 +- test/tpch01.test | 187 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 194 insertions(+), 6 deletions(-) create mode 100644 test/tpch01.test diff --git a/manifest b/manifest index 11dfa9b55b..cc548c6232 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Deterministically\sinitialize\sthe\sPRNG\sused\sas\sa\stie-breaker\sin\sthe\sANALYZE\ncommand,\sso\sthat\sthe\sanalysis\sis\salways\sthe\ssame\sgiven\sthe\ssame\sdatabase.\nThis\ssimplifies\stesting. -D 2013-09-10T01:41:25.676 +C Add\stest\scases\sto\scover\sTPC-H\sQ8. +D 2013-09-11T14:57:11.714 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5e41da95d92656a5004b03d3576e8b226858a28e F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -964,6 +964,7 @@ F test/tkt3992.test f3e7d548ac26f763b47bc0f750da3d03c81071da F test/tkt3997.test a335fa41ca3985660a139df7b734a26ef53284bd F test/tkt4018.test 7c2c9ba4df489c676a0a7a0e809a1fb9b2185bd1 F test/tokenize.test ce430a7aed48fc98301611429595883fdfcab5d7 +F test/tpch01.test 8f4ac52f62f3e9f6bce0889105aecdf0275e331b F test/trace.test 4b36a41a3e9c7842151af6da5998f5080cdad9e5 F test/trace2.test e7a988fdd982cdec62f1f1f34b0360e6476d01a0 F test/trans.test 6e1b4c6a42dba31bd65f8fa5e61a2708e08ddde6 @@ -1111,7 +1112,7 @@ F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 F tool/wherecosttest.c f407dc4c79786982a475261866a161cd007947ae F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac -P d6e361d7fb8013d616af91ef2c10038c97d1be5f -R f0dc49c77588220f9d25d9d712edfe4a +P 48ed8b565b84c8fa7898c2f9817c01f7e9c9182e +R b9522deba37561644e51654b6b510026 U drh -Z e68c71d629e67be96bb05aa541d1ef71 +Z 8b5488a345e69fd6a7996d8b2149a33e diff --git a/manifest.uuid b/manifest.uuid index b31980649d..d5a16fdb23 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -48ed8b565b84c8fa7898c2f9817c01f7e9c9182e \ No newline at end of file +eb5cef8351d12c0f8550dac96ee7a6e495975b5a \ No newline at end of file diff --git a/test/tpch01.test b/test/tpch01.test new file mode 100644 index 0000000000..2d099d63fb --- /dev/null +++ b/test/tpch01.test @@ -0,0 +1,187 @@ +# 2013-09-05 +# +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. +# +#*********************************************************************** +# +# TPC-H test queries. +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl +set testprefix tpch01 + +do_execsql_test tpch01-1.0 { + CREATE TABLE NATION ( N_NATIONKEY INTEGER NOT NULL, + N_NAME CHAR(25) NOT NULL, + N_REGIONKEY INTEGER NOT NULL, + N_COMMENT VARCHAR(152)); + CREATE TABLE REGION ( R_REGIONKEY INTEGER NOT NULL, + R_NAME CHAR(25) NOT NULL, + R_COMMENT VARCHAR(152)); + CREATE TABLE PART ( P_PARTKEY INTEGER NOT NULL, + P_NAME VARCHAR(55) NOT NULL, + P_MFGR CHAR(25) NOT NULL, + P_BRAND CHAR(10) NOT NULL, + P_TYPE VARCHAR(25) NOT NULL, + P_SIZE INTEGER NOT NULL, + P_CONTAINER CHAR(10) NOT NULL, + P_RETAILPRICE DECIMAL(15,2) NOT NULL, + P_COMMENT VARCHAR(23) NOT NULL ); + CREATE TABLE SUPPLIER ( S_SUPPKEY INTEGER NOT NULL, + S_NAME CHAR(25) NOT NULL, + S_ADDRESS VARCHAR(40) NOT NULL, + S_NATIONKEY INTEGER NOT NULL, + S_PHONE CHAR(15) NOT NULL, + S_ACCTBAL DECIMAL(15,2) NOT NULL, + S_COMMENT VARCHAR(101) NOT NULL); + CREATE TABLE PARTSUPP ( PS_PARTKEY INTEGER NOT NULL, + PS_SUPPKEY INTEGER NOT NULL, + PS_AVAILQTY INTEGER NOT NULL, + PS_SUPPLYCOST DECIMAL(15,2) NOT NULL, + PS_COMMENT VARCHAR(199) NOT NULL ); + CREATE TABLE CUSTOMER ( C_CUSTKEY INTEGER NOT NULL, + C_NAME VARCHAR(25) NOT NULL, + C_ADDRESS VARCHAR(40) NOT NULL, + C_NATIONKEY INTEGER NOT NULL, + C_PHONE CHAR(15) NOT NULL, + C_ACCTBAL DECIMAL(15,2) NOT NULL, + C_MKTSEGMENT CHAR(10) NOT NULL, + C_COMMENT VARCHAR(117) NOT NULL); + CREATE TABLE ORDERS ( O_ORDERKEY INTEGER NOT NULL, + O_CUSTKEY INTEGER NOT NULL, + O_ORDERSTATUS CHAR(1) NOT NULL, + O_TOTALPRICE DECIMAL(15,2) NOT NULL, + O_ORDERDATE DATE NOT NULL, + O_ORDERPRIORITY CHAR(15) NOT NULL, + O_CLERK CHAR(15) NOT NULL, + O_SHIPPRIORITY INTEGER NOT NULL, + O_COMMENT VARCHAR(79) NOT NULL); + CREATE TABLE LINEITEM ( L_ORDERKEY INTEGER NOT NULL, + L_PARTKEY INTEGER NOT NULL, + L_SUPPKEY INTEGER NOT NULL, + L_LINENUMBER INTEGER NOT NULL, + L_QUANTITY DECIMAL(15,2) NOT NULL, + L_EXTENDEDPRICE DECIMAL(15,2) NOT NULL, + L_DISCOUNT DECIMAL(15,2) NOT NULL, + L_TAX DECIMAL(15,2) NOT NULL, + L_RETURNFLAG CHAR(1) NOT NULL, + L_LINESTATUS CHAR(1) NOT NULL, + L_SHIPDATE DATE NOT NULL, + L_COMMITDATE DATE NOT NULL, + L_RECEIPTDATE DATE NOT NULL, + L_SHIPINSTRUCT CHAR(25) NOT NULL, + L_SHIPMODE CHAR(10) NOT NULL, + L_COMMENT VARCHAR(44) NOT NULL); + CREATE INDEX npki on nation(N_NATIONKEY); + CREATE INDEX rpki on region(R_REGIONKEY); + CREATE INDEX ppki on part(P_PARTKEY); + CREATE INDEX spki on supplier(S_SUPPKEY); + CREATE INDEX pspki on partsupp(PS_PARTKEY, PS_SUPPKEY); + CREATE INDEX cpki on customer(C_CUSTKEY); + CREATE INDEX opki on orders(O_ORDERKEY); + CREATE INDEX lpki on lineitem(L_ORDERKEY, L_LINENUMBER); + CREATE INDEX nrki on nation(n_regionkey); + CREATE INDEX snki on supplier(s_nationkey); + CREATE INDEX cnki on customer(c_nationkey); + CREATE INDEX ocki on orders(O_CUSTKEY); + CREATE INDEX odi on orders(O_ORDERDATE); + CREATE INDEX lpki2 on lineitem(L_PARTKEY); + CREATE INDEX lski on lineitem(L_SUPPKEY); + CREATE INDEX lsdi on lineitem(L_SHIPDATE); + CREATE INDEX lcdi on lineitem(L_COMMITDATE); + CREATE INDEX lrdi on lineitem(L_RECEIPTDATE); + CREATE INDEX bootleg_nni on nation(N_NAME); + CREATE INDEX bootleg_psi on part(p_size); + CREATE INDEX bootleg_pti on part(p_type); + ANALYZE sqlite_master; + INSERT INTO sqlite_stat1 VALUES('LINEITEM','lrdi','600572 236'); + INSERT INTO sqlite_stat1 VALUES('LINEITEM','lcdi','600572 244'); + INSERT INTO sqlite_stat1 VALUES('LINEITEM','lsdi','600572 238'); + INSERT INTO sqlite_stat1 VALUES('LINEITEM','lski','600572 601'); + INSERT INTO sqlite_stat1 VALUES('LINEITEM','lpki2','600572 31'); + INSERT INTO sqlite_stat1 VALUES('LINEITEM','lpki','600572 5 1'); + INSERT INTO sqlite_stat1 VALUES('ORDERS','odi','150000 63'); + INSERT INTO sqlite_stat1 VALUES('ORDERS','ocki','150000 15'); + INSERT INTO sqlite_stat1 VALUES('ORDERS','opki','150000 1'); + INSERT INTO sqlite_stat1 VALUES('CUSTOMER','cnki','15000 600'); + INSERT INTO sqlite_stat1 VALUES('CUSTOMER','cpki','15000 1'); + INSERT INTO sqlite_stat1 VALUES('PARTSUPP','pspki','80000 4 1'); + INSERT INTO sqlite_stat1 VALUES('SUPPLIER','snki','1000 40'); + INSERT INTO sqlite_stat1 VALUES('SUPPLIER','spki','1000 1'); + INSERT INTO sqlite_stat1 VALUES('PART','bootleg_pti','20000 134'); + INSERT INTO sqlite_stat1 VALUES('PART','bootleg_psi','20000 400'); + INSERT INTO sqlite_stat1 VALUES('PART','ppki','20000 1'); + INSERT INTO sqlite_stat1 VALUES('REGION','rpki','5 1'); + INSERT INTO sqlite_stat1 VALUES('NATION','bootleg_nni','25 1'); + INSERT INTO sqlite_stat1 VALUES('NATION','nrki','25 5'); + INSERT INTO sqlite_stat1 VALUES('NATION','npki','25 1'); + ANALYZE sqlite_master; +} {} + +do_test tpch01-1.1 { + unset -nocomplain ::eqpres + set ::eqpres [db eval {EXPLAIN QUERY PLAN + select + o_year, + sum(case + when nation = 'EGYPT' then volume + else 0 + end) / sum(volume) as mkt_share + from + ( + select + strftime('%Y', o_orderdate) as o_year, + l_extendedprice * (1 - l_discount) as volume, + n2.n_name as nation + from + part, + supplier, + lineitem, + orders, + customer, + nation n1, + nation n2, + region + where + p_partkey = l_partkey + and s_suppkey = l_suppkey + and l_orderkey = o_orderkey + and o_custkey = c_custkey + and c_nationkey = n1.n_nationkey + and n1.n_regionkey = r_regionkey + and r_name = 'MIDDLE EAST' + and s_nationkey = n2.n_nationkey + and o_orderdate between '1995-01-01' and '1996-12-31' + and p_type = 'LARGE PLATED STEEL' + ) as all_nations + group by + o_year + order by + o_year;}] + set ::eqpres +} {/0 0 0 {SEARCH TABLE part USING INDEX bootleg_pti .P_TYPE=..} 0 1 2 {SEARCH TABLE lineitem USING INDEX lpki2 .L_PARTKEY=..}.*/} +do_test tpch01-1.1b { + set ::eqpres +} {/.* customer .* nation AS n1 .* nation AS n2 .*/} + +do_eqp_test tpch01-1.2 { +select + c_custkey, c_name, sum(l_extendedprice * (1 - l_discount)) as revenue, + c_acctbal, n_name, c_address, c_phone, c_comment +from + customer, orders, lineitem, nation +where + c_custkey = o_custkey and l_orderkey = o_orderkey + and o_orderdate >= '1994-08-01' and o_orderdate < date('1994-08-01', '+3 month') + and l_returnflag = 'R' and c_nationkey = n_nationkey +group by + c_custkey, c_name, c_acctbal, c_phone, n_name, c_address, c_comment +order by + revenue desc; +} {0 0 1 {SEARCH TABLE orders USING INDEX odi (O_ORDERDATE>? AND O_ORDERDATE Date: Wed, 11 Sep 2013 17:39:09 +0000 Subject: [PATCH 028/101] Improvements to likelihood processing so that commuting an unindexed term in the WHERE clause does not change the query plan. FossilOrigin-Name: 6e6bded055cdbc902731687c86d92c39a3ba5904 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/where.c | 26 +++++++++++--------------- test/whereG.test | 20 ++++++++++++++++++++ 4 files changed, 39 insertions(+), 23 deletions(-) diff --git a/manifest b/manifest index 9e53d5e7f4..8e7446d805 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Additional\sunlikely()\stest\scases.\s\sLogic\stweaks\sto\ssupport\stest\scoverage. -D 2013-09-11T14:34:58.423 +C Improvements\sto\slikelihood\sprocessing\sso\sthat\scommuting\san\sunindexed\sterm\sin\nthe\sWHERE\sclause\sdoes\snot\schange\sthe\squery\splan. +D 2013-09-11T17:39:09.434 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5e41da95d92656a5004b03d3576e8b226858a28e F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -290,7 +290,7 @@ F src/vtab.c 5a423b042eb1402ef77697d03d6a67378d97bc8d F src/wal.c 7dc3966ef98b74422267e7e6e46e07ff6c6eb1b4 F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4 F src/walker.c 4fa43583d0a84b48f93b1e88f11adf2065be4e73 -F src/where.c 74beca71522c95dde151a379cef6badb168a49de +F src/where.c 47a9d554aa12e37d00c87ed6557edff3f96d1980 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 F test/aggnested.test 45c0201e28045ad38a530b5a144b73cd4aa2cfd6 @@ -1059,7 +1059,7 @@ F test/whereC.test d6f4ecd4fa2d9429681a5b22a25d2bda8e86ab8a F test/whereD.test 6c2feb79ef1f68381b07f39017fe5f9b96da8d62 F test/whereE.test b3a055eef928c992b0a33198a7b8dc10eea5ad2f F test/whereF.test 5b2ba0dbe8074aa13e416b37c753991f0a2492d7 -F test/whereG.test 5e6954236069469b939d3e0ccaf09dc38dc8320b +F test/whereG.test 2a3d5181decc801b36600fa1c40b0dad2ccc267f F test/wherelimit.test 5e9fd41e79bb2b2d588ed999d641d9c965619b31 F test/wild001.test bca33f499866f04c24510d74baf1e578d4e44b1c F test/win32lock.test 7a6bd73a5dcdee39b5bb93e92395e1773a194361 @@ -1112,7 +1112,7 @@ F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 F tool/wherecosttest.c f407dc4c79786982a475261866a161cd007947ae F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac -P 29a359b8d7f90e6fa2b28ce2a112284fd3870494 -R 93dee01cdf95f7285a0f10ba394514d9 +P 5d00cce74a7aefaf30022ae971ab1e0451e0ad6e +R aedc9ce3e88fcb8ddfac4258d6222c86 U drh -Z 1aa243de8c46c2869ae531db3feb1a86 +Z 4fd6b6c258c46144822c202b8357c6fb diff --git a/manifest.uuid b/manifest.uuid index a7dc88fb9b..b142052f40 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -5d00cce74a7aefaf30022ae971ab1e0451e0ad6e \ No newline at end of file +6e6bded055cdbc902731687c86d92c39a3ba5904 \ No newline at end of file diff --git a/src/where.c b/src/where.c index 540ab075e6..86863451fb 100644 --- a/src/where.c +++ b/src/where.c @@ -689,9 +689,7 @@ static int whereClauseInsert(WhereClause *pWC, Expr *p, u8 wtFlags){ pWC->nSlot = sqlite3DbMallocSize(db, pWC->a)/sizeof(pWC->a[0]); } pTerm = &pWC->a[idx = pWC->nTerm++]; - if( wtFlags & TERM_VIRTUAL ){ - pTerm->truthProb = 0; - }else if( ALWAYS(p) && ExprHasAnyProperty(p, EP_Hint) ){ + if( p && ExprHasAnyProperty(p, EP_Hint) ){ pTerm->truthProb = whereCost(p->iTable) - 99; }else{ pTerm->truthProb = -1; @@ -4286,24 +4284,24 @@ whereLoopInsert_noop: ** reduces the number of output rows by sqrt(2). */ static void whereLoopOutputAdjust(WhereClause *pWC, WhereLoop *pLoop, int iCur){ - WhereTerm *pTerm; + WhereTerm *pTerm, *pX; Bitmask notAllowed = ~(pLoop->prereq|pLoop->maskSelf); - int x = 0; - int i; + int i, j; if( !OptimizationEnabled(pWC->pWInfo->pParse->db, SQLITE_AdjustOutEst) ){ return; } for(i=pWC->nTerm, pTerm=pWC->a; i>0; i--, pTerm++){ - if( (pTerm->wtFlags & TERM_VIRTUAL)!=0 ) continue; + if( (pTerm->wtFlags & TERM_VIRTUAL)!=0 ) break; if( (pTerm->prereqAll & pLoop->maskSelf)==0 ) continue; if( (pTerm->prereqAll & notAllowed)!=0 ) continue; - x += pTerm->truthProb; + for(j=pLoop->nLTerm-1; j>=0; j--){ + pX = pLoop->aLTerm[j]; + if( pX==pTerm ) break; + if( pX->iParent>=0 && (&pWC->a[pX->iParent])==pTerm ) break; + } + if( j<0 ) pLoop->nOut += pTerm->truthProb; } - for(i=pLoop->nLTerm-1; i>=0; i--){ - x -= pLoop->aLTerm[i]->truthProb; - } - if( x<0 ) pLoop->nOut += x; } /* @@ -5426,9 +5424,7 @@ static int wherePathSolver(WhereInfo *pWInfo, WhereCost nRowEst){ } } if( jj>=nTo ){ - if( nTo>=mxChoice - && (rCost>mxCost || (rCost==mxCost && nOut>=mxOut)) - ){ + if( nTo>=mxChoice && rCost>=mxCost ){ #ifdef WHERETRACE_ENABLED if( sqlite3WhereTrace&0x4 ){ sqlite3DebugPrintf("Skip %s cost=%-3d,%3d order=%c\n", diff --git a/test/whereG.test b/test/whereG.test index 38dfeb07bc..1b6a861855 100644 --- a/test/whereG.test +++ b/test/whereG.test @@ -147,4 +147,24 @@ do_test whereG-2.3 { } } {1 {second argument to likelihood() must be a constant between 0.0 and 1.0}} +# Commuting a term of the WHERE clause should not change the query plan +# +do_execsql_test whereG-3.0 { + CREATE TABLE a(a1 PRIMARY KEY, a2); + CREATE TABLE b(b1 PRIMARY KEY, b2); +} {} +do_eqp_test whereG-3.1 { + SELECT * FROM a, b WHERE b1=a1 AND a2=5; +} {/.*SCAN TABLE a.*SEARCH TABLE b USING INDEX .*b_1 .b1=..*/} +do_eqp_test whereG-3.2 { + SELECT * FROM a, b WHERE a1=b1 AND a2=5; +} {/.*SCAN TABLE a.*SEARCH TABLE b USING INDEX .*b_1 .b1=..*/} +do_eqp_test whereG-3.3 { + SELECT * FROM a, b WHERE a2=5 AND b1=a1; +} {/.*SCAN TABLE a.*SEARCH TABLE b USING INDEX .*b_1 .b1=..*/} +do_eqp_test whereG-3.4 { + SELECT * FROM a, b WHERE a2=5 AND a1=b1; +} {/.*SCAN TABLE a.*SEARCH TABLE b USING INDEX .*b_1 .b1=..*/} + + finish_test From 61b7060c4faec065f37ab36944d372ce0e7e8097 Mon Sep 17 00:00:00 2001 From: mistachkin Date: Thu, 12 Sep 2013 00:54:59 +0000 Subject: [PATCH 029/101] Fix harmless compiler warning. FossilOrigin-Name: 2b510614dc6d878bd49eb428f167014f7f2e2568 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/os_win.c | 2 ++ 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index cc548c6232..e561aa5847 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\stest\scases\sto\scover\sTPC-H\sQ8. -D 2013-09-11T14:57:11.714 +C Fix\sharmless\scompiler\swarning. +D 2013-09-12T00:54:59.015 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5e41da95d92656a5004b03d3576e8b226858a28e F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -203,7 +203,7 @@ F src/os.c b4ad71336fd96f97776f75587cd9e8218288f5be F src/os.h 4a46270a64e9193af4a0aaa3bc2c66dc07c29b3f F src/os_common.h 92815ed65f805560b66166e3583470ff94478f04 F src/os_unix.c 243fb37f47dc072fc59839ea241ff0a17c8d76e6 -F src/os_win.c bb592dfb850e4ee3e4caecce461dca74dc40936d +F src/os_win.c af9db76467add89679d3ebb451069c2f842ecd3c F src/pager.c 2aa4444ffe86e9282d03bc349a4a5e49bd77c0e8 F src/pager.h f094af9f6ececfaa8a1e93876905a4f34233fb0c F src/parse.y 27c6b4138497d6f8360ba7847da6ed48033f957f @@ -1112,7 +1112,7 @@ F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 F tool/wherecosttest.c f407dc4c79786982a475261866a161cd007947ae F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac -P 48ed8b565b84c8fa7898c2f9817c01f7e9c9182e -R b9522deba37561644e51654b6b510026 -U drh -Z 8b5488a345e69fd6a7996d8b2149a33e +P eb5cef8351d12c0f8550dac96ee7a6e495975b5a +R bf7885bb1c586c43940718dd93c9bac5 +U mistachkin +Z ad1bbbbf78cb709221466a1e4ff47ba4 diff --git a/manifest.uuid b/manifest.uuid index d5a16fdb23..d77a97bee1 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -eb5cef8351d12c0f8550dac96ee7a6e495975b5a \ No newline at end of file +2b510614dc6d878bd49eb428f167014f7f2e2568 \ No newline at end of file diff --git a/src/os_win.c b/src/os_win.c index 72d6e8ba5c..3cadd036ab 100644 --- a/src/os_win.c +++ b/src/os_win.c @@ -3919,6 +3919,7 @@ static const sqlite3_io_methods winIoMethod = { ** sqlite3_vfs object. */ +#if 0 /* ** Convert a filename from whatever the underlying operating system ** supports for filenames into UTF-8. Space to hold the result is @@ -3937,6 +3938,7 @@ static char *winConvertToUtf8Filename(const void *zFilename){ /* caller will handle out of memory */ return zConverted; } +#endif /* ** Convert a UTF-8 filename into whatever form the underlying From 4a1f4ff53bd6be2f083f3fc77e6df8941ec24c59 Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 12 Sep 2013 01:33:53 +0000 Subject: [PATCH 030/101] Remove two obsolete fields from the sqlite3 object. FossilOrigin-Name: 117fa5fbc9bed1a7b982c8ddc21b7e228905ccb4 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/sqliteInt.h | 2 -- 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index e561aa5847..6cddbe1bc9 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sharmless\scompiler\swarning. -D 2013-09-12T00:54:59.015 +C Remove\stwo\sobsolete\sfields\sfrom\sthe\ssqlite3\sobject. +D 2013-09-12T01:33:53.069 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5e41da95d92656a5004b03d3576e8b226858a28e F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -221,7 +221,7 @@ F src/shell.c d920a891ca09b8bd262cced7fb0ab9d723f7a747 F src/sqlite.h.in ec40aa958a270416fb04b4f72210357bf163d2c5 F src/sqlite3.rc fea433eb0a59f4c9393c8e6d76a6e2596b1fe0c0 F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc -F src/sqliteInt.h 32e959dba9899360ce4ae3cd6cc77b4a8df277e8 +F src/sqliteInt.h 600a1da8ca71c919a1a270146b052a66a128533a F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158 F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e @@ -1112,7 +1112,7 @@ F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 F tool/wherecosttest.c f407dc4c79786982a475261866a161cd007947ae F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac -P eb5cef8351d12c0f8550dac96ee7a6e495975b5a -R bf7885bb1c586c43940718dd93c9bac5 -U mistachkin -Z ad1bbbbf78cb709221466a1e4ff47ba4 +P 2b510614dc6d878bd49eb428f167014f7f2e2568 +R c3304550dc7e156a767f11782ed297f6 +U drh +Z 81bb05c3046a00cec99b12eff1620df6 diff --git a/manifest.uuid b/manifest.uuid index d77a97bee1..8f27c878e4 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -2b510614dc6d878bd49eb428f167014f7f2e2568 \ No newline at end of file +117fa5fbc9bed1a7b982c8ddc21b7e228905ccb4 \ No newline at end of file diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 6b3fbe8518..f017229f71 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -921,8 +921,6 @@ struct sqlite3 { void(*xCollNeeded16)(void*,sqlite3*,int eTextRep,const void*); void *pCollNeededArg; sqlite3_value *pErr; /* Most recent error message */ - char *zErrMsg; /* Most recent error message (UTF-8 encoded) */ - char *zErrMsg16; /* Most recent error message (UTF-16 encoded) */ union { volatile int isInterrupted; /* True if sqlite3_interrupt has been called */ double notUsed1; /* Spacer */ From 36ca5359dc5eed1886a3f97bb9bac1ae90957989 Mon Sep 17 00:00:00 2001 From: mistachkin Date: Thu, 12 Sep 2013 01:47:57 +0000 Subject: [PATCH 031/101] Fix a couple more harmless compiler warnings. FossilOrigin-Name: 59708674f66e06c9c31c1a24f2f1c51f0bf4fa3e --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/os_win.c | 16 +++++++++++++--- 3 files changed, 21 insertions(+), 11 deletions(-) diff --git a/manifest b/manifest index 6cddbe1bc9..121d808050 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Remove\stwo\sobsolete\sfields\sfrom\sthe\ssqlite3\sobject. -D 2013-09-12T01:33:53.069 +C Fix\sa\scouple\smore\sharmless\scompiler\swarnings. +D 2013-09-12T01:47:57.395 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5e41da95d92656a5004b03d3576e8b226858a28e F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -203,7 +203,7 @@ F src/os.c b4ad71336fd96f97776f75587cd9e8218288f5be F src/os.h 4a46270a64e9193af4a0aaa3bc2c66dc07c29b3f F src/os_common.h 92815ed65f805560b66166e3583470ff94478f04 F src/os_unix.c 243fb37f47dc072fc59839ea241ff0a17c8d76e6 -F src/os_win.c af9db76467add89679d3ebb451069c2f842ecd3c +F src/os_win.c d18f670eeca4ab3da61230628d9042dfa282bd89 F src/pager.c 2aa4444ffe86e9282d03bc349a4a5e49bd77c0e8 F src/pager.h f094af9f6ececfaa8a1e93876905a4f34233fb0c F src/parse.y 27c6b4138497d6f8360ba7847da6ed48033f957f @@ -1112,7 +1112,7 @@ F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 F tool/wherecosttest.c f407dc4c79786982a475261866a161cd007947ae F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac -P 2b510614dc6d878bd49eb428f167014f7f2e2568 -R c3304550dc7e156a767f11782ed297f6 -U drh -Z 81bb05c3046a00cec99b12eff1620df6 +P 117fa5fbc9bed1a7b982c8ddc21b7e228905ccb4 +R 381ae7788d46844675761732daa8c2f7 +U mistachkin +Z 423fbd0e140db731445f28d728ebdbaa diff --git a/manifest.uuid b/manifest.uuid index 8f27c878e4..e87cede53b 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -117fa5fbc9bed1a7b982c8ddc21b7e228905ccb4 \ No newline at end of file +59708674f66e06c9c31c1a24f2f1c51f0bf4fa3e \ No newline at end of file diff --git a/src/os_win.c b/src/os_win.c index 3cadd036ab..c1b95d565e 100644 --- a/src/os_win.c +++ b/src/os_win.c @@ -108,6 +108,14 @@ # define winIsDirSep(a) (((a) == '/') || ((a) == '\\')) #endif +/* +** This macro is used when a local variable is set to a value that is +** [sometimes] not used by the code (e.g. via conditional compilation). +*/ +#ifndef UNUSED_VARIABLE_VALUE +# define UNUSED_VARIABLE_VALUE(x) (void)(x) +#endif + /* ** Returns the string that should be used as the directory separator. */ @@ -358,7 +366,8 @@ const sqlite3_mem_methods *sqlite3MemGetWin32(void); */ #ifdef SQLITE_TEST int sqlite3_os_type = 0; -#else +#elif !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && \ + defined(SQLITE_WIN32_HAS_ANSI) && defined(SQLITE_WIN32_HAS_WIDE) static int sqlite3_os_type = 0; #endif @@ -3185,7 +3194,6 @@ static int winDelete(sqlite3_vfs *,const char*,int); static void winShmPurge(sqlite3_vfs *pVfs, int deleteFlag){ winShmNode **pp; winShmNode *p; - BOOL bRc; assert( winShmMutexHeld() ); OSTRACE(("SHM-PURGE pid=%lu, deleteFlag=%d\n", osGetCurrentProcessId(), deleteFlag)); @@ -3195,12 +3203,14 @@ static void winShmPurge(sqlite3_vfs *pVfs, int deleteFlag){ int i; if( p->mutex ) sqlite3_mutex_free(p->mutex); for(i=0; inRegion; i++){ - bRc = osUnmapViewOfFile(p->aRegion[i].pMap); + BOOL bRc = osUnmapViewOfFile(p->aRegion[i].pMap); OSTRACE(("SHM-PURGE-UNMAP pid=%lu, region=%d, rc=%s\n", osGetCurrentProcessId(), i, bRc ? "ok" : "failed")); + UNUSED_VARIABLE_VALUE(bRc); bRc = osCloseHandle(p->aRegion[i].hMap); OSTRACE(("SHM-PURGE-CLOSE pid=%lu, region=%d, rc=%s\n", osGetCurrentProcessId(), i, bRc ? "ok" : "failed")); + UNUSED_VARIABLE_VALUE(bRc); } if( p->hFile.h!=NULL && p->hFile.h!=INVALID_HANDLE_VALUE ){ SimulateIOErrorBenign(1); From a9cb5be49aed9014dfc7fcc74f7bf4bfe62909cf Mon Sep 17 00:00:00 2001 From: mistachkin Date: Thu, 12 Sep 2013 02:09:05 +0000 Subject: [PATCH 032/101] For error log messages generated by the Win32 native allocator, make sure the correct format specifier is used for the value returned by GetLastError(). FossilOrigin-Name: 75a8a8c1b39725d36db627536d0c69401f8e0815 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/os_win.c | 14 +++++++------- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/manifest b/manifest index 121d808050..b4006aefdd 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\scouple\smore\sharmless\scompiler\swarnings. -D 2013-09-12T01:47:57.395 +C For\serror\slog\smessages\sgenerated\sby\sthe\sWin32\snative\sallocator,\smake\ssure\sthe\scorrect\sformat\sspecifier\sis\sused\sfor\sthe\svalue\sreturned\sby\sGetLastError(). +D 2013-09-12T02:09:05.258 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5e41da95d92656a5004b03d3576e8b226858a28e F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -203,7 +203,7 @@ F src/os.c b4ad71336fd96f97776f75587cd9e8218288f5be F src/os.h 4a46270a64e9193af4a0aaa3bc2c66dc07c29b3f F src/os_common.h 92815ed65f805560b66166e3583470ff94478f04 F src/os_unix.c 243fb37f47dc072fc59839ea241ff0a17c8d76e6 -F src/os_win.c d18f670eeca4ab3da61230628d9042dfa282bd89 +F src/os_win.c 0e73f891dd806b82a76d4e19179c532f02236b86 F src/pager.c 2aa4444ffe86e9282d03bc349a4a5e49bd77c0e8 F src/pager.h f094af9f6ececfaa8a1e93876905a4f34233fb0c F src/parse.y 27c6b4138497d6f8360ba7847da6ed48033f957f @@ -1112,7 +1112,7 @@ F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 F tool/wherecosttest.c f407dc4c79786982a475261866a161cd007947ae F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac -P 117fa5fbc9bed1a7b982c8ddc21b7e228905ccb4 -R 381ae7788d46844675761732daa8c2f7 +P 59708674f66e06c9c31c1a24f2f1c51f0bf4fa3e +R 1ed3fe4d70c0b22924a418f004301c6c U mistachkin -Z 423fbd0e140db731445f28d728ebdbaa +Z 0449c470c02ad9774090312d2090be91 diff --git a/manifest.uuid b/manifest.uuid index e87cede53b..85af47ce04 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -59708674f66e06c9c31c1a24f2f1c51f0bf4fa3e \ No newline at end of file +75a8a8c1b39725d36db627536d0c69401f8e0815 \ No newline at end of file diff --git a/src/os_win.c b/src/os_win.c index c1b95d565e..10016ed423 100644 --- a/src/os_win.c +++ b/src/os_win.c @@ -1168,7 +1168,7 @@ static void *winMemMalloc(int nBytes){ assert( nBytes>=0 ); p = osHeapAlloc(hHeap, SQLITE_WIN32_HEAP_FLAGS, (SIZE_T)nBytes); if( !p ){ - sqlite3_log(SQLITE_NOMEM, "failed to HeapAlloc %u bytes (%d), heap=%p", + sqlite3_log(SQLITE_NOMEM, "failed to HeapAlloc %u bytes (%lu), heap=%p", nBytes, osGetLastError(), (void*)hHeap); } return p; @@ -1189,7 +1189,7 @@ static void winMemFree(void *pPrior){ #endif if( !pPrior ) return; /* Passing NULL to HeapFree is undefined. */ if( !osHeapFree(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior) ){ - sqlite3_log(SQLITE_NOMEM, "failed to HeapFree block %p (%d), heap=%p", + sqlite3_log(SQLITE_NOMEM, "failed to HeapFree block %p (%lu), heap=%p", pPrior, osGetLastError(), (void*)hHeap); } } @@ -1215,7 +1215,7 @@ static void *winMemRealloc(void *pPrior, int nBytes){ p = osHeapReAlloc(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior, (SIZE_T)nBytes); } if( !p ){ - sqlite3_log(SQLITE_NOMEM, "failed to %s %u bytes (%d), heap=%p", + sqlite3_log(SQLITE_NOMEM, "failed to %s %u bytes (%lu), heap=%p", pPrior ? "HeapReAlloc" : "HeapAlloc", nBytes, osGetLastError(), (void*)hHeap); } @@ -1239,7 +1239,7 @@ static int winMemSize(void *p){ if( !p ) return 0; n = osHeapSize(hHeap, SQLITE_WIN32_HEAP_FLAGS, p); if( n==(SIZE_T)-1 ){ - sqlite3_log(SQLITE_NOMEM, "failed to HeapSize block %p (%d), heap=%p", + sqlite3_log(SQLITE_NOMEM, "failed to HeapSize block %p (%lu), heap=%p", p, osGetLastError(), (void*)hHeap); return 0; } @@ -1269,7 +1269,7 @@ static int winMemInit(void *pAppData){ SQLITE_WIN32_HEAP_MAX_SIZE); if( !pWinMemData->hHeap ){ sqlite3_log(SQLITE_NOMEM, - "failed to HeapCreate (%d), flags=%u, initSize=%u, maxSize=%u", + "failed to HeapCreate (%lu), flags=%u, initSize=%u, maxSize=%u", osGetLastError(), SQLITE_WIN32_HEAP_FLAGS, SQLITE_WIN32_HEAP_INIT_SIZE, SQLITE_WIN32_HEAP_MAX_SIZE); return SQLITE_NOMEM; @@ -1281,7 +1281,7 @@ static int winMemInit(void *pAppData){ pWinMemData->hHeap = osGetProcessHeap(); if( !pWinMemData->hHeap ){ sqlite3_log(SQLITE_NOMEM, - "failed to GetProcessHeap (%d)", osGetLastError()); + "failed to GetProcessHeap (%lu)", osGetLastError()); return SQLITE_NOMEM; } pWinMemData->bOwned = FALSE; @@ -1309,7 +1309,7 @@ static void winMemShutdown(void *pAppData){ #endif if( pWinMemData->bOwned ){ if( !osHeapDestroy(pWinMemData->hHeap) ){ - sqlite3_log(SQLITE_NOMEM, "failed to HeapDestroy (%d), heap=%p", + sqlite3_log(SQLITE_NOMEM, "failed to HeapDestroy (%lu), heap=%p", osGetLastError(), (void*)pWinMemData->hHeap); } pWinMemData->bOwned = FALSE; From c5cd124900f463df0410da7f30e8d47ec07810d5 Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 12 Sep 2013 16:50:49 +0000 Subject: [PATCH 033/101] Increase the number of bits available in Expr.flags. Other tweaks aimed at making expression processing more robust. FossilOrigin-Name: 579a512538528cf4bb4381ba393c5d9e7310086b --- manifest | 29 ++++++++++++++------------ manifest.uuid | 2 +- src/attach.c | 2 +- src/expr.c | 54 ++++++++++++++++++++++++------------------------- src/parse.y | 5 +++-- src/resolve.c | 6 +++--- src/select.c | 4 ++-- src/sqliteInt.h | 53 ++++++++++++++++++++++-------------------------- src/walker.c | 2 +- 9 files changed, 77 insertions(+), 80 deletions(-) diff --git a/manifest b/manifest index b4006aefdd..16e249cf48 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C For\serror\slog\smessages\sgenerated\sby\sthe\sWin32\snative\sallocator,\smake\ssure\sthe\scorrect\sformat\sspecifier\sis\sused\sfor\sthe\svalue\sreturned\sby\sGetLastError(). -D 2013-09-12T02:09:05.258 +C Increase\sthe\snumber\sof\sbits\savailable\sin\sExpr.flags.\s\sOther\stweaks\saimed\sat\nmaking\sexpression\sprocessing\smore\srobust. +D 2013-09-12T16:50:49.178 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5e41da95d92656a5004b03d3576e8b226858a28e F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -158,7 +158,7 @@ F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a F src/alter.c 2af0330bb1b601af7a7789bf7229675fd772a083 F src/analyze.c d322972af09e3f8debb45f420dfe3ded142b108b -F src/attach.c eeb8d9d2c791caa0a54a835170ea898e96c2802d +F src/attach.c 4a2b6a6d9b5f9fd55a8b59488ff7929fef73a195 F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34 F src/backup.c 2f1987981139bd2f6d8c728d64bf09fb387443c3 F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb @@ -172,7 +172,7 @@ F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac F src/ctime.c ea4b7f3623a0fcb1146e7f245d7410033e86859c F src/date.c 067a81c9942c497aafd2c260e13add8a7d0c7dd4 F src/delete.c 2dc64ca360b7d7da481183ea920a813a0c203c97 -F src/expr.c 33ae44812d25799000dbcfd54bb2142b30cdd049 +F src/expr.c 7f93e51fd7ca0d3ea1be2715a29c86a69e7b1e93 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fkey.c be866cd8c4fa6cae98ba33109578fd1a3311ee5b F src/func.c 7650d35651bb0ca903d24f4e5e944bfdaac9f152 @@ -206,7 +206,7 @@ F src/os_unix.c 243fb37f47dc072fc59839ea241ff0a17c8d76e6 F src/os_win.c 0e73f891dd806b82a76d4e19179c532f02236b86 F src/pager.c 2aa4444ffe86e9282d03bc349a4a5e49bd77c0e8 F src/pager.h f094af9f6ececfaa8a1e93876905a4f34233fb0c -F src/parse.y 27c6b4138497d6f8360ba7847da6ed48033f957f +F src/parse.y a97566d6da75075589a7c716d1bda14b586cf8da F src/pcache.c f8043b433a57aba85384a531e3937a804432a346 F src/pcache.h a5e4f5d9f5d592051d91212c5949517971ae6222 F src/pcache1.c a467393909a4ed7ca9de066d85ba5c5b04a5be63 @@ -214,14 +214,14 @@ F src/pragma.c 3aa3d8c8623b7b71c5b1bfb72dcc31fb0c25665f F src/prepare.c fa6988589f39af8504a61731614cd4f6ae71554f F src/printf.c da9119eb31a187a4b99f60aa4a225141c0ebb74b F src/random.c 0b2dbc37fdfbfa6bd455b091dfcef5bdb32dba68 -F src/resolve.c 9d53899cc6e1f4ec0b4632d07e97d57827bf63b9 +F src/resolve.c d336be12493bb376c6756c214379c727cd8c01a8 F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0 -F src/select.c 9239586282bd146ec5843a2cde7d54cd7816cf78 +F src/select.c d96bcdbc2e7de89cb72febeccd232746f67839fd F src/shell.c d920a891ca09b8bd262cced7fb0ab9d723f7a747 F src/sqlite.h.in ec40aa958a270416fb04b4f72210357bf163d2c5 F src/sqlite3.rc fea433eb0a59f4c9393c8e6d76a6e2596b1fe0c0 F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc -F src/sqliteInt.h 600a1da8ca71c919a1a270146b052a66a128533a +F src/sqliteInt.h e4cb0c8700ca77889570bf30cf75a5c56f297615 F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158 F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e @@ -289,7 +289,7 @@ F src/vdbetrace.c e7ec40e1999ff3c6414424365d5941178966dcbc F src/vtab.c 5a423b042eb1402ef77697d03d6a67378d97bc8d F src/wal.c 7dc3966ef98b74422267e7e6e46e07ff6c6eb1b4 F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4 -F src/walker.c 4fa43583d0a84b48f93b1e88f11adf2065be4e73 +F src/walker.c e9e593d5bb798c3e67fc3893dfe7055c9e7d8d74 F src/where.c b5d59b899b85aa03800905ecdc0a17565d51a6ab F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 @@ -1112,7 +1112,10 @@ F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 F tool/wherecosttest.c f407dc4c79786982a475261866a161cd007947ae F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac -P 59708674f66e06c9c31c1a24f2f1c51f0bf4fa3e -R 1ed3fe4d70c0b22924a418f004301c6c -U mistachkin -Z 0449c470c02ad9774090312d2090be91 +P 75a8a8c1b39725d36db627536d0c69401f8e0815 +R 14e40117cf5ed4a868935b4adf8b8b0d +T *branch * expr-tuning +T *sym-expr-tuning * +T -sym-trunk * +U drh +Z e578fc31598c846285e1a40bbc280fc4 diff --git a/manifest.uuid b/manifest.uuid index 85af47ce04..5ea118d1db 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -75a8a8c1b39725d36db627536d0c69401f8e0815 \ No newline at end of file +579a512538528cf4bb4381ba393c5d9e7310086b \ No newline at end of file diff --git a/src/attach.c b/src/attach.c index 6d965ace65..805305dab6 100644 --- a/src/attach.c +++ b/src/attach.c @@ -509,7 +509,7 @@ int sqlite3FixExpr( Expr *pExpr /* The expression to be fixed to one database */ ){ while( pExpr ){ - if( ExprHasAnyProperty(pExpr, EP_TokenOnly) ) break; + if( ExprHasProperty(pExpr, EP_TokenOnly) ) break; if( ExprHasProperty(pExpr, EP_xIsSelect) ){ if( sqlite3FixSelect(pFix, pExpr->x.pSelect) ) return 1; }else{ diff --git a/src/expr.c b/src/expr.c index 6587ee1f78..82623b14ba 100644 --- a/src/expr.c +++ b/src/expr.c @@ -596,7 +596,7 @@ void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr){ const char *z; if( pExpr==0 ) return; - assert( !ExprHasAnyProperty(pExpr, EP_IntValue|EP_Reduced|EP_TokenOnly) ); + assert( !ExprHasProperty(pExpr, EP_IntValue|EP_Reduced|EP_TokenOnly) ); z = pExpr->u.zToken; assert( z!=0 ); assert( z[0]!=0 ); @@ -666,12 +666,12 @@ void sqlite3ExprDelete(sqlite3 *db, Expr *p){ if( p==0 ) return; /* Sanity check: Assert that the IntValue is non-negative if it exists */ assert( !ExprHasProperty(p, EP_IntValue) || p->u.iValue>=0 ); - if( !ExprHasAnyProperty(p, EP_TokenOnly) ){ + if( !ExprHasProperty(p, EP_TokenOnly) ){ + /* The Expr.x union is never used at the same time as Expr.pRight */ + assert( p->x.pList==0 || p->pRight==0 ); sqlite3ExprDelete(db, p->pLeft); sqlite3ExprDelete(db, p->pRight); - if( !ExprHasProperty(p, EP_Reduced) && (p->flags2 & EP2_MallocedToken)!=0 ){ - sqlite3DbFree(db, p->u.zToken); - } + if( ExprHasProperty(p, EP_MemToken) ) sqlite3DbFree(db, p->u.zToken); if( ExprHasProperty(p, EP_xIsSelect) ){ sqlite3SelectDelete(db, p->x.pSelect); }else{ @@ -734,10 +734,10 @@ static int dupedExprStructSize(Expr *p, int flags){ if( 0==(flags&EXPRDUP_REDUCE) ){ nSize = EXPR_FULLSIZE; }else{ - assert( !ExprHasAnyProperty(p, EP_TokenOnly|EP_Reduced) ); + assert( !ExprHasProperty(p, EP_TokenOnly|EP_Reduced) ); assert( !ExprHasProperty(p, EP_FromJoin) ); - assert( (p->flags2 & EP2_MallocedToken)==0 ); - assert( (p->flags2 & EP2_Irreducible)==0 ); + assert( !ExprHasProperty(p, EP_MemToken) ); + assert( !ExprHasProperty(p, EP_Irreduce) ); if( p->pLeft || p->pRight || p->x.pList ){ nSize = EXPR_REDUCEDSIZE | EP_Reduced; }else{ @@ -834,7 +834,7 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int flags, u8 **pzBuffer){ } /* Set the EP_Reduced, EP_TokenOnly, and EP_Static flags appropriately. */ - pNew->flags &= ~(EP_Reduced|EP_TokenOnly|EP_Static); + pNew->flags &= ~(EP_Reduced|EP_TokenOnly|EP_Static|EP_MemToken); pNew->flags |= nStructSize & (EP_Reduced|EP_TokenOnly); pNew->flags |= staticFlag; @@ -854,7 +854,7 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int flags, u8 **pzBuffer){ } /* Fill in pNew->pLeft and pNew->pRight. */ - if( ExprHasAnyProperty(pNew, EP_Reduced|EP_TokenOnly) ){ + if( ExprHasProperty(pNew, EP_Reduced|EP_TokenOnly) ){ zAlloc += dupedExprNodeSize(p, flags); if( ExprHasProperty(pNew, EP_Reduced) ){ pNew->pLeft = exprDup(db, p->pLeft, EXPRDUP_REDUCE, &zAlloc); @@ -864,8 +864,7 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int flags, u8 **pzBuffer){ *pzBuffer = zAlloc; } }else{ - pNew->flags2 = 0; - if( !ExprHasAnyProperty(p, EP_TokenOnly) ){ + if( !ExprHasProperty(p, EP_TokenOnly) ){ pNew->pLeft = sqlite3ExprDup(db, p->pLeft, 0); pNew->pRight = sqlite3ExprDup(db, p->pRight, 0); } @@ -1175,7 +1174,7 @@ static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){ /* If pWalker->u.i is 3 then any term of the expression that comes from ** the ON or USING clauses of a join disqualifies the expression ** from being considered constant. */ - if( pWalker->u.i==3 && ExprHasAnyProperty(pExpr, EP_FromJoin) ){ + if( pWalker->u.i==3 && ExprHasProperty(pExpr, EP_FromJoin) ){ pWalker->u.i = 0; return WRC_Abort; } @@ -1606,7 +1605,7 @@ int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){ }else{ testcase( pParse->nQueryLoop>0 ); pParse->nQueryLoop = 0; - if( pX->pLeft->iColumn<0 && !ExprHasAnyProperty(pX, EP_xIsSelect) ){ + if( pX->pLeft->iColumn<0 && !ExprHasProperty(pX, EP_xIsSelect) ){ eType = IN_INDEX_ROWID; } } @@ -1675,7 +1674,7 @@ int sqlite3CodeSubselect( ** If all of the above are false, then we can run this code just once ** save the results, and reuse the same result on subsequent invocations. */ - if( !ExprHasAnyProperty(pExpr, EP_VarSelect) ){ + if( !ExprHasProperty(pExpr, EP_VarSelect) ){ testAddr = sqlite3CodeOnce(pParse); } @@ -2615,7 +2614,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); testcase( op==TK_CONST_FUNC ); testcase( op==TK_FUNCTION ); - if( ExprHasAnyProperty(pExpr, EP_TokenOnly) ){ + if( ExprHasProperty(pExpr, EP_TokenOnly) ){ pFarg = 0; }else{ pFarg = pExpr->x.pList; @@ -2846,9 +2845,9 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ ** WHEN x=eN THEN rN ELSE y END ** ** X (if it exists) is in pExpr->pLeft. - ** Y is in pExpr->pRight. The Y is also optional. If there is no - ** ELSE clause and no other term matches, then the result of the - ** exprssion is NULL. + ** Y is in the last element of pExpr->x.pList if pExpr->x.pList->nExpr is + ** odd. The Y is also optional. If the number of elements in x.pList + ** is even, then Y is omitted and the "otherwise" result is NULL. ** Ei is in pExpr->pList->a[i*2] and Ri is pExpr->pList->a[i*2+1]. ** ** The result of the expression is the Ri for the first matching Ei, @@ -2869,7 +2868,6 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ VVA_ONLY( int iCacheLevel = pParse->iCacheLevel; ) assert( !ExprHasProperty(pExpr, EP_xIsSelect) && pExpr->x.pList ); - assert((pExpr->x.pList->nExpr % 2) == 0); assert(pExpr->x.pList->nExpr > 0); pEList = pExpr->x.pList; aListelem = pEList->a; @@ -2891,7 +2889,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ ** purposes and possibly overwritten. */ regFree1 = 0; } - for(i=0; ipRight ){ + if( (nExpr&1)!=0 ){ sqlite3ExprCachePush(pParse); - sqlite3ExprCode(pParse, pExpr->pRight, target); + sqlite3ExprCode(pParse, pEList->a[nExpr-1].pExpr, target); sqlite3ExprCachePop(pParse, 1); }else{ sqlite3VdbeAddOp2(v, OP_Null, 0, target); @@ -3155,7 +3153,7 @@ void sqlite3ExplainExpr(Vdbe *pOut, Expr *pExpr){ case TK_CONST_FUNC: case TK_FUNCTION: { ExprList *pFarg; /* List of function arguments */ - if( ExprHasAnyProperty(pExpr, EP_TokenOnly) ){ + if( ExprHasProperty(pExpr, EP_TokenOnly) ){ pFarg = 0; }else{ pFarg = pExpr->x.pList; @@ -3821,8 +3819,8 @@ int sqlite3ExprCompare(Expr *pA, Expr *pB, int iTab){ if( pA==0||pB==0 ){ return pB==pA ? 0 : 2; } - assert( !ExprHasAnyProperty(pA, EP_TokenOnly|EP_Reduced) ); - assert( !ExprHasAnyProperty(pB, EP_TokenOnly|EP_Reduced) ); + assert( !ExprHasProperty(pA, EP_TokenOnly|EP_Reduced) ); + assert( !ExprHasProperty(pB, EP_TokenOnly|EP_Reduced) ); if( ExprHasProperty(pA, EP_xIsSelect) || ExprHasProperty(pB, EP_xIsSelect) ){ return 2; } @@ -4036,7 +4034,7 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){ struct SrcList_item *pItem = pSrcList->a; for(i=0; inSrc; i++, pItem++){ struct AggInfo_col *pCol; - assert( !ExprHasAnyProperty(pExpr, EP_TokenOnly|EP_Reduced) ); + assert( !ExprHasProperty(pExpr, EP_TokenOnly|EP_Reduced) ); if( pExpr->iTable==pItem->iCursor ){ /* If we reach this point, it means that pExpr refers to a table ** that is in the FROM clause of the aggregate query. @@ -4131,7 +4129,7 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){ } /* Make pExpr point to the appropriate pAggInfo->aFunc[] entry */ - assert( !ExprHasAnyProperty(pExpr, EP_TokenOnly|EP_Reduced) ); + assert( !ExprHasProperty(pExpr, EP_TokenOnly|EP_Reduced) ); ExprSetIrreducible(pExpr); pExpr->iAgg = (i16)i; pExpr->pAggInfo = pAggInfo; diff --git a/src/parse.y b/src/parse.y index e9c8a15635..1e8d7f751c 100644 --- a/src/parse.y +++ b/src/parse.y @@ -1081,12 +1081,13 @@ expr(A) ::= expr(W) between_op(N) expr(X) AND expr(Y). [BETWEEN] { /* CASE expressions */ expr(A) ::= CASE(C) case_operand(X) case_exprlist(Y) case_else(Z) END(E). { - A.pExpr = sqlite3PExpr(pParse, TK_CASE, X, Z, 0); + A.pExpr = sqlite3PExpr(pParse, TK_CASE, X, 0, 0); if( A.pExpr ){ - A.pExpr->x.pList = Y; + A.pExpr->x.pList = Z ? sqlite3ExprListAppend(pParse,Y,Z) : Y; sqlite3ExprSetHeight(pParse, A.pExpr); }else{ sqlite3ExprListDelete(pParse->db, Y); + sqlite3ExprDelete(pParse->db, Z); } A.zStart = C.z; A.zEnd = &E.z[E.n]; diff --git a/src/resolve.c b/src/resolve.c index 43a3870e23..54ce3adf54 100644 --- a/src/resolve.c +++ b/src/resolve.c @@ -129,7 +129,7 @@ static void resolveAlias( if( !ExprHasProperty(pExpr, EP_IntValue) && pExpr->u.zToken!=0 ){ assert( (pExpr->flags & (EP_Reduced|EP_TokenOnly))==0 ); pExpr->u.zToken = sqlite3DbStrDup(db, pExpr->u.zToken); - pExpr->flags2 |= EP2_MallocedToken; + pExpr->flags |= EP_MemToken; } sqlite3DbFree(db, pDup); } @@ -229,7 +229,7 @@ static int lookupName( assert( pNC ); /* the name context cannot be NULL. */ assert( zCol ); /* The Z in X.Y.Z cannot be NULL */ - assert( !ExprHasAnyProperty(pExpr, EP_TokenOnly|EP_Reduced) ); + assert( !ExprHasProperty(pExpr, EP_TokenOnly|EP_Reduced) ); /* Initialize the node to no-match */ pExpr->iTable = -1; @@ -591,7 +591,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ pParse = pNC->pParse; assert( pParse==pWalker->pParse ); - if( ExprHasAnyProperty(pExpr, EP_Resolved) ) return WRC_Prune; + if( ExprHasProperty(pExpr, EP_Resolved) ) return WRC_Prune; ExprSetProperty(pExpr, EP_Resolved); #ifndef NDEBUG if( pNC->pSrcList && pNC->pSrcList->nAlloc>0 ){ diff --git a/src/select.c b/src/select.c index 6e409e73a5..f0dbf80918 100644 --- a/src/select.c +++ b/src/select.c @@ -264,7 +264,7 @@ static void addWhereTerm( pEq = sqlite3PExpr(pParse, TK_EQ, pE1, pE2, 0); if( pEq && isOuterJoin ){ ExprSetProperty(pEq, EP_FromJoin); - assert( !ExprHasAnyProperty(pEq, EP_TokenOnly|EP_Reduced) ); + assert( !ExprHasProperty(pEq, EP_TokenOnly|EP_Reduced) ); ExprSetIrreducible(pEq); pEq->iRightJoinTable = (i16)pE2->iTable; } @@ -300,7 +300,7 @@ static void addWhereTerm( static void setJoinExpr(Expr *p, int iTable){ while( p ){ ExprSetProperty(p, EP_FromJoin); - assert( !ExprHasAnyProperty(p, EP_TokenOnly|EP_Reduced) ); + assert( !ExprHasProperty(p, EP_TokenOnly|EP_Reduced) ); ExprSetIrreducible(p); p->iRightJoinTable = (i16)iTable; setJoinExpr(p->pLeft, iTable); diff --git a/src/sqliteInt.h b/src/sqliteInt.h index f017229f71..7585613621 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -1722,7 +1722,7 @@ typedef int ynVar; struct Expr { u8 op; /* Operation performed by this node */ char affinity; /* The affinity of the column or 0 if not a column */ - u16 flags; /* Various flags. EP_* See below */ + u32 flags; /* Various flags. EP_* See below */ union { char *zToken; /* Token value. Zero terminated and dequoted */ int iValue; /* Non-negative integer value if EP_IntValue */ @@ -1736,8 +1736,8 @@ struct Expr { Expr *pLeft; /* Left subnode */ Expr *pRight; /* Right subnode */ union { - ExprList *pList; /* Function arguments or in " IN ( IN (