Merge all the latest trunk changes into the sessions branch.

FossilOrigin-Name: d69d21903b883067c66dbcdefe6b369a6fe328b0
This commit is contained in:
drh 2013-03-06 02:12:18 +00:00
commit b05567ed4b
43 changed files with 1029 additions and 339 deletions

View File

@ -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 \

View File

@ -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

View File

@ -1 +1 @@
7e14dc734d7d941da5c3aa6612e26d93b5b929bd
d69d21903b883067c66dbcdefe6b369a6fe328b0

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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 */

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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 ),

View File

@ -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
};
/*

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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 );
}

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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>

View File

@ -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))

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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++;
}

View File

@ -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;

View File

@ -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);
}

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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
View 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

View File

@ -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}]

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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
View 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
View 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

View File

@ -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

View File

@ -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

View File

@ -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;