Merge all the latest trunk changes into the sessions branch.
FossilOrigin-Name: d69d21903b883067c66dbcdefe6b369a6fe328b0
This commit is contained in:
commit
b05567ed4b
@ -357,6 +357,7 @@ TESTSRC = \
|
||||
$(TOP)/src/test_config.c \
|
||||
$(TOP)/src/test_demovfs.c \
|
||||
$(TOP)/src/test_devsym.c \
|
||||
$(TOP)/src/test_fs.c \
|
||||
$(TOP)/src/test_func.c \
|
||||
$(TOP)/src/test_fuzzer.c \
|
||||
$(TOP)/src/test_hexio.c \
|
||||
|
89
manifest
89
manifest
@ -1,7 +1,7 @@
|
||||
C Enhancements\sto\sthe\squery\splanner\sto\smake\suse\sof\sindices\sfor\sORDER\sBY\seven\nwhen\sIN\sconstraints\sare\sin\sthe\sWHERE\sclause.\s\sAdd\sextended\serror\scodes\sfor\nall\sSQLITE_CONSTRAINT\serrors.
|
||||
D 2013-02-13T13:42:50.179
|
||||
C Merge\sall\sthe\slatest\strunk\schanges\sinto\sthe\ssessions\sbranch.
|
||||
D 2013-03-06T02:12:18.694
|
||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||
F Makefile.in a48faa9e7dd7d556d84f5456eabe5825dd8a6282
|
||||
F Makefile.in 9a804abbd3cae82d196e4d33aba13239e32522a5
|
||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||
F Makefile.msc 5de508f802789aae3e96d86261c5cf633d67ce00
|
||||
F Makefile.vxworks b18ad88e9a8c6a001f5cf4a389116a4f1a7ab45f
|
||||
@ -127,25 +127,25 @@ F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
|
||||
F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc
|
||||
F sqlite3.pc.in ae6f59a76e862f5c561eb32a380228a02afc3cad
|
||||
F src/alter.c f8db986c03eb0bfb221523fc9bbb9d0b70de3168
|
||||
F src/analyze.c 7553068d21e32a57fc33ab6b2393fc8c1ba41410
|
||||
F src/analyze.c d5f895810e8ff9737c9ec7b76abc3dcff5860335
|
||||
F src/attach.c ea5247f240e2c08afd608e9beb380814b86655e1
|
||||
F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34
|
||||
F src/backup.c 32e35a3a4ea55b45c0e5f74eeb793aec71491517
|
||||
F src/backup.c b2cac9f7993f3f9588827b824b1501d0c820fa68
|
||||
F src/bitvec.c 26675fe8e431dc555e6f2d0e11e651d172234aa1
|
||||
F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7
|
||||
F src/btree.c 7a80e4a67f32a2494c383a28a495bf3bd71cc230
|
||||
F src/btree.c c7ce6045f023ba6426d5cca63fab5e1e3d282309
|
||||
F src/btree.h 3ad7964d6c5b1c7bff569aab6adfa075f8bf06cd
|
||||
F src/btreeInt.h 4e5c2bd0f9b36b2a815a6d84f771a61a65830621
|
||||
F src/build.c 73ca65f32938e4e0d94e831b61b5749b211b79be
|
||||
F src/btreeInt.h eecc84f02375b2bb7a44abbcbbe3747dde73edb2
|
||||
F src/build.c 375e5df716e03b9343c5e1211be3b24e6d6dff05
|
||||
F src/callback.c d7e46f40c3cf53c43550b7da7a1d0479910b62cc
|
||||
F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
|
||||
F src/ctime.c 72a70dcfda75d3a1f81041ce4573e7afddcd8e4e
|
||||
F src/date.c 067a81c9942c497aafd2c260e13add8a7d0c7dd4
|
||||
F src/delete.c 9bc9463952bdc9fc43111b1f9c83a0af9b8e2239
|
||||
F src/expr.c f6c20285bd36e87ec47f4d840e90a32755e2a90c
|
||||
F src/expr.c a23b4aac2a455b2e76b55bef5dcfbe62b665375c
|
||||
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
|
||||
F src/fkey.c e16942bd5c8a868ac53287886464a5ed0e72b179
|
||||
F src/func.c 8147799b048065a1590805be464d05b4913e652c
|
||||
F src/func.c 91bc65eb68ef6cf29198aac92f11489fa85a8de4
|
||||
F src/global.c e59ecd2c553ad0d4bfbc84ca71231336f8993a7a
|
||||
F src/hash.c ac3470bbf1ca4ae4e306a8ecb0fdf1731810ffe4
|
||||
F src/hash.h 2894c932d84d9f892d4b4023a75e501f83050970
|
||||
@ -154,8 +154,8 @@ F src/insert.c 02f8a1867088cb654eb756f98389f10441a65216
|
||||
F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d
|
||||
F src/legacy.c a199d7683d60cef73089e892409113e69c23a99f
|
||||
F src/lempar.c cdf0a000315332fc9b50b62f3b5e22e080a0952b
|
||||
F src/loadext.c f20382fbaeec832438a1ba7797bee3d3c8a6d51d
|
||||
F src/main.c e8e33e613698f3138031c037ce9d87a0030955c1
|
||||
F src/loadext.c 1422eba4aa2b1fb5f7b3aef574752272477d21e2
|
||||
F src/main.c 40097dfb4844b9272dc45926a73cd9b01a1bd137
|
||||
F src/malloc.c fe085aa851b666b7c375c1ff957643dc20a04bf6
|
||||
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
|
||||
F src/mem1.c 437c7c4af964895d4650f29881df63535caaa1fa
|
||||
@ -172,31 +172,31 @@ F src/notify.c 976dd0f6171d4588e89e874fcc765e92914b6d30
|
||||
F src/os.c e1acdc09ff3ac2412945cca9766e2dcf4675f31c
|
||||
F src/os.h 027491c77d2404c0a678bb3fb06286f331eb9b57
|
||||
F src/os_common.h 92815ed65f805560b66166e3583470ff94478f04
|
||||
F src/os_unix.c dfdc04b126f7b05dcb2e2cc5c1262f98acbb49d9
|
||||
F src/os_win.c e988c2de4266fbb3b8c58e4b5550a2e17f541327
|
||||
F src/pager.c 4092c907222cfd451c74fe6bd2fd64b342f7190f
|
||||
F src/os_unix.c f6387eef0cf8f6b808738f4f3aa47e6132af0940
|
||||
F src/os_win.c f7da4dc0a2545c0a430080380809946ae4d676d6
|
||||
F src/pager.c 582f8da52d0bd4b43d3bdaeba0ea7702c1f23702
|
||||
F src/pager.h 1109a06578ec5574dc2c74cf8d9f69daf36fe3e0
|
||||
F src/parse.y 5d5e12772845805fdfeb889163516b84fbb9ae95
|
||||
F src/pcache.c f8043b433a57aba85384a531e3937a804432a346
|
||||
F src/pcache.h 1b5dcc3dc8103d03e625b177023ee67764fa6b7c
|
||||
F src/pcache1.c 9fd22671c270b35131ef480bbc00392b8b5f8ab9
|
||||
F src/pragma.c eb9d39e30f00e3ba51892749ddf9d7b86541c43e
|
||||
F src/pragma.c bdb484d0283965c431d4153f28c30f836a1f16b1
|
||||
F src/prepare.c 931ad0d852a0df48f79adcba6ce79ca5f475625c
|
||||
F src/printf.c 4a9f882f1c1787a8b494a2987765acf9d97ac21f
|
||||
F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50
|
||||
F src/resolve.c 652ae6dc0f185b01b4536bb2fa7d878f13f0f1df
|
||||
F src/resolve.c 9079da7d59aed2bb14ec8315bc7f720dd85b5b65
|
||||
F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0
|
||||
F src/select.c 7818b5c9b497499d8bd8c6d0e347a3cf67724867
|
||||
F src/shell.c 266791241d7add796ccce2317977ae6c3c67d77f
|
||||
F src/sqlite.h.in ebb2e60b1d92290597f8520dc55a5885c88aefc0
|
||||
F src/select.c e1c6f6abdf9f359f4e735cb8ae11d2f359bf52a9
|
||||
F src/shell.c 7c41bfcd9e5bf9d96b9215f79b03a5b2b44a3bca
|
||||
F src/sqlite.h.in 7c9b66c397025a9e93e1ec1faa03324b757a2880
|
||||
F src/sqlite3.rc fea433eb0a59f4c9393c8e6d76a6e2596b1fe0c0
|
||||
F src/sqlite3ext.h 6904f4aadf976f95241311fbffb00823075d9477
|
||||
F src/sqliteInt.h 61a59586451072ec2b3aaa209e5df87fa6e1bf75
|
||||
F src/sqlite3ext.h 7183ab832e23db0f934494f16928da127a571d75
|
||||
F src/sqliteInt.h 4b854bf7da123c2bab96664afaac8d14e6027524
|
||||
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
|
||||
F src/status.c bedc37ec1a6bb9399944024d63f4c769971955a9
|
||||
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
|
||||
F src/tclsqlite.c bc021495cad081c13ccdcebd524857aedd831e11
|
||||
F src/test1.c 50003e3beccad5569f757598fc7ce81b4f21aa7e
|
||||
F src/test1.c ff3e68eedfbd858c9b89cf03e3db233cd29be1d0
|
||||
F src/test2.c 4178056dd1e7d70f954ad8a1e3edb71a2a784daf
|
||||
F src/test3.c 3c3c2407fa6ec7a19e24ae23f7cb439d0275a60d
|
||||
F src/test4.c bf9fa9bece01de08e6f5e02314e4af5c13590dfa
|
||||
@ -228,20 +228,20 @@ F src/test_mutex.c a6bd7b9cf6e19d989e31392b06ac8d189f0d573e
|
||||
F src/test_onefile.c 0396f220561f3b4eedc450cef26d40c593c69a25
|
||||
F src/test_osinst.c 90a845c8183013d80eccb1f29e8805608516edba
|
||||
F src/test_pcache.c a5cd24730cb43c5b18629043314548c9169abb00
|
||||
F src/test_quota.c 0e0e2e3bf6766b101ecccd8c042b66e44e9be8f5
|
||||
F src/test_quota.c 1ec82e02fd3643899e9a5de9684515e84641c91f
|
||||
F src/test_quota.h 8761e463b25e75ebc078bd67d70e39b9c817a0cb
|
||||
F src/test_regexp.c 58e0349f155bc307dfa209df4b03add0a7749866
|
||||
F src/test_regexp.c 5ff0eafd66c9a209417142fa319006f7028fbda8
|
||||
F src/test_rtree.c aba603c949766c4193f1068b91c787f57274e0d9
|
||||
F src/test_schema.c 8c06ef9ddb240c7a0fcd31bc221a6a2aade58bf0
|
||||
F src/test_server.c 2f99eb2837dfa06a4aacf24af24c6affdf66a84f
|
||||
F src/test_spellfix.c 860eb723100d4e3cff846ba5d25e02815b2a5cac
|
||||
F src/test_spellfix.c 56dfa6d583ac34f61af0834d7b58d674e7e18e13
|
||||
F src/test_sqllog.c 8acb843ddb9928dea8962e31bb09f421a72ffccb
|
||||
F src/test_stat.c d1569c7a4839f13e80187e2c26b2ab4da2d03935
|
||||
F src/test_superlock.c 2b97936ca127d13962c3605dbc9a4ef269c424cd
|
||||
F src/test_syscall.c a992d8c80ea91fbf21fb2dd570db40e77dd7e6ae
|
||||
F src/test_tclvar.c f4dc67d5f780707210d6bb0eb6016a431c04c7fa
|
||||
F src/test_thread.c e286f2173563f2a1747c24bcda6b9d030bf4f4e4
|
||||
F src/test_vfs.c c6260ef238c1142c8f8bd402db02216afd182ae3
|
||||
F src/test_vfs.c fb16b2d9938cf0c1afc5a423b55b952fcc024275
|
||||
F src/test_vfstrace.c 34b544e80ba7fb77be15395a609c669df2e660a2
|
||||
F src/test_wholenumber.c 3d2b9ed1505c40ad5c5ca2ad16ae7a289d6cc251
|
||||
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
|
||||
@ -254,7 +254,7 @@ F src/vacuum.c 2727bdd08847fcb6b2d2da6d14f018910e8645d3
|
||||
F src/vdbe.c 9e4164ac85aa01e1a563e6c7f565b106ff0bf67b
|
||||
F src/vdbe.h 1223e2548e0970cf96f573ff6b99f804a36ad683
|
||||
F src/vdbeInt.h 0112cab1c820a599005c6bcc9504bdb17f5dbcdb
|
||||
F src/vdbeapi.c 58fdcd56109c05876f69c25d47a138ef370d3647
|
||||
F src/vdbeapi.c b816227ece97354aee7a741c1fc3c5445202d8bb
|
||||
F src/vdbeaux.c 684c159170453c8a118786b9c174627ece825f3a
|
||||
F src/vdbeblob.c 11248c6362389569764682eb0f59ce910f3cc381
|
||||
F src/vdbemem.c cb55e84b8e2c15704968ee05f0fae25883299b74
|
||||
@ -264,7 +264,7 @@ F src/vtab.c b05e5f1f4902461ba9f5fc49bb7eb7c3a0741a83
|
||||
F src/wal.c f5c7b5027d0ed0e9bc9afeb4a3a8dfea762ec7d2
|
||||
F src/wal.h 29c197540b19044e6cd73487017e5e47a1d3dac6
|
||||
F src/walker.c 3d75ba73de15e0f8cd0737643badbeb0e002f07b
|
||||
F src/where.c 43e05406f0e05960a62d4719ed77f551f8204d3f
|
||||
F src/where.c 8b7690cae8700b385d8a53a39387cf8054d8cc47
|
||||
F test/8_3_names.test 631ea964a3edb091cf73c3b540f6bcfdb36ce823
|
||||
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
||||
F test/aggnested.test 45c0201e28045ad38a530b5a144b73cd4aa2cfd6
|
||||
@ -520,7 +520,7 @@ F test/fts4merge2.test 5faa558d1b672f82b847d2a337465fa745e46891
|
||||
F test/fts4merge3.test aab02a09f50fe6baaddc2e159c3eabc116d45fc7
|
||||
F test/fts4unicode.test 25ccad45896f8e50f6a694cff738a35f798cdb40
|
||||
F test/full.test 6b3c8fb43c6beab6b95438c1675374b95fab245d
|
||||
F test/func.test 0d89043dab9a8853358d14c68e028ee0093bf066
|
||||
F test/func.test b058483c17952eff7797b837bbb61e27e6b05606
|
||||
F test/func2.test 772d66227e4e6684b86053302e2d74a2500e1e0f
|
||||
F test/func3.test 001021e5b88bd02a3b365a5c5fd8f6f49d39744a
|
||||
F test/fuzz-oss1.test 4912e528ec9cf2f42134456933659d371c9e0d74
|
||||
@ -546,12 +546,13 @@ F test/incrblob_err.test d2562d2771ebffd4b3af89ef64c140dd44371597
|
||||
F test/incrblobfault.test 917c0292224c64a56ef7215fd633a3a82f805be0
|
||||
F test/incrvacuum.test d2a6ddf5e429720b5fe502766af747915ccf6c32
|
||||
F test/incrvacuum2.test 379eeb8740b0ef60c372c439ad4cbea20b34bb9b
|
||||
F test/incrvacuum_ioerr.test 22f208d01c528403240e05beecc41dc98ed01637
|
||||
F test/incrvacuum3.test 2ffa9e4a23f072bd7902b9ae6471f8822a6522a7
|
||||
F test/incrvacuum_ioerr.test 293f2714571255539c8c789da2f7de4ec3f7101e
|
||||
F test/index.test b5429732b3b983fa810e3ac867d7ca85dae35097
|
||||
F test/index2.test ee83c6b5e3173a3d7137140d945d9a5d4fdfb9d6
|
||||
F test/index3.test 423a25c789fc8cc51aaf2a4370bbdde2d9e9eed7
|
||||
F test/index4.test 2983216eb8c86ee62d9ed7cb206b5cc3331c0026
|
||||
F test/index5.test edc8c64ca78bee140c21ce3836820fadf47906bb
|
||||
F test/index5.test fc07c14193c0430814e7a08b5da46888ee795c33
|
||||
F test/indexedby.test be501e381b82b2f8ab406309ba7aac46e221f4ad
|
||||
F test/indexfault.test 31d4ab9a7d2f6e9616933eb079722362a883eb1d
|
||||
F test/init.test 15c823093fdabbf7b531fe22cf037134d09587a7
|
||||
@ -639,7 +640,7 @@ F test/misc3.test fe55130a43e444ee75e2156ff75dc96e964b5738
|
||||
F test/misc4.test 9c078510fbfff05a9869a0b6d8b86a623ad2c4f6
|
||||
F test/misc5.test 528468b26d03303b1f047146e5eefc941b9069f5
|
||||
F test/misc6.test 953cc693924d88e6117aeba16f46f0bf5abede91
|
||||
F test/misc7.test f00dad9a004da659330013e6f21819d018b683d3
|
||||
F test/misc7.test dd82ec9250b89178b96cd28b2aca70639d21e5b3
|
||||
F test/misuse.test ba4fb5d1a6101d1c171ea38b3c613d0661c83054
|
||||
F test/multiplex.test e08cc7177bd6d85990ee1d71100bb6c684c02256
|
||||
F test/multiplex2.test 580ca5817c7edbe4cc68fa150609c9473393003a
|
||||
@ -657,7 +658,7 @@ F test/orderby1.test f33968647da5c546528fe4d2bf86c6a6a2e5a7ae
|
||||
F test/orderby2.test bc11009f7cd99d96b1b11e57b199b00633eb5b04
|
||||
F test/orderby3.test 8619d06a3debdcd80a27c0fdea5c40b468854b99
|
||||
F test/oserror.test 50417780d0e0d7cd23cf12a8277bb44024765df3
|
||||
F test/pager1.test 8e14e7cfd2fbfe65eabead73af10ceeb2fc676aa
|
||||
F test/pager1.test 31c04bec797dda1bde337810b52efa08d1f1f08e
|
||||
F test/pager2.test 745b911dde3d1f24ae0870bd433dfa83d7c658c1
|
||||
F test/pager3.test 3856d9c80839be0668efee1b74811b1b7f7fc95f
|
||||
F test/pagerfault.test 452f2cc23e3bfcfa935f4442aec1da4fe1dc0442
|
||||
@ -668,7 +669,7 @@ F test/pagesize.test 1dd51367e752e742f58e861e65ed7390603827a0
|
||||
F test/pcache.test 065aa286e722ab24f2e51792c1f093bf60656b16
|
||||
F test/pcache2.test a83efe2dec0d392f814bfc998def1d1833942025
|
||||
F test/permutations.test 379cfbb9a5eea2499d05008c04d18ddb4f2c01a9
|
||||
F test/pragma.test 5ce333cae37d86cfe9b3add840906e375e2272b0
|
||||
F test/pragma.test 60d29cd3d8098a2c20bf4c072810f99e3bf2757a
|
||||
F test/pragma2.test 3a55f82b954242c642f8342b17dffc8b47472947
|
||||
F test/printf.test ec9870c4dce8686a37818e0bf1aba6e6a1863552
|
||||
F test/progress.test 5b075c3c790c7b2a61419bc199db87aaf48b8301
|
||||
@ -747,7 +748,7 @@ F test/speed3.test d32043614c08c53eafdc80f33191d5bd9b920523
|
||||
F test/speed4.test abc0ad3399dcf9703abed2fff8705e4f8e416715
|
||||
F test/speed4p.explain 6b5f104ebeb34a038b2f714150f51d01143e59aa
|
||||
F test/speed4p.test 0e51908951677de5a969b723e03a27a1c45db38b
|
||||
F test/spellfix.test 2953e9da0e46dab5f83059ef6bfdebca66e13418
|
||||
F test/spellfix.test 52ae2680b1247c52b9e2b2116de3fd26a78e6bd2
|
||||
F test/sqllimits1.test b1aae27cc98eceb845e7f7adf918561256e31298
|
||||
F test/stat.test be8d477306006ec696bc86757cfb34bec79447ce
|
||||
F test/stmt.test 25d64e3dbf9a3ce89558667d7f39d966fe2a71b9
|
||||
@ -765,7 +766,7 @@ F test/tclsqlite.test a7308276aad2e6c0bfb5b0414424dd0d9cc0cad7
|
||||
F test/tempdb.test 19d0f66e2e3eeffd68661a11c83ba5e6ace9128c
|
||||
F test/temptable.test 51edd31c65ed1560dd600b1796e8325df96318e2
|
||||
F test/temptrigger.test 26670ed7a39cf2296a7f0a9e0a1d7bdb7abe936d
|
||||
F test/tester.tcl 92c630363217d4e2af8464d1acd387fadd710ab7
|
||||
F test/tester.tcl a59fdc17860da8590988352ae4ba0dadf4266e10
|
||||
F test/thread001.test 9f22fd3525a307ff42a326b6bc7b0465be1745a5
|
||||
F test/thread002.test e630504f8a06c00bf8bbe68528774dd96aeb2e58
|
||||
F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7
|
||||
@ -796,6 +797,7 @@ F test/tkt-5e10420e8d.test 904d1687b3c06d43e5b3555bbcf6802e7c0ffd84
|
||||
F test/tkt-5ee23731f.test 9db6e1d7209dc0794948b260d6f82b2b1de83a9f
|
||||
F test/tkt-752e1646fc.test ea78d88d14fe9866bdd991c634483334639e13bf
|
||||
F test/tkt-78e04e52ea.test 703e0bfb23d543edf0426a97e3bbd0ca346508ec
|
||||
F test/tkt-7a31705a7e6.test 5a7889fdb095ffbe1622413e0145de1637d421bd
|
||||
F test/tkt-7bbfb7d442.test dfa5c8097a8c353ae40705d6cddeb1f99c18b81a
|
||||
F test/tkt-80ba201079.test 105a721e6aad0ae3c5946d7615d1e4d03f6145b8
|
||||
F test/tkt-80e031a00f.test 9a154173461a4dbe2de49cda73963e04842d52f7
|
||||
@ -820,6 +822,7 @@ F test/tkt-f7b4edec.test d998a08ff2b18b7f62edce8e3044317c45efe6c7
|
||||
F test/tkt-f973c7ac31.test 1da0ed15ec2c7749fb5ce2828cd69d07153ad9f4
|
||||
F test/tkt-fa7bf5ec.test 9102dfea58aa371d78969da735f9392c57e2e035
|
||||
F test/tkt-fc62af4523.test 72825d3febdedcd5593a27989fc05accdbfc2bb4
|
||||
F test/tkt-fc7bd6358f.test 634bb4af7d661e82d6b61b80c86727bad698e08f
|
||||
F test/tkt1435.test f8c52c41de6e5ca02f1845f3a46e18e25cadac00
|
||||
F test/tkt1443.test bacc311da5c96a227bf8c167e77a30c99f8e8368
|
||||
F test/tkt1444.test a9d72f9e942708bd82dde6c707da61c489e213e9
|
||||
@ -884,7 +887,7 @@ F test/tkt3718.test 3b59dcb5c4e7754dacd91e7fd353a61492cc402a
|
||||
F test/tkt3731.test 0c5f4cbffe102d43c3b2188af91a9e36348f974b
|
||||
F test/tkt3757.test 10cd679a88675c880533083fc79ac04324525595
|
||||
F test/tkt3761.test b95ea9c98f21cf91325f18a984887e62caceab33
|
||||
F test/tkt3762.test 2a9f3b03df44ec49ec0cfa8d5da6574c2a7853df
|
||||
F test/tkt3762.test 4d439ff7abdc8d9323150269d182c37c2d514576
|
||||
F test/tkt3773.test 7bca904d2a647a6a4a291bd86d7fd7c73855b789
|
||||
F test/tkt3791.test a6624b9a80b216a26cf473607f42f3e51898c267
|
||||
F test/tkt3793.test d90ffd75c52413908d15e1c44fc2ea9c80fcc449
|
||||
@ -939,7 +942,7 @@ F test/vacuum3.test 77ecdd54592b45a0bcb133339f99f1ae0ae94d0d
|
||||
F test/vacuum4.test d3f8ecff345f166911568f397d2432c16d2867d9
|
||||
F test/varint.test ab7b110089a08b9926ed7390e7e97bdefeb74102
|
||||
F test/veryquick.test 7701bb609fe8bf6535514e8b849a309e8f00573b
|
||||
F test/view.test 977eb3fa17b44f73fc2b636172dc9136311024ce
|
||||
F test/view.test 4057630287bfa5955628fe90a13d4c225d1c7352
|
||||
F test/vtab1.test 4403f987860ebddef1ce2de6db7216421035339d
|
||||
F test/vtab2.test 7bcffc050da5c68f4f312e49e443063e2d391c0d
|
||||
F test/vtab3.test baad99fd27217f5d6db10660522e0b7192446de1
|
||||
@ -1027,7 +1030,7 @@ F tool/omittest.tcl 4665982e95a6e5c1bd806cf7bc3dea95be422d77
|
||||
F tool/opcodeDoc.awk b3a2a3d5d3075b8bd90b7afe24283efdd586659c
|
||||
F tool/restore_jrnl.tcl 6957a34f8f1f0f8285e07536225ec3b292a9024a
|
||||
F tool/rollback-test.c 9fc98427d1e23e84429d7e6d07d9094fbdec65a5
|
||||
F tool/showdb.c aca2644aa4de7c0cad5821e50bbd55397e0974b8
|
||||
F tool/showdb.c acd24ea035a3bd2ffe266f1ef8a161812c29b2f0
|
||||
F tool/showjournal.c b62cecaab86a4053d944c276bb5232e4d17ece02
|
||||
F tool/showwal.c 3f7f7da5ec0cba51b1449a75f700493377da57b5
|
||||
F tool/soak1.tcl 8d407956e1a45b485a8e072470a3e629a27037fe
|
||||
@ -1047,7 +1050,7 @@ F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381
|
||||
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
||||
F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
|
||||
F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac
|
||||
P 82d3d1ae824e1fbc7958657be79231590ec17ace 2cef8b68f0e1216cf68bb7dd45a5a9a330748070
|
||||
R e54b78fdc1653174f63d383c576bd990
|
||||
P 7e14dc734d7d941da5c3aa6612e26d93b5b929bd 7097241c1220ada318f8eda938c3e3430b94a606
|
||||
R e469c56b0b932202c050a14daa3532bb
|
||||
U drh
|
||||
Z ee3bd01f1e30ad2e6302010368aa9999
|
||||
Z a8cbf1c861240eb4a7fc756e2ad3beac
|
||||
|
@ -1 +1 @@
|
||||
7e14dc734d7d941da5c3aa6612e26d93b5b929bd
|
||||
d69d21903b883067c66dbcdefe6b369a6fe328b0
|
@ -473,7 +473,7 @@ static void analyzeOneTable(
|
||||
/* Do not gather statistics on views or virtual tables */
|
||||
return;
|
||||
}
|
||||
if( memcmp(pTab->zName, "sqlite_", 7)==0 ){
|
||||
if( sqlite3_strnicmp(pTab->zName, "sqlite_", 7)==0 ){
|
||||
/* Do not gather statistics on system tables */
|
||||
return;
|
||||
}
|
||||
@ -883,7 +883,7 @@ static int analysisLoader(void *pData, int argc, char **argv, char **NotUsed){
|
||||
if( pIndex==0 ) break;
|
||||
pIndex->aiRowEst[i] = v;
|
||||
if( *z==' ' ) z++;
|
||||
if( memcmp(z, "unordered", 10)==0 ){
|
||||
if( strcmp(z, "unordered")==0 ){
|
||||
pIndex->bUnordered = 1;
|
||||
break;
|
||||
}
|
||||
|
21
src/backup.c
21
src/backup.c
@ -462,7 +462,6 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){
|
||||
nDestTruncate = nSrcPage * (pgszSrc/pgszDest);
|
||||
}
|
||||
assert( nDestTruncate>0 );
|
||||
sqlite3PagerTruncateImage(pDestPager, nDestTruncate);
|
||||
|
||||
if( pgszSrc<pgszDest ){
|
||||
/* If the source page-size is smaller than the destination page-size,
|
||||
@ -476,6 +475,8 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){
|
||||
*/
|
||||
const i64 iSize = (i64)pgszSrc * (i64)nSrcPage;
|
||||
sqlite3_file * const pFile = sqlite3PagerFile(pDestPager);
|
||||
Pgno iPg;
|
||||
int nDstPage;
|
||||
i64 iOff;
|
||||
i64 iEnd;
|
||||
|
||||
@ -486,13 +487,26 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){
|
||||
&& iSize>=PENDING_BYTE && iSize<=PENDING_BYTE+pgszDest
|
||||
));
|
||||
|
||||
/* This call ensures that all data required to recreate the original
|
||||
/* This block ensures that all data required to recreate the original
|
||||
** database has been stored in the journal for pDestPager and the
|
||||
** journal synced to disk. So at this point we may safely modify
|
||||
** the database file in any way, knowing that if a power failure
|
||||
** occurs, the original database will be reconstructed from the
|
||||
** journal file. */
|
||||
rc = sqlite3PagerCommitPhaseOne(pDestPager, 0, 1);
|
||||
sqlite3PagerPagecount(pDestPager, &nDstPage);
|
||||
for(iPg=nDestTruncate; rc==SQLITE_OK && iPg<=(Pgno)nDstPage; iPg++){
|
||||
if( iPg!=PENDING_BYTE_PAGE(p->pDest->pBt) ){
|
||||
DbPage *pPg;
|
||||
rc = sqlite3PagerGet(pDestPager, iPg, &pPg);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3PagerWrite(pPg);
|
||||
sqlite3PagerUnref(pPg);
|
||||
}
|
||||
}
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3PagerCommitPhaseOne(pDestPager, 0, 1);
|
||||
}
|
||||
|
||||
/* Write the extra pages and truncate the database file as required */
|
||||
iEnd = MIN(PENDING_BYTE + pgszDest, iSize);
|
||||
@ -519,6 +533,7 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){
|
||||
rc = sqlite3PagerSync(pDestPager);
|
||||
}
|
||||
}else{
|
||||
sqlite3PagerTruncateImage(pDestPager, nDestTruncate);
|
||||
rc = sqlite3PagerCommitPhaseOne(pDestPager, 0, 0);
|
||||
}
|
||||
|
||||
|
253
src/btree.c
253
src/btree.c
@ -2595,6 +2595,7 @@ int sqlite3BtreeBeginTrans(Btree *p, int wrflag){
|
||||
if( p->inTrans==TRANS_WRITE || (p->inTrans==TRANS_READ && !wrflag) ){
|
||||
goto trans_begun;
|
||||
}
|
||||
assert( pBt->bDoTruncate==0 );
|
||||
|
||||
/* Write transactions are not possible on a read-only database */
|
||||
if( (pBt->btsFlags & BTS_READ_ONLY)!=0 && wrflag ){
|
||||
@ -2909,26 +2910,28 @@ static int relocatePage(
|
||||
|
||||
/* Forward declaration required by incrVacuumStep(). */
|
||||
static int allocateBtreePage(BtShared *, MemPage **, Pgno *, Pgno, u8);
|
||||
#define BTALLOC_ANY 0 /* Allocate any page */
|
||||
#define BTALLOC_EXACT 1 /* Allocate exact page if possible */
|
||||
#define BTALLOC_LE 2 /* Allocate any page <= the parameter */
|
||||
|
||||
/*
|
||||
** Perform a single step of an incremental-vacuum. If successful,
|
||||
** return SQLITE_OK. If there is no work to do (and therefore no
|
||||
** point in calling this function again), return SQLITE_DONE.
|
||||
** Perform a single step of an incremental-vacuum. If successful, return
|
||||
** SQLITE_OK. If there is no work to do (and therefore no point in
|
||||
** calling this function again), return SQLITE_DONE. Or, if an error
|
||||
** occurs, return some other error code.
|
||||
**
|
||||
** More specificly, this function attempts to re-organize the
|
||||
** database so that the last page of the file currently in use
|
||||
** is no longer in use.
|
||||
** More specificly, this function attempts to re-organize the database so
|
||||
** that the last page of the file currently in use is no longer in use.
|
||||
**
|
||||
** If the nFin parameter is non-zero, this function assumes
|
||||
** that the caller will keep calling incrVacuumStep() until
|
||||
** it returns SQLITE_DONE or an error, and that nFin is the
|
||||
** number of pages the database file will contain after this
|
||||
** process is complete. If nFin is zero, it is assumed that
|
||||
** incrVacuumStep() will be called a finite amount of times
|
||||
** which may or may not empty the freelist. A full autovacuum
|
||||
** has nFin>0. A "PRAGMA incremental_vacuum" has nFin==0.
|
||||
** Parameter nFin is the number of pages that this database would contain
|
||||
** were this function called until it returns SQLITE_DONE.
|
||||
**
|
||||
** If the bCommit parameter is non-zero, this function assumes that the
|
||||
** caller will keep calling incrVacuumStep() until it returns SQLITE_DONE
|
||||
** or an error. bCommit is passed true for an auto-vacuum-on-commmit
|
||||
** operation, or false for an incremental vacuum.
|
||||
*/
|
||||
static int incrVacuumStep(BtShared *pBt, Pgno nFin, Pgno iLastPg){
|
||||
static int incrVacuumStep(BtShared *pBt, Pgno nFin, Pgno iLastPg, int bCommit){
|
||||
Pgno nFreeList; /* Number of pages still on the free-list */
|
||||
int rc;
|
||||
|
||||
@ -2953,15 +2956,15 @@ static int incrVacuumStep(BtShared *pBt, Pgno nFin, Pgno iLastPg){
|
||||
}
|
||||
|
||||
if( eType==PTRMAP_FREEPAGE ){
|
||||
if( nFin==0 ){
|
||||
if( bCommit==0 ){
|
||||
/* Remove the page from the files free-list. This is not required
|
||||
** if nFin is non-zero. In that case, the free-list will be
|
||||
** if bCommit is non-zero. In that case, the free-list will be
|
||||
** truncated to zero after this function returns, so it doesn't
|
||||
** matter if it still contains some garbage entries.
|
||||
*/
|
||||
Pgno iFreePg;
|
||||
MemPage *pFreePg;
|
||||
rc = allocateBtreePage(pBt, &pFreePg, &iFreePg, iLastPg, 1);
|
||||
rc = allocateBtreePage(pBt, &pFreePg, &iFreePg, iLastPg, BTALLOC_EXACT);
|
||||
if( rc!=SQLITE_OK ){
|
||||
return rc;
|
||||
}
|
||||
@ -2971,34 +2974,37 @@ static int incrVacuumStep(BtShared *pBt, Pgno nFin, Pgno iLastPg){
|
||||
} else {
|
||||
Pgno iFreePg; /* Index of free page to move pLastPg to */
|
||||
MemPage *pLastPg;
|
||||
u8 eMode = BTALLOC_ANY; /* Mode parameter for allocateBtreePage() */
|
||||
Pgno iNear = 0; /* nearby parameter for allocateBtreePage() */
|
||||
|
||||
rc = btreeGetPage(pBt, iLastPg, &pLastPg, 0);
|
||||
if( rc!=SQLITE_OK ){
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* If nFin is zero, this loop runs exactly once and page pLastPg
|
||||
/* If bCommit is zero, this loop runs exactly once and page pLastPg
|
||||
** is swapped with the first free page pulled off the free list.
|
||||
**
|
||||
** On the other hand, if nFin is greater than zero, then keep
|
||||
** On the other hand, if bCommit is greater than zero, then keep
|
||||
** looping until a free-page located within the first nFin pages
|
||||
** of the file is found.
|
||||
*/
|
||||
if( bCommit==0 ){
|
||||
eMode = BTALLOC_LE;
|
||||
iNear = nFin;
|
||||
}
|
||||
do {
|
||||
MemPage *pFreePg;
|
||||
rc = allocateBtreePage(pBt, &pFreePg, &iFreePg, 0, 0);
|
||||
rc = allocateBtreePage(pBt, &pFreePg, &iFreePg, iNear, eMode);
|
||||
if( rc!=SQLITE_OK ){
|
||||
releasePage(pLastPg);
|
||||
return rc;
|
||||
}
|
||||
releasePage(pFreePg);
|
||||
}while( nFin!=0 && iFreePg>nFin );
|
||||
}while( bCommit && iFreePg>nFin );
|
||||
assert( iFreePg<iLastPg );
|
||||
|
||||
rc = sqlite3PagerWrite(pLastPg->pDbPage);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = relocatePage(pBt, pLastPg, eType, iPtrPage, iFreePg, nFin!=0);
|
||||
}
|
||||
rc = relocatePage(pBt, pLastPg, eType, iPtrPage, iFreePg, bCommit);
|
||||
releasePage(pLastPg);
|
||||
if( rc!=SQLITE_OK ){
|
||||
return rc;
|
||||
@ -3006,29 +3012,39 @@ static int incrVacuumStep(BtShared *pBt, Pgno nFin, Pgno iLastPg){
|
||||
}
|
||||
}
|
||||
|
||||
if( nFin==0 ){
|
||||
iLastPg--;
|
||||
while( iLastPg==PENDING_BYTE_PAGE(pBt)||PTRMAP_ISPAGE(pBt, iLastPg) ){
|
||||
if( PTRMAP_ISPAGE(pBt, iLastPg) ){
|
||||
MemPage *pPg;
|
||||
rc = btreeGetPage(pBt, iLastPg, &pPg, 0);
|
||||
if( rc!=SQLITE_OK ){
|
||||
return rc;
|
||||
}
|
||||
rc = sqlite3PagerWrite(pPg->pDbPage);
|
||||
releasePage(pPg);
|
||||
if( rc!=SQLITE_OK ){
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
if( bCommit==0 ){
|
||||
do {
|
||||
iLastPg--;
|
||||
}
|
||||
sqlite3PagerTruncateImage(pBt->pPager, iLastPg);
|
||||
}while( iLastPg==PENDING_BYTE_PAGE(pBt) || PTRMAP_ISPAGE(pBt, iLastPg) );
|
||||
pBt->bDoTruncate = 1;
|
||||
pBt->nPage = iLastPg;
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** The database opened by the first argument is an auto-vacuum database
|
||||
** nOrig pages in size containing nFree free pages. Return the expected
|
||||
** size of the database in pages following an auto-vacuum operation.
|
||||
*/
|
||||
static Pgno finalDbSize(BtShared *pBt, Pgno nOrig, Pgno nFree){
|
||||
int nEntry; /* Number of entries on one ptrmap page */
|
||||
Pgno nPtrmap; /* Number of PtrMap pages to be freed */
|
||||
Pgno nFin; /* Return value */
|
||||
|
||||
nEntry = pBt->usableSize/5;
|
||||
nPtrmap = (nFree-nOrig+PTRMAP_PAGENO(pBt, nOrig)+nEntry)/nEntry;
|
||||
nFin = nOrig - nFree - nPtrmap;
|
||||
if( nOrig>PENDING_BYTE_PAGE(pBt) && nFin<PENDING_BYTE_PAGE(pBt) ){
|
||||
nFin--;
|
||||
}
|
||||
while( PTRMAP_ISPAGE(pBt, nFin) || nFin==PENDING_BYTE_PAGE(pBt) ){
|
||||
nFin--;
|
||||
}
|
||||
|
||||
return nFin;
|
||||
}
|
||||
|
||||
/*
|
||||
** A write-transaction must be opened before calling this function.
|
||||
** It performs a single unit of work towards an incremental vacuum.
|
||||
@ -3046,11 +3062,21 @@ int sqlite3BtreeIncrVacuum(Btree *p){
|
||||
if( !pBt->autoVacuum ){
|
||||
rc = SQLITE_DONE;
|
||||
}else{
|
||||
invalidateAllOverflowCache(pBt);
|
||||
rc = incrVacuumStep(pBt, 0, btreePagecount(pBt));
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3PagerWrite(pBt->pPage1->pDbPage);
|
||||
put4byte(&pBt->pPage1->aData[28], pBt->nPage);
|
||||
Pgno nOrig = btreePagecount(pBt);
|
||||
Pgno nFree = get4byte(&pBt->pPage1->aData[36]);
|
||||
Pgno nFin = finalDbSize(pBt, nOrig, nFree);
|
||||
|
||||
if( nOrig<nFin ){
|
||||
rc = SQLITE_CORRUPT_BKPT;
|
||||
}else if( nFree>0 ){
|
||||
invalidateAllOverflowCache(pBt);
|
||||
rc = incrVacuumStep(pBt, nFin, nOrig, 0);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3PagerWrite(pBt->pPage1->pDbPage);
|
||||
put4byte(&pBt->pPage1->aData[28], pBt->nPage);
|
||||
}
|
||||
}else{
|
||||
rc = SQLITE_DONE;
|
||||
}
|
||||
}
|
||||
sqlite3BtreeLeave(p);
|
||||
@ -3077,9 +3103,7 @@ static int autoVacuumCommit(BtShared *pBt){
|
||||
if( !pBt->incrVacuum ){
|
||||
Pgno nFin; /* Number of pages in database after autovacuuming */
|
||||
Pgno nFree; /* Number of pages on the freelist initially */
|
||||
Pgno nPtrmap; /* Number of PtrMap pages to be freed */
|
||||
Pgno iFree; /* The next page to be freed */
|
||||
int nEntry; /* Number of entries on one ptrmap page */
|
||||
Pgno nOrig; /* Database size before freeing */
|
||||
|
||||
nOrig = btreePagecount(pBt);
|
||||
@ -3092,26 +3116,18 @@ static int autoVacuumCommit(BtShared *pBt){
|
||||
}
|
||||
|
||||
nFree = get4byte(&pBt->pPage1->aData[36]);
|
||||
nEntry = pBt->usableSize/5;
|
||||
nPtrmap = (nFree-nOrig+PTRMAP_PAGENO(pBt, nOrig)+nEntry)/nEntry;
|
||||
nFin = nOrig - nFree - nPtrmap;
|
||||
if( nOrig>PENDING_BYTE_PAGE(pBt) && nFin<PENDING_BYTE_PAGE(pBt) ){
|
||||
nFin--;
|
||||
}
|
||||
while( PTRMAP_ISPAGE(pBt, nFin) || nFin==PENDING_BYTE_PAGE(pBt) ){
|
||||
nFin--;
|
||||
}
|
||||
nFin = finalDbSize(pBt, nOrig, nFree);
|
||||
if( nFin>nOrig ) return SQLITE_CORRUPT_BKPT;
|
||||
|
||||
for(iFree=nOrig; iFree>nFin && rc==SQLITE_OK; iFree--){
|
||||
rc = incrVacuumStep(pBt, nFin, iFree);
|
||||
rc = incrVacuumStep(pBt, nFin, iFree, 1);
|
||||
}
|
||||
if( (rc==SQLITE_DONE || rc==SQLITE_OK) && nFree>0 ){
|
||||
rc = sqlite3PagerWrite(pBt->pPage1->pDbPage);
|
||||
put4byte(&pBt->pPage1->aData[32], 0);
|
||||
put4byte(&pBt->pPage1->aData[36], 0);
|
||||
put4byte(&pBt->pPage1->aData[28], nFin);
|
||||
sqlite3PagerTruncateImage(pBt->pPager, nFin);
|
||||
pBt->bDoTruncate = 1;
|
||||
pBt->nPage = nFin;
|
||||
}
|
||||
if( rc!=SQLITE_OK ){
|
||||
@ -3166,6 +3182,9 @@ int sqlite3BtreeCommitPhaseOne(Btree *p, const char *zMaster){
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
if( pBt->bDoTruncate ){
|
||||
sqlite3PagerTruncateImage(pBt->pPager, pBt->nPage);
|
||||
}
|
||||
#endif
|
||||
rc = sqlite3PagerCommitPhaseOne(pBt->pPager, zMaster, 0);
|
||||
sqlite3BtreeLeave(p);
|
||||
@ -3181,6 +3200,9 @@ static void btreeEndTransaction(Btree *p){
|
||||
BtShared *pBt = p->pBt;
|
||||
assert( sqlite3BtreeHoldsMutex(p) );
|
||||
|
||||
#ifndef SQLITE_OMIT_AUTOVACUUM
|
||||
pBt->bDoTruncate = 0;
|
||||
#endif
|
||||
btreeClearHasContent(pBt);
|
||||
if( p->inTrans>TRANS_NONE && p->db->activeVdbeCnt>1 ){
|
||||
/* If there are other active statements that belong to this database
|
||||
@ -4853,21 +4875,23 @@ int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){
|
||||
** an error. *ppPage and *pPgno are undefined in the event of an error.
|
||||
** Do not invoke sqlite3PagerUnref() on *ppPage if an error is returned.
|
||||
**
|
||||
** If the "nearby" parameter is not 0, then a (feeble) effort is made to
|
||||
** If the "nearby" parameter is not 0, then an effort is made to
|
||||
** locate a page close to the page number "nearby". This can be used in an
|
||||
** attempt to keep related pages close to each other in the database file,
|
||||
** which in turn can make database access faster.
|
||||
**
|
||||
** If the "exact" parameter is not 0, and the page-number nearby exists
|
||||
** anywhere on the free-list, then it is guarenteed to be returned. This
|
||||
** is only used by auto-vacuum databases when allocating a new table.
|
||||
** If the eMode parameter is BTALLOC_EXACT and the nearby page exists
|
||||
** anywhere on the free-list, then it is guaranteed to be returned. If
|
||||
** eMode is BTALLOC_LT then the page returned will be less than or equal
|
||||
** to nearby if any such page exists. If eMode is BTALLOC_ANY then there
|
||||
** are no restrictions on which page is returned.
|
||||
*/
|
||||
static int allocateBtreePage(
|
||||
BtShared *pBt,
|
||||
MemPage **ppPage,
|
||||
Pgno *pPgno,
|
||||
Pgno nearby,
|
||||
u8 exact
|
||||
BtShared *pBt, /* The btree */
|
||||
MemPage **ppPage, /* Store pointer to the allocated page here */
|
||||
Pgno *pPgno, /* Store the page number here */
|
||||
Pgno nearby, /* Search for a page near this one */
|
||||
u8 eMode /* BTALLOC_EXACT, BTALLOC_LT, or BTALLOC_ANY */
|
||||
){
|
||||
MemPage *pPage1;
|
||||
int rc;
|
||||
@ -4878,6 +4902,7 @@ static int allocateBtreePage(
|
||||
Pgno mxPage; /* Total size of the database file */
|
||||
|
||||
assert( sqlite3_mutex_held(pBt->mutex) );
|
||||
assert( eMode==BTALLOC_ANY || (nearby>0 && pBt->autoVacuum) );
|
||||
pPage1 = pBt->pPage1;
|
||||
mxPage = btreePagecount(pBt);
|
||||
n = get4byte(&pPage1->aData[36]);
|
||||
@ -4890,21 +4915,24 @@ static int allocateBtreePage(
|
||||
Pgno iTrunk;
|
||||
u8 searchList = 0; /* If the free-list must be searched for 'nearby' */
|
||||
|
||||
/* If the 'exact' parameter was true and a query of the pointer-map
|
||||
/* If eMode==BTALLOC_EXACT and a query of the pointer-map
|
||||
** shows that the page 'nearby' is somewhere on the free-list, then
|
||||
** the entire-list will be searched for that page.
|
||||
*/
|
||||
#ifndef SQLITE_OMIT_AUTOVACUUM
|
||||
if( exact && nearby<=mxPage ){
|
||||
u8 eType;
|
||||
assert( nearby>0 );
|
||||
assert( pBt->autoVacuum );
|
||||
rc = ptrmapGet(pBt, nearby, &eType, 0);
|
||||
if( rc ) return rc;
|
||||
if( eType==PTRMAP_FREEPAGE ){
|
||||
searchList = 1;
|
||||
if( eMode==BTALLOC_EXACT ){
|
||||
if( nearby<=mxPage ){
|
||||
u8 eType;
|
||||
assert( nearby>0 );
|
||||
assert( pBt->autoVacuum );
|
||||
rc = ptrmapGet(pBt, nearby, &eType, 0);
|
||||
if( rc ) return rc;
|
||||
if( eType==PTRMAP_FREEPAGE ){
|
||||
searchList = 1;
|
||||
}
|
||||
}
|
||||
*pPgno = nearby;
|
||||
}else if( eMode==BTALLOC_LE ){
|
||||
searchList = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -4917,7 +4945,8 @@ static int allocateBtreePage(
|
||||
|
||||
/* The code within this loop is run only once if the 'searchList' variable
|
||||
** is not true. Otherwise, it runs once for each trunk-page on the
|
||||
** free-list until the page 'nearby' is located.
|
||||
** free-list until the page 'nearby' is located (eMode==BTALLOC_EXACT)
|
||||
** or until a page less than 'nearby' is located (eMode==BTALLOC_LT)
|
||||
*/
|
||||
do {
|
||||
pPrevTrunk = pTrunk;
|
||||
@ -4959,11 +4988,13 @@ static int allocateBtreePage(
|
||||
rc = SQLITE_CORRUPT_BKPT;
|
||||
goto end_allocate_page;
|
||||
#ifndef SQLITE_OMIT_AUTOVACUUM
|
||||
}else if( searchList && nearby==iTrunk ){
|
||||
}else if( searchList
|
||||
&& (nearby==iTrunk || (iTrunk<nearby && eMode==BTALLOC_LE))
|
||||
){
|
||||
/* The list is being searched and this trunk page is the page
|
||||
** to allocate, regardless of whether it has leaves.
|
||||
*/
|
||||
assert( *pPgno==iTrunk );
|
||||
*pPgno = iTrunk;
|
||||
*ppPage = pTrunk;
|
||||
searchList = 0;
|
||||
rc = sqlite3PagerWrite(pTrunk->pDbPage);
|
||||
@ -5026,14 +5057,24 @@ static int allocateBtreePage(
|
||||
unsigned char *aData = pTrunk->aData;
|
||||
if( nearby>0 ){
|
||||
u32 i;
|
||||
int dist;
|
||||
closest = 0;
|
||||
dist = sqlite3AbsInt32(get4byte(&aData[8]) - nearby);
|
||||
for(i=1; i<k; i++){
|
||||
int d2 = sqlite3AbsInt32(get4byte(&aData[8+i*4]) - nearby);
|
||||
if( d2<dist ){
|
||||
closest = i;
|
||||
dist = d2;
|
||||
if( eMode==BTALLOC_LE ){
|
||||
for(i=0; i<k; i++){
|
||||
iPage = get4byte(&aData[8+i*4]);
|
||||
if( iPage<=nearby ){
|
||||
closest = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
int dist;
|
||||
dist = sqlite3AbsInt32(get4byte(&aData[8]) - nearby);
|
||||
for(i=1; i<k; i++){
|
||||
int d2 = sqlite3AbsInt32(get4byte(&aData[8+i*4]) - nearby);
|
||||
if( d2<dist ){
|
||||
closest = i;
|
||||
dist = d2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}else{
|
||||
@ -5047,7 +5088,9 @@ static int allocateBtreePage(
|
||||
goto end_allocate_page;
|
||||
}
|
||||
testcase( iPage==mxPage );
|
||||
if( !searchList || iPage==nearby ){
|
||||
if( !searchList
|
||||
|| (iPage==nearby || (iPage<nearby && eMode==BTALLOC_LE))
|
||||
){
|
||||
int noContent;
|
||||
*pPgno = iPage;
|
||||
TRACE(("ALLOCATE: %d was leaf %d of %d on trunk %d"
|
||||
@ -5074,8 +5117,26 @@ static int allocateBtreePage(
|
||||
pPrevTrunk = 0;
|
||||
}while( searchList );
|
||||
}else{
|
||||
/* There are no pages on the freelist, so create a new page at the
|
||||
** end of the file */
|
||||
/* There are no pages on the freelist, so append a new page to the
|
||||
** database image.
|
||||
**
|
||||
** Normally, new pages allocated by this block can be requested from the
|
||||
** pager layer with the 'no-content' flag set. This prevents the pager
|
||||
** from trying to read the pages content from disk. However, if the
|
||||
** current transaction has already run one or more incremental-vacuum
|
||||
** steps, then the page we are about to allocate may contain content
|
||||
** that is required in the event of a rollback. In this case, do
|
||||
** not set the no-content flag. This causes the pager to load and journal
|
||||
** the current page content before overwriting it.
|
||||
**
|
||||
** Note that the pager will not actually attempt to load or journal
|
||||
** content for any page that really does lie past the end of the database
|
||||
** file on disk. So the effects of disabling the no-content optimization
|
||||
** here are confined to those pages that lie between the end of the
|
||||
** database image and the end of the database file.
|
||||
*/
|
||||
int bNoContent = (0==pBt->bDoTruncate);
|
||||
|
||||
rc = sqlite3PagerWrite(pBt->pPage1->pDbPage);
|
||||
if( rc ) return rc;
|
||||
pBt->nPage++;
|
||||
@ -5090,7 +5151,7 @@ static int allocateBtreePage(
|
||||
MemPage *pPg = 0;
|
||||
TRACE(("ALLOCATE: %d from end of file (pointer-map page)\n", pBt->nPage));
|
||||
assert( pBt->nPage!=PENDING_BYTE_PAGE(pBt) );
|
||||
rc = btreeGetPage(pBt, pBt->nPage, &pPg, 1);
|
||||
rc = btreeGetPage(pBt, pBt->nPage, &pPg, bNoContent);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3PagerWrite(pPg->pDbPage);
|
||||
releasePage(pPg);
|
||||
@ -5104,7 +5165,7 @@ static int allocateBtreePage(
|
||||
*pPgno = pBt->nPage;
|
||||
|
||||
assert( *pPgno!=PENDING_BYTE_PAGE(pBt) );
|
||||
rc = btreeGetPage(pBt, *pPgno, ppPage, 1);
|
||||
rc = btreeGetPage(pBt, *pPgno, ppPage, bNoContent);
|
||||
if( rc ) return rc;
|
||||
rc = sqlite3PagerWrite((*ppPage)->pDbPage);
|
||||
if( rc!=SQLITE_OK ){
|
||||
@ -7119,7 +7180,7 @@ static int btreeCreateTable(Btree *p, int *piTable, int createTabFlags){
|
||||
** be moved to the allocated page (unless the allocated page happens
|
||||
** to reside at pgnoRoot).
|
||||
*/
|
||||
rc = allocateBtreePage(pBt, &pPageMove, &pgnoMove, pgnoRoot, 1);
|
||||
rc = allocateBtreePage(pBt, &pPageMove, &pgnoMove, pgnoRoot, BTALLOC_EXACT);
|
||||
if( rc!=SQLITE_OK ){
|
||||
return rc;
|
||||
}
|
||||
|
@ -411,6 +411,7 @@ struct BtShared {
|
||||
#ifndef SQLITE_OMIT_AUTOVACUUM
|
||||
u8 autoVacuum; /* True if auto-vacuum is enabled */
|
||||
u8 incrVacuum; /* True if incr-vacuum is enabled */
|
||||
u8 bDoTruncate; /* True to truncate db on commit */
|
||||
#endif
|
||||
u8 inTransaction; /* Transaction state */
|
||||
u8 max1bytePayload; /* Maximum first byte of cell for a 1-byte payload */
|
||||
|
@ -2594,7 +2594,7 @@ Index *sqlite3CreateIndex(
|
||||
assert( pTab!=0 );
|
||||
assert( pParse->nErr==0 );
|
||||
if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0
|
||||
&& memcmp(&pTab->zName[7],"altertab_",9)!=0 ){
|
||||
&& sqlite3StrNICmp(&pTab->zName[7],"altertab_",9)!=0 ){
|
||||
sqlite3ErrorMsg(pParse, "table %s may not be indexed", pTab->zName);
|
||||
goto exit_create_index;
|
||||
}
|
||||
|
@ -638,7 +638,7 @@ void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr){
|
||||
*/
|
||||
ynVar i;
|
||||
for(i=0; i<pParse->nzVar; i++){
|
||||
if( pParse->azVar[i] && memcmp(pParse->azVar[i],z,n+1)==0 ){
|
||||
if( pParse->azVar[i] && strcmp(pParse->azVar[i],z)==0 ){
|
||||
pExpr->iColumn = x = (ynVar)i+1;
|
||||
break;
|
||||
}
|
||||
|
53
src/func.c
53
src/func.c
@ -962,6 +962,57 @@ static void quoteFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** The unicode() function. Return the integer unicode code-point value
|
||||
** for the first character of the input string.
|
||||
*/
|
||||
static void unicodeFunc(
|
||||
sqlite3_context *context,
|
||||
int argc,
|
||||
sqlite3_value **argv
|
||||
){
|
||||
const unsigned char *z = sqlite3_value_text(argv[0]);
|
||||
(void)argc;
|
||||
if( z && z[0] ) sqlite3_result_int(context, sqlite3Utf8Read(&z));
|
||||
}
|
||||
|
||||
/*
|
||||
** The char() function takes zero or more arguments, each of which is
|
||||
** an integer. It constructs a string where each character of the string
|
||||
** is the unicode character for the corresponding integer argument.
|
||||
*/
|
||||
static void charFunc(
|
||||
sqlite3_context *context,
|
||||
int argc,
|
||||
sqlite3_value **argv
|
||||
){
|
||||
unsigned char *z, *zOut;
|
||||
int i;
|
||||
zOut = z = sqlite3_malloc( argc*4 );
|
||||
if( z==0 ){
|
||||
sqlite3_result_error_nomem(context);
|
||||
return;
|
||||
}
|
||||
for(i=0; i<argc; i++){
|
||||
sqlite3_int64 x;
|
||||
unsigned c;
|
||||
x = sqlite3_value_int64(argv[i]);
|
||||
if( x<0 || x>0x10ffff ) x = 0xfffd;
|
||||
c = (unsigned)(x & 0x1fffff);
|
||||
if( c<=0xFFFF ){
|
||||
if( c>=0xd800 && c<=0xdfff ) c = 0xfffd;
|
||||
*zOut++ = (u8)(c&0x00FF);
|
||||
*zOut++ = (u8)((c>>8)&0x00FF);
|
||||
}else{
|
||||
*zOut++ = (u8)(((c>>10)&0x003F) + (((c-0x10000)>>10)&0x00C0));
|
||||
*zOut++ = (u8)(0x00D8 + (((c-0x10000)>>18)&0x03));
|
||||
*zOut++ = (u8)(c&0x00FF);
|
||||
*zOut++ = (u8)(0x00DC + ((c>>8)&0x03));
|
||||
}
|
||||
}
|
||||
sqlite3_result_text16le(context, (char*)z, (int)(zOut-z), sqlite3_free);
|
||||
}
|
||||
|
||||
/*
|
||||
** The hex() function. Interpret the argument as a blob. Return
|
||||
** a hexadecimal rendering as text.
|
||||
@ -1589,6 +1640,8 @@ void sqlite3RegisterGlobalFunctions(void){
|
||||
FUNCTION(instr, 2, 0, 0, instrFunc ),
|
||||
FUNCTION(substr, 2, 0, 0, substrFunc ),
|
||||
FUNCTION(substr, 3, 0, 0, substrFunc ),
|
||||
FUNCTION(unicode, 1, 0, 0, unicodeFunc ),
|
||||
FUNCTION(char, -1, 0, 0, charFunc ),
|
||||
FUNCTION(abs, 1, 0, 0, absFunc ),
|
||||
#ifndef SQLITE_OMIT_FLOATING_POINT
|
||||
FUNCTION(round, 1, 0, 0, roundFunc ),
|
||||
|
@ -378,6 +378,19 @@ static const sqlite3_api_routines sqlite3Apis = {
|
||||
sqlite3_blob_reopen,
|
||||
sqlite3_vtab_config,
|
||||
sqlite3_vtab_on_conflict,
|
||||
sqlite3_close_v2,
|
||||
sqlite3_db_filename,
|
||||
sqlite3_db_readonly,
|
||||
sqlite3_db_release_memory,
|
||||
sqlite3_errstr,
|
||||
sqlite3_stmt_busy,
|
||||
sqlite3_stmt_readonly,
|
||||
sqlite3_stricmp,
|
||||
sqlite3_uri_boolean,
|
||||
sqlite3_uri_int64,
|
||||
sqlite3_uri_parameter,
|
||||
sqlite3_vsnprintf,
|
||||
sqlite3_wal_checkpoint_v2
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -1002,7 +1002,7 @@ void sqlite3RollbackAll(sqlite3 *db, int tripCode){
|
||||
sqlite3VtabRollback(db);
|
||||
sqlite3EndBenignMalloc();
|
||||
|
||||
if( db->flags&SQLITE_InternChanges ){
|
||||
if( (db->flags&SQLITE_InternChanges)!=0 && db->init.busy==0 ){
|
||||
sqlite3ExpirePreparedStatements(db);
|
||||
sqlite3ResetAllSchemasOfConnection(db);
|
||||
}
|
||||
|
@ -552,7 +552,10 @@ static int robust_open(const char *z, int f, mode_t m){
|
||||
if( fd>=0 ){
|
||||
if( m!=0 ){
|
||||
struct stat statbuf;
|
||||
if( osFstat(fd, &statbuf)==0 && (statbuf.st_mode&0777)!=m ){
|
||||
if( osFstat(fd, &statbuf)==0
|
||||
&& statbuf.st_size==0
|
||||
&& (statbuf.st_mode&0777)!=m
|
||||
){
|
||||
osFchmod(fd, m);
|
||||
}
|
||||
}
|
||||
@ -4752,7 +4755,7 @@ static int fillInUnixFile(
|
||||
"psow", SQLITE_POWERSAFE_OVERWRITE) ){
|
||||
pNew->ctrlFlags |= UNIXFILE_PSOW;
|
||||
}
|
||||
if( memcmp(pVfs->zName,"unix-excl",10)==0 ){
|
||||
if( strcmp(pVfs->zName,"unix-excl")==0 ){
|
||||
pNew->ctrlFlags |= UNIXFILE_EXCL;
|
||||
}
|
||||
|
||||
|
79
src/os_win.c
79
src/os_win.c
@ -1838,7 +1838,8 @@ static BOOL winceLockFile(
|
||||
}
|
||||
|
||||
/* Want a pending lock? */
|
||||
else if (dwFileOffsetLow == (DWORD)PENDING_BYTE && nNumberOfBytesToLockLow == 1){
|
||||
else if (dwFileOffsetLow == (DWORD)PENDING_BYTE
|
||||
&& nNumberOfBytesToLockLow == 1){
|
||||
/* If no pending lock has been acquired, then acquire it */
|
||||
if (pFile->shared->bPending == 0) {
|
||||
pFile->shared->bPending = TRUE;
|
||||
@ -1848,7 +1849,8 @@ static BOOL winceLockFile(
|
||||
}
|
||||
|
||||
/* Want a reserved lock? */
|
||||
else if (dwFileOffsetLow == (DWORD)RESERVED_BYTE && nNumberOfBytesToLockLow == 1){
|
||||
else if (dwFileOffsetLow == (DWORD)RESERVED_BYTE
|
||||
&& nNumberOfBytesToLockLow == 1){
|
||||
if (pFile->shared->bReserved == 0) {
|
||||
pFile->shared->bReserved = TRUE;
|
||||
pFile->local.bReserved = TRUE;
|
||||
@ -1891,7 +1893,8 @@ static BOOL winceUnlockFile(
|
||||
|
||||
/* Did we just have a reader lock? */
|
||||
else if (pFile->local.nReaders){
|
||||
assert(nNumberOfBytesToUnlockLow == (DWORD)SHARED_SIZE || nNumberOfBytesToUnlockLow == 1);
|
||||
assert(nNumberOfBytesToUnlockLow == (DWORD)SHARED_SIZE
|
||||
|| nNumberOfBytesToUnlockLow == 1);
|
||||
pFile->local.nReaders --;
|
||||
if (pFile->local.nReaders == 0)
|
||||
{
|
||||
@ -1902,7 +1905,8 @@ static BOOL winceUnlockFile(
|
||||
}
|
||||
|
||||
/* Releasing a pending lock */
|
||||
else if (dwFileOffsetLow == (DWORD)PENDING_BYTE && nNumberOfBytesToUnlockLow == 1){
|
||||
else if (dwFileOffsetLow == (DWORD)PENDING_BYTE
|
||||
&& nNumberOfBytesToUnlockLow == 1){
|
||||
if (pFile->local.bPending){
|
||||
pFile->local.bPending = FALSE;
|
||||
pFile->shared->bPending = FALSE;
|
||||
@ -1910,7 +1914,8 @@ static BOOL winceUnlockFile(
|
||||
}
|
||||
}
|
||||
/* Releasing a reserved lock */
|
||||
else if (dwFileOffsetLow == (DWORD)RESERVED_BYTE && nNumberOfBytesToUnlockLow == 1){
|
||||
else if (dwFileOffsetLow == (DWORD)RESERVED_BYTE
|
||||
&& nNumberOfBytesToUnlockLow == 1){
|
||||
if (pFile->local.bReserved) {
|
||||
pFile->local.bReserved = FALSE;
|
||||
pFile->shared->bReserved = FALSE;
|
||||
@ -2076,6 +2081,7 @@ static int winClose(sqlite3_file *id){
|
||||
assert( pFile->pShm==0 );
|
||||
#endif
|
||||
OSTRACE(("CLOSE %d\n", pFile->h));
|
||||
assert( pFile->h!=NULL && pFile->h!=INVALID_HANDLE_VALUE );
|
||||
do{
|
||||
rc = osCloseHandle(pFile->h);
|
||||
/* SimulateIOError( rc=0; cnt=MX_CLOSE_ATTEMPT; ); */
|
||||
@ -2992,7 +2998,7 @@ static void winShmPurge(sqlite3_vfs *pVfs, int deleteFlag){
|
||||
(int)osGetCurrentProcessId(), i,
|
||||
bRc ? "ok" : "failed"));
|
||||
}
|
||||
if( p->hFile.h != INVALID_HANDLE_VALUE ){
|
||||
if( p->hFile.h!=NULL && p->hFile.h!=INVALID_HANDLE_VALUE ){
|
||||
SimulateIOErrorBenign(1);
|
||||
winClose((sqlite3_file *)&p->hFile);
|
||||
SimulateIOErrorBenign(0);
|
||||
@ -3072,7 +3078,7 @@ static int winOpenSharedMemory(winFile *pDbFd){
|
||||
rc = winOpen(pDbFd->pVfs,
|
||||
pShmNode->zFilename, /* Name of the file (UTF-8) */
|
||||
(sqlite3_file*)&pShmNode->hFile, /* File handle here */
|
||||
SQLITE_OPEN_WAL | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, /* Mode flags */
|
||||
SQLITE_OPEN_WAL | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
|
||||
0);
|
||||
if( SQLITE_OK!=rc ){
|
||||
goto shm_open_err;
|
||||
@ -3687,8 +3693,9 @@ static int winOpen(
|
||||
|| eType==SQLITE_OPEN_TRANSIENT_DB || eType==SQLITE_OPEN_WAL
|
||||
);
|
||||
|
||||
assert( id!=0 );
|
||||
UNUSED_PARAMETER(pVfs);
|
||||
assert( pFile!=0 );
|
||||
memset(pFile, 0, sizeof(winFile));
|
||||
pFile->h = INVALID_HANDLE_VALUE;
|
||||
|
||||
#if SQLITE_OS_WINRT
|
||||
if( !sqlite3_temp_directory ){
|
||||
@ -3697,8 +3704,6 @@ static int winOpen(
|
||||
}
|
||||
#endif
|
||||
|
||||
pFile->h = INVALID_HANDLE_VALUE;
|
||||
|
||||
/* If the second argument to this function is NULL, generate a
|
||||
** temporary file name to use
|
||||
*/
|
||||
@ -3827,7 +3832,9 @@ static int winOpen(
|
||||
sqlite3_free(zConverted);
|
||||
if( isReadWrite && !isExclusive ){
|
||||
return winOpen(pVfs, zName, id,
|
||||
((flags|SQLITE_OPEN_READONLY)&~(SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE)), pOutFlags);
|
||||
((flags|SQLITE_OPEN_READONLY) &
|
||||
~(SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE)),
|
||||
pOutFlags);
|
||||
}else{
|
||||
return SQLITE_CANTOPEN_BKPT;
|
||||
}
|
||||
@ -3841,19 +3848,6 @@ static int winOpen(
|
||||
}
|
||||
}
|
||||
|
||||
memset(pFile, 0, sizeof(*pFile));
|
||||
pFile->pMethod = &winIoMethod;
|
||||
pFile->h = h;
|
||||
pFile->lastErrno = NO_ERROR;
|
||||
pFile->pVfs = pVfs;
|
||||
#ifndef SQLITE_OMIT_WAL
|
||||
pFile->pShm = 0;
|
||||
#endif
|
||||
pFile->zPath = zName;
|
||||
if( sqlite3_uri_boolean(zName, "psow", SQLITE_POWERSAFE_OVERWRITE) ){
|
||||
pFile->ctrlFlags |= WINFILE_PSOW;
|
||||
}
|
||||
|
||||
#if SQLITE_OS_WINCE
|
||||
if( isReadWrite && eType==SQLITE_OPEN_MAIN_DB
|
||||
&& (rc = winceCreateLock(zName, pFile))!=SQLITE_OK
|
||||
@ -3870,6 +3864,15 @@ static int winOpen(
|
||||
sqlite3_free(zConverted);
|
||||
}
|
||||
|
||||
pFile->pMethod = &winIoMethod;
|
||||
pFile->pVfs = pVfs;
|
||||
pFile->h = h;
|
||||
if( sqlite3_uri_boolean(zName, "psow", SQLITE_POWERSAFE_OVERWRITE) ){
|
||||
pFile->ctrlFlags |= WINFILE_PSOW;
|
||||
}
|
||||
pFile->lastErrno = NO_ERROR;
|
||||
pFile->zPath = zName;
|
||||
|
||||
OpenCounter(+1);
|
||||
return rc;
|
||||
}
|
||||
@ -3914,7 +3917,8 @@ static int winDelete(
|
||||
attr = sAttrData.dwFileAttributes;
|
||||
}else{
|
||||
lastErrno = osGetLastError();
|
||||
if( lastErrno==ERROR_FILE_NOT_FOUND || lastErrno==ERROR_PATH_NOT_FOUND ){
|
||||
if( lastErrno==ERROR_FILE_NOT_FOUND
|
||||
|| lastErrno==ERROR_PATH_NOT_FOUND ){
|
||||
rc = SQLITE_IOERR_DELETE_NOENT; /* Already gone? */
|
||||
}else{
|
||||
rc = SQLITE_ERROR;
|
||||
@ -3926,7 +3930,8 @@ static int winDelete(
|
||||
#endif
|
||||
if ( attr==INVALID_FILE_ATTRIBUTES ){
|
||||
lastErrno = osGetLastError();
|
||||
if( lastErrno==ERROR_FILE_NOT_FOUND || lastErrno==ERROR_PATH_NOT_FOUND ){
|
||||
if( lastErrno==ERROR_FILE_NOT_FOUND
|
||||
|| lastErrno==ERROR_PATH_NOT_FOUND ){
|
||||
rc = SQLITE_IOERR_DELETE_NOENT; /* Already gone? */
|
||||
}else{
|
||||
rc = SQLITE_ERROR;
|
||||
@ -3953,7 +3958,8 @@ static int winDelete(
|
||||
attr = osGetFileAttributesA(zConverted);
|
||||
if ( attr==INVALID_FILE_ATTRIBUTES ){
|
||||
lastErrno = osGetLastError();
|
||||
if( lastErrno==ERROR_FILE_NOT_FOUND || lastErrno==ERROR_PATH_NOT_FOUND ){
|
||||
if( lastErrno==ERROR_FILE_NOT_FOUND
|
||||
|| lastErrno==ERROR_PATH_NOT_FOUND ){
|
||||
rc = SQLITE_IOERR_DELETE_NOENT; /* Already gone? */
|
||||
}else{
|
||||
rc = SQLITE_ERROR;
|
||||
@ -4121,16 +4127,12 @@ static int winFullPathname(
|
||||
*/
|
||||
char zOut[MAX_PATH+1];
|
||||
memset(zOut, 0, MAX_PATH+1);
|
||||
cygwin_conv_to_win32_path(zRelative, zOut); /* POSIX to Win32 */
|
||||
cygwin_conv_path(CCP_POSIX_TO_WIN_A|CCP_RELATIVE, zRelative, zOut,
|
||||
MAX_PATH+1);
|
||||
sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s\\%s",
|
||||
sqlite3_data_directory, zOut);
|
||||
}else{
|
||||
/*
|
||||
** NOTE: The Cygwin docs state that the maximum length needed
|
||||
** for the buffer passed to cygwin_conv_to_full_win32_path
|
||||
** is MAX_PATH.
|
||||
*/
|
||||
cygwin_conv_to_full_win32_path(zRelative, zFull);
|
||||
cygwin_conv_path(CCP_POSIX_TO_WIN_A, zRelative, zFull, nFull);
|
||||
}
|
||||
return SQLITE_OK;
|
||||
#endif
|
||||
@ -4288,9 +4290,9 @@ static void winDlError(sqlite3_vfs *pVfs, int nBuf, char *zBufOut){
|
||||
UNUSED_PARAMETER(pVfs);
|
||||
getLastErrorMsg(osGetLastError(), nBuf, zBufOut);
|
||||
}
|
||||
static void (*winDlSym(sqlite3_vfs *pVfs, void *pHandle, const char *zSymbol))(void){
|
||||
static void (*winDlSym(sqlite3_vfs *pVfs,void *pH,const char *zSym))(void){
|
||||
UNUSED_PARAMETER(pVfs);
|
||||
return (void(*)(void))osGetProcAddressA((HANDLE)pHandle, zSymbol);
|
||||
return (void(*)(void))osGetProcAddressA((HANDLE)pH, zSym);
|
||||
}
|
||||
static void winDlClose(sqlite3_vfs *pVfs, void *pHandle){
|
||||
UNUSED_PARAMETER(pVfs);
|
||||
@ -4388,7 +4390,8 @@ static int winCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *piNow){
|
||||
#endif
|
||||
/* 2^32 - to avoid use of LL and warnings in gcc */
|
||||
static const sqlite3_int64 max32BitValue =
|
||||
(sqlite3_int64)2000000000 + (sqlite3_int64)2000000000 + (sqlite3_int64)294967296;
|
||||
(sqlite3_int64)2000000000 + (sqlite3_int64)2000000000 +
|
||||
(sqlite3_int64)294967296;
|
||||
|
||||
#if SQLITE_OS_WINCE
|
||||
SYSTEMTIME time;
|
||||
|
91
src/pager.c
91
src/pager.c
@ -1838,6 +1838,8 @@ static int pager_error(Pager *pPager, int rc){
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int pager_truncate(Pager *pPager, Pgno nPage);
|
||||
|
||||
/*
|
||||
** This routine ends a transaction. A transaction is usually ended by
|
||||
** either a COMMIT or a ROLLBACK operation. This routine may be called
|
||||
@ -1891,7 +1893,7 @@ static int pager_error(Pager *pPager, int rc){
|
||||
** to the first error encountered (the journal finalization one) is
|
||||
** returned.
|
||||
*/
|
||||
static int pager_end_transaction(Pager *pPager, int hasMaster){
|
||||
static int pager_end_transaction(Pager *pPager, int hasMaster, int bCommit){
|
||||
int rc = SQLITE_OK; /* Error code from journal finalization operation */
|
||||
int rc2 = SQLITE_OK; /* Error code from db file unlock operation */
|
||||
|
||||
@ -1977,7 +1979,17 @@ static int pager_end_transaction(Pager *pPager, int hasMaster){
|
||||
*/
|
||||
rc2 = sqlite3WalEndWriteTransaction(pPager->pWal);
|
||||
assert( rc2==SQLITE_OK );
|
||||
}else if( rc==SQLITE_OK && bCommit && pPager->dbFileSize>pPager->dbSize ){
|
||||
/* This branch is taken when committing a transaction in rollback-journal
|
||||
** mode if the database file on disk is larger than the database image.
|
||||
** At this point the journal has been finalized and the transaction
|
||||
** successfully committed, but the EXCLUSIVE lock is still held on the
|
||||
** file. So it is safe to truncate the database file to its minimum
|
||||
** required size. */
|
||||
assert( pPager->eLock==EXCLUSIVE_LOCK );
|
||||
rc = pager_truncate(pPager, pPager->dbSize);
|
||||
}
|
||||
|
||||
if( !pPager->exclusiveMode
|
||||
&& (!pagerUseWal(pPager) || sqlite3WalExclusiveMode(pPager->pWal, 0))
|
||||
){
|
||||
@ -2016,7 +2028,7 @@ static void pagerUnlockAndRollback(Pager *pPager){
|
||||
sqlite3EndBenignMalloc();
|
||||
}else if( !pPager->exclusiveMode ){
|
||||
assert( pPager->eState==PAGER_READER );
|
||||
pager_end_transaction(pPager, 0);
|
||||
pager_end_transaction(pPager, 0, 0);
|
||||
}
|
||||
}
|
||||
pager_unlock(pPager);
|
||||
@ -2791,7 +2803,7 @@ end_playback:
|
||||
rc = sqlite3PagerSync(pPager);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = pager_end_transaction(pPager, zMaster[0]!='\0');
|
||||
rc = pager_end_transaction(pPager, zMaster[0]!='\0', 0);
|
||||
testcase( rc!=SQLITE_OK );
|
||||
}
|
||||
if( rc==SQLITE_OK && zMaster[0] && res ){
|
||||
@ -3743,12 +3755,26 @@ static void assertTruncateConstraint(Pager *pPager){
|
||||
** function does not actually modify the database file on disk. It
|
||||
** just sets the internal state of the pager object so that the
|
||||
** truncation will be done when the current transaction is committed.
|
||||
**
|
||||
** This function is only called right before committing a transaction.
|
||||
** Once this function has been called, the transaction must either be
|
||||
** rolled back or committed. It is not safe to call this function and
|
||||
** then continue writing to the database.
|
||||
*/
|
||||
void sqlite3PagerTruncateImage(Pager *pPager, Pgno nPage){
|
||||
assert( pPager->dbSize>=nPage );
|
||||
assert( pPager->eState>=PAGER_WRITER_CACHEMOD );
|
||||
pPager->dbSize = nPage;
|
||||
assertTruncateConstraint(pPager);
|
||||
|
||||
/* At one point the code here called assertTruncateConstraint() to
|
||||
** ensure that all pages being truncated away by this operation are,
|
||||
** if one or more savepoints are open, present in the savepoint
|
||||
** journal so that they can be restored if the savepoint is rolled
|
||||
** back. This is no longer necessary as this function is now only
|
||||
** called right before committing a transaction. So although the
|
||||
** Pager object may still have open savepoints (Pager.nSavepoint!=0),
|
||||
** they cannot be rolled back. So the assertTruncateConstraint() call
|
||||
** is no longer correct. */
|
||||
}
|
||||
|
||||
|
||||
@ -4801,6 +4827,11 @@ int sqlite3PagerSharedLock(Pager *pPager){
|
||||
goto failed;
|
||||
}
|
||||
if( bHotJournal ){
|
||||
if( pPager->readOnly ){
|
||||
rc = SQLITE_READONLY_ROLLBACK;
|
||||
goto failed;
|
||||
}
|
||||
|
||||
/* Get an EXCLUSIVE lock on the database file. At this point it is
|
||||
** important that a RESERVED lock is not obtained on the way to the
|
||||
** EXCLUSIVE lock. If it were, another process might open the
|
||||
@ -5885,36 +5916,6 @@ int sqlite3PagerCommitPhaseOne(
|
||||
#endif
|
||||
if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
|
||||
|
||||
/* If this transaction has made the database smaller, then all pages
|
||||
** being discarded by the truncation must be written to the journal
|
||||
** file.
|
||||
**
|
||||
** Before reading the pages with page numbers larger than the
|
||||
** current value of Pager.dbSize, set dbSize back to the value
|
||||
** that it took at the start of the transaction. Otherwise, the
|
||||
** calls to sqlite3PagerGet() return zeroed pages instead of
|
||||
** reading data from the database file.
|
||||
*/
|
||||
if( pPager->dbSize<pPager->dbOrigSize
|
||||
&& pPager->journalMode!=PAGER_JOURNALMODE_OFF
|
||||
){
|
||||
Pgno i; /* Iterator variable */
|
||||
const Pgno iSkip = PAGER_MJ_PGNO(pPager); /* Pending lock page */
|
||||
const Pgno dbSize = pPager->dbSize; /* Database image size */
|
||||
pPager->dbSize = pPager->dbOrigSize;
|
||||
for( i=dbSize+1; i<=pPager->dbOrigSize; i++ ){
|
||||
if( !sqlite3BitvecTest(pPager->pInJournal, i) && i!=iSkip ){
|
||||
PgHdr *pPage; /* Page to journal */
|
||||
rc = sqlite3PagerGet(pPager, i, &pPage);
|
||||
if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
|
||||
rc = sqlite3PagerWrite(pPage);
|
||||
sqlite3PagerUnref(pPage);
|
||||
if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
|
||||
}
|
||||
}
|
||||
pPager->dbSize = dbSize;
|
||||
}
|
||||
|
||||
/* Write the master journal name into the journal file. If a master
|
||||
** journal file name has already been written to the journal file,
|
||||
** or if zMaster is NULL (no master journal), then this call is a no-op.
|
||||
@ -5942,11 +5943,14 @@ int sqlite3PagerCommitPhaseOne(
|
||||
goto commit_phase_one_exit;
|
||||
}
|
||||
sqlite3PcacheCleanAll(pPager->pPCache);
|
||||
|
||||
/* If the file on disk is not the same size as the database image,
|
||||
** then use pager_truncate to grow or shrink the file here.
|
||||
*/
|
||||
if( pPager->dbSize!=pPager->dbFileSize ){
|
||||
|
||||
/* If the file on disk is smaller than the database image, use
|
||||
** pager_truncate to grow the file here. This can happen if the database
|
||||
** image was extended as part of the current transaction and then the
|
||||
** last page in the db image moved to the free-list. In this case the
|
||||
** last page is never written out to disk, leaving the database file
|
||||
** undersized. Fix this now if it is the case. */
|
||||
if( pPager->dbSize>pPager->dbFileSize ){
|
||||
Pgno nNew = pPager->dbSize - (pPager->dbSize==PAGER_MJ_PGNO(pPager));
|
||||
assert( pPager->eState==PAGER_WRITER_DBMOD );
|
||||
rc = pager_truncate(pPager, nNew);
|
||||
@ -6019,7 +6023,7 @@ int sqlite3PagerCommitPhaseTwo(Pager *pPager){
|
||||
}
|
||||
|
||||
PAGERTRACE(("COMMIT %d\n", PAGERID(pPager)));
|
||||
rc = pager_end_transaction(pPager, pPager->setMaster);
|
||||
rc = pager_end_transaction(pPager, pPager->setMaster, 1);
|
||||
return pager_error(pPager, rc);
|
||||
}
|
||||
|
||||
@ -6064,11 +6068,11 @@ int sqlite3PagerRollback(Pager *pPager){
|
||||
if( pagerUseWal(pPager) ){
|
||||
int rc2;
|
||||
rc = sqlite3PagerSavepoint(pPager, SAVEPOINT_ROLLBACK, -1);
|
||||
rc2 = pager_end_transaction(pPager, pPager->setMaster);
|
||||
rc2 = pager_end_transaction(pPager, pPager->setMaster, 0);
|
||||
if( rc==SQLITE_OK ) rc = rc2;
|
||||
}else if( !isOpen(pPager->jfd) || pPager->eState==PAGER_WRITER_LOCKED ){
|
||||
int eState = pPager->eState;
|
||||
rc = pager_end_transaction(pPager, 0);
|
||||
rc = pager_end_transaction(pPager, 0, 0);
|
||||
if( !MEMDB && eState>PAGER_WRITER_LOCKED ){
|
||||
/* This can happen using journal_mode=off. Move the pager to the error
|
||||
** state to indicate that the contents of the cache may not be trusted.
|
||||
@ -6466,7 +6470,8 @@ int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, int isCommit){
|
||||
*/
|
||||
if( (pPg->flags&PGHDR_NEED_SYNC) && !isCommit ){
|
||||
needSyncPgno = pPg->pgno;
|
||||
assert( pageInJournal(pPg) || pPg->pgno>pPager->dbOrigSize );
|
||||
assert( pPager->journalMode==PAGER_JOURNALMODE_OFF ||
|
||||
pageInJournal(pPg) || pPg->pgno>pPager->dbOrigSize );
|
||||
assert( pPg->flags&PGHDR_DIRTY );
|
||||
}
|
||||
|
||||
|
@ -958,6 +958,7 @@ void sqlite3Pragma(
|
||||
for(pPk=pTab->pIndex; pPk && pPk->autoIndex!=2; pPk=pPk->pNext){}
|
||||
sqlite3VdbeSetNumCols(v, 6);
|
||||
pParse->nMem = 6;
|
||||
sqlite3CodeVerifySchema(pParse, iDb);
|
||||
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "cid", SQLITE_STATIC);
|
||||
sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE_STATIC);
|
||||
sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "type", SQLITE_STATIC);
|
||||
@ -1003,6 +1004,7 @@ void sqlite3Pragma(
|
||||
pTab = pIdx->pTable;
|
||||
sqlite3VdbeSetNumCols(v, 3);
|
||||
pParse->nMem = 3;
|
||||
sqlite3CodeVerifySchema(pParse, iDb);
|
||||
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seqno", SQLITE_STATIC);
|
||||
sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "cid", SQLITE_STATIC);
|
||||
sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "name", SQLITE_STATIC);
|
||||
@ -1029,6 +1031,7 @@ void sqlite3Pragma(
|
||||
int i = 0;
|
||||
sqlite3VdbeSetNumCols(v, 3);
|
||||
pParse->nMem = 3;
|
||||
sqlite3CodeVerifySchema(pParse, iDb);
|
||||
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", SQLITE_STATIC);
|
||||
sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE_STATIC);
|
||||
sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "unique", SQLITE_STATIC);
|
||||
@ -1092,6 +1095,7 @@ void sqlite3Pragma(
|
||||
int i = 0;
|
||||
sqlite3VdbeSetNumCols(v, 8);
|
||||
pParse->nMem = 8;
|
||||
sqlite3CodeVerifySchema(pParse, iDb);
|
||||
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "id", SQLITE_STATIC);
|
||||
sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "seq", SQLITE_STATIC);
|
||||
sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "table", SQLITE_STATIC);
|
||||
|
@ -165,12 +165,12 @@ int sqlite3MatchSpanName(
|
||||
){
|
||||
int n;
|
||||
for(n=0; ALWAYS(zSpan[n]) && zSpan[n]!='.'; n++){}
|
||||
if( zDb && sqlite3StrNICmp(zSpan, zDb, n)!=0 ){
|
||||
if( zDb && (sqlite3StrNICmp(zSpan, zDb, n)!=0 || zDb[n]!=0) ){
|
||||
return 0;
|
||||
}
|
||||
zSpan += n+1;
|
||||
for(n=0; ALWAYS(zSpan[n]) && zSpan[n]!='.'; n++){}
|
||||
if( zTab && sqlite3StrNICmp(zSpan, zTab, n)!=0 ){
|
||||
if( zTab && (sqlite3StrNICmp(zSpan, zTab, n)!=0 || zTab[n]!=0) ){
|
||||
return 0;
|
||||
}
|
||||
zSpan += n+1;
|
||||
|
@ -2366,7 +2366,8 @@ static int multiSelectOrderBy(
|
||||
}else{
|
||||
int nExpr = p->pEList->nExpr;
|
||||
assert( nOrderBy>=nExpr || db->mallocFailed );
|
||||
regPrev = sqlite3GetTempRange(pParse, nExpr+1);
|
||||
regPrev = pParse->nMem+1;
|
||||
pParse->nMem += nExpr+1;
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, 0, regPrev);
|
||||
pKeyDup = sqlite3DbMallocZero(db,
|
||||
sizeof(*pKeyDup) + nExpr*(sizeof(CollSeq*)+1) );
|
||||
@ -2548,12 +2549,6 @@ static int multiSelectOrderBy(
|
||||
sqlite3VdbeChangeP5(v, OPFLAG_PERMUTE);
|
||||
sqlite3VdbeAddOp3(v, OP_Jump, addrAltB, addrAeqB, addrAgtB);
|
||||
|
||||
/* Release temporary registers
|
||||
*/
|
||||
if( regPrev ){
|
||||
sqlite3ReleaseTempRange(pParse, regPrev, nOrderBy+1);
|
||||
}
|
||||
|
||||
/* Jump to the this point in order to terminate the query.
|
||||
*/
|
||||
sqlite3VdbeResolveLabel(v, labelEnd);
|
||||
|
@ -90,7 +90,8 @@ static int enableTimer = 0;
|
||||
#define IsDigit(X) isdigit((unsigned char)X)
|
||||
#define ToLower(X) (char)tolower((unsigned char)X)
|
||||
|
||||
#if !defined(_WIN32) && !defined(WIN32) && !defined(_WRS_KERNEL)
|
||||
#if !defined(_WIN32) && !defined(WIN32) && !defined(_WRS_KERNEL) \
|
||||
&& !defined(__minux)
|
||||
#include <sys/time.h>
|
||||
#include <sys/resource.h>
|
||||
|
||||
|
@ -478,6 +478,7 @@ int sqlite3_exec(
|
||||
#define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8))
|
||||
#define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8))
|
||||
#define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8))
|
||||
#define SQLITE_READONLY_ROLLBACK (SQLITE_READONLY | (3<<8))
|
||||
#define SQLITE_ABORT_ROLLBACK (SQLITE_ABORT | (2<<8))
|
||||
#define SQLITE_CONSTRAINT_CHECK (SQLITE_CONSTRAINT | (1<<8))
|
||||
#define SQLITE_CONSTRAINT_COMMITHOOK (SQLITE_CONSTRAINT | (2<<8))
|
||||
|
@ -236,6 +236,20 @@ struct sqlite3_api_routines {
|
||||
int (*blob_reopen)(sqlite3_blob*,sqlite3_int64);
|
||||
int (*vtab_config)(sqlite3*,int op,...);
|
||||
int (*vtab_on_conflict)(sqlite3*);
|
||||
/* Version 3.7.16 and later */
|
||||
int (*close_v2)(sqlite3*);
|
||||
const char *(*db_filename)(sqlite3*,const char*);
|
||||
int (*db_readonly)(sqlite3*,const char*);
|
||||
int (*db_release_memory)(sqlite3*);
|
||||
const char *(*errstr)(int);
|
||||
int (*stmt_busy)(sqlite3_stmt*);
|
||||
int (*stmt_readonly)(sqlite3_stmt*);
|
||||
int (*stricmp)(const char*,const char*);
|
||||
int (*uri_boolean)(const char*,const char*,int);
|
||||
sqlite3_int64 (*uri_int64)(const char*,const char*,sqlite3_int64);
|
||||
const char *(*uri_parameter)(const char*,const char*);
|
||||
char *(*vsnprintf)(int,char*,const char*,va_list);
|
||||
int (*wal_checkpoint_v2)(sqlite3*,const char*,int,int*,int*);
|
||||
};
|
||||
|
||||
/*
|
||||
@ -439,6 +453,20 @@ struct sqlite3_api_routines {
|
||||
#define sqlite3_blob_reopen sqlite3_api->blob_reopen
|
||||
#define sqlite3_vtab_config sqlite3_api->vtab_config
|
||||
#define sqlite3_vtab_on_conflict sqlite3_api->vtab_on_conflict
|
||||
/* Version 3.7.16 and later */
|
||||
#define sqlite3_close_v2 sqlite3_api->close_v2
|
||||
#define sqlite3_db_filename sqlite3_api->db_filename
|
||||
#define sqlite3_db_readonly sqlite3_api->db_readonly
|
||||
#define sqlite3_db_release_memory sqlite3_api->db_release_memory
|
||||
#define sqlite3_errstr sqlite3_api->errstr
|
||||
#define sqlite3_stmt_busy sqlite3_api->stmt_busy
|
||||
#define sqlite3_stmt_readonly sqlite3_api->stmt_readonly
|
||||
#define sqlite3_stricmp sqlite3_api->stricmp
|
||||
#define sqlite3_uri_boolean sqlite3_api->uri_boolean
|
||||
#define sqlite3_uri_int64 sqlite3_api->uri_int64
|
||||
#define sqlite3_uri_parameter sqlite3_api->uri_parameter
|
||||
#define sqlite3_uri_vsnprintf sqlite3_api->vsnprintf
|
||||
#define sqlite3_wal_checkpoint_v2 sqlite3_api->wal_checkpoint_v2
|
||||
#endif /* SQLITE_CORE */
|
||||
|
||||
#define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api = 0;
|
||||
|
@ -200,7 +200,8 @@
|
||||
**
|
||||
** See also ticket #2741.
|
||||
*/
|
||||
#if !defined(_XOPEN_SOURCE) && !defined(__DARWIN__) && !defined(__APPLE__) && SQLITE_THREADSAFE
|
||||
#if !defined(_XOPEN_SOURCE) && !defined(__DARWIN__) \
|
||||
&& !defined(__APPLE__) && SQLITE_THREADSAFE
|
||||
# define _XOPEN_SOURCE 500 /* Needed to enable pthread recursive mutexes */
|
||||
#endif
|
||||
|
||||
@ -2849,7 +2850,7 @@ Table *sqlite3SrcListLookup(Parse*, SrcList*);
|
||||
int sqlite3IsReadOnly(Parse*, Table*, int);
|
||||
void sqlite3OpenTable(Parse*, int iCur, int iDb, Table*, int);
|
||||
#if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY)
|
||||
Expr *sqlite3LimitWhere(Parse *, SrcList *, Expr *, ExprList *, Expr *, Expr *, char *);
|
||||
Expr *sqlite3LimitWhere(Parse*,SrcList*,Expr*,ExprList*,Expr*,Expr*,char*);
|
||||
#endif
|
||||
void sqlite3DeleteFrom(Parse*, SrcList*, Expr*);
|
||||
void sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int);
|
||||
@ -3030,8 +3031,11 @@ int sqlite3VarintLen(u64 v);
|
||||
** x = putVarint32( A, B );
|
||||
**
|
||||
*/
|
||||
#define getVarint32(A,B) (u8)((*(A)<(u8)0x80) ? ((B) = (u32)*(A)),1 : sqlite3GetVarint32((A), (u32 *)&(B)))
|
||||
#define putVarint32(A,B) (u8)(((u32)(B)<(u32)0x80) ? (*(A) = (unsigned char)(B)),1 : sqlite3PutVarint32((A), (B)))
|
||||
#define getVarint32(A,B) \
|
||||
(u8)((*(A)<(u8)0x80)?((B)=(u32)*(A)),1:sqlite3GetVarint32((A),(u32 *)&(B)))
|
||||
#define putVarint32(A,B) \
|
||||
(u8)(((u32)(B)<(u32)0x80)?(*(A)=(unsigned char)(B)),1:\
|
||||
sqlite3PutVarint32((A),(B)))
|
||||
#define getVarint sqlite3GetVarint
|
||||
#define putVarint sqlite3PutVarint
|
||||
|
||||
|
@ -178,6 +178,7 @@ const char *sqlite3TestErrorName(int rc){
|
||||
case SQLITE_CORRUPT_VTAB: zName = "SQLITE_CORRUPT_VTAB"; break;
|
||||
case SQLITE_READONLY_RECOVERY: zName = "SQLITE_READONLY_RECOVERY"; break;
|
||||
case SQLITE_READONLY_CANTLOCK: zName = "SQLITE_READONLY_CANTLOCK"; break;
|
||||
case SQLITE_READONLY_ROLLBACK: zName = "SQLITE_READONLY_ROLLBACK"; break;
|
||||
default: zName = "SQLITE_Unknown"; break;
|
||||
}
|
||||
return zName;
|
||||
|
@ -1295,7 +1295,7 @@ int sqlite3_quota_remove(const char *zFilename){
|
||||
if( pGroup ){
|
||||
for(pFile=pGroup->pFiles; pFile && rc==SQLITE_OK; pFile=pNextFile){
|
||||
pNextFile = pFile->pNext;
|
||||
diff = memcmp(zFull, pFile->zFilename, nFull);
|
||||
diff = strncmp(zFull, pFile->zFilename, nFull);
|
||||
if( diff==0 && ((c = pFile->zFilename[nFull])==0 || c=='/' || c=='\\') ){
|
||||
if( pFile->nRef ){
|
||||
pFile->deleteOnClose = 1;
|
||||
|
@ -107,7 +107,7 @@ struct ReCompiled {
|
||||
char *aOp; /* Operators for the virtual machine */
|
||||
int *aArg; /* Arguments to each operator */
|
||||
unsigned (*xNextChar)(ReInput*); /* Next character function */
|
||||
char zInit[12]; /* Initial text to match */
|
||||
unsigned char zInit[12]; /* Initial text to match */
|
||||
int nInit; /* Number of characters in zInit */
|
||||
unsigned nState; /* Number of entries in aOp[] and aArg[] */
|
||||
unsigned nAlloc; /* Slots allocated for aOp[] and aArg[] */
|
||||
@ -194,7 +194,8 @@ int re_match(ReCompiled *pRe, const unsigned char *zIn, int nIn){
|
||||
if( pRe->nInit ){
|
||||
unsigned char x = pRe->zInit[0];
|
||||
while( in.i+pRe->nInit<=in.mx
|
||||
&& (zIn[in.i]!=x || memcmp(zIn+in.i, pRe->zInit, pRe->nInit)!=0)
|
||||
&& (zIn[in.i]!=x ||
|
||||
strncmp((const char*)zIn+in.i, (const char*)pRe->zInit, pRe->nInit)!=0)
|
||||
){
|
||||
in.i++;
|
||||
}
|
||||
|
@ -744,22 +744,22 @@ static int utf8Len(unsigned char c, int N){
|
||||
}
|
||||
|
||||
/*
|
||||
** Return TRUE (non-zero) of the To side of the given cost matches
|
||||
** Return TRUE (non-zero) if the To side of the given cost matches
|
||||
** the given string.
|
||||
*/
|
||||
static int matchTo(EditDist3Cost *p, const char *z, int n){
|
||||
if( p->nTo>n ) return 0;
|
||||
if( memcmp(p->a+p->nFrom, z, p->nTo)!=0 ) return 0;
|
||||
if( strncmp(p->a+p->nFrom, z, p->nTo)!=0 ) return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return TRUE (non-zero) of the To side of the given cost matches
|
||||
** Return TRUE (non-zero) if the From side of the given cost matches
|
||||
** the given string.
|
||||
*/
|
||||
static int matchFrom(EditDist3Cost *p, const char *z, int n){
|
||||
assert( p->nFrom<=n );
|
||||
if( memcmp(p->a, z, p->nFrom)!=0 ) return 0;
|
||||
if( strncmp(p->a, z, p->nFrom)!=0 ) return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -1952,7 +1952,7 @@ static int spellfix1Init(
|
||||
);
|
||||
}
|
||||
for(i=3; rc==SQLITE_OK && i<argc; i++){
|
||||
if( memcmp(argv[i],"edit_cost_table=",16)==0 && pNew->zCostTable==0 ){
|
||||
if( strncmp(argv[i],"edit_cost_table=",16)==0 && pNew->zCostTable==0 ){
|
||||
pNew->zCostTable = spellfix1Dequote(&argv[i][16]);
|
||||
if( pNew->zCostTable==0 ) rc = SQLITE_NOMEM;
|
||||
continue;
|
||||
@ -2681,6 +2681,18 @@ static int spellfix1Update(
|
||||
p->pConfig3 = 0;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
if( strncmp(zCmd,"edit_cost_table=",16)==0 ){
|
||||
editDist3ConfigDelete(p->pConfig3);
|
||||
p->pConfig3 = 0;
|
||||
sqlite3_free(p->zCostTable);
|
||||
p->zCostTable = spellfix1Dequote(zCmd+16);
|
||||
if( p->zCostTable==0 ) return SQLITE_NOMEM;
|
||||
if( p->zCostTable[0]==0 || sqlite3_stricmp(p->zCostTable,"null")==0 ){
|
||||
sqlite3_free(p->zCostTable);
|
||||
p->zCostTable = 0;
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
pVTab->zErrMsg = sqlite3_mprintf("unknown value for %s.command: \"%w\"",
|
||||
p->zTableName, zCmd);
|
||||
return SQLITE_ERROR;
|
||||
|
@ -265,7 +265,8 @@ static void tvfsExecTcl(
|
||||
const char *zMethod,
|
||||
Tcl_Obj *arg1,
|
||||
Tcl_Obj *arg2,
|
||||
Tcl_Obj *arg3
|
||||
Tcl_Obj *arg3,
|
||||
Tcl_Obj *arg4
|
||||
){
|
||||
int rc; /* Return code from Tcl_EvalObj() */
|
||||
Tcl_Obj *pEval;
|
||||
@ -282,6 +283,7 @@ static void tvfsExecTcl(
|
||||
if( arg1 ) Tcl_ListObjAppendElement(p->interp, pEval, arg1);
|
||||
if( arg2 ) Tcl_ListObjAppendElement(p->interp, pEval, arg2);
|
||||
if( arg3 ) Tcl_ListObjAppendElement(p->interp, pEval, arg3);
|
||||
if( arg4 ) Tcl_ListObjAppendElement(p->interp, pEval, arg4);
|
||||
|
||||
rc = Tcl_EvalObjEx(p->interp, pEval, TCL_EVAL_GLOBAL);
|
||||
if( rc!=TCL_OK ){
|
||||
@ -302,7 +304,7 @@ static int tvfsClose(sqlite3_file *pFile){
|
||||
|
||||
if( p->pScript && p->mask&TESTVFS_CLOSE_MASK ){
|
||||
tvfsExecTcl(p, "xClose",
|
||||
Tcl_NewStringObj(pFd->zFilename, -1), pFd->pShmId, 0
|
||||
Tcl_NewStringObj(pFd->zFilename, -1), pFd->pShmId, 0, 0
|
||||
);
|
||||
}
|
||||
|
||||
@ -333,7 +335,7 @@ static int tvfsRead(
|
||||
Testvfs *p = (Testvfs *)pFd->pVfs->pAppData;
|
||||
if( p->pScript && p->mask&TESTVFS_READ_MASK ){
|
||||
tvfsExecTcl(p, "xRead",
|
||||
Tcl_NewStringObj(pFd->zFilename, -1), pFd->pShmId, 0
|
||||
Tcl_NewStringObj(pFd->zFilename, -1), pFd->pShmId, 0, 0
|
||||
);
|
||||
tvfsResultCode(p, &rc);
|
||||
}
|
||||
@ -362,7 +364,7 @@ static int tvfsWrite(
|
||||
if( p->pScript && p->mask&TESTVFS_WRITE_MASK ){
|
||||
tvfsExecTcl(p, "xWrite",
|
||||
Tcl_NewStringObj(pFd->zFilename, -1), pFd->pShmId,
|
||||
Tcl_NewWideIntObj(iOfst)
|
||||
Tcl_NewWideIntObj(iOfst), Tcl_NewIntObj(iAmt)
|
||||
);
|
||||
tvfsResultCode(p, &rc);
|
||||
}
|
||||
@ -390,7 +392,7 @@ static int tvfsTruncate(sqlite3_file *pFile, sqlite_int64 size){
|
||||
|
||||
if( p->pScript && p->mask&TESTVFS_TRUNCATE_MASK ){
|
||||
tvfsExecTcl(p, "xTruncate",
|
||||
Tcl_NewStringObj(pFd->zFilename, -1), pFd->pShmId, 0
|
||||
Tcl_NewStringObj(pFd->zFilename, -1), pFd->pShmId, 0, 0
|
||||
);
|
||||
tvfsResultCode(p, &rc);
|
||||
}
|
||||
@ -431,7 +433,7 @@ static int tvfsSync(sqlite3_file *pFile, int flags){
|
||||
|
||||
tvfsExecTcl(p, "xSync",
|
||||
Tcl_NewStringObj(pFd->zFilename, -1), pFd->pShmId,
|
||||
Tcl_NewStringObj(zFlags, -1)
|
||||
Tcl_NewStringObj(zFlags, -1), 0
|
||||
);
|
||||
tvfsResultCode(p, &rc);
|
||||
}
|
||||
@ -578,7 +580,7 @@ static int tvfsOpen(
|
||||
z += strlen(z) + 1;
|
||||
}
|
||||
}
|
||||
tvfsExecTcl(p, "xOpen", Tcl_NewStringObj(pFd->zFilename, -1), pArg, 0);
|
||||
tvfsExecTcl(p, "xOpen", Tcl_NewStringObj(pFd->zFilename, -1), pArg, 0, 0);
|
||||
Tcl_DecrRefCount(pArg);
|
||||
if( tvfsResultCode(p, &rc) ){
|
||||
if( rc!=SQLITE_OK ) return rc;
|
||||
@ -635,7 +637,7 @@ static int tvfsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
|
||||
|
||||
if( p->pScript && p->mask&TESTVFS_DELETE_MASK ){
|
||||
tvfsExecTcl(p, "xDelete",
|
||||
Tcl_NewStringObj(zPath, -1), Tcl_NewIntObj(dirSync), 0
|
||||
Tcl_NewStringObj(zPath, -1), Tcl_NewIntObj(dirSync), 0, 0
|
||||
);
|
||||
tvfsResultCode(p, &rc);
|
||||
}
|
||||
@ -663,7 +665,7 @@ static int tvfsAccess(
|
||||
if( flags==SQLITE_ACCESS_READWRITE ) zArg = "SQLITE_ACCESS_READWRITE";
|
||||
if( flags==SQLITE_ACCESS_READ ) zArg = "SQLITE_ACCESS_READ";
|
||||
tvfsExecTcl(p, "xAccess",
|
||||
Tcl_NewStringObj(zPath, -1), Tcl_NewStringObj(zArg, -1), 0
|
||||
Tcl_NewStringObj(zPath, -1), Tcl_NewStringObj(zArg, -1), 0, 0
|
||||
);
|
||||
if( tvfsResultCode(p, &rc) ){
|
||||
if( rc!=SQLITE_OK ) return rc;
|
||||
@ -691,7 +693,7 @@ static int tvfsFullPathname(
|
||||
Testvfs *p = (Testvfs *)pVfs->pAppData;
|
||||
if( p->pScript && p->mask&TESTVFS_FULLPATHNAME_MASK ){
|
||||
int rc;
|
||||
tvfsExecTcl(p, "xFullPathname", Tcl_NewStringObj(zPath, -1), 0, 0);
|
||||
tvfsExecTcl(p, "xFullPathname", Tcl_NewStringObj(zPath, -1), 0, 0, 0);
|
||||
if( tvfsResultCode(p, &rc) ){
|
||||
if( rc!=SQLITE_OK ) return rc;
|
||||
}
|
||||
@ -771,7 +773,7 @@ static int tvfsShmOpen(sqlite3_file *pFile){
|
||||
*/
|
||||
Tcl_ResetResult(p->interp);
|
||||
if( p->pScript && p->mask&TESTVFS_SHMOPEN_MASK ){
|
||||
tvfsExecTcl(p, "xShmOpen", Tcl_NewStringObj(pFd->zFilename, -1), 0, 0);
|
||||
tvfsExecTcl(p, "xShmOpen", Tcl_NewStringObj(pFd->zFilename, -1), 0, 0, 0);
|
||||
if( tvfsResultCode(p, &rc) ){
|
||||
if( rc!=SQLITE_OK ) return rc;
|
||||
}
|
||||
@ -841,7 +843,7 @@ static int tvfsShmMap(
|
||||
Tcl_ListObjAppendElement(p->interp, pArg, Tcl_NewIntObj(pgsz));
|
||||
Tcl_ListObjAppendElement(p->interp, pArg, Tcl_NewIntObj(isWrite));
|
||||
tvfsExecTcl(p, "xShmMap",
|
||||
Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, pArg
|
||||
Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, pArg, 0
|
||||
);
|
||||
tvfsResultCode(p, &rc);
|
||||
Tcl_DecrRefCount(pArg);
|
||||
@ -891,7 +893,7 @@ static int tvfsShmLock(
|
||||
}
|
||||
tvfsExecTcl(p, "xShmLock",
|
||||
Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId,
|
||||
Tcl_NewStringObj(zLock, -1)
|
||||
Tcl_NewStringObj(zLock, -1), 0
|
||||
);
|
||||
tvfsResultCode(p, &rc);
|
||||
}
|
||||
@ -937,7 +939,7 @@ static void tvfsShmBarrier(sqlite3_file *pFile){
|
||||
|
||||
if( p->pScript && p->mask&TESTVFS_SHMBARRIER_MASK ){
|
||||
tvfsExecTcl(p, "xShmBarrier",
|
||||
Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, 0
|
||||
Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, 0, 0
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -961,7 +963,7 @@ static int tvfsShmUnmap(
|
||||
|
||||
if( p->pScript && p->mask&TESTVFS_SHMCLOSE_MASK ){
|
||||
tvfsExecTcl(p, "xShmUnmap",
|
||||
Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, 0
|
||||
Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, 0, 0
|
||||
);
|
||||
tvfsResultCode(p, &rc);
|
||||
}
|
||||
|
@ -1218,7 +1218,7 @@ int sqlite3VdbeParameterIndex(Vdbe *p, const char *zName, int nName){
|
||||
if( zName ){
|
||||
for(i=0; i<p->nzVar; i++){
|
||||
const char *z = p->azVar[i];
|
||||
if( z && memcmp(z,zName,nName)==0 && z[nName]==0 ){
|
||||
if( z && strncmp(z,zName,nName)==0 && z[nName]==0 ){
|
||||
return i+1;
|
||||
}
|
||||
}
|
||||
|
14
src/where.c
14
src/where.c
@ -643,9 +643,8 @@ static u16 operatorMask(int op){
|
||||
** then try for the one with no dependencies on <expr> - in other words where
|
||||
** <expr> is a constant expression of some kind. Only return entries of
|
||||
** the form "X <op> Y" where Y is a column in another table if no terms of
|
||||
** the form "X <op> <const-expr>" exist. Other than this priority, if there
|
||||
** are two or more terms that match, then the choice of which term to return
|
||||
** is arbitrary.
|
||||
** the form "X <op> <const-expr>" exist. If no terms with a constant RHS
|
||||
** exist, try to return a term that does not use WO_EQUIV.
|
||||
*/
|
||||
static WhereTerm *findTerm(
|
||||
WhereClause *pWC, /* The WHERE clause to be searched */
|
||||
@ -704,8 +703,12 @@ static WhereTerm *findTerm(
|
||||
continue;
|
||||
}
|
||||
}
|
||||
pResult = pTerm;
|
||||
if( pTerm->prereqRight==0 ) goto findTerm_success;
|
||||
if( pTerm->prereqRight==0 ){
|
||||
pResult = pTerm;
|
||||
goto findTerm_success;
|
||||
}else if( pResult==0 ){
|
||||
pResult = pTerm;
|
||||
}
|
||||
}
|
||||
if( (pTerm->eOperator & WO_EQUIV)!=0
|
||||
&& nEquiv<ArraySize(aEquiv)
|
||||
@ -4231,6 +4234,7 @@ static Bitmask codeOneLoopStart(
|
||||
addrNxt = pLevel->addrNxt;
|
||||
sqlite3VdbeAddOp2(v, OP_MustBeInt, iRowidReg, addrNxt);
|
||||
sqlite3VdbeAddOp3(v, OP_NotExists, iCur, addrNxt, iRowidReg);
|
||||
sqlite3ExprCacheAffinityChange(pParse, iRowidReg, 1);
|
||||
sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg);
|
||||
VdbeComment((v, "pk"));
|
||||
pLevel->op = OP_Noop;
|
||||
|
@ -1289,6 +1289,21 @@ do_test func-29.6 {
|
||||
if {$x<5} {set x 1}
|
||||
set x
|
||||
} {1}
|
||||
|
||||
|
||||
do_execsql_test func-30.1 {SELECT unicode('$');} 36
|
||||
do_execsql_test func-30.2 [subst {SELECT unicode('\u00A2');}] 162
|
||||
do_execsql_test func-30.3 [subst {SELECT unicode('\u20AC');}] 8364
|
||||
do_execsql_test func-30.4 {SELECT char(36,162,8364);} [subst {$\u00A2\u20AC}]
|
||||
|
||||
for {set i 1} {$i<0xd800} {incr i 13} {
|
||||
do_execsql_test func-30.5.$i {SELECT unicode(char($i))} $i
|
||||
}
|
||||
for {set i 57344} {$i<=0xfffd} {incr i 17} {
|
||||
if {$i==0xfeff} continue
|
||||
do_execsql_test func-30.5.$i {SELECT unicode(char($i))} $i
|
||||
}
|
||||
for {set i 65536} {$i<=0x10ffff} {incr i 139} {
|
||||
do_execsql_test func-30.5.$i {SELECT unicode(char($i))} $i
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
154
test/incrvacuum3.test
Normal file
154
test/incrvacuum3.test
Normal file
@ -0,0 +1,154 @@
|
||||
# 2013 Feb 25
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
# This file implements regression tests for the SQLite library, focusing
|
||||
# on the incremental vacuum feature.
|
||||
#
|
||||
# The tests in this file were added at the same time as optimizations
|
||||
# were made to:
|
||||
#
|
||||
# * Truncate the database after a rollback mode commit, and
|
||||
#
|
||||
# * Avoid moving pages to locations from which they may need to be moved
|
||||
# a second time if an incremental-vacuum proccess is allowed to vacuum
|
||||
# the entire database.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix incrvacuum3
|
||||
|
||||
# If this build of the library does not support auto-vacuum, omit this
|
||||
# whole file.
|
||||
ifcapable {!autovacuum || !pragma} {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
proc check_on_disk {} {
|
||||
|
||||
# Copy the wal and journal files for database "test.db" to "test2.db".
|
||||
forcedelete test2.db test2.db-journal test2.db-wal
|
||||
if {[file exists test.db-journal]} {
|
||||
forcecopy test.db-journal test2.db-journal
|
||||
}
|
||||
if {[file exists test.db-wal]} {
|
||||
forcecopy test.db-wal test2.db-wal
|
||||
}
|
||||
|
||||
# Now copy the database file itself. Do this using open/read/puts
|
||||
# instead of the [file copy] command in order to avoid attempting
|
||||
# to read the 512 bytes begining at offset $sqlite_pending_byte.
|
||||
#
|
||||
set sz [file size test.db]
|
||||
set fd [open test.db]
|
||||
set fd2 [open test2.db w]
|
||||
fconfigure $fd -encoding binary -translation binary
|
||||
fconfigure $fd2 -encoding binary -translation binary
|
||||
if {$sz>$::sqlite_pending_byte} {
|
||||
puts -nonewline $fd2 [read $fd $::sqlite_pending_byte]
|
||||
seek $fd [expr $::sqlite_pending_byte+512]
|
||||
seek $fd2 [expr $::sqlite_pending_byte+512]
|
||||
}
|
||||
puts -nonewline $fd2 [read $fd]
|
||||
close $fd2
|
||||
close $fd
|
||||
|
||||
# Open "test2.db" and check it is Ok.
|
||||
sqlite3 dbcheck test2.db
|
||||
set ret [dbcheck eval { PRAGMA integrity_check }]
|
||||
dbcheck close
|
||||
set ret
|
||||
}
|
||||
|
||||
# Run these tests once in rollback journal mode, and once in wal mode.
|
||||
#
|
||||
foreach {T jrnl_mode} {
|
||||
1 delete
|
||||
2 wal
|
||||
} {
|
||||
catch { db close }
|
||||
forcedelete test.db test.db-journal test.db-wal
|
||||
sqlite3 db test.db
|
||||
db eval {
|
||||
PRAGMA cache_size = 5;
|
||||
PRAGMA page_size = 1024;
|
||||
PRAGMA auto_vacuum = 2;
|
||||
}
|
||||
db eval "PRAGMA journal_mode = $jrnl_mode"
|
||||
|
||||
foreach {tn sql} {
|
||||
1 {
|
||||
CREATE TABLE t1(x UNIQUE);
|
||||
INSERT INTO t1 VALUES(randomblob(400));
|
||||
INSERT INTO t1 VALUES(randomblob(400));
|
||||
INSERT INTO t1 SELECT randomblob(400) FROM t1; -- 4
|
||||
INSERT INTO t1 SELECT randomblob(400) FROM t1; -- 8
|
||||
INSERT INTO t1 SELECT randomblob(400) FROM t1; -- 16
|
||||
INSERT INTO t1 SELECT randomblob(400) FROM t1; -- 32
|
||||
INSERT INTO t1 SELECT randomblob(400) FROM t1; -- 64
|
||||
INSERT INTO t1 SELECT randomblob(400) FROM t1; -- 128
|
||||
INSERT INTO t1 SELECT randomblob(400) FROM t1; -- 256
|
||||
}
|
||||
|
||||
2 {
|
||||
DELETE FROM t1 WHERE rowid%8;
|
||||
}
|
||||
|
||||
3 {
|
||||
BEGIN;
|
||||
PRAGMA incremental_vacuum = 100;
|
||||
INSERT INTO t1 SELECT randomblob(400) FROM t1; -- 64
|
||||
INSERT INTO t1 SELECT randomblob(400) FROM t1; -- 128
|
||||
INSERT INTO t1 SELECT randomblob(400) FROM t1; -- 256
|
||||
ROLLBACK;
|
||||
}
|
||||
|
||||
4 {
|
||||
BEGIN;
|
||||
SAVEPOINT one;
|
||||
PRAGMA incremental_vacuum = 100;
|
||||
SAVEPOINT two;
|
||||
INSERT INTO t1 SELECT randomblob(400) FROM t1; -- 64
|
||||
INSERT INTO t1 SELECT randomblob(400) FROM t1; -- 128
|
||||
INSERT INTO t1 SELECT randomblob(400) FROM t1; -- 256
|
||||
}
|
||||
|
||||
5 { ROLLBACK to two }
|
||||
|
||||
6 { ROLLBACK to one }
|
||||
|
||||
7 {
|
||||
INSERT INTO t1 SELECT randomblob(400) FROM t1; -- 64
|
||||
PRAGMA incremental_vacuum = 1000;
|
||||
INSERT INTO t1 SELECT randomblob(400) FROM t1; -- 128
|
||||
INSERT INTO t1 SELECT randomblob(400) FROM t1; -- 256
|
||||
ROLLBACK;
|
||||
}
|
||||
|
||||
8 {
|
||||
BEGIN;
|
||||
INSERT INTO t1 SELECT randomblob(400) FROM t1; -- 64
|
||||
PRAGMA incremental_vacuum = 1000;
|
||||
INSERT INTO t1 SELECT randomblob(400) FROM t1; -- 128
|
||||
COMMIT;
|
||||
}
|
||||
} {
|
||||
do_execsql_test $T.1.$tn.1 $sql
|
||||
do_execsql_test $T.1.$tn.2 {PRAGMA integrity_check} ok
|
||||
do_test $T.1.$tn.3 { check_on_disk } ok
|
||||
}
|
||||
|
||||
do_execsql_test $T.1.x.1 { PRAGMA freelist_count } 0
|
||||
do_execsql_test $T.1.x.2 { SELECT count(*) FROM t1 } 128
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
@ -139,8 +139,8 @@ ifcapable shared_cache {
|
||||
# Figure out how big the database is and how many free pages it
|
||||
# has before running incremental-vacuum.
|
||||
#
|
||||
set nPage [expr {[file size test.db]/1024}]
|
||||
set nFree [execsql {pragma freelist_count} db1]
|
||||
set nPage [execsql {pragma page_count} db1]
|
||||
|
||||
# Now run incremental-vacuum to vacuum 5 pages from the db file.
|
||||
# The iTest'th I/O call is set to fail.
|
||||
@ -158,7 +158,7 @@ ifcapable shared_cache {
|
||||
set ::sqlite_io_error_hardhit 0
|
||||
|
||||
set nFree2 [execsql {pragma freelist_count} db1]
|
||||
set nPage2 [expr {[file size test.db]/1024}]
|
||||
set nPage2 [execsql {pragma page_count} db1]
|
||||
|
||||
do_test incrvacuum-ioerr-4.$iTest.2 {
|
||||
set shrink [expr {$nPage-$nPage2}]
|
||||
|
@ -36,11 +36,10 @@ db close
|
||||
testvfs tvfs
|
||||
tvfs filter xWrite
|
||||
tvfs script write_cb
|
||||
proc write_cb {xCall file handle iOfst} {
|
||||
proc write_cb {xCall file handle iOfst args} {
|
||||
if {[file tail $file]=="test.db"} {
|
||||
lappend ::write_list [expr $iOfst/1024]
|
||||
}
|
||||
puts "$xCall $file $args"
|
||||
}
|
||||
|
||||
do_test 1.2 {
|
||||
@ -65,11 +64,12 @@ do_test 1.3 {
|
||||
}
|
||||
set iPrev $iNext
|
||||
}
|
||||
puts -nonewline \
|
||||
" (forward=$nForward, back=$nBackward, noncontiguous=$nNoncont)"
|
||||
|
||||
expr {$nForward > $nBackward}
|
||||
expr {$nForward > 2*($nBackward + $nNoncont)}
|
||||
} {1}
|
||||
db close
|
||||
tvfs delete
|
||||
|
||||
finish_test
|
||||
|
||||
|
@ -488,6 +488,34 @@ do_test misc7-21.1 {
|
||||
list $rc $msg
|
||||
} {1 {unable to open database file}}
|
||||
|
||||
# Try to do hot-journal rollback with a read-only connection. The
|
||||
# error code should be SQLITE_READONLY_ROLLBACK.
|
||||
#
|
||||
do_test misc7-22.1 {
|
||||
db close
|
||||
forcedelete test.db copy.db-journal
|
||||
sqlite3 db test.db
|
||||
execsql {
|
||||
CREATE TABLE t1(a, b);
|
||||
INSERT INTO t1 VALUES(1, 2);
|
||||
INSERT INTO t1 VALUES(3, 4);
|
||||
}
|
||||
db close
|
||||
sqlite3 db test.db -readonly 1
|
||||
catchsql {
|
||||
INSERT INTO t1 VALUES(5, 6);
|
||||
}
|
||||
} {1 {attempt to write a readonly database}}
|
||||
do_test misc7-22.2 { execsql { SELECT * FROM t1 } } {1 2 3 4}
|
||||
do_test misc7-22.3 {
|
||||
set fd [open test.db-journal w]
|
||||
puts $fd [string repeat abc 1000]
|
||||
close $fd
|
||||
catchsql { SELECT * FROM t1 }
|
||||
} {1 {attempt to write a readonly database}}
|
||||
do_test misc7-22.4 {
|
||||
sqlite3_extended_errcode db
|
||||
} SQLITE_READONLY_ROLLBACK
|
||||
|
||||
db close
|
||||
forcedelete test.db
|
||||
|
@ -752,7 +752,7 @@ sqlite3 db test.db -readonly 1
|
||||
do_catchsql_test pager1.4.5.6 {
|
||||
SELECT * FROM t1;
|
||||
SELECT * FROM t2;
|
||||
} {1 {disk I/O error}}
|
||||
} {1 {attempt to write a readonly database}}
|
||||
db close
|
||||
|
||||
# Snapshot the file-system just before multi-file commit. Save the name
|
||||
|
@ -1626,4 +1626,48 @@ do_test 22.4.3 {
|
||||
execsql { PRAGMA aux.integrity_check; }
|
||||
} {ok}
|
||||
|
||||
db close
|
||||
forcedelete test.db test.db-wal test.db-journal
|
||||
sqlite3 db test.db
|
||||
sqlite3 db2 test.db
|
||||
do_test 23.1 {
|
||||
db eval {
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY,b,c,d);
|
||||
CREATE INDEX i1 ON t1(b,c);
|
||||
CREATE INDEX i2 ON t1(c,d);
|
||||
CREATE TABLE t2(x INTEGER REFERENCES t1);
|
||||
}
|
||||
db2 eval {SELECT name FROM sqlite_master}
|
||||
} {t1 i1 i2 t2}
|
||||
do_test 23.2 {
|
||||
db eval {
|
||||
DROP INDEX i2;
|
||||
CREATE INDEX i2 ON t1(c,d,b);
|
||||
}
|
||||
db2 eval {PRAGMA index_info(i2)}
|
||||
} {0 2 c 1 3 d 2 1 b}
|
||||
do_test 23.3 {
|
||||
db eval {
|
||||
CREATE INDEX i3 ON t1(d,b,c);
|
||||
}
|
||||
db2 eval {PRAGMA index_list(t1)}
|
||||
} {0 i3 0 1 i2 0 2 i1 0}
|
||||
do_test 23.4 {
|
||||
db eval {
|
||||
ALTER TABLE t1 ADD COLUMN e;
|
||||
}
|
||||
db2 eval {
|
||||
PRAGMA table_info(t1);
|
||||
}
|
||||
} {/4 e {} 0 {} 0/}
|
||||
do_test 23.5 {
|
||||
db eval {
|
||||
DROP TABLE t2;
|
||||
CREATE TABLE t2(x, y INTEGER REFERENCES t1);
|
||||
}
|
||||
db2 eval {
|
||||
PRAGMA foreign_key_list(t2);
|
||||
}
|
||||
} {0 0 t1 y {} {NO ACTION} {NO ACTION} NONE}
|
||||
|
||||
finish_test
|
||||
|
@ -136,16 +136,52 @@ do_test 3.2 {
|
||||
}
|
||||
} {}
|
||||
|
||||
breakpoint
|
||||
foreach {tn word res} {
|
||||
1 kos* {kosher 3 kiosk 4 kudo 2 kiss 3 kissed 3}
|
||||
2 kellj* {killjoy 5 kill 4 killed 4 killer 4 killers 4}
|
||||
3 kellj {kill 4 kills 5 killjoy 7 keel 4 killed 6}
|
||||
} {
|
||||
do_execsql_test 1.2.$tn {
|
||||
do_execsql_test 3.2.$tn {
|
||||
SELECT word, matchlen FROM t3 WHERE word MATCH $word
|
||||
ORDER BY score, word LIMIT 5
|
||||
} $res
|
||||
}
|
||||
}
|
||||
|
||||
do_execsql_test 4.0 {
|
||||
INSERT INTO t3(command) VALUES('edit_cost_table=NULL');
|
||||
}
|
||||
foreach {tn word res} {
|
||||
1 kosher {kosher 0 kisser 51 kissers 76 kissed 126 kisses 126}
|
||||
2 kellj {keels 60 killjoy 68 kills 80 keel 120 kill 125}
|
||||
3 kashar {kosher 80 kisser 91 kissers 116 kissed 166 kisses 166}
|
||||
} {
|
||||
do_execsql_test 4.1.$tn {
|
||||
SELECT word, distance FROM t3 WHERE word MATCH $word
|
||||
ORDER BY score, word LIMIT 5
|
||||
} $res
|
||||
}
|
||||
do_execsql_test 5.0 {
|
||||
CREATE TABLE costs2(iLang, cFrom, cTo, iCost);
|
||||
INSERT INTO costs2 VALUES(0, 'a', 'o', 1);
|
||||
INSERT INTO costs2 VALUES(0, 'e', 'o', 4);
|
||||
INSERT INTO costs2 VALUES(0, 'i', 'o', 8);
|
||||
INSERT INTO costs2 VALUES(0, 'u', 'o', 16);
|
||||
INSERT INTO t3(command) VALUES('edit_cost_table="costs2"');
|
||||
}
|
||||
|
||||
foreach {tn word res} {
|
||||
1 kasher {kosher 1}
|
||||
2 kesher {kosher 4}
|
||||
3 kisher {kosher 8}
|
||||
4 kosher {kosher 0}
|
||||
5 kusher {kosher 16}
|
||||
} {
|
||||
do_execsql_test 5.1.$tn {
|
||||
SELECT word, distance FROM t3 WHERE word MATCH $word
|
||||
ORDER BY score, word LIMIT 1
|
||||
} $res
|
||||
}
|
||||
|
||||
|
||||
|
||||
finish_test
|
||||
|
@ -1124,6 +1124,25 @@ proc crashsql {args} {
|
||||
lappend r $msg
|
||||
}
|
||||
|
||||
proc run_ioerr_prep {} {
|
||||
set ::sqlite_io_error_pending 0
|
||||
catch {db close}
|
||||
catch {db2 close}
|
||||
catch {forcedelete test.db}
|
||||
catch {forcedelete test.db-journal}
|
||||
catch {forcedelete test2.db}
|
||||
catch {forcedelete test2.db-journal}
|
||||
set ::DB [sqlite3 db test.db; sqlite3_connection_pointer db]
|
||||
sqlite3_extended_result_codes $::DB $::ioerropts(-erc)
|
||||
if {[info exists ::ioerropts(-tclprep)]} {
|
||||
eval $::ioerropts(-tclprep)
|
||||
}
|
||||
if {[info exists ::ioerropts(-sqlprep)]} {
|
||||
execsql $::ioerropts(-sqlprep)
|
||||
}
|
||||
expr 0
|
||||
}
|
||||
|
||||
# Usage: do_ioerr_test <test number> <options...>
|
||||
#
|
||||
# This proc is used to implement test cases that check that IO errors
|
||||
@ -1156,10 +1175,26 @@ proc do_ioerr_test {testname args} {
|
||||
# TEMPORARY: For 3.5.9, disable testing of extended result codes. There are
|
||||
# a couple of obscure IO errors that do not return them.
|
||||
set ::ioerropts(-erc) 0
|
||||
|
||||
# Create a single TCL script from the TCL and SQL specified
|
||||
# as the body of the test.
|
||||
set ::ioerrorbody {}
|
||||
if {[info exists ::ioerropts(-tclbody)]} {
|
||||
append ::ioerrorbody "$::ioerropts(-tclbody)\n"
|
||||
}
|
||||
if {[info exists ::ioerropts(-sqlbody)]} {
|
||||
append ::ioerrorbody "db eval {$::ioerropts(-sqlbody)}"
|
||||
}
|
||||
|
||||
save_prng_state
|
||||
if {$::ioerropts(-cksum)} {
|
||||
run_ioerr_prep
|
||||
eval $::ioerrorbody
|
||||
set ::goodcksum [cksum]
|
||||
}
|
||||
|
||||
set ::go 1
|
||||
#reset_prng_state
|
||||
save_prng_state
|
||||
for {set n $::ioerropts(-start)} {$::go} {incr n} {
|
||||
set ::TN $n
|
||||
incr ::ioerropts(-count) -1
|
||||
@ -1176,27 +1211,12 @@ proc do_ioerr_test {testname args} {
|
||||
# Delete the files test.db and test2.db, then execute the TCL and
|
||||
# SQL (in that order) to prepare for the test case.
|
||||
do_test $testname.$n.1 {
|
||||
set ::sqlite_io_error_pending 0
|
||||
catch {db close}
|
||||
catch {db2 close}
|
||||
catch {forcedelete test.db}
|
||||
catch {forcedelete test.db-journal}
|
||||
catch {forcedelete test2.db}
|
||||
catch {forcedelete test2.db-journal}
|
||||
set ::DB [sqlite3 db test.db; sqlite3_connection_pointer db]
|
||||
sqlite3_extended_result_codes $::DB $::ioerropts(-erc)
|
||||
if {[info exists ::ioerropts(-tclprep)]} {
|
||||
eval $::ioerropts(-tclprep)
|
||||
}
|
||||
if {[info exists ::ioerropts(-sqlprep)]} {
|
||||
execsql $::ioerropts(-sqlprep)
|
||||
}
|
||||
expr 0
|
||||
run_ioerr_prep
|
||||
} {0}
|
||||
|
||||
# Read the 'checksum' of the database.
|
||||
if {$::ioerropts(-cksum)} {
|
||||
set checksum [cksum]
|
||||
set ::checksum [cksum]
|
||||
}
|
||||
|
||||
# Set the Nth IO error to fail.
|
||||
@ -1204,20 +1224,10 @@ proc do_ioerr_test {testname args} {
|
||||
set ::sqlite_io_error_persist $::ioerropts(-persist)
|
||||
set ::sqlite_io_error_pending $n
|
||||
}] $n
|
||||
|
||||
# Create a single TCL script from the TCL and SQL specified
|
||||
# as the body of the test.
|
||||
set ::ioerrorbody {}
|
||||
if {[info exists ::ioerropts(-tclbody)]} {
|
||||
append ::ioerrorbody "$::ioerropts(-tclbody)\n"
|
||||
}
|
||||
if {[info exists ::ioerropts(-sqlbody)]} {
|
||||
append ::ioerrorbody "db eval {$::ioerropts(-sqlbody)}"
|
||||
}
|
||||
|
||||
# Execute the TCL Script created in the above block. If
|
||||
# there are at least N IO operations performed by SQLite as
|
||||
# a result of the script, the Nth will fail.
|
||||
# Execute the TCL script created for the body of this test. If
|
||||
# at least N IO operations performed by SQLite as a result of
|
||||
# the script, the Nth will fail.
|
||||
do_test $testname.$n.3 {
|
||||
set ::sqlite_io_error_hit 0
|
||||
set ::sqlite_io_error_hardhit 0
|
||||
@ -1321,8 +1331,15 @@ proc do_ioerr_test {testname args} {
|
||||
catch {db close}
|
||||
catch {db2 close}
|
||||
set ::DB [sqlite3 db test.db; sqlite3_connection_pointer db]
|
||||
cksum
|
||||
} $checksum
|
||||
set nowcksum [cksum]
|
||||
set res [expr {$nowcksum==$::checksum || $nowcksum==$::goodcksum}]
|
||||
if {$res==0} {
|
||||
puts "now=$nowcksum"
|
||||
puts "the=$::checksum"
|
||||
puts "fwd=$::goodcksum"
|
||||
}
|
||||
set res
|
||||
} 1
|
||||
}
|
||||
|
||||
set ::sqlite_io_error_hardhit 0
|
||||
|
26
test/tkt-7a31705a7e6.test
Normal file
26
test/tkt-7a31705a7e6.test
Normal file
@ -0,0 +1,26 @@
|
||||
# 2013 February 26
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
# This file implements regression tests for SQLite library. Specifically,
|
||||
# it tests that ticket [7a31705a7e6c95d514e6f20a6900f436bbc9fed8] in the
|
||||
# name resolver has been fixed.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
do_execsql_test tkt-7a31705a7e6-1.1 {
|
||||
CREATE TABLE t1 (a INTEGER PRIMARY KEY);
|
||||
CREATE TABLE t2 (a INTEGER PRIMARY KEY, b INTEGER);
|
||||
CREATE TABLE t2x (b INTEGER PRIMARY KEY);
|
||||
SELECT t1.a FROM ((t1 JOIN t2 ON t1.a=t2.a) AS x JOIN t2x ON x.b=t2x.b) as y;
|
||||
} {}
|
||||
|
78
test/tkt-fc7bd6358f.test
Normal file
78
test/tkt-fc7bd6358f.test
Normal file
@ -0,0 +1,78 @@
|
||||
# 2013 March 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.
|
||||
#
|
||||
#***********************************************************************
|
||||
# This file implements regression tests for SQLite library. Specifically,
|
||||
# it tests that ticket [fc7bd6358f]:
|
||||
#
|
||||
# The following SQL yields an incorrect result (zero rows) in all
|
||||
# versions of SQLite between 3.6.14 and 3.7.15.2:
|
||||
#
|
||||
# CREATE TABLE t(textid TEXT);
|
||||
# INSERT INTO t VALUES('12');
|
||||
# INSERT INTO t VALUES('34');
|
||||
# CREATE TABLE i(intid INTEGER PRIMARY KEY);
|
||||
# INSERT INTO i VALUES(12);
|
||||
# INSERT INTO i VALUES(34);
|
||||
#
|
||||
# SELECT t1.textid AS a, i.intid AS b, t2.textid AS c
|
||||
# FROM t t1, i, t t2
|
||||
# WHERE t1.textid = i.intid
|
||||
# AND t1.textid = t2.textid;
|
||||
#
|
||||
# The correct result should be two rows, one with 12|12|12 and the other
|
||||
# with 34|34|34. With this bug, no rows are returned. Bisecting shows that
|
||||
# this bug was introduced with check-in [dd4d67a67454] on 2009-04-23.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
do_test tkt-fc7bd6358f.100 {
|
||||
db eval {
|
||||
CREATE TABLE t(textid TEXT);
|
||||
INSERT INTO t VALUES('12');
|
||||
INSERT INTO t VALUES('34');
|
||||
CREATE TABLE i(intid INTEGER PRIMARY KEY);
|
||||
INSERT INTO i VALUES(12);
|
||||
INSERT INTO i VALUES(34);
|
||||
}
|
||||
} {}
|
||||
unset -nocomplain from
|
||||
unset -nocomplain where
|
||||
unset -nocomplain a
|
||||
unset -nocomplain b
|
||||
foreach {a from} {
|
||||
1 {FROM t t1, i, t t2}
|
||||
2 {FROM i, t t1, t t2}
|
||||
3 {FROM t t1, t t2, i}
|
||||
} {
|
||||
foreach {b where} {
|
||||
1 {WHERE t1.textid=i.intid AND t1.textid=t2.textid}
|
||||
2 {WHERE i.intid=t1.textid AND t1.textid=t2.textid}
|
||||
3 {WHERE t1.textid=i.intid AND i.intid=t2.textid}
|
||||
4 {WHERE t1.textid=i.intid AND t2.textid=i.intid}
|
||||
5 {WHERE i.intid=t1.textid AND i.intid=t2.textid}
|
||||
6 {WHERE i.intid=t1.textid AND t2.textid=i.intid}
|
||||
7 {WHERE t1.textid=t2.textid AND i.intid=t2.textid}
|
||||
8 {WHERE t1.textid=t2.textid AND t2.textid=i.intid}
|
||||
} {
|
||||
do_test tkt-fc7bd6358f.110.$a.$b.1 {
|
||||
db eval {PRAGMA automatic_index=ON}
|
||||
db eval "SELECT t1.textid, i.intid, t2.textid $from $where"
|
||||
} {12 12 12 34 34 34}
|
||||
do_test tkt-fc7bd6358f.110.$a.$b.2 {
|
||||
db eval {PRAGMA automatic_index=OFF}
|
||||
db eval "SELECT t1.textid, i.intid, t2.textid $from $where"
|
||||
} {12 12 12 34 34 34}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
finish_test
|
@ -10,8 +10,8 @@
|
||||
#***********************************************************************
|
||||
#
|
||||
# Ticket #3762: Make sure that an incremental vacuum that reduces the
|
||||
# size of the database file such that a pointer-map page is elemented
|
||||
# can be correctly rolled back.
|
||||
# size of the database file such that if a pointer-map page is eliminated
|
||||
# it can be correctly rolled back.
|
||||
#
|
||||
# That ticket #3762 has been fixed has already been verified by the
|
||||
# savepoint6.test test script. But this script is simplier and a
|
||||
|
@ -602,11 +602,13 @@ do_test view-21.1 {
|
||||
CREATE VIEW vx AS SELECT * FROM v32768 UNION SELECT * FROM v32768;
|
||||
}
|
||||
} {1 {too many references to "v1": max 65535}}
|
||||
do_test view-21.2 {
|
||||
db progress 1000 {expr 1}
|
||||
catchsql {
|
||||
SELECT * FROM v32768;
|
||||
}
|
||||
} {1 interrupted}
|
||||
ifcapable progress {
|
||||
do_test view-21.2 {
|
||||
db progress 1000 {expr 1}
|
||||
catchsql {
|
||||
SELECT * FROM v32768;
|
||||
}
|
||||
} {1 interrupted}
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
105
tool/showdb.c
105
tool/showdb.c
@ -471,7 +471,7 @@ static void page_usage_msg(int pgno, const char *zFormat, ...){
|
||||
zMsg = sqlite3_vmprintf(zFormat, ap);
|
||||
va_end(ap);
|
||||
if( pgno<=0 || pgno>mxPage ){
|
||||
printf("ERROR: page %d out of bounds. Range=1..%d. Msg: %s\n",
|
||||
printf("ERROR: page %d out of range 1..%d: %s\n",
|
||||
pgno, mxPage, zMsg);
|
||||
sqlite3_free(zMsg);
|
||||
return;
|
||||
@ -479,7 +479,7 @@ static void page_usage_msg(int pgno, const char *zFormat, ...){
|
||||
if( zPageUse[pgno]!=0 ){
|
||||
printf("ERROR: page %d used multiple times:\n", pgno);
|
||||
printf("ERROR: previous: %s\n", zPageUse[pgno]);
|
||||
printf("ERROR: current: %s\n", zPageUse[pgno]);
|
||||
printf("ERROR: current: %s\n", zMsg);
|
||||
sqlite3_free(zPageUse[pgno]);
|
||||
}
|
||||
zPageUse[pgno] = zMsg;
|
||||
@ -615,15 +615,32 @@ static void page_usage_freelist(int pgno){
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Determine pages used as PTRMAP pages
|
||||
*/
|
||||
static void page_usage_ptrmap(unsigned char *a){
|
||||
if( a[55] ){
|
||||
int usable = pagesize - a[20];
|
||||
int pgno = 2;
|
||||
int perPage = usable/5;
|
||||
while( pgno<=mxPage ){
|
||||
page_usage_msg(pgno, "PTRMAP page covering %d..%d",
|
||||
pgno+1, pgno+perPage);
|
||||
pgno += perPage + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Try to figure out how every page in the database file is being used.
|
||||
*/
|
||||
static void page_usage_report(const char *zDbName){
|
||||
int i;
|
||||
int i, j;
|
||||
int rc;
|
||||
sqlite3 *db;
|
||||
sqlite3_stmt *pStmt;
|
||||
unsigned char *a;
|
||||
char zQuery[200];
|
||||
|
||||
/* Avoid the pathological case */
|
||||
if( mxPage<1 ){
|
||||
@ -648,20 +665,26 @@ static void page_usage_report(const char *zDbName){
|
||||
/* Discover the usage of each page */
|
||||
a = getContent(0, 100);
|
||||
page_usage_freelist(decodeInt32(a+32));
|
||||
page_usage_ptrmap(a);
|
||||
free(a);
|
||||
page_usage_btree(1, 0, 0, "sqlite_master");
|
||||
rc = sqlite3_prepare_v2(db,
|
||||
"SELECT type, name, rootpage FROM SQLITE_MASTER WHERE rootpage",
|
||||
-1, &pStmt, 0);
|
||||
if( rc==SQLITE_OK ){
|
||||
while( sqlite3_step(pStmt)==SQLITE_ROW ){
|
||||
int pgno = sqlite3_column_int(pStmt, 2);
|
||||
page_usage_btree(pgno, 0, 0, sqlite3_column_text(pStmt, 1));
|
||||
sqlite3_exec(db, "PRAGMA writable_schema=ON", 0, 0, 0);
|
||||
for(j=0; j<2; j++){
|
||||
sqlite3_snprintf(sizeof(zQuery), zQuery,
|
||||
"SELECT type, name, rootpage FROM SQLITE_MASTER WHERE rootpage"
|
||||
" ORDER BY rowid %s", j?"DESC":"");
|
||||
rc = sqlite3_prepare_v2(db, zQuery, -1, &pStmt, 0);
|
||||
if( rc==SQLITE_OK ){
|
||||
while( sqlite3_step(pStmt)==SQLITE_ROW ){
|
||||
int pgno = sqlite3_column_int(pStmt, 2);
|
||||
page_usage_btree(pgno, 0, 0, sqlite3_column_text(pStmt, 1));
|
||||
}
|
||||
}else{
|
||||
printf("ERROR: cannot query database: %s\n", sqlite3_errmsg(db));
|
||||
}
|
||||
}else{
|
||||
printf("ERROR: cannot query database: %s\n", sqlite3_errmsg(db));
|
||||
rc = sqlite3_finalize(pStmt);
|
||||
if( rc==SQLITE_OK ) break;
|
||||
}
|
||||
sqlite3_finalize(pStmt);
|
||||
sqlite3_close(db);
|
||||
|
||||
/* Print the report and free memory used */
|
||||
@ -673,6 +696,53 @@ static void page_usage_report(const char *zDbName){
|
||||
zPageUse = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Try to figure out how every page in the database file is being used.
|
||||
*/
|
||||
static void ptrmap_coverage_report(const char *zDbName){
|
||||
unsigned int pgno;
|
||||
unsigned char *aHdr;
|
||||
unsigned char *a;
|
||||
int usable;
|
||||
int perPage;
|
||||
unsigned int i;
|
||||
|
||||
/* Avoid the pathological case */
|
||||
if( mxPage<1 ){
|
||||
printf("empty database\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Make sure PTRMAPs are used in this database */
|
||||
aHdr = getContent(0, 100);
|
||||
if( aHdr[55]==0 ){
|
||||
printf("database does not use PTRMAP pages\n");
|
||||
return;
|
||||
}
|
||||
usable = pagesize - aHdr[20];
|
||||
perPage = usable/5;
|
||||
free(aHdr);
|
||||
printf("%5d: root of sqlite_master\n", 1);
|
||||
for(pgno=2; pgno<=mxPage; pgno += perPage+1){
|
||||
printf("%5d: PTRMAP page covering %d..%d\n", pgno,
|
||||
pgno+1, pgno+perPage);
|
||||
a = getContent((pgno-1)*pagesize, usable);
|
||||
for(i=0; i+5<=usable && pgno+1+i/5<=mxPage; i+=5){
|
||||
const char *zType = "???";
|
||||
unsigned int iFrom = decodeInt32(&a[i+1]);
|
||||
switch( a[i] ){
|
||||
case 1: zType = "b-tree root page"; break;
|
||||
case 2: zType = "freelist page"; break;
|
||||
case 3: zType = "first page of overflow"; break;
|
||||
case 4: zType = "later page of overflow"; break;
|
||||
case 5: zType = "b-tree non-root page"; break;
|
||||
}
|
||||
printf("%5d: %s, parent=%u\n", pgno+1+i/5, zType, iFrom);
|
||||
}
|
||||
free(a);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Print a usage comment
|
||||
*/
|
||||
@ -682,6 +752,7 @@ static void usage(const char *argv0){
|
||||
"args:\n"
|
||||
" dbheader Show database header\n"
|
||||
" pgidx Index of how each page is used\n"
|
||||
" ptrmap Show all PTRMAP page content\n"
|
||||
" NNN..MMM Show hex of pages NNN through MMM\n"
|
||||
" NNN..end Show hex of pages NNN through end of file\n"
|
||||
" NNNb Decode btree page NNN\n"
|
||||
@ -731,6 +802,14 @@ int main(int argc, char **argv){
|
||||
page_usage_report(argv[1]);
|
||||
continue;
|
||||
}
|
||||
if( strcmp(argv[i], "ptrmap")==0 ){
|
||||
ptrmap_coverage_report(argv[1]);
|
||||
continue;
|
||||
}
|
||||
if( strcmp(argv[i], "help")==0 ){
|
||||
usage(argv[0]);
|
||||
continue;
|
||||
}
|
||||
if( !isdigit(argv[i][0]) ){
|
||||
fprintf(stderr, "%s: unknown option: [%s]\n", argv[0], argv[i]);
|
||||
continue;
|
||||
|
Loading…
Reference in New Issue
Block a user