Merge updates from trunk.
FossilOrigin-Name: 435ce3b3fc0cffb4d7e6f2694c3100066e19f9ed
This commit is contained in:
commit
bbff218016
11
Makefile.msc
11
Makefile.msc
@ -491,6 +491,17 @@ LTLIBOPTS = /MACHINE:$(PLATFORM)
|
||||
#
|
||||
!IF $(FOR_WINRT)!=0
|
||||
LTLINKOPTS = $(LTLINKOPTS) /APPCONTAINER
|
||||
!IF "$(VISUALSTUDIOVERSION)"=="12.0"
|
||||
!IF "$(PLATFORM)"=="x86"
|
||||
LTLINKOPTS = $(LTLINKOPTS) "/LIBPATH:$(VCINSTALLDIR)\lib\store"
|
||||
!ELSEIF "$(PLATFORM)"=="x64"
|
||||
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
|
||||
|
||||
# If either debugging or symbols are enabled, enable PDBs.
|
||||
|
81
manifest
81
manifest
@ -1,9 +1,9 @@
|
||||
C Merge\supdates\sfrom\strunk.
|
||||
D 2013-09-06T22:27:55.935
|
||||
D 2013-09-24T19:07:48.655
|
||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||
F Makefile.in 5e41da95d92656a5004b03d3576e8b226858a28e
|
||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||
F Makefile.msc bf73c5d1f39a132901cc0a9aea88e724cd0340ad
|
||||
F Makefile.msc ef17891ca710b1e7bc9cbab2061381884362aeb3
|
||||
F Makefile.vxworks db21ed42a01d5740e656b16f92cb5d8d5e5dd315
|
||||
F README cd04a36fbc7ea56932a4052d7d0b7f09f27c33d6
|
||||
F VERSION a8d1f6839521130dc73c5408cdd24bcfd791df34
|
||||
@ -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 7da9d6a0d04a3662d110a28f4a7e7b73a6171e75
|
||||
F src/attach.c eeb8d9d2c791caa0a54a835170ea898e96c2802d
|
||||
F src/analyze.c d322972af09e3f8debb45f420dfe3ded142b108b
|
||||
F src/attach.c 4a2b6a6d9b5f9fd55a8b59488ff7929fef73a195
|
||||
F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34
|
||||
F src/backup.c 2f1987981139bd2f6d8c728d64bf09fb387443c3
|
||||
F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb
|
||||
@ -170,12 +170,12 @@ F src/build.c f63e8929c7f89c0074fbc74929bc946ea117b2f8
|
||||
F src/callback.c f99a8957ba2adf369645fac0db09ad8adcf1caa2
|
||||
F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
|
||||
F src/ctime.c ea4b7f3623a0fcb1146e7f245d7410033e86859c
|
||||
F src/date.c 067a81c9942c497aafd2c260e13add8a7d0c7dd4
|
||||
F src/date.c 65196e95e69f36993659bd7781abe7c2f1994739
|
||||
F src/delete.c 2dc64ca360b7d7da481183ea920a813a0c203c97
|
||||
F src/expr.c 33ae44812d25799000dbcfd54bb2142b30cdd049
|
||||
F src/expr.c 1017f482217e093ecdaca91e8666681e83733252
|
||||
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
|
||||
F src/fkey.c be866cd8c4fa6cae98ba33109578fd1a3311ee5b
|
||||
F src/func.c 8eed739f11acd20fb89a82bf0ad60f75b0a8f907
|
||||
F src/func.c 5fb4103cc5fd2920696e0a263e6a56a2844ab35d
|
||||
F src/global.c 5caf4deab621abb45b4c607aad1bd21c20aac759
|
||||
F src/hash.c ac3470bbf1ca4ae4e306a8ecb0fdf1731810ffe4
|
||||
F src/hash.h 8890a25af81fb85a9ad7790d32eedab4b994da22
|
||||
@ -186,7 +186,7 @@ F src/legacy.c 0df0b1550b9cc1f58229644735e317ac89131f12
|
||||
F src/lempar.c cdf0a000315332fc9b50b62f3b5e22e080a0952b
|
||||
F src/loadext.c 867c7b330b740c6c917af9956b13b81d0a048303
|
||||
F src/main.c 35931467ec026b05babb279cb8a573e62f6fe1a3
|
||||
F src/malloc.c fe085aa851b666b7c375c1ff957643dc20a04bf6
|
||||
F src/malloc.c 543a8eb5508eaf4cadf55a9b503379eba2088128
|
||||
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
|
||||
F src/mem1.c 437c7c4af964895d4650f29881df63535caaa1fa
|
||||
F src/mem2.c dce31758da87ec2cfa52ba4c5df1aed6e07d8e8f
|
||||
@ -203,25 +203,25 @@ 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 b8f54f42d9c232c48cb694b7dbe94e601c816b5c
|
||||
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
|
||||
F src/pragma.c 3aa3d8c8623b7b71c5b1bfb72dcc31fb0c25665f
|
||||
F src/pragma.c 0c7a67a75cb4f9849190f33f62534d37f38ff8ed
|
||||
F src/prepare.c fa6988589f39af8504a61731614cd4f6ae71554f
|
||||
F src/printf.c da9119eb31a187a4b99f60aa4a225141c0ebb74b
|
||||
F src/random.c 0b2dbc37fdfbfa6bd455b091dfcef5bdb32dba68
|
||||
F src/resolve.c 9d53899cc6e1f4ec0b4632d07e97d57827bf63b9
|
||||
F src/resolve.c 7459801d02997b07e8b8da85ef255392ba1d022b
|
||||
F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0
|
||||
F src/select.c 9239586282bd146ec5843a2cde7d54cd7816cf78
|
||||
F src/select.c fc60e8e539cb9a895cac197de95048759b0f3ab0
|
||||
F src/shell.c d920a891ca09b8bd262cced7fb0ab9d723f7a747
|
||||
F src/sqlite.h.in ec40aa958a270416fb04b4f72210357bf163d2c5
|
||||
F src/sqlite3.rc fea433eb0a59f4c9393c8e6d76a6e2596b1fe0c0
|
||||
F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e
|
||||
F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc
|
||||
F src/sqliteInt.h 32e959dba9899360ce4ae3cd6cc77b4a8df277e8
|
||||
F src/sqliteInt.h 18c7f80e7e23098942436f7286e9c93adc6908be
|
||||
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
|
||||
F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158
|
||||
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
|
||||
@ -275,13 +275,13 @@ F src/tokenize.c 70061085a51f2f4fc15ece94f32c03bcb78e63b2
|
||||
F src/trigger.c 5c0ea9b8755e7c5e1a700f3e27ac4f8d92dd221e
|
||||
F src/update.c f5182157f5d0d0a97bc5f5e3c9bdba0dfbe08f08
|
||||
F src/utf.c 6fc6c88d50448c469c5c196acf21617a24f90269
|
||||
F src/util.c f566b5138099a2df8533b190d0dcc74b7dfbe0c9
|
||||
F src/util.c 7f3e35432d6888d1e770c488c35bd98970c44eec
|
||||
F src/vacuum.c d9c5759f4c5a438bb43c2086f72c5d2edabc36c8
|
||||
F src/vdbe.c a393a94c0d77b86c7c4ad2cfb43ec4ba278d9596
|
||||
F src/vdbe.c 56e648f5ba9a91810caf216857adfed9039cd174
|
||||
F src/vdbe.h 4f554b5627f26710c4c36d919110a3fc611ca5c4
|
||||
F src/vdbeInt.h cbe71b8b36d8b3bba5709cc3f436c7e3b47b7b08
|
||||
F src/vdbeapi.c 96b24b946cf21894f63d9393e821baa2f0a80979
|
||||
F src/vdbeaux.c 88beca92f2ed0bbe2c6f87946d0e999a6807ea1b
|
||||
F src/vdbeInt.h ff57f67aee1ba26a3a47e786533dab155ab6dad6
|
||||
F src/vdbeapi.c 93a22a9ba2abe292d5c2cf304d7eb2e894dde0ed
|
||||
F src/vdbeaux.c 55f4858fe6abd84bd7311acbf30a75a28903ec25
|
||||
F src/vdbeblob.c 5dc79627775bd9a9b494dd956e26297946417d69
|
||||
F src/vdbemem.c 817ce21ab4ca57f902619bb8fef3f8a51bbd0ed8
|
||||
F src/vdbesort.c 3937e06b2a0e354500e17dc206ef4c35770a5017
|
||||
@ -289,8 +289,8 @@ 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/where.c 06c249a5137575ecf4d527e5a1dadb1087e4375c
|
||||
F src/walker.c e9e593d5bb798c3e67fc3893dfe7055c9e7d8d74
|
||||
F src/where.c d2f58a441ba8709a99df6654b26a50b7ca7dada4
|
||||
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 1b9b7e9a096d1536f03d9ad7b72f638ef5669347
|
||||
F test/analyzeA.test 1a5c40079894847976d983ca39c707aaa44b6944
|
||||
F test/analyzeB.test 8bf35ee0a548aea831bf56762cb8e7fdb1db083d
|
||||
F test/async.test 1d0e056ba1bb9729283a0f22718d3a25e82c277b
|
||||
@ -341,7 +341,7 @@ F test/badutf2.test f5bc7f2d280670ecd79b9cf4f0f1760c607fe51f
|
||||
F test/bc_common.tcl 5c8689cc6d2fb44b7c0968ae4f85eb26d50022fa
|
||||
F test/between.test 34d375fb5ce1ae283ffe82b6b233e9f38e84fc6c
|
||||
F test/bigfile.test aa74f4e5db51c8e54a1d9de9fa65d01d1eb20b59
|
||||
F test/bigfile2.test 7c79f1ef0c6c2c2bc1e7bd895596fab32bfb4796
|
||||
F test/bigfile2.test 1b489a3a39ae90c7f027b79110d6b4e1dbc71bfc
|
||||
F test/bigrow.test f0aeb7573dcb8caaafea76454be3ade29b7fc747
|
||||
F test/bind.test 3c7b320969000c441a70952b0b15938fbb66237c
|
||||
F test/bindxfer.test efecd12c580c14df5f4ad3b3e83c667744a4f7e0
|
||||
@ -413,7 +413,7 @@ F test/crashtest1.c 09c1c7d728ccf4feb9e481671e29dda5669bbcc2
|
||||
F test/createtab.test b5de160630b209c4b8925bdcbbaf48cc90b67fe8
|
||||
F test/cse.test 277350a26264495e86b1785f34d2d0c8600e021c
|
||||
F test/ctime.test 7bd009071e242aac4f18521581536b652b789a47
|
||||
F test/date.test f3228180c87bbe5d39c9397bf001c0095c3821b9
|
||||
F test/date.test 502ddcbaaac9ce103bcd76d8e9d9bc8aa04e61b0
|
||||
F test/dbstatus.test aee30c3f337e6c217ff06df59fb8fe6e6448dce2
|
||||
F test/dbstatus2.test 10418e62b3db5dca070f0c3eef3ea13946f339c2
|
||||
F test/default.test 6faf23ccb300114924353007795aa9a8ec0aa9dc
|
||||
@ -559,7 +559,7 @@ F test/fts4merge2.test 5faa558d1b672f82b847d2a337465fa745e46891
|
||||
F test/fts4merge3.test aab02a09f50fe6baaddc2e159c3eabc116d45fc7
|
||||
F test/fts4merge4.test c19c85ca1faa7b6d536832b49c12e1867235f584
|
||||
F test/fts4noti.test aed33ba44808852dcb24bf70fa132e7bf530f057
|
||||
F test/fts4unicode.test 5fa8e0a7899d906d114345c605250ebfa9d8ed28
|
||||
F test/fts4unicode.test ebd937061e1ce096240d2352feb424587f2187b9
|
||||
F test/full.test 6b3c8fb43c6beab6b95438c1675374b95fab245d
|
||||
F test/func.test cd25cf605c5a345d038dc7b84232204c6a901c84
|
||||
F test/func2.test 772d66227e4e6684b86053302e2d74a2500e1e0f
|
||||
@ -728,8 +728,8 @@ F test/ptrchng.test ef1aa72d6cf35a2bbd0869a649b744e9d84977fc
|
||||
F test/queryonly.test 5f653159e0f552f0552d43259890c1089391dcca
|
||||
F test/quick.test 1681febc928d686362d50057c642f77a02c62e57
|
||||
F test/quota-glob.test 32901e9eed6705d68ca3faee2a06b73b57cb3c26
|
||||
F test/quota.test b5b3eec55a059e0fe493c66c6e27bd2c07676cfd
|
||||
F test/quota2.test 6d2bd57e8a4da28817f46db9da18551211cd325f
|
||||
F test/quota.test 2379902c25e291eac5c12b4cf96946a3447e3744
|
||||
F test/quota2.test 7dc12e08b11cbc4c16c9ba2aa2e040ea8d8ab4b8
|
||||
F test/quote.test 215897dbe8de1a6f701265836d6601cc6ed103e6
|
||||
F test/randexpr1.tcl 40dec52119ed3a2b8b2a773bce24b63a3a746459
|
||||
F test/randexpr1.test eda062a97e60f9c38ae8d806b03b0ddf23d796df
|
||||
@ -783,16 +783,16 @@ 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 474ed53bb461c4ba9b6468d3a74e86eb8ee0d9d0
|
||||
F test/shell2.test 037d6ad16e873354195d30bb2dc4b5321788154a
|
||||
F test/shell3.test 9196c42772d575685e722c92b4b39053c6ebba59
|
||||
F test/shell1.test e7c0b9ebda25d5e78f0a3ea0dc4e31bb6d8098c0
|
||||
F test/shell2.test e1d3790f064e50b2f973502f45750012667486df
|
||||
F test/shell3.test 5e8545ec72c4413a0e8d4c6be56496e3c257ca29
|
||||
F test/shell4.test aa4eef8118b412d1a01477a53426ece169ea86a9
|
||||
F test/shell5.test bfa21ecc173adcbc15db2c075baa468778f67f88
|
||||
F test/shell5.test 46c8c18d62732415c4fe084816c13d559831705e
|
||||
F test/shortread1.test bb591ef20f0fd9ed26d0d12e80eee6d7ac8897a3
|
||||
F test/shrink.test 8c70f62b6e8eb4d54533de6d65bd06b1b9a17868
|
||||
F test/sidedelete.test f0ad71abe6233e3b153100f3b8d679b19a488329
|
||||
F test/soak.test 0b5b6375c9f4110c828070b826b3b4b0bb65cd5f
|
||||
F test/softheap1.test c16709a16ad79fa43b32929b2e623d1d117ccf53
|
||||
F test/softheap1.test 40562fe6cac6d9827b7b42b86d45aedf12c15e24
|
||||
F test/sort.test 0e4456e729e5a92a625907c63dcdedfbe72c5dc5
|
||||
F test/speed1.test f2974a91d79f58507ada01864c0e323093065452
|
||||
F test/speed1p.explain d841e650a04728b39e6740296b852dccdca9b2cb
|
||||
@ -965,6 +965,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
|
||||
@ -1060,13 +1061,14 @@ F test/whereC.test d6f4ecd4fa2d9429681a5b22a25d2bda8e86ab8a
|
||||
F test/whereD.test 6c2feb79ef1f68381b07f39017fe5f9b96da8d62
|
||||
F test/whereE.test b3a055eef928c992b0a33198a7b8dc10eea5ad2f
|
||||
F test/whereF.test 5b2ba0dbe8074aa13e416b37c753991f0a2492d7
|
||||
F test/whereG.test 2a3d5181decc801b36600fa1c40b0dad2ccc267f
|
||||
F test/wherelimit.test 5e9fd41e79bb2b2d588ed999d641d9c965619b31
|
||||
F test/wild001.test bca33f499866f04c24510d74baf1e578d4e44b1c
|
||||
F test/win32lock.test 7a6bd73a5dcdee39b5bb93e92395e1773a194361
|
||||
F test/win32longpath.test e2aafc07e6990fe86c69be22a3d1a0e210cd329b
|
||||
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
|
||||
@ -1080,12 +1082,13 @@ F tool/lempar.c 01ca97f87610d1dac6d8cd96ab109ab1130e76dc
|
||||
F tool/mkautoconfamal.sh f8d8dbf7d62f409ebed5134998bf5b51d7266383
|
||||
F tool/mkkeywordhash.c bb52064aa614e1426445e4b2b9b00eeecd23cc79
|
||||
F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e
|
||||
F tool/mkpragmatab.tcl e24da1496b4af6de448e9673cf6adbef53e6e830
|
||||
F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97
|
||||
F tool/mksqlite3c-noext.tcl 8bce31074e4cbe631bb7676526a048335f4c9f02
|
||||
F tool/mksqlite3c.tcl d344cc3144a0271cd853c5e3df36e9f31d78d619
|
||||
F tool/mksqlite3h.tcl ba24038056f51fde07c0079c41885ab85e2cff12
|
||||
F tool/mksqlite3internalh.tcl 3dca7bb5374cee003379b8cbac73714f610ef795
|
||||
F tool/mkvsix.tcl 0be7f7a591f1e83f9199cb82911b66668ca484c9
|
||||
F tool/mkvsix.tcl f3312df26fd9938a27fa0a845ec96bea84b0c16b
|
||||
F tool/offsets.c fe4262fdfa378e8f5499a42136d17bf3b98f6091
|
||||
F tool/omittest.tcl 4665982e95a6e5c1bd806cf7bc3dea95be422d77
|
||||
F tool/opcodeDoc.awk b3a2a3d5d3075b8bd90b7afe24283efdd586659c
|
||||
@ -1111,8 +1114,8 @@ F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381
|
||||
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
||||
F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
|
||||
F tool/wherecosttest.c f407dc4c79786982a475261866a161cd007947ae
|
||||
F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac
|
||||
P 6caa2cd10421a85db6740fb2ae8a42b573959562 97b10e66e98e84755aa577f8da017bf1aea2056c
|
||||
R 10ba881e2c7b774138e3a52c0d93d6d1
|
||||
F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff
|
||||
P 8922be1a3e0269552e12b87fe1e5141c38a8d3f8 ed24051462c09220ebfb82a347b4a2b5c820ef63
|
||||
R 4d2894e447b5c39e0b9e2bc56076987a
|
||||
U mistachkin
|
||||
Z d4c0acc5b28a494c6ee6d9515debd6eb
|
||||
Z 7dee757dc233dca1626329d37ad8fbdb
|
||||
|
@ -1 +1 @@
|
||||
8922be1a3e0269552e12b87fe1e5141c38a8d3f8
|
||||
435ce3b3fc0cffb4d7e6f2694c3100066e19f9ed
|
@ -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];
|
||||
|
@ -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{
|
||||
|
@ -294,8 +294,8 @@ static int parseYyyyMmDd(const char *zDate, DateTime *p){
|
||||
** Return the number of errors.
|
||||
*/
|
||||
static int setDateTimeToCurrent(sqlite3_context *context, DateTime *p){
|
||||
sqlite3 *db = sqlite3_context_db_handle(context);
|
||||
if( sqlite3OsCurrentTimeInt64(db->pVfs, &p->iJD)==SQLITE_OK ){
|
||||
p->iJD = sqlite3StmtCurrentTime(context);
|
||||
if( p->iJD>0 ){
|
||||
p->validJD = 1;
|
||||
return 0;
|
||||
}else{
|
||||
@ -1078,8 +1078,8 @@ static void currentTimeFunc(
|
||||
UNUSED_PARAMETER(argc);
|
||||
UNUSED_PARAMETER(argv);
|
||||
|
||||
db = sqlite3_context_db_handle(context);
|
||||
if( sqlite3OsCurrentTimeInt64(db->pVfs, &iT) ) return;
|
||||
iT = sqlite3StmtCurrentTime(context);
|
||||
if( iT<=0 ) return;
|
||||
t = iT/1000 - 10000*(sqlite3_int64)21086676;
|
||||
#ifdef HAVE_GMTIME_R
|
||||
pTm = gmtime_r(&t, &sNow);
|
||||
|
118
src/expr.c
118
src/expr.c
@ -70,7 +70,7 @@ Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr *pExpr, Token *pCollName){
|
||||
Expr *pNew = sqlite3ExprAlloc(pParse->db, TK_COLLATE, pCollName, 1);
|
||||
if( pNew ){
|
||||
pNew->pLeft = pExpr;
|
||||
pNew->flags |= EP_Collate;
|
||||
pNew->flags |= EP_Collate|EP_Skip;
|
||||
pExpr = pNew;
|
||||
}
|
||||
}
|
||||
@ -85,13 +85,21 @@ Expr *sqlite3ExprAddCollateString(Parse *pParse, Expr *pExpr, const char *zC){
|
||||
}
|
||||
|
||||
/*
|
||||
** Skip over any TK_COLLATE and/or TK_AS operators at the root of
|
||||
** an expression.
|
||||
** Skip over any TK_COLLATE or TK_AS operators and any unlikely()
|
||||
** or likelihood() function at the root of an expression.
|
||||
*/
|
||||
Expr *sqlite3ExprSkipCollate(Expr *pExpr){
|
||||
while( pExpr && (pExpr->op==TK_COLLATE || pExpr->op==TK_AS) ){
|
||||
pExpr = pExpr->pLeft;
|
||||
}
|
||||
while( pExpr && ExprHasProperty(pExpr, EP_Skip) ){
|
||||
if( ExprHasProperty(pExpr, EP_Unlikely) ){
|
||||
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
|
||||
assert( pExpr->x.pList->nExpr>0 );
|
||||
assert( pExpr->op==TK_FUNCTION );
|
||||
pExpr = pExpr->x.pList->a[0].pExpr;
|
||||
}else{
|
||||
assert( pExpr->op==TK_COLLATE || pExpr->op==TK_AS );
|
||||
pExpr = pExpr->pLeft;
|
||||
}
|
||||
}
|
||||
return pExpr;
|
||||
}
|
||||
|
||||
@ -596,7 +604,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 +674,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{
|
||||
@ -731,16 +739,19 @@ static int exprStructSize(Expr *p){
|
||||
static int dupedExprStructSize(Expr *p, int flags){
|
||||
int nSize;
|
||||
assert( flags==EXPRDUP_REDUCE || flags==0 ); /* Only one flag value allowed */
|
||||
assert( EXPR_FULLSIZE<=0xfff );
|
||||
assert( (0xfff & (EP_Reduced|EP_TokenOnly))==0 );
|
||||
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 );
|
||||
if( p->pLeft || p->pRight || p->x.pList ){
|
||||
assert( !ExprHasProperty(p, EP_MemToken) );
|
||||
assert( !ExprHasProperty(p, EP_NoReduce) );
|
||||
if( p->pLeft || p->x.pList ){
|
||||
nSize = EXPR_REDUCEDSIZE | EP_Reduced;
|
||||
}else{
|
||||
assert( p->pRight==0 );
|
||||
nSize = EXPR_TOKENONLYSIZE | EP_TokenOnly;
|
||||
}
|
||||
}
|
||||
@ -834,7 +845,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 +865,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 +875,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 +1185,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 +1616,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 +1685,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);
|
||||
}
|
||||
|
||||
@ -1844,7 +1854,7 @@ int sqlite3CodeSubselect(
|
||||
return 0;
|
||||
}
|
||||
rReg = dest.iSDParm;
|
||||
ExprSetIrreducible(pExpr);
|
||||
ExprSetVVAProperty(pExpr, EP_NoReduce);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -2316,6 +2326,16 @@ static int usedAsColumnCache(Parse *pParse, int iFrom, int iTo){
|
||||
}
|
||||
#endif /* SQLITE_DEBUG || SQLITE_COVERAGE_TEST */
|
||||
|
||||
/*
|
||||
** Convert an expression node to a TK_REGISTER
|
||||
*/
|
||||
static void exprToRegister(Expr *p, int iReg){
|
||||
p->op2 = p->op;
|
||||
p->op = TK_REGISTER;
|
||||
p->iTable = iReg;
|
||||
ExprClearProperty(p, EP_Skip);
|
||||
}
|
||||
|
||||
/*
|
||||
** Generate code into the current Vdbe to evaluate the given
|
||||
** expression. Attempt to store the results in register "target".
|
||||
@ -2615,7 +2635,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;
|
||||
@ -2649,6 +2669,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);
|
||||
@ -2846,9 +2874,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 +2897,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;
|
||||
@ -2879,9 +2906,8 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
||||
cacheX = *pX;
|
||||
testcase( pX->op==TK_COLUMN );
|
||||
testcase( pX->op==TK_REGISTER );
|
||||
cacheX.iTable = sqlite3ExprCodeTemp(pParse, pX, ®Free1);
|
||||
exprToRegister(&cacheX, sqlite3ExprCodeTemp(pParse, pX, ®Free1));
|
||||
testcase( regFree1==0 );
|
||||
cacheX.op = TK_REGISTER;
|
||||
opCompare.op = TK_EQ;
|
||||
opCompare.pLeft = &cacheX;
|
||||
pTest = &opCompare;
|
||||
@ -2891,7 +2917,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
||||
** purposes and possibly overwritten. */
|
||||
regFree1 = 0;
|
||||
}
|
||||
for(i=0; i<nExpr; i=i+2){
|
||||
for(i=0; i<nExpr-1; i=i+2){
|
||||
sqlite3ExprCachePush(pParse);
|
||||
if( pX ){
|
||||
assert( pTest!=0 );
|
||||
@ -2909,9 +2935,9 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
||||
sqlite3ExprCachePop(pParse, 1);
|
||||
sqlite3VdbeResolveLabel(v, nextCase);
|
||||
}
|
||||
if( pExpr->pRight ){
|
||||
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);
|
||||
@ -3023,9 +3049,7 @@ int sqlite3ExprCodeAndCache(Parse *pParse, Expr *pExpr, int target){
|
||||
int iMem;
|
||||
iMem = ++pParse->nMem;
|
||||
sqlite3VdbeAddOp2(v, OP_Copy, inReg, iMem);
|
||||
pExpr->iTable = iMem;
|
||||
pExpr->op2 = pExpr->op;
|
||||
pExpr->op = TK_REGISTER;
|
||||
exprToRegister(pExpr, iMem);
|
||||
}
|
||||
return inReg;
|
||||
}
|
||||
@ -3155,7 +3179,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;
|
||||
@ -3404,9 +3428,7 @@ static int evalConstExpr(Walker *pWalker, Expr *pExpr){
|
||||
** but suboptimal, so we want to know about the situation to fix it.
|
||||
** Hence the following assert: */
|
||||
assert( r2==r1 );
|
||||
pExpr->op2 = pExpr->op;
|
||||
pExpr->op = TK_REGISTER;
|
||||
pExpr->iTable = r2;
|
||||
exprToRegister(pExpr, r2);
|
||||
return WRC_Prune;
|
||||
}
|
||||
return WRC_Continue;
|
||||
@ -3504,9 +3526,7 @@ static void exprCodeBetween(
|
||||
compRight.op = TK_LE;
|
||||
compRight.pLeft = &exprX;
|
||||
compRight.pRight = pExpr->x.pList->a[1].pExpr;
|
||||
exprX.iTable = sqlite3ExprCodeTemp(pParse, &exprX, ®Free1);
|
||||
exprX.op2 = exprX.op;
|
||||
exprX.op = TK_REGISTER;
|
||||
exprToRegister(&exprX, sqlite3ExprCodeTemp(pParse, &exprX, ®Free1));
|
||||
if( jumpIfTrue ){
|
||||
sqlite3ExprIfTrue(pParse, &exprAnd, dest, jumpIfNull);
|
||||
}else{
|
||||
@ -3821,8 +3841,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 +4056,7 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
|
||||
struct SrcList_item *pItem = pSrcList->a;
|
||||
for(i=0; i<pSrcList->nSrc; 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.
|
||||
@ -4085,7 +4105,7 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
|
||||
** Convert the pExpr to be a TK_AGG_COLUMN referring to that
|
||||
** pAggInfo->aCol[] entry.
|
||||
*/
|
||||
ExprSetIrreducible(pExpr);
|
||||
ExprSetVVAProperty(pExpr, EP_NoReduce);
|
||||
pExpr->pAggInfo = pAggInfo;
|
||||
pExpr->op = TK_AGG_COLUMN;
|
||||
pExpr->iAgg = (i16)k;
|
||||
@ -4131,8 +4151,8 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
|
||||
}
|
||||
/* Make pExpr point to the appropriate pAggInfo->aFunc[] entry
|
||||
*/
|
||||
assert( !ExprHasAnyProperty(pExpr, EP_TokenOnly|EP_Reduced) );
|
||||
ExprSetIrreducible(pExpr);
|
||||
assert( !ExprHasProperty(pExpr, EP_TokenOnly|EP_Reduced) );
|
||||
ExprSetVVAProperty(pExpr, EP_NoReduce);
|
||||
pExpr->iAgg = (i16)i;
|
||||
pExpr->pAggInfo = pAggInfo;
|
||||
return WRC_Prune;
|
||||
|
34
src/func.c
34
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.
|
||||
@ -544,9 +544,9 @@ struct compareInfo {
|
||||
*/
|
||||
#if defined(SQLITE_EBCDIC)
|
||||
# define sqlite3Utf8Read(A) (*((*A)++))
|
||||
# define GlogUpperToLower(A) A = sqlite3UpperToLower[A]
|
||||
# define GlobUpperToLower(A) A = sqlite3UpperToLower[A]
|
||||
#else
|
||||
# define GlogUpperToLower(A) if( !((A)&~0x7f) ){ A = sqlite3UpperToLower[A]; }
|
||||
# define GlobUpperToLower(A) if( !((A)&~0x7f) ){ A = sqlite3UpperToLower[A]; }
|
||||
#endif
|
||||
|
||||
static const struct compareInfo globInfo = { '*', '?', '[', 0 };
|
||||
@ -625,11 +625,11 @@ static int patternCompare(
|
||||
}
|
||||
while( (c2 = sqlite3Utf8Read(&zString))!=0 ){
|
||||
if( noCase ){
|
||||
GlogUpperToLower(c2);
|
||||
GlogUpperToLower(c);
|
||||
GlobUpperToLower(c2);
|
||||
GlobUpperToLower(c);
|
||||
while( c2 != 0 && c2 != c ){
|
||||
c2 = sqlite3Utf8Read(&zString);
|
||||
GlogUpperToLower(c2);
|
||||
GlobUpperToLower(c2);
|
||||
}
|
||||
}else{
|
||||
while( c2 != 0 && c2 != c ){
|
||||
@ -681,8 +681,8 @@ static int patternCompare(
|
||||
}else{
|
||||
c2 = sqlite3Utf8Read(&zString);
|
||||
if( noCase ){
|
||||
GlogUpperToLower(c);
|
||||
GlogUpperToLower(c2);
|
||||
GlobUpperToLower(c);
|
||||
GlobUpperToLower(c2);
|
||||
}
|
||||
if( c!=c2 ){
|
||||
return 0;
|
||||
@ -1798,9 +1798,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(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 ),
|
||||
|
@ -484,6 +484,7 @@ void sqlite3_free(void *p){
|
||||
*/
|
||||
void sqlite3DbFree(sqlite3 *db, void *p){
|
||||
assert( db==0 || sqlite3_mutex_held(db->mutex) );
|
||||
if( p==0 ) return;
|
||||
if( db ){
|
||||
if( db->pnBytesFreed ){
|
||||
*db->pnBytesFreed += sqlite3DbMallocSize(db, p);
|
||||
|
131
src/os_win.c
131
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
|
||||
|
||||
@ -673,10 +682,19 @@ static struct win_syscall {
|
||||
#define osGetVersionExA ((BOOL(WINAPI*)( \
|
||||
LPOSVERSIONINFOA))aSyscall[34].pCurrent)
|
||||
|
||||
#if defined(SQLITE_WIN32_HAS_WIDE)
|
||||
{ "GetVersionExW", (SYSCALL)GetVersionExW, 0 },
|
||||
#else
|
||||
{ "GetVersionExW", (SYSCALL)0, 0 },
|
||||
#endif
|
||||
|
||||
#define osGetVersionExW ((BOOL(WINAPI*)( \
|
||||
LPOSVERSIONINFOW))aSyscall[35].pCurrent)
|
||||
|
||||
{ "HeapAlloc", (SYSCALL)HeapAlloc, 0 },
|
||||
|
||||
#define osHeapAlloc ((LPVOID(WINAPI*)(HANDLE,DWORD, \
|
||||
SIZE_T))aSyscall[35].pCurrent)
|
||||
SIZE_T))aSyscall[36].pCurrent)
|
||||
|
||||
#if !SQLITE_OS_WINRT
|
||||
{ "HeapCreate", (SYSCALL)HeapCreate, 0 },
|
||||
@ -685,7 +703,7 @@ static struct win_syscall {
|
||||
#endif
|
||||
|
||||
#define osHeapCreate ((HANDLE(WINAPI*)(DWORD,SIZE_T, \
|
||||
SIZE_T))aSyscall[36].pCurrent)
|
||||
SIZE_T))aSyscall[37].pCurrent)
|
||||
|
||||
#if !SQLITE_OS_WINRT
|
||||
{ "HeapDestroy", (SYSCALL)HeapDestroy, 0 },
|
||||
@ -693,21 +711,21 @@ static struct win_syscall {
|
||||
{ "HeapDestroy", (SYSCALL)0, 0 },
|
||||
#endif
|
||||
|
||||
#define osHeapDestroy ((BOOL(WINAPI*)(HANDLE))aSyscall[37].pCurrent)
|
||||
#define osHeapDestroy ((BOOL(WINAPI*)(HANDLE))aSyscall[38].pCurrent)
|
||||
|
||||
{ "HeapFree", (SYSCALL)HeapFree, 0 },
|
||||
|
||||
#define osHeapFree ((BOOL(WINAPI*)(HANDLE,DWORD,LPVOID))aSyscall[38].pCurrent)
|
||||
#define osHeapFree ((BOOL(WINAPI*)(HANDLE,DWORD,LPVOID))aSyscall[39].pCurrent)
|
||||
|
||||
{ "HeapReAlloc", (SYSCALL)HeapReAlloc, 0 },
|
||||
|
||||
#define osHeapReAlloc ((LPVOID(WINAPI*)(HANDLE,DWORD,LPVOID, \
|
||||
SIZE_T))aSyscall[39].pCurrent)
|
||||
SIZE_T))aSyscall[40].pCurrent)
|
||||
|
||||
{ "HeapSize", (SYSCALL)HeapSize, 0 },
|
||||
|
||||
#define osHeapSize ((SIZE_T(WINAPI*)(HANDLE,DWORD, \
|
||||
LPCVOID))aSyscall[40].pCurrent)
|
||||
LPCVOID))aSyscall[41].pCurrent)
|
||||
|
||||
#if !SQLITE_OS_WINRT
|
||||
{ "HeapValidate", (SYSCALL)HeapValidate, 0 },
|
||||
@ -716,7 +734,7 @@ static struct win_syscall {
|
||||
#endif
|
||||
|
||||
#define osHeapValidate ((BOOL(WINAPI*)(HANDLE,DWORD, \
|
||||
LPCVOID))aSyscall[41].pCurrent)
|
||||
LPCVOID))aSyscall[42].pCurrent)
|
||||
|
||||
#if defined(SQLITE_WIN32_HAS_ANSI) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
|
||||
{ "LoadLibraryA", (SYSCALL)LoadLibraryA, 0 },
|
||||
@ -724,7 +742,7 @@ static struct win_syscall {
|
||||
{ "LoadLibraryA", (SYSCALL)0, 0 },
|
||||
#endif
|
||||
|
||||
#define osLoadLibraryA ((HMODULE(WINAPI*)(LPCSTR))aSyscall[42].pCurrent)
|
||||
#define osLoadLibraryA ((HMODULE(WINAPI*)(LPCSTR))aSyscall[43].pCurrent)
|
||||
|
||||
#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) && \
|
||||
!defined(SQLITE_OMIT_LOAD_EXTENSION)
|
||||
@ -733,7 +751,7 @@ static struct win_syscall {
|
||||
{ "LoadLibraryW", (SYSCALL)0, 0 },
|
||||
#endif
|
||||
|
||||
#define osLoadLibraryW ((HMODULE(WINAPI*)(LPCWSTR))aSyscall[43].pCurrent)
|
||||
#define osLoadLibraryW ((HMODULE(WINAPI*)(LPCWSTR))aSyscall[44].pCurrent)
|
||||
|
||||
#if !SQLITE_OS_WINRT
|
||||
{ "LocalFree", (SYSCALL)LocalFree, 0 },
|
||||
@ -741,7 +759,7 @@ static struct win_syscall {
|
||||
{ "LocalFree", (SYSCALL)0, 0 },
|
||||
#endif
|
||||
|
||||
#define osLocalFree ((HLOCAL(WINAPI*)(HLOCAL))aSyscall[44].pCurrent)
|
||||
#define osLocalFree ((HLOCAL(WINAPI*)(HLOCAL))aSyscall[45].pCurrent)
|
||||
|
||||
#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
|
||||
{ "LockFile", (SYSCALL)LockFile, 0 },
|
||||
@ -751,7 +769,7 @@ static struct win_syscall {
|
||||
|
||||
#ifndef osLockFile
|
||||
#define osLockFile ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
|
||||
DWORD))aSyscall[45].pCurrent)
|
||||
DWORD))aSyscall[46].pCurrent)
|
||||
#endif
|
||||
|
||||
#if !SQLITE_OS_WINCE
|
||||
@ -762,7 +780,7 @@ static struct win_syscall {
|
||||
|
||||
#ifndef osLockFileEx
|
||||
#define osLockFileEx ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD,DWORD, \
|
||||
LPOVERLAPPED))aSyscall[46].pCurrent)
|
||||
LPOVERLAPPED))aSyscall[47].pCurrent)
|
||||
#endif
|
||||
|
||||
#if SQLITE_OS_WINCE || (!SQLITE_OS_WINRT && !defined(SQLITE_OMIT_WAL))
|
||||
@ -772,26 +790,26 @@ static struct win_syscall {
|
||||
#endif
|
||||
|
||||
#define osMapViewOfFile ((LPVOID(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
|
||||
SIZE_T))aSyscall[47].pCurrent)
|
||||
SIZE_T))aSyscall[48].pCurrent)
|
||||
|
||||
{ "MultiByteToWideChar", (SYSCALL)MultiByteToWideChar, 0 },
|
||||
|
||||
#define osMultiByteToWideChar ((int(WINAPI*)(UINT,DWORD,LPCSTR,int,LPWSTR, \
|
||||
int))aSyscall[48].pCurrent)
|
||||
int))aSyscall[49].pCurrent)
|
||||
|
||||
{ "QueryPerformanceCounter", (SYSCALL)QueryPerformanceCounter, 0 },
|
||||
|
||||
#define osQueryPerformanceCounter ((BOOL(WINAPI*)( \
|
||||
LARGE_INTEGER*))aSyscall[49].pCurrent)
|
||||
LARGE_INTEGER*))aSyscall[50].pCurrent)
|
||||
|
||||
{ "ReadFile", (SYSCALL)ReadFile, 0 },
|
||||
|
||||
#define osReadFile ((BOOL(WINAPI*)(HANDLE,LPVOID,DWORD,LPDWORD, \
|
||||
LPOVERLAPPED))aSyscall[50].pCurrent)
|
||||
LPOVERLAPPED))aSyscall[51].pCurrent)
|
||||
|
||||
{ "SetEndOfFile", (SYSCALL)SetEndOfFile, 0 },
|
||||
|
||||
#define osSetEndOfFile ((BOOL(WINAPI*)(HANDLE))aSyscall[51].pCurrent)
|
||||
#define osSetEndOfFile ((BOOL(WINAPI*)(HANDLE))aSyscall[52].pCurrent)
|
||||
|
||||
#if !SQLITE_OS_WINRT
|
||||
{ "SetFilePointer", (SYSCALL)SetFilePointer, 0 },
|
||||
@ -800,7 +818,7 @@ static struct win_syscall {
|
||||
#endif
|
||||
|
||||
#define osSetFilePointer ((DWORD(WINAPI*)(HANDLE,LONG,PLONG, \
|
||||
DWORD))aSyscall[52].pCurrent)
|
||||
DWORD))aSyscall[53].pCurrent)
|
||||
|
||||
#if !SQLITE_OS_WINRT
|
||||
{ "Sleep", (SYSCALL)Sleep, 0 },
|
||||
@ -808,12 +826,12 @@ static struct win_syscall {
|
||||
{ "Sleep", (SYSCALL)0, 0 },
|
||||
#endif
|
||||
|
||||
#define osSleep ((VOID(WINAPI*)(DWORD))aSyscall[53].pCurrent)
|
||||
#define osSleep ((VOID(WINAPI*)(DWORD))aSyscall[54].pCurrent)
|
||||
|
||||
{ "SystemTimeToFileTime", (SYSCALL)SystemTimeToFileTime, 0 },
|
||||
|
||||
#define osSystemTimeToFileTime ((BOOL(WINAPI*)(CONST SYSTEMTIME*, \
|
||||
LPFILETIME))aSyscall[54].pCurrent)
|
||||
LPFILETIME))aSyscall[55].pCurrent)
|
||||
|
||||
#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
|
||||
{ "UnlockFile", (SYSCALL)UnlockFile, 0 },
|
||||
@ -823,7 +841,7 @@ static struct win_syscall {
|
||||
|
||||
#ifndef osUnlockFile
|
||||
#define osUnlockFile ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
|
||||
DWORD))aSyscall[55].pCurrent)
|
||||
DWORD))aSyscall[56].pCurrent)
|
||||
#endif
|
||||
|
||||
#if !SQLITE_OS_WINCE
|
||||
@ -833,7 +851,7 @@ static struct win_syscall {
|
||||
#endif
|
||||
|
||||
#define osUnlockFileEx ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
|
||||
LPOVERLAPPED))aSyscall[56].pCurrent)
|
||||
LPOVERLAPPED))aSyscall[57].pCurrent)
|
||||
|
||||
#if SQLITE_OS_WINCE || !defined(SQLITE_OMIT_WAL)
|
||||
{ "UnmapViewOfFile", (SYSCALL)UnmapViewOfFile, 0 },
|
||||
@ -841,17 +859,17 @@ static struct win_syscall {
|
||||
{ "UnmapViewOfFile", (SYSCALL)0, 0 },
|
||||
#endif
|
||||
|
||||
#define osUnmapViewOfFile ((BOOL(WINAPI*)(LPCVOID))aSyscall[57].pCurrent)
|
||||
#define osUnmapViewOfFile ((BOOL(WINAPI*)(LPCVOID))aSyscall[58].pCurrent)
|
||||
|
||||
{ "WideCharToMultiByte", (SYSCALL)WideCharToMultiByte, 0 },
|
||||
|
||||
#define osWideCharToMultiByte ((int(WINAPI*)(UINT,DWORD,LPCWSTR,int,LPSTR,int, \
|
||||
LPCSTR,LPBOOL))aSyscall[58].pCurrent)
|
||||
LPCSTR,LPBOOL))aSyscall[59].pCurrent)
|
||||
|
||||
{ "WriteFile", (SYSCALL)WriteFile, 0 },
|
||||
|
||||
#define osWriteFile ((BOOL(WINAPI*)(HANDLE,LPCVOID,DWORD,LPDWORD, \
|
||||
LPOVERLAPPED))aSyscall[59].pCurrent)
|
||||
LPOVERLAPPED))aSyscall[60].pCurrent)
|
||||
|
||||
#if SQLITE_OS_WINRT
|
||||
{ "CreateEventExW", (SYSCALL)CreateEventExW, 0 },
|
||||
@ -860,7 +878,7 @@ static struct win_syscall {
|
||||
#endif
|
||||
|
||||
#define osCreateEventExW ((HANDLE(WINAPI*)(LPSECURITY_ATTRIBUTES,LPCWSTR, \
|
||||
DWORD,DWORD))aSyscall[60].pCurrent)
|
||||
DWORD,DWORD))aSyscall[61].pCurrent)
|
||||
|
||||
#if !SQLITE_OS_WINRT
|
||||
{ "WaitForSingleObject", (SYSCALL)WaitForSingleObject, 0 },
|
||||
@ -869,7 +887,7 @@ static struct win_syscall {
|
||||
#endif
|
||||
|
||||
#define osWaitForSingleObject ((DWORD(WINAPI*)(HANDLE, \
|
||||
DWORD))aSyscall[61].pCurrent)
|
||||
DWORD))aSyscall[62].pCurrent)
|
||||
|
||||
#if SQLITE_OS_WINRT
|
||||
{ "WaitForSingleObjectEx", (SYSCALL)WaitForSingleObjectEx, 0 },
|
||||
@ -878,7 +896,7 @@ static struct win_syscall {
|
||||
#endif
|
||||
|
||||
#define osWaitForSingleObjectEx ((DWORD(WINAPI*)(HANDLE,DWORD, \
|
||||
BOOL))aSyscall[62].pCurrent)
|
||||
BOOL))aSyscall[63].pCurrent)
|
||||
|
||||
#if SQLITE_OS_WINRT
|
||||
{ "SetFilePointerEx", (SYSCALL)SetFilePointerEx, 0 },
|
||||
@ -887,7 +905,7 @@ static struct win_syscall {
|
||||
#endif
|
||||
|
||||
#define osSetFilePointerEx ((BOOL(WINAPI*)(HANDLE,LARGE_INTEGER, \
|
||||
PLARGE_INTEGER,DWORD))aSyscall[63].pCurrent)
|
||||
PLARGE_INTEGER,DWORD))aSyscall[64].pCurrent)
|
||||
|
||||
#if SQLITE_OS_WINRT
|
||||
{ "GetFileInformationByHandleEx", (SYSCALL)GetFileInformationByHandleEx, 0 },
|
||||
@ -896,7 +914,7 @@ static struct win_syscall {
|
||||
#endif
|
||||
|
||||
#define osGetFileInformationByHandleEx ((BOOL(WINAPI*)(HANDLE, \
|
||||
FILE_INFO_BY_HANDLE_CLASS,LPVOID,DWORD))aSyscall[64].pCurrent)
|
||||
FILE_INFO_BY_HANDLE_CLASS,LPVOID,DWORD))aSyscall[65].pCurrent)
|
||||
|
||||
#if SQLITE_OS_WINRT && !defined(SQLITE_OMIT_WAL)
|
||||
{ "MapViewOfFileFromApp", (SYSCALL)MapViewOfFileFromApp, 0 },
|
||||
@ -905,7 +923,7 @@ static struct win_syscall {
|
||||
#endif
|
||||
|
||||
#define osMapViewOfFileFromApp ((LPVOID(WINAPI*)(HANDLE,ULONG,ULONG64, \
|
||||
SIZE_T))aSyscall[65].pCurrent)
|
||||
SIZE_T))aSyscall[66].pCurrent)
|
||||
|
||||
#if SQLITE_OS_WINRT
|
||||
{ "CreateFile2", (SYSCALL)CreateFile2, 0 },
|
||||
@ -914,7 +932,7 @@ static struct win_syscall {
|
||||
#endif
|
||||
|
||||
#define osCreateFile2 ((HANDLE(WINAPI*)(LPCWSTR,DWORD,DWORD,DWORD, \
|
||||
LPCREATEFILE2_EXTENDED_PARAMETERS))aSyscall[66].pCurrent)
|
||||
LPCREATEFILE2_EXTENDED_PARAMETERS))aSyscall[67].pCurrent)
|
||||
|
||||
#if SQLITE_OS_WINRT && !defined(SQLITE_OMIT_LOAD_EXTENSION)
|
||||
{ "LoadPackagedLibrary", (SYSCALL)LoadPackagedLibrary, 0 },
|
||||
@ -923,7 +941,7 @@ static struct win_syscall {
|
||||
#endif
|
||||
|
||||
#define osLoadPackagedLibrary ((HMODULE(WINAPI*)(LPCWSTR, \
|
||||
DWORD))aSyscall[67].pCurrent)
|
||||
DWORD))aSyscall[68].pCurrent)
|
||||
|
||||
#if SQLITE_OS_WINRT
|
||||
{ "GetTickCount64", (SYSCALL)GetTickCount64, 0 },
|
||||
@ -931,7 +949,7 @@ static struct win_syscall {
|
||||
{ "GetTickCount64", (SYSCALL)0, 0 },
|
||||
#endif
|
||||
|
||||
#define osGetTickCount64 ((ULONGLONG(WINAPI*)(VOID))aSyscall[68].pCurrent)
|
||||
#define osGetTickCount64 ((ULONGLONG(WINAPI*)(VOID))aSyscall[69].pCurrent)
|
||||
|
||||
#if SQLITE_OS_WINRT
|
||||
{ "GetNativeSystemInfo", (SYSCALL)GetNativeSystemInfo, 0 },
|
||||
@ -940,7 +958,7 @@ static struct win_syscall {
|
||||
#endif
|
||||
|
||||
#define osGetNativeSystemInfo ((VOID(WINAPI*)( \
|
||||
LPSYSTEM_INFO))aSyscall[69].pCurrent)
|
||||
LPSYSTEM_INFO))aSyscall[70].pCurrent)
|
||||
|
||||
#if defined(SQLITE_WIN32_HAS_ANSI)
|
||||
{ "OutputDebugStringA", (SYSCALL)OutputDebugStringA, 0 },
|
||||
@ -948,7 +966,7 @@ static struct win_syscall {
|
||||
{ "OutputDebugStringA", (SYSCALL)0, 0 },
|
||||
#endif
|
||||
|
||||
#define osOutputDebugStringA ((VOID(WINAPI*)(LPCSTR))aSyscall[70].pCurrent)
|
||||
#define osOutputDebugStringA ((VOID(WINAPI*)(LPCSTR))aSyscall[71].pCurrent)
|
||||
|
||||
#if defined(SQLITE_WIN32_HAS_WIDE)
|
||||
{ "OutputDebugStringW", (SYSCALL)OutputDebugStringW, 0 },
|
||||
@ -956,11 +974,11 @@ static struct win_syscall {
|
||||
{ "OutputDebugStringW", (SYSCALL)0, 0 },
|
||||
#endif
|
||||
|
||||
#define osOutputDebugStringW ((VOID(WINAPI*)(LPCWSTR))aSyscall[71].pCurrent)
|
||||
#define osOutputDebugStringW ((VOID(WINAPI*)(LPCWSTR))aSyscall[72].pCurrent)
|
||||
|
||||
{ "GetProcessHeap", (SYSCALL)GetProcessHeap, 0 },
|
||||
|
||||
#define osGetProcessHeap ((HANDLE(WINAPI*)(VOID))aSyscall[72].pCurrent)
|
||||
#define osGetProcessHeap ((HANDLE(WINAPI*)(VOID))aSyscall[73].pCurrent)
|
||||
|
||||
#if SQLITE_OS_WINRT && !defined(SQLITE_OMIT_WAL)
|
||||
{ "CreateFileMappingFromApp", (SYSCALL)CreateFileMappingFromApp, 0 },
|
||||
@ -969,7 +987,7 @@ static struct win_syscall {
|
||||
#endif
|
||||
|
||||
#define osCreateFileMappingFromApp ((HANDLE(WINAPI*)(HANDLE, \
|
||||
LPSECURITY_ATTRIBUTES,ULONG,ULONG64,LPCWSTR))aSyscall[73].pCurrent)
|
||||
LPSECURITY_ATTRIBUTES,ULONG,ULONG64,LPCWSTR))aSyscall[74].pCurrent)
|
||||
|
||||
}; /* End of the overrideable system calls */
|
||||
|
||||
@ -1125,6 +1143,10 @@ void sqlite3_win32_sleep(DWORD milliseconds){
|
||||
** WinNT/2K/XP so that we will know whether or not we can safely call
|
||||
** the LockFileEx() API.
|
||||
*/
|
||||
#ifndef NTDDI_WIN8
|
||||
# define NTDDI_WIN8 0x06020000
|
||||
#endif
|
||||
|
||||
#if SQLITE_OS_WINCE || SQLITE_OS_WINRT || !defined(SQLITE_WIN32_HAS_ANSI)
|
||||
# define osIsNT() (1)
|
||||
#elif !defined(SQLITE_WIN32_HAS_WIDE)
|
||||
@ -1132,9 +1154,15 @@ void sqlite3_win32_sleep(DWORD milliseconds){
|
||||
#else
|
||||
static int osIsNT(void){
|
||||
if( sqlite3_os_type==0 ){
|
||||
#if defined(NTDDI_VERSION) && NTDDI_VERSION >= NTDDI_WIN8
|
||||
OSVERSIONINFOW sInfo;
|
||||
sInfo.dwOSVersionInfoSize = sizeof(sInfo);
|
||||
osGetVersionExW(&sInfo);
|
||||
#else
|
||||
OSVERSIONINFOA sInfo;
|
||||
sInfo.dwOSVersionInfoSize = sizeof(sInfo);
|
||||
osGetVersionExA(&sInfo);
|
||||
#endif
|
||||
sqlite3_os_type = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1;
|
||||
}
|
||||
return sqlite3_os_type==2;
|
||||
@ -1159,7 +1187,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;
|
||||
@ -1180,7 +1208,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);
|
||||
}
|
||||
}
|
||||
@ -1206,7 +1234,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);
|
||||
}
|
||||
@ -1230,7 +1258,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;
|
||||
}
|
||||
@ -1260,7 +1288,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;
|
||||
@ -1272,7 +1300,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;
|
||||
@ -1300,7 +1328,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;
|
||||
@ -3185,7 +3213,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 +3222,14 @@ static void winShmPurge(sqlite3_vfs *pVfs, int deleteFlag){
|
||||
int i;
|
||||
if( p->mutex ) sqlite3_mutex_free(p->mutex);
|
||||
for(i=0; i<p->nRegion; 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);
|
||||
@ -3919,6 +3948,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 +3967,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
|
||||
@ -5154,7 +5185,7 @@ int sqlite3_os_init(void){
|
||||
|
||||
/* Double-check that the aSyscall[] array has been constructed
|
||||
** correctly. See ticket [bb3a86e890c8e96ab] */
|
||||
assert( ArraySize(aSyscall)==74 );
|
||||
assert( ArraySize(aSyscall)==75 );
|
||||
|
||||
/* get memory map allocation granularity */
|
||||
memset(&winSysInfo, 0, sizeof(SYSTEM_INFO));
|
||||
|
@ -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];
|
||||
|
654
src/pragma.c
654
src/pragma.c
File diff suppressed because it is too large
Load Diff
@ -107,6 +107,7 @@ static void resolveAlias(
|
||||
incrAggFunctionDepth(pDup, nSubquery);
|
||||
pDup = sqlite3PExpr(pParse, TK_AS, pDup, 0, 0);
|
||||
if( pDup==0 ) return;
|
||||
ExprSetProperty(pDup, EP_Skip);
|
||||
if( pEList->a[iCol].iAlias==0 ){
|
||||
pEList->a[iCol].iAlias = (u16)(++pParse->nAlias);
|
||||
}
|
||||
@ -129,7 +130,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,12 +230,12 @@ 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;
|
||||
pExpr->pTab = 0;
|
||||
ExprSetIrreducible(pExpr);
|
||||
ExprSetVVAProperty(pExpr, EP_NoReduce);
|
||||
|
||||
/* Translate the schema name in zDb into a pointer to the corresponding
|
||||
** schema. If not found, pSchema will remain NULL and nothing will match
|
||||
@ -570,6 +571,19 @@ 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);
|
||||
assert( r>=0.0 );
|
||||
if( r>1.0 ) return -1;
|
||||
return (int)(r*1000.0);
|
||||
}
|
||||
|
||||
/*
|
||||
** This routine is callback for sqlite3WalkExpr().
|
||||
@ -591,7 +605,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 ){
|
||||
@ -683,6 +697,19 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
|
||||
}
|
||||
}else{
|
||||
is_agg = pDef->xFunc==0;
|
||||
if( pDef->funcFlags & SQLITE_FUNC_UNLIKELY ){
|
||||
ExprSetProperty(pExpr, EP_Unlikely|EP_Skip);
|
||||
if( n==2 ){
|
||||
pExpr->iTable = exprProbability(pList->a[1].pExpr);
|
||||
if( pExpr->iTable<0 ){
|
||||
sqlite3ErrorMsg(pParse, "second argument to likelihood() must be a "
|
||||
"constant between 0.0 and 1.0");
|
||||
pNC->nErr++;
|
||||
}
|
||||
}else{
|
||||
pExpr->iTable = 62; /* TUNING: Default 2nd arg to unlikely() is 0.0625 */
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifndef SQLITE_OMIT_AUTHORIZATION
|
||||
if( pDef ){
|
||||
|
@ -264,8 +264,8 @@ 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) );
|
||||
ExprSetIrreducible(pEq);
|
||||
assert( !ExprHasProperty(pEq, EP_TokenOnly|EP_Reduced) );
|
||||
ExprSetVVAProperty(pEq, EP_NoReduce);
|
||||
pEq->iRightJoinTable = (i16)pE2->iTable;
|
||||
}
|
||||
*ppWhere = sqlite3ExprAnd(db, *ppWhere, pEq);
|
||||
@ -300,8 +300,8 @@ static void addWhereTerm(
|
||||
static void setJoinExpr(Expr *p, int iTable){
|
||||
while( p ){
|
||||
ExprSetProperty(p, EP_FromJoin);
|
||||
assert( !ExprHasAnyProperty(p, EP_TokenOnly|EP_Reduced) );
|
||||
ExprSetIrreducible(p);
|
||||
assert( !ExprHasProperty(p, EP_TokenOnly|EP_Reduced) );
|
||||
ExprSetVVAProperty(p, EP_NoReduce);
|
||||
p->iRightJoinTable = (i16)iTable;
|
||||
setJoinExpr(p->pLeft, iTable);
|
||||
p = p->pRight;
|
||||
|
@ -17,7 +17,11 @@
|
||||
#include "winresrc.h"
|
||||
#else
|
||||
#include "windows.h"
|
||||
#endif
|
||||
#endif /* !defined(_WIN32_WCE) */
|
||||
|
||||
#if !defined(VS_FF_NONE)
|
||||
# define VS_FF_NONE 0x00000000L
|
||||
#endif /* !defined(VS_FF_NONE) */
|
||||
|
||||
#include "sqlite3.h"
|
||||
#include "sqlite3rc.h"
|
||||
@ -26,10 +30,10 @@
|
||||
* English (U.S.) resources
|
||||
*/
|
||||
|
||||
#ifdef _WIN32
|
||||
#if defined(_WIN32)
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
#pragma code_page(1252)
|
||||
#endif /* _WIN32 */
|
||||
#endif /* defined(_WIN32) */
|
||||
|
||||
/*
|
||||
* Version
|
||||
@ -38,14 +42,14 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION SQLITE_RESOURCE_VERSION
|
||||
PRODUCTVERSION SQLITE_RESOURCE_VERSION
|
||||
FILEFLAGSMASK 0x3F
|
||||
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
|
||||
#if defined(_DEBUG)
|
||||
FILEFLAGS 0x1L
|
||||
FILEFLAGS VS_FF_DEBUG
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEFLAGS VS_FF_NONE
|
||||
#endif /* defined(_DEBUG) */
|
||||
FILEOS VOS__WINDOWS32
|
||||
FILETYPE VFT_APP
|
||||
FILETYPE VFT_DLL
|
||||
FILESUBTYPE VFT2_UNKNOWN
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
@ -64,6 +68,6 @@ BEGIN
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1200
|
||||
VALUE "Translation", 0x409, 0x4b0
|
||||
END
|
||||
END
|
||||
|
@ -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 */
|
||||
@ -1032,6 +1030,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 */
|
||||
|
||||
/*
|
||||
@ -1724,7 +1723,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 */
|
||||
@ -1738,8 +1737,8 @@ struct Expr {
|
||||
Expr *pLeft; /* Left subnode */
|
||||
Expr *pRight; /* Right subnode */
|
||||
union {
|
||||
ExprList *pList; /* Function arguments or in "<expr> IN (<expr-list)" */
|
||||
Select *pSelect; /* Used for sub-selects and "<expr> IN (<select>)" */
|
||||
ExprList *pList; /* op = IN, EXISTS, SELECT, CASE, FUNCTION, BETWEEN */
|
||||
Select *pSelect; /* EP_xIsSelect and op = IN, EXISTS, SELECT */
|
||||
} x;
|
||||
|
||||
/* If the EP_Reduced flag is set in the Expr.flags mask, then no
|
||||
@ -1752,12 +1751,12 @@ 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_Unlikely: 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[] */
|
||||
i16 iRightJoinTable; /* If EP_FromJoin, the right table of the join */
|
||||
u8 flags2; /* Second set of flags. EP2_... */
|
||||
u8 op2; /* TK_REGISTER: original value of Expr.op
|
||||
** TK_COLUMN: the value of p5 for OP_Column
|
||||
** TK_AGG_FUNCTION: nesting depth */
|
||||
@ -1768,50 +1767,45 @@ struct Expr {
|
||||
/*
|
||||
** The following are the meanings of bits in the Expr.flags field.
|
||||
*/
|
||||
#define EP_FromJoin 0x0001 /* Originated in ON or USING clause of a join */
|
||||
#define EP_Agg 0x0002 /* Contains one or more aggregate functions */
|
||||
#define EP_Resolved 0x0004 /* IDs have been resolved to COLUMNs */
|
||||
#define EP_Error 0x0008 /* Expression contains one or more errors */
|
||||
#define EP_Distinct 0x0010 /* Aggregate function with DISTINCT keyword */
|
||||
#define EP_VarSelect 0x0020 /* pSelect is correlated, not constant */
|
||||
#define EP_DblQuoted 0x0040 /* token.z was originally in "..." */
|
||||
#define EP_InfixFunc 0x0080 /* True for an infix function: LIKE, GLOB, etc */
|
||||
#define EP_Collate 0x0100 /* Tree contains a TK_COLLATE opeartor */
|
||||
#define EP_FixedDest 0x0200 /* Result needed in a specific register */
|
||||
#define EP_IntValue 0x0400 /* Integer value contained in u.iValue */
|
||||
#define EP_xIsSelect 0x0800 /* x.pSelect is valid (otherwise x.pList is) */
|
||||
#define EP_Hint 0x1000 /* Not used */
|
||||
#define EP_Reduced 0x2000 /* Expr struct is EXPR_REDUCEDSIZE bytes only */
|
||||
#define EP_TokenOnly 0x4000 /* Expr struct is EXPR_TOKENONLYSIZE bytes only */
|
||||
#define EP_Static 0x8000 /* Held in memory not obtained from malloc() */
|
||||
|
||||
/*
|
||||
** The following are the meanings of bits in the Expr.flags2 field.
|
||||
*/
|
||||
#define EP2_MallocedToken 0x0001 /* Need to sqlite3DbFree() Expr.zToken */
|
||||
#define EP2_Irreducible 0x0002 /* Cannot EXPRDUP_REDUCE this Expr */
|
||||
|
||||
/*
|
||||
** The pseudo-routine sqlite3ExprSetIrreducible sets the EP2_Irreducible
|
||||
** flag on an expression structure. This flag is used for VV&A only. The
|
||||
** routine is implemented as a macro that only works when in debugging mode,
|
||||
** so as not to burden production code.
|
||||
*/
|
||||
#ifdef SQLITE_DEBUG
|
||||
# define ExprSetIrreducible(X) (X)->flags2 |= EP2_Irreducible
|
||||
#else
|
||||
# define ExprSetIrreducible(X)
|
||||
#endif
|
||||
#define EP_FromJoin 0x000001 /* Originated in ON or USING clause of a join */
|
||||
#define EP_Agg 0x000002 /* Contains one or more aggregate functions */
|
||||
#define EP_Resolved 0x000004 /* IDs have been resolved to COLUMNs */
|
||||
#define EP_Error 0x000008 /* Expression contains one or more errors */
|
||||
#define EP_Distinct 0x000010 /* Aggregate function with DISTINCT keyword */
|
||||
#define EP_VarSelect 0x000020 /* pSelect is correlated, not constant */
|
||||
#define EP_DblQuoted 0x000040 /* token.z was originally in "..." */
|
||||
#define EP_InfixFunc 0x000080 /* True for an infix function: LIKE, GLOB, etc */
|
||||
#define EP_Collate 0x000100 /* Tree contains a TK_COLLATE opeartor */
|
||||
#define EP_FixedDest 0x000200 /* Result needed in a specific register */
|
||||
#define EP_IntValue 0x000400 /* Integer value contained in u.iValue */
|
||||
#define EP_xIsSelect 0x000800 /* x.pSelect is valid (otherwise x.pList is) */
|
||||
#define EP_Skip 0x001000 /* COLLATE, AS, or UNLIKELY */
|
||||
#define EP_Reduced 0x002000 /* Expr struct EXPR_REDUCEDSIZE bytes only */
|
||||
#define EP_TokenOnly 0x004000 /* Expr struct EXPR_TOKENONLYSIZE bytes only */
|
||||
#define EP_Static 0x008000 /* Held in memory not obtained from malloc() */
|
||||
#define EP_MemToken 0x010000 /* Need to sqlite3DbFree() Expr.zToken */
|
||||
#define EP_NoReduce 0x020000 /* Cannot EXPRDUP_REDUCE this Expr */
|
||||
#define EP_Unlikely 0x040000 /* unlikely() or likelihood() function */
|
||||
|
||||
/*
|
||||
** These macros can be used to test, set, or clear bits in the
|
||||
** Expr.flags field.
|
||||
*/
|
||||
#define ExprHasProperty(E,P) (((E)->flags&(P))==(P))
|
||||
#define ExprHasAnyProperty(E,P) (((E)->flags&(P))!=0)
|
||||
#define ExprHasProperty(E,P) (((E)->flags&(P))!=0)
|
||||
#define ExprHasAllProperty(E,P) (((E)->flags&(P))==(P))
|
||||
#define ExprSetProperty(E,P) (E)->flags|=(P)
|
||||
#define ExprClearProperty(E,P) (E)->flags&=~(P)
|
||||
|
||||
/* The ExprSetVVAProperty() macro is used for Verification, Validation,
|
||||
** and Accreditation only. It works like ExprSetProperty() during VVA
|
||||
** processes but is a no-op for delivery.
|
||||
*/
|
||||
#ifdef SQLITE_DEBUG
|
||||
# define ExprSetVVAProperty(E,P) (E)->flags|=(P)
|
||||
#else
|
||||
# define ExprSetVVAProperty(E,P)
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Macros to determine the number of bytes required by a normal Expr
|
||||
** struct, an Expr struct with the EP_Reduced flag set in Expr.flags
|
||||
@ -3190,6 +3184,7 @@ int sqlite3VtabCallDestroy(sqlite3*, int, const char *);
|
||||
int sqlite3VtabBegin(sqlite3 *, VTable *);
|
||||
FuncDef *sqlite3VtabOverloadFunction(sqlite3 *,FuncDef*, int nArg, Expr*);
|
||||
void sqlite3InvalidFunction(sqlite3_context*,int,sqlite3_value**);
|
||||
sqlite3_int64 sqlite3StmtCurrentTime(sqlite3_context*);
|
||||
int sqlite3VdbeParameterIndex(Vdbe*, const char*, int);
|
||||
int sqlite3TransferBindings(sqlite3_stmt *, sqlite3_stmt *);
|
||||
int sqlite3Reprepare(Vdbe*);
|
||||
|
@ -193,7 +193,8 @@ int sqlite3Dequote(char *z){
|
||||
case '[': quote = ']'; break; /* For MS SqlServer compatibility */
|
||||
default: return -1;
|
||||
}
|
||||
for(i=1, j=0; ALWAYS(z[i]); i++){
|
||||
for(i=1, j=0;; i++){
|
||||
assert( z[i] );
|
||||
if( z[i]==quote ){
|
||||
if( z[i+1]==quote ){
|
||||
z[j++] = quote;
|
||||
|
@ -567,6 +567,7 @@ int sqlite3VdbeExec(
|
||||
assert( p->rc==SQLITE_OK || p->rc==SQLITE_BUSY );
|
||||
assert( p->bIsReader || p->readOnly!=0 );
|
||||
p->rc = SQLITE_OK;
|
||||
p->iCurrentTime = 0;
|
||||
assert( p->explain==0 );
|
||||
p->pResultSet = 0;
|
||||
db->busyHandler.nBusy = 0;
|
||||
|
@ -350,6 +350,7 @@ struct Vdbe {
|
||||
#ifndef SQLITE_OMIT_TRACE
|
||||
i64 startTime; /* Time when query started - used for profiling */
|
||||
#endif
|
||||
i64 iCurrentTime; /* Value of julianday('now') for this statement */
|
||||
i64 nFkConstraint; /* Number of imm. FK constraints this VM */
|
||||
i64 nStmtDefCons; /* Number of def. constraints when stmt started */
|
||||
i64 nStmtDefImmCons; /* Number of def. imm constraints when stmt started */
|
||||
|
@ -510,6 +510,7 @@ int sqlite3_step(sqlite3_stmt *pStmt){
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Extract the user data from a sqlite3_context structure and return a
|
||||
** pointer to it.
|
||||
@ -534,6 +535,19 @@ sqlite3 *sqlite3_context_db_handle(sqlite3_context *p){
|
||||
return p->s.db;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the current time for a statement
|
||||
*/
|
||||
sqlite3_int64 sqlite3StmtCurrentTime(sqlite3_context *p){
|
||||
Vdbe *v = p->pVdbe;
|
||||
int rc;
|
||||
if( v->iCurrentTime==0 ){
|
||||
rc = sqlite3OsCurrentTimeInt64(p->s.db->pVfs, &v->iCurrentTime);
|
||||
if( rc ) v->iCurrentTime = 0;
|
||||
}
|
||||
return v->iCurrentTime;
|
||||
}
|
||||
|
||||
/*
|
||||
** The following is the implementation of an SQL function that always
|
||||
** fails with an error message stating that the function is used in the
|
||||
|
@ -2436,6 +2436,7 @@ int sqlite3VdbeReset(Vdbe *p){
|
||||
}
|
||||
}
|
||||
#endif
|
||||
p->iCurrentTime = 0;
|
||||
p->magic = VDBE_MAGIC_INIT;
|
||||
return p->rc & db->errMask;
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ int sqlite3WalkExpr(Walker *pWalker, Expr *pExpr){
|
||||
testcase( ExprHasProperty(pExpr, EP_Reduced) );
|
||||
rc = pWalker->xExprCallback(pWalker, pExpr);
|
||||
if( rc==WRC_Continue
|
||||
&& !ExprHasAnyProperty(pExpr,EP_TokenOnly) ){
|
||||
&& !ExprHasProperty(pExpr,EP_TokenOnly) ){
|
||||
if( sqlite3WalkExpr(pWalker, pExpr->pLeft) ) return WRC_Abort;
|
||||
if( sqlite3WalkExpr(pWalker, pExpr->pRight) ) return WRC_Abort;
|
||||
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
|
||||
|
146
src/where.c
146
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
|
||||
@ -106,6 +107,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 */
|
||||
};
|
||||
|
||||
/*
|
||||
@ -268,6 +270,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 <op> */
|
||||
u8 wtFlags; /* TERM_xxx bit flags. See below */
|
||||
u8 nChild; /* Number of children that must disable us */
|
||||
@ -642,6 +645,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 +689,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 && ExprHasProperty(p, EP_Unlikely) ){
|
||||
pTerm->truthProb = whereCost(p->iTable) - 99;
|
||||
}else{
|
||||
pTerm->truthProb = -1;
|
||||
}
|
||||
pTerm->pExpr = sqlite3ExprSkipCollate(p);
|
||||
pTerm->wtFlags = wtFlags;
|
||||
pTerm->pWC = pWC;
|
||||
@ -2544,6 +2555,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;
|
||||
@ -2606,6 +2618,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--;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2620,12 +2633,12 @@ static int whereRangeScanEst(
|
||||
whereKeyStats(pParse, p, pRec, 1, a);
|
||||
iNew = a[0] + ((pUpper->eOperator & WO_LE) ? a[1] : 0);
|
||||
if( iNew<iUpper ) iUpper = iNew;
|
||||
nOut--;
|
||||
}
|
||||
}
|
||||
|
||||
pBuilder->pRec = pRec;
|
||||
if( rc==SQLITE_OK ){
|
||||
WhereCost nNew;
|
||||
if( iUpper>iLower ){
|
||||
nNew = whereCost(iUpper - iLower);
|
||||
}else{
|
||||
@ -2647,13 +2660,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( nNew<nOut ) nOut = nNew;
|
||||
*pnOut = (WhereCost)nOut;
|
||||
return rc;
|
||||
}
|
||||
@ -2799,6 +2816,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 +3242,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 +3251,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 +3904,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 +3913,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 +3945,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 +3973,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 +3984,7 @@ static Bitmask codeOneLoopStart(
|
||||
}
|
||||
sqlite3ReleaseTempReg(pParse, iReleaseReg);
|
||||
|
||||
return newNotReady;
|
||||
return pLevel->notReady;
|
||||
}
|
||||
|
||||
#ifdef WHERETRACE_ENABLED
|
||||
@ -4188,9 +4205,9 @@ static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){
|
||||
assert( p->rSetup==pTemplate->rSetup );
|
||||
if( p->prereq==pTemplate->prereq
|
||||
&& p->nLTerm<pTemplate->nLTerm
|
||||
&& (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
|
||||
|| pTemplate->rRun+p->nLTerm<=p->rRun+pTemplate->nLTerm)
|
||||
){
|
||||
/* Overwrite an existing WhereLoop with an similar one that uses
|
||||
** more terms of the index */
|
||||
@ -4205,12 +4222,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;
|
||||
}
|
||||
@ -4257,6 +4274,36 @@ 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, *pX;
|
||||
Bitmask notAllowed = ~(pLoop->prereq|pLoop->maskSelf);
|
||||
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 ) break;
|
||||
if( (pTerm->prereqAll & pLoop->maskSelf)==0 ) continue;
|
||||
if( (pTerm->prereqAll & notAllowed)!=0 ) continue;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** We have so far matched pBuilder->pNew->u.btree.nEq terms of the index pIndex.
|
||||
** Try to match one more.
|
||||
@ -4423,7 +4470,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 +4674,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 +4708,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;
|
||||
}
|
||||
}
|
||||
@ -5266,9 +5317,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 */
|
||||
@ -5337,6 +5391,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,
|
||||
@ -5359,7 +5414,11 @@ 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; jj<nTo; jj++, pTo++){
|
||||
if( pTo->maskLoop==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;
|
||||
}
|
||||
@ -5368,8 +5427,8 @@ static int wherePathSolver(WhereInfo *pWInfo, WhereCost nRowEst){
|
||||
if( nTo>=mxChoice && rCost>=mxCost ){
|
||||
#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
|
||||
@ -5381,26 +5440,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].rCost<mxCost; jj--){ assert(jj>0); }
|
||||
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
|
||||
@ -5412,11 +5471,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
|
||||
@ -5424,16 +5483,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]; jj<mxChoice; jj++, pTo++){
|
||||
if( pTo->rCost>mxCost ) mxCost = pTo->rCost;
|
||||
if( pTo->rCost>mxCost || (pTo->rCost==mxCost && pTo->nRow>mxOut) ){
|
||||
mxCost = pTo->rCost;
|
||||
mxOut = pTo->nRow;
|
||||
mxI = jj;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -5470,12 +5535,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; ii<nFrom; ii++){
|
||||
if( pFrom->rCost>aFrom[ii].rCost ) pFrom = &aFrom[ii];
|
||||
}
|
||||
#endif
|
||||
assert( pWInfo->nLevel==nLoop );
|
||||
/* Load the lowest cost path into pWInfo */
|
||||
for(iLoop=0; iLoop<nLoop; iLoop++){
|
||||
|
@ -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}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
@ -845,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 {
|
||||
@ -950,4 +950,3 @@ for {set i 0} {$i<16} {incr i} {
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
@ -57,6 +57,6 @@ do_test 1.3 {
|
||||
} $str
|
||||
|
||||
db close
|
||||
file delete test.db
|
||||
delete_file test.db
|
||||
|
||||
finish_test
|
||||
|
@ -528,4 +528,23 @@ if {0==[sqlite3 -has-codec]} {
|
||||
} {1}
|
||||
}
|
||||
}
|
||||
|
||||
# Verify that multiple calls to date functions with 'now' return the
|
||||
# same answer.
|
||||
#
|
||||
proc sleeper {} {after 100}
|
||||
do_test date-15.1 {
|
||||
db func sleeper sleeper
|
||||
db eval {
|
||||
SELECT c - a FROM (SELECT julianday('now') AS a,
|
||||
sleeper(), julianday('now') AS c);
|
||||
}
|
||||
} {0.0}
|
||||
do_test date-15.2 {
|
||||
db eval {
|
||||
SELECT a==b FROM (SELECT current_timestamp AS a,
|
||||
sleeper(), current_timestamp AS b);
|
||||
}
|
||||
} {1}
|
||||
|
||||
finish_test
|
||||
|
@ -438,4 +438,121 @@ do_execsql_test 8.2.3 {
|
||||
SELECT rowid FROM t4 WHERE t4 MATCH 'a';
|
||||
} {2 4}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
foreach {tn sql} {
|
||||
1 {
|
||||
CREATE VIRTUAL TABLE t5 USING fts4(tokenize=unicode61 [tokenchars= .]);
|
||||
CREATE VIRTUAL TABLE t6 USING fts4(
|
||||
tokenize=unicode61 [tokenchars=="] "tokenchars=[]");
|
||||
CREATE VIRTUAL TABLE t7 USING fts4(tokenize=unicode61 [separators=x\xC4]);
|
||||
}
|
||||
2 {
|
||||
CREATE VIRTUAL TABLE t5 USING fts4(tokenize=unicode61 "tokenchars= .");
|
||||
CREATE VIRTUAL TABLE t6 USING fts4(tokenize=unicode61 "tokenchars=[=""]");
|
||||
CREATE VIRTUAL TABLE t7 USING fts4(tokenize=unicode61 "separators=x\xC4");
|
||||
}
|
||||
3 {
|
||||
CREATE VIRTUAL TABLE t5 USING fts4(tokenize=unicode61 'tokenchars= .');
|
||||
CREATE VIRTUAL TABLE t6 USING fts4(tokenize=unicode61 'tokenchars=="[]');
|
||||
CREATE VIRTUAL TABLE t7 USING fts4(tokenize=unicode61 'separators=x\xC4');
|
||||
}
|
||||
4 {
|
||||
CREATE VIRTUAL TABLE t5 USING fts4(tokenize=unicode61 `tokenchars= .`);
|
||||
CREATE VIRTUAL TABLE t6 USING fts4(tokenize=unicode61 `tokenchars=[="]`);
|
||||
CREATE VIRTUAL TABLE t7 USING fts4(tokenize=unicode61 `separators=x\xC4`);
|
||||
}
|
||||
} {
|
||||
do_execsql_test 9.$tn.0 {
|
||||
DROP TABLE IF EXISTS t5;
|
||||
DROP TABLE IF EXISTS t5aux;
|
||||
DROP TABLE IF EXISTS t6;
|
||||
DROP TABLE IF EXISTS t6aux;
|
||||
DROP TABLE IF EXISTS t7;
|
||||
DROP TABLE IF EXISTS t7aux;
|
||||
}
|
||||
do_execsql_test 9.$tn.1 $sql
|
||||
|
||||
do_execsql_test 9.$tn.2 {
|
||||
CREATE VIRTUAL TABLE t5aux USING fts4aux(t5);
|
||||
INSERT INTO t5 VALUES('one two three/four.five.six');
|
||||
SELECT * FROM t5aux;
|
||||
} {
|
||||
four.five.six * 1 1 four.five.six 0 1 1
|
||||
{one two three} * 1 1 {one two three} 0 1 1
|
||||
}
|
||||
|
||||
do_execsql_test 9.$tn.3 {
|
||||
CREATE VIRTUAL TABLE t6aux USING fts4aux(t6);
|
||||
INSERT INTO t6 VALUES('alpha=beta"gamma/delta[epsilon]zeta');
|
||||
SELECT * FROM t6aux;
|
||||
} {
|
||||
{alpha=beta"gamma} * 1 1 {alpha=beta"gamma} 0 1 1
|
||||
{delta[epsilon]zeta} * 1 1 {delta[epsilon]zeta} 0 1 1
|
||||
}
|
||||
|
||||
do_execsql_test 9.$tn.4 {
|
||||
CREATE VIRTUAL TABLE t7aux USING fts4aux(t7);
|
||||
INSERT INTO t7 VALUES('alephxbeth\xC4gimel');
|
||||
SELECT * FROM t7aux;
|
||||
} {
|
||||
aleph * 1 1 aleph 0 1 1
|
||||
beth * 1 1 beth 0 1 1
|
||||
gimel * 1 1 gimel 0 1 1
|
||||
}
|
||||
}
|
||||
|
||||
# Check that multiple options are handled correctly.
|
||||
#
|
||||
do_execsql_test 10.1 {
|
||||
DROP TABLE IF EXISTS t1;
|
||||
CREATE VIRTUAL TABLE t1 USING fts4(tokenize=unicode61
|
||||
"tokenchars=xyz" "tokenchars=.=" "separators=.=" "separators=xy"
|
||||
"separators=a" "separators=a" "tokenchars=a" "tokenchars=a"
|
||||
);
|
||||
|
||||
INSERT INTO t1 VALUES('oneatwoxthreeyfour');
|
||||
INSERT INTO t1 VALUES('a.single=word');
|
||||
CREATE VIRTUAL TABLE t1aux USING fts4aux(t1);
|
||||
SELECT * FROM t1aux;
|
||||
} {
|
||||
.single=word * 1 1 .single=word 0 1 1
|
||||
four * 1 1 four 0 1 1
|
||||
one * 1 1 one 0 1 1
|
||||
three * 1 1 three 0 1 1
|
||||
two * 1 1 two 0 1 1
|
||||
}
|
||||
|
||||
# Test that case folding happens after tokenization, not before.
|
||||
#
|
||||
do_execsql_test 10.2 {
|
||||
DROP TABLE IF EXISTS t2;
|
||||
CREATE VIRTUAL TABLE t2 USING fts4(tokenize=unicode61 "separators=aB");
|
||||
INSERT INTO t2 VALUES('oneatwoBthree');
|
||||
INSERT INTO t2 VALUES('onebtwoAthree');
|
||||
CREATE VIRTUAL TABLE t2aux USING fts4aux(t2);
|
||||
SELECT * FROM t2aux;
|
||||
} {
|
||||
one * 1 1 one 0 1 1
|
||||
onebtwoathree * 1 1 onebtwoathree 0 1 1
|
||||
three * 1 1 three 0 1 1
|
||||
two * 1 1 two 0 1 1
|
||||
}
|
||||
|
||||
# Test that the tokenchars and separators options work with the
|
||||
# fts3tokenize table.
|
||||
#
|
||||
do_execsql_test 11.1 {
|
||||
CREATE VIRTUAL TABLE ft1 USING fts3tokenize(
|
||||
"unicode61", "tokenchars=@.", "separators=1234567890"
|
||||
);
|
||||
SELECT token FROM ft1 WHERE input = 'berlin@street123sydney.road';
|
||||
} {
|
||||
berlin@street sydney.road
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -361,7 +361,7 @@ foreach file [glob -nocomplain quota-test-A*] {
|
||||
do_test quota-4.4.1 {
|
||||
set ::quota {}
|
||||
sqlite3_quota_set $::quotagroup 10000 quota_callback
|
||||
file delete -force ./quota-test-A1.db ./quota-test-A2.db
|
||||
forcedelete ./quota-test-A1.db ./quota-test-A2.db
|
||||
sqlite3 db ./quota-test-A1.db
|
||||
db eval {
|
||||
CREATE TABLE t1(x);
|
||||
|
@ -25,7 +25,7 @@ db close
|
||||
sqlite3_quota_initialize "" 1
|
||||
|
||||
foreach dir {quota2a/x1 quota2a/x2 quota2a quota2b quota2c} {
|
||||
file delete -force $dir
|
||||
forcedelete $dir
|
||||
}
|
||||
foreach dir {quota2a quota2a/x1 quota2a/x2 quota2b quota2c} {
|
||||
file mkdir $dir
|
||||
|
@ -536,7 +536,7 @@ do_test shell1-3.19.1 {
|
||||
catchcmd "test.db" ".read"
|
||||
} {1 {Error: unknown command or invalid arguments: "read". Enter ".help" for help}}
|
||||
do_test shell1-3.19.2 {
|
||||
file delete -force FOO
|
||||
forcedelete FOO
|
||||
catchcmd "test.db" ".read FOO"
|
||||
} {1 {Error: cannot open "FOO"}}
|
||||
do_test shell1-3.19.3 {
|
||||
|
@ -42,7 +42,7 @@ sqlite3 db test.db
|
||||
# Reported on mailing list by Ken Zalewski.
|
||||
# Ticket [aeff892c57].
|
||||
do_test shell2-1.1.1 {
|
||||
file delete -force foo.db
|
||||
forcedelete foo.db
|
||||
set rc [ catchcmd "-batch foo.db" "CREATE TABLE t1(a);" ]
|
||||
set fexist [file exist foo.db]
|
||||
list $rc $fexist
|
||||
@ -81,7 +81,7 @@ do_test shell2-1.3 {
|
||||
# Test with echo off
|
||||
# NB. whitespace is important
|
||||
do_test shell2-1.4.1 {
|
||||
file delete -force foo.db
|
||||
forcedelete foo.db
|
||||
catchcmd "foo.db" {CREATE TABLE foo(a);
|
||||
INSERT INTO foo(a) VALUES(1);
|
||||
SELECT * FROM foo;}
|
||||
@ -90,7 +90,7 @@ SELECT * FROM foo;}
|
||||
# Test with echo on using command line option
|
||||
# NB. whitespace is important
|
||||
do_test shell2-1.4.2 {
|
||||
file delete -force foo.db
|
||||
forcedelete foo.db
|
||||
catchcmd "-echo foo.db" {CREATE TABLE foo(a);
|
||||
INSERT INTO foo(a) VALUES(1);
|
||||
SELECT * FROM foo;}
|
||||
@ -102,7 +102,7 @@ SELECT * FROM foo;
|
||||
# Test with echo on using dot command
|
||||
# NB. whitespace is important
|
||||
do_test shell2-1.4.3 {
|
||||
file delete -force foo.db
|
||||
forcedelete foo.db
|
||||
catchcmd "foo.db" {.echo ON
|
||||
CREATE TABLE foo(a);
|
||||
INSERT INTO foo(a) VALUES(1);
|
||||
@ -116,7 +116,7 @@ SELECT * FROM foo;
|
||||
# turning off mid- processing.
|
||||
# NB. whitespace is important
|
||||
do_test shell2-1.4.4 {
|
||||
file delete -force foo.db
|
||||
forcedelete foo.db
|
||||
catchcmd "foo.db" {.echo ON
|
||||
CREATE TABLE foo(a);
|
||||
.echo OFF
|
||||
@ -130,7 +130,7 @@ SELECT * FROM foo;}
|
||||
# multiple commands per line.
|
||||
# NB. whitespace is important
|
||||
do_test shell2-1.4.5 {
|
||||
file delete -force foo.db
|
||||
forcedelete foo.db
|
||||
catchcmd "foo.db" {.echo ON
|
||||
CREATE TABLE foo1(a);
|
||||
INSERT INTO foo1(a) VALUES(1);
|
||||
@ -161,7 +161,7 @@ SELECT * FROM foo2;
|
||||
# multiple commands per line.
|
||||
# NB. whitespace is important
|
||||
do_test shell2-1.4.6 {
|
||||
file delete -force foo.db
|
||||
forcedelete foo.db
|
||||
catchcmd "foo.db" {.echo ON
|
||||
.headers ON
|
||||
CREATE TABLE foo1(a);
|
||||
|
@ -40,7 +40,7 @@ sqlite3 db test.db
|
||||
|
||||
# Run SQL statement from command line
|
||||
do_test shell3-1.1 {
|
||||
file delete -force foo.db
|
||||
forcedelete foo.db
|
||||
set rc [ catchcmd "foo.db \"CREATE TABLE t1(a);\"" ]
|
||||
set fexist [file exist foo.db]
|
||||
list $rc $fexist
|
||||
@ -70,7 +70,7 @@ do_test shell3-1.7 {
|
||||
|
||||
# Run SQL file from command line
|
||||
do_test shell3-2.1 {
|
||||
file delete -force foo.db
|
||||
forcedelete foo.db
|
||||
set rc [ catchcmd "foo.db" "CREATE TABLE t1(a);" ]
|
||||
set fexist [file exist foo.db]
|
||||
list $rc $fexist
|
||||
|
@ -32,7 +32,6 @@ if {![file executable $CLI]} {
|
||||
}
|
||||
db close
|
||||
forcedelete test.db test.db-journal test.db-wal
|
||||
sqlite3 db test.db
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# Test cases shell5-1.*: Basic handling of the .import and .separator commands.
|
||||
@ -81,14 +80,14 @@ do_test shell5-1.3.2 {
|
||||
|
||||
# import file doesn't exist
|
||||
do_test shell5-1.4.1 {
|
||||
file delete -force FOO
|
||||
forcedelete FOO
|
||||
set res [catchcmd "test.db" {CREATE TABLE t1(a, b);
|
||||
.import FOO t1}]
|
||||
} {1 {Error: cannot open "FOO"}}
|
||||
|
||||
# empty import file
|
||||
do_test shell5-1.4.2 {
|
||||
file delete -force shell5.csv
|
||||
forcedelete shell5.csv
|
||||
set in [open shell5.csv w]
|
||||
close $in
|
||||
set res [catchcmd "test.db" {.import shell5.csv t1
|
||||
@ -231,7 +230,7 @@ SELECT COUNT(*) FROM t3;}]
|
||||
# Inport from a pipe. (Unix only, as it requires "awk")
|
||||
if {$tcl_platform(platform)=="unix"} {
|
||||
do_test shell5-1.8 {
|
||||
file delete -force test.db
|
||||
forcedelete test.db
|
||||
catchcmd test.db {.mode csv
|
||||
.import "|awk 'END{print \"x,y\";for(i=1;i<=5;i++){print i \",this is \" i}}'" t1
|
||||
SELECT * FROM t1;}
|
||||
@ -245,6 +244,7 @@ SELECT * FROM t1;}
|
||||
# Import columns containing quoted strings
|
||||
do_test shell5-1.9 {
|
||||
set out [open shell5.csv w]
|
||||
fconfigure $out -translation lf
|
||||
puts $out {1,"",11}
|
||||
puts $out {2,"x",22}
|
||||
puts $out {3,"""",33}
|
||||
@ -258,7 +258,7 @@ do_test shell5-1.9 {
|
||||
puts $out {"""",11,121}
|
||||
puts $out {"hello",12,132}
|
||||
close $out
|
||||
file delete -force test.db
|
||||
forcedelete test.db
|
||||
catchcmd test.db {.mode csv
|
||||
CREATE TABLE t1(a,b,c);
|
||||
.import shell5.csv t1
|
||||
|
@ -24,10 +24,27 @@ ifcapable !integrityck {
|
||||
return
|
||||
}
|
||||
|
||||
sqlite3_soft_heap_limit -1
|
||||
sqlite3_soft_heap_limit 0
|
||||
sqlite3_soft_heap_limit 5000
|
||||
do_test softheap1-1.0 {
|
||||
execsql {PRAGMA soft_heap_limit}
|
||||
} [sqlite3_soft_heap_limit -1]
|
||||
do_test softheap1-1.1 {
|
||||
execsql {PRAGMA soft_heap_limit=123456; PRAGMA soft_heap_limit;}
|
||||
} {123456 123456}
|
||||
do_test softheap1-1.2 {
|
||||
sqlite3_soft_heap_limit -1
|
||||
} {123456}
|
||||
do_test softheap1-1.3 {
|
||||
execsql {PRAGMA soft_heap_limit(-1); PRAGMA soft_heap_limit;}
|
||||
} {123456 123456}
|
||||
do_test softheap1-1.4 {
|
||||
execsql {PRAGMA soft_heap_limit(0); PRAGMA soft_heap_limit;}
|
||||
} {0 0}
|
||||
|
||||
sqlite3_soft_heap_limit 5000
|
||||
do_test softheap1-2.0 {
|
||||
execsql {PRAGMA soft_heap_limit}
|
||||
} {5000}
|
||||
do_test softheap1-2.1 {
|
||||
execsql {
|
||||
PRAGMA auto_vacuum=1;
|
||||
CREATE TABLE t1(x);
|
||||
|
187
test/tpch01.test
Normal file
187
test/tpch01.test
Normal file
@ -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<?)} 0 1 0 {SEARCH TABLE customer USING INDEX cpki (C_CUSTKEY=?)} 0 2 3 {SEARCH TABLE nation USING INDEX npki (N_NATIONKEY=?)} 0 3 2 {SEARCH TABLE lineitem USING INDEX lpki (L_ORDERKEY=?)} 0 0 0 {USE TEMP B-TREE FOR GROUP BY} 0 0 0 {USE TEMP B-TREE FOR ORDER BY}}
|
170
test/whereG.test
Normal file
170
test/whereG.test
Normal file
@ -0,0 +1,170 @@
|
||||
# 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);
|
||||
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
|
||||
FROM album, composer, track
|
||||
WHERE unlikely(cname LIKE '%bach%')
|
||||
AND composer.cid=track.cid
|
||||
AND album.aid=track.aid;
|
||||
} {/.*composer.*track.*album.*/}
|
||||
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_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_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 {
|
||||
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}}
|
||||
|
||||
# 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
|
@ -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
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
|
349
tool/mkpragmatab.tcl
Normal file
349
tool/mkpragmatab.tcl
Normal file
@ -0,0 +1,349 @@
|
||||
#!/usr/bin/tclsh
|
||||
#
|
||||
# Run this script to generate the pragma name lookup table C code.
|
||||
#
|
||||
# To add new pragmas, first add the name and other relevant attributes
|
||||
# of the pragma to the "pragma_def" object below. Then run this script
|
||||
# to generate the C-code for the lookup table and copy/paste the output
|
||||
# of this script into the appropriate spot in the pragma.c source file.
|
||||
# Then add the extra "case PragTyp_XXXXX:" and subsequent code for the
|
||||
# new pragma.
|
||||
#
|
||||
|
||||
set pragma_def {
|
||||
NAME: full_column_names
|
||||
TYPE: FLAG
|
||||
ARG: SQLITE_FullColNames
|
||||
|
||||
NAME: short_column_names
|
||||
TYPE: FLAG
|
||||
ARG: SQLITE_ShortColNames
|
||||
|
||||
NAME: count_changes
|
||||
TYPE: FLAG
|
||||
ARG: SQLITE_CountRows
|
||||
|
||||
NAME: empty_result_callbacks
|
||||
TYPE: FLAG
|
||||
ARG: SQLITE_NullCallback
|
||||
|
||||
NAME: legacy_file_format
|
||||
TYPE: FLAG
|
||||
ARG: SQLITE_LegacyFileFmt
|
||||
|
||||
NAME: fullfsync
|
||||
TYPE: FLAG
|
||||
ARG: SQLITE_FullFSync
|
||||
|
||||
NAME: checkpoint_fullfsync
|
||||
TYPE: FLAG
|
||||
ARG: SQLITE_CkptFullFSync
|
||||
|
||||
NAME: cache_spill
|
||||
TYPE: FLAG
|
||||
ARG: SQLITE_CacheSpill
|
||||
|
||||
NAME: reverse_unordered_selects
|
||||
TYPE: FLAG
|
||||
ARG: SQLITE_ReverseOrder
|
||||
|
||||
NAME: query_only
|
||||
TYPE: FLAG
|
||||
ARG: SQLITE_QueryOnly
|
||||
|
||||
NAME: automatic_index
|
||||
TYPE: FLAG
|
||||
ARG: SQLITE_AutoIndex
|
||||
IF: !defined(SQLITE_OMIT_AUTOMATIC_INDEX)
|
||||
|
||||
NAME: sql_trace
|
||||
TYPE: FLAG
|
||||
ARG: SQLITE_SqlTrace
|
||||
IF: defined(SQLITE_DEBUG)
|
||||
|
||||
NAME: vdbe_listing
|
||||
TYPE: FLAG
|
||||
ARG: SQLITE_VdbeListing
|
||||
IF: defined(SQLITE_DEBUG)
|
||||
|
||||
NAME: vdbe_trace
|
||||
TYPE: FLAG
|
||||
ARG: SQLITE_VdbeTrace
|
||||
IF: defined(SQLITE_DEBUG)
|
||||
|
||||
NAME: vdbe_addoptrace
|
||||
TYPE: FLAG
|
||||
ARG: SQLITE_VdbeAddopTrace
|
||||
IF: defined(SQLITE_DEBUG)
|
||||
|
||||
NAME: vdbe_debug
|
||||
TYPE: FLAG
|
||||
ARG: SQLITE_SqlTrace|SQLITE_VdbeListing|SQLITE_VdbeTrace
|
||||
IF: defined(SQLITE_DEBUG)
|
||||
|
||||
NAME: ignore_check_constraints
|
||||
TYPE: FLAG
|
||||
ARG: SQLITE_IgnoreChecks
|
||||
IF: !defined(SQLITE_OMIT_CHECK)
|
||||
|
||||
NAME: writable_schema
|
||||
TYPE: FLAG
|
||||
ARG: SQLITE_WriteSchema|SQLITE_RecoveryMode
|
||||
|
||||
NAME: read_uncommitted
|
||||
TYPE: FLAG
|
||||
ARG: SQLITE_ReadUncommitted
|
||||
|
||||
NAME: recursive_triggers
|
||||
TYPE: FLAG
|
||||
ARG: SQLITE_RecTriggers
|
||||
|
||||
NAME: foreign_keys
|
||||
TYPE: FLAG
|
||||
ARG: SQLITE_ForeignKeys
|
||||
IF: !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
|
||||
|
||||
NAME: defer_foreign_keys
|
||||
TYPE: FLAG
|
||||
ARG: SQLITE_DeferFKs
|
||||
IF: !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
|
||||
|
||||
NAME: default_cache_size
|
||||
IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED)
|
||||
|
||||
NAME: page_size
|
||||
IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS)
|
||||
|
||||
NAME: secure_delete
|
||||
IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS)
|
||||
|
||||
NAME: page_count
|
||||
IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS)
|
||||
|
||||
NAME: max_page_count
|
||||
TYPE: PAGE_COUNT
|
||||
IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS)
|
||||
|
||||
NAME: locking_mode
|
||||
IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS)
|
||||
|
||||
NAME: journal_mode
|
||||
IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS)
|
||||
|
||||
NAME: journal_size_limit
|
||||
IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS)
|
||||
|
||||
NAME: cache_size
|
||||
IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS)
|
||||
|
||||
NAME: mmap_size
|
||||
IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS)
|
||||
|
||||
NAME: auto_vacuum
|
||||
IF: !defined(SQLITE_OMIT_AUTOVACUUM)
|
||||
|
||||
NAME: incremental_vacuum
|
||||
IF: !defined(SQLITE_OMIT_AUTOVACUUM)
|
||||
|
||||
NAME: temp_store
|
||||
IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS)
|
||||
|
||||
NAME: temp_store_directory
|
||||
IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS)
|
||||
|
||||
NAME: data_store_directory
|
||||
IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS) && SQLITE_OS_WIN
|
||||
|
||||
NAME: lock_proxy_file
|
||||
IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS) && SQLITE_ENABLE_LOCKING_STYLE
|
||||
|
||||
NAME: synchronous
|
||||
IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS)
|
||||
|
||||
NAME: table_info
|
||||
IF: !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
|
||||
|
||||
NAME: index_info
|
||||
IF: !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
|
||||
|
||||
NAME: index_list
|
||||
IF: !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
|
||||
|
||||
NAME: database_list
|
||||
IF: !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
|
||||
|
||||
NAME: collation_list
|
||||
IF: !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
|
||||
|
||||
NAME: foreign_key_list
|
||||
IF: !defined(SQLITE_OMIT_FOREIGN_KEY)
|
||||
|
||||
NAME: foreign_key_check
|
||||
IF: !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
|
||||
|
||||
NAME: parser_trace
|
||||
IF: defined(SQLITE_DEBUG)
|
||||
|
||||
NAME: case_sensitive_like
|
||||
|
||||
NAME: integrity_check
|
||||
IF: !defined(SQLITE_OMIT_INTEGRITY_CHECK)
|
||||
|
||||
NAME: quick_check
|
||||
TYPE: INTEGRITY_CHECK
|
||||
IF: !defined(SQLITE_OMIT_INTEGRITY_CHECK)
|
||||
|
||||
NAME: encoding
|
||||
IF: !defined(SQLITE_OMIT_UTF16)
|
||||
|
||||
NAME: schema_version
|
||||
TYPE: HEADER_VALUE
|
||||
IF: !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
|
||||
|
||||
NAME: user_version
|
||||
TYPE: HEADER_VALUE
|
||||
IF: !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
|
||||
|
||||
NAME: freelist_count
|
||||
TYPE: HEADER_VALUE
|
||||
IF: !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
|
||||
|
||||
NAME: application_id
|
||||
TYPE: HEADER_VALUE
|
||||
IF: !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
|
||||
|
||||
NAME: compile_options
|
||||
IF: !defined(SQLITE_OMIT_COMPILEOPTION_DIAGS)
|
||||
|
||||
NAME: wal_checkpoint
|
||||
IF: !defined(SQLITE_OMIT_WAL)
|
||||
|
||||
NAME: wal_autocheckpoint
|
||||
IF: !defined(SQLITE_OMIT_WAL)
|
||||
|
||||
NAME: shrink_memory
|
||||
|
||||
NAME: busy_timeout
|
||||
|
||||
NAME: lock_status
|
||||
IF: defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
|
||||
|
||||
NAME: key
|
||||
IF: defined(SQLITE_HAS_CODEC)
|
||||
|
||||
NAME: rekey
|
||||
IF: defined(SQLITE_HAS_CODEC)
|
||||
|
||||
NAME: hexkey
|
||||
IF: defined(SQLITE_HAS_CODEC)
|
||||
|
||||
NAME: activate_extensions
|
||||
IF: defined(SQLITE_HAS_CODEC) || defined(SQLITE_ENABLE_CEROD)
|
||||
|
||||
NAME: soft_heap_limit
|
||||
}
|
||||
set name {}
|
||||
set type {}
|
||||
set if {}
|
||||
set arg 0
|
||||
proc record_one {} {
|
||||
global name type if arg allbyname typebyif
|
||||
if {$name==""} return
|
||||
set allbyname($name) [list $type $arg $if]
|
||||
set name {}
|
||||
set type {}
|
||||
set if {}
|
||||
set arg 0
|
||||
}
|
||||
foreach line [split $pragma_def \n] {
|
||||
set line [string trim $line]
|
||||
if {$line==""} continue
|
||||
foreach {id val} [split $line :] break
|
||||
set val [string trim $val]
|
||||
if {$id=="NAME"} {
|
||||
record_one
|
||||
set name $val
|
||||
set type [string toupper $val]
|
||||
} elseif {$id=="TYPE"} {
|
||||
set type $val
|
||||
} elseif {$id=="ARG"} {
|
||||
set arg $val
|
||||
} elseif {$id=="IF"} {
|
||||
set if $val
|
||||
} else {
|
||||
error "bad pragma_def line: $line"
|
||||
}
|
||||
}
|
||||
record_one
|
||||
set allnames [lsort [array names allbyname]]
|
||||
|
||||
# Generate #defines for all pragma type names. Group the pragmas that are
|
||||
# omit in default builds (defined(SQLITE_DEBUG) and defined(SQLITE_HAS_CODEC))
|
||||
# at the end.
|
||||
#
|
||||
set pnum 0
|
||||
foreach name $allnames {
|
||||
set type [lindex $allbyname($name) 0]
|
||||
if {[info exists seentype($type)]} continue
|
||||
set if [lindex $allbyname($name) 2]
|
||||
if {[regexp SQLITE_DEBUG $if] || [regexp SQLITE_HAS_CODEC $if]} continue
|
||||
set seentype($type) 1
|
||||
puts [format {#define %-35s %4d} PragTyp_$type $pnum]
|
||||
incr pnum
|
||||
}
|
||||
foreach name $allnames {
|
||||
set type [lindex $allbyname($name) 0]
|
||||
if {[info exists seentype($type)]} continue
|
||||
set if [lindex $allbyname($name) 2]
|
||||
if {[regexp SQLITE_DEBUG $if]} continue
|
||||
set seentype($type) 1
|
||||
puts [format {#define %-35s %4d} PragTyp_$type $pnum]
|
||||
incr pnum
|
||||
}
|
||||
foreach name $allnames {
|
||||
set type [lindex $allbyname($name) 0]
|
||||
if {[info exists seentype($type)]} continue
|
||||
set seentype($type) 1
|
||||
puts [format {#define %-35s %4d} PragTyp_$type $pnum]
|
||||
incr pnum
|
||||
}
|
||||
|
||||
# Generate the lookup table
|
||||
#
|
||||
puts "static const struct sPragmaNames \173"
|
||||
puts " const char *const zName; /* Name of pragma */"
|
||||
puts " u8 ePragTyp; /* PragTyp_XXX value */"
|
||||
puts " u32 iArg; /* Extra argument */"
|
||||
puts "\175 aPragmaNames\[\] = \173"
|
||||
|
||||
set current_if {}
|
||||
set spacer [format { %26s } {}]
|
||||
foreach name $allnames {
|
||||
foreach {type arg if} $allbyname($name) break
|
||||
if {$if!=$current_if} {
|
||||
if {$current_if!=""} {puts "#endif"}
|
||||
set current_if $if
|
||||
if {$current_if!=""} {puts "#if $current_if"}
|
||||
}
|
||||
set namex [format %-26s \"$name\",]
|
||||
set typex [format PragTyp_%-23s $type,]
|
||||
if {[string length $arg]>10} {
|
||||
puts " \173 $namex $typex\n$spacer$arg \175,"
|
||||
} else {
|
||||
puts " \173 $namex $typex $arg \175,"
|
||||
}
|
||||
}
|
||||
if {$current_if!=""} {puts "#endif"}
|
||||
puts "\175;"
|
||||
|
||||
# count the number of pragmas, for information purposes
|
||||
#
|
||||
set allcnt 0
|
||||
set dfltcnt 0
|
||||
foreach name $allnames {
|
||||
incr allcnt
|
||||
set if [lindex $allbyname($name) 2]
|
||||
if {[regexp {^defined} $if] || [regexp {[^!]defined} $if]} continue
|
||||
incr dfltcnt
|
||||
}
|
||||
puts "/* Number of pragmas: $dfltcnt on by default, $allcnt total. */"
|
@ -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
|
||||
@ -255,18 +255,32 @@ 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 {
|
||||
fail "unsupported package flavor, must be \"WinRT\" or \"WP80\""
|
||||
fail "unsupported package flavor, must be \"WinRT\", \"WinRT81\", or \"WP80\""
|
||||
}
|
||||
|
||||
if {$argc >= 4} then {
|
||||
|
Binary file not shown.
Loading…
Reference in New Issue
Block a user