Compare commits

...

31 Commits

Author SHA1 Message Date
drh 0c0fb9cf80 Fix a minor typo in a comment.
FossilOrigin-Name: 06a5bf4348d3125bb5407fe9b7d451800b113a91fd1a9dff7d840e2317a7284d
2021-11-02 10:54:39 +00:00
larrybr 8f09f4b264 Add globbing option to shell's .archive command.
FossilOrigin-Name: 13fb74ac5e7578ab612af2ccc8147569d60dc35af84f496bcc5d648d223d6d6e
2021-11-02 00:18:11 +00:00
larrybr 719506f9af zap trailing whitespace
FossilOrigin-Name: f2a908e9c86efb11bb179ce7121f0d510f952284891abfa69517b773fd88324c
2021-11-01 22:33:20 +00:00
larrybr 7774fc010a Add a test for .ar -r and fix a use-of-uninitialized-variable bug
FossilOrigin-Name: 978d5ed4379b631a79cd46a75d9b5b403f3ec4ce7d9d52ed36a5678cdf04f7f2
2021-11-01 22:30:24 +00:00
larrybr 47061b9d57 Add --remove subcommand to shell's .archive command
FossilOrigin-Name: 23525449b883ae6e1d62100bdbc9ff2ca788f67e8ae7d7e4b1a770413a70a7f0
2021-11-01 17:22:52 +00:00
drh 16fc5e67a0 The VVA() macro in json1.c must be active during SQLITE_COVERAGE_TEST because
it affects the outcome of testcase() macros.

FossilOrigin-Name: 92c3d253797f9bde4670984d60bbd50b7b28540d2b5f503f318843580bab8765
2021-11-01 12:53:01 +00:00
drh d4cc4d02cb Add the sqlite3_autovacuum_pages() interface.
FossilOrigin-Name: ca2703c339f76101f25051a2ed380398b018782883bfee68b5f2d69a1de9091a
2021-10-30 20:22:32 +00:00
drh 362c181913 Fix an incorrect assert() statement in sqlite3GenerateConstraintChecks().
dbsqlfuzz 4190cff310aeab359a55f354e560db95d3a6f47d

FossilOrigin-Name: 623c0d086bda135c49bfc238c31498facdcbe8ecc7659cc1af61594df0c6e899
2021-10-30 18:17:59 +00:00
dan 21b1c6ddac Fix a memory leak in test code on this branch.
FossilOrigin-Name: 60cd9da9258e0b701d4bb3f9c91c5d0a12e925b9b937df619b09f33a287b4a33
2021-10-30 17:58:25 +00:00
dan e7c23433fb Merge trunk changes into this branch.
FossilOrigin-Name: 638c1b0c50229800067eb1ba29d829b4d6e008256c21a1f67b4ce4d19ea307b3
2021-10-30 17:30:48 +00:00
drh e4e1af5efb Reorder a test add earlier today to OP_Transaction for easier testing.
FossilOrigin-Name: 8ba73b3cadb72ffcf176d19f9f946c1b90b224e5ab9a0e9eb9a83affa7476d23
2021-10-29 16:19:03 +00:00
drh cfb5249622 Allow "VACUUM INTO" to change the page_size of a database even if the
original database is in WAL mode.  Enhancement suggested by
[forum:/forumpost/033f2c9d1f|forum post 033f2c9d1f].

FossilOrigin-Name: efc7e8c99a86e9d9eb81655ce96353847bd2cca64eb8f8d10e297f6f4d38e563
2021-10-29 13:10:02 +00:00
drh 37bbcb48a9 Add pragmas "multiplex_enabled", "multiplex_chunksize", and "multiplex_filecount" to the multiplexer implementation.
FossilOrigin-Name: 39c5e80dbf94ac3079b3e0c2c3e6608ac366e3f3de3cea4f4947addc3f52bc36
2021-10-29 12:29:22 +00:00
drh 8cb63f5a5e Fix the OP_Transaction opcode so that if an error other than SQLITE_SCHEMA
occurs first, the original error is not overwritten by SQLITE_SCHEMA.
dbsqlfuzz 85bf7e262017c6c7bddb03ff6d8541511985d36c.

FossilOrigin-Name: 5374226df4a2c1b59258839532b67a399c447ac8ec1408fdf2dffb9c41e1349e
2021-10-29 09:59:06 +00:00
larrybr 6ac9a5cf5a Fix .import -skip issue reported at https://sqlite.org/forum/forumpost/4c0816c24fc9d16f?t=h
FossilOrigin-Name: 3aadbe17edc1efc7fa6c9600de84e23242ba7866d2dcef2189afd7ba4c97979f
2021-10-28 19:49:23 +00:00
drh 33d28ab4cf Minor changes to make it easier for static analyzers to reason about the code.
FossilOrigin-Name: ba4104aa02625b51113978c1bb540b75bd88cb1959c7e9bfb4113db4159df5d4
2021-10-28 12:07:43 +00:00
drh e8837211bc Ensure that the WAL code correctly handles all possible outcomes from the
walIndexPage() routine.

FossilOrigin-Name: 6979efbf07d93e7afad508165df684dcc6fe33b91ca772397c8afa00d16d1a0d
2021-10-28 00:09:31 +00:00
drh eaad533e54 Ensure that all possible outcomes for walIndexPage() are accounted for by
callers.

FossilOrigin-Name: 12715c6b234a04627ca27e94bfa8bd456998360a9f0117480e0038f4747818d6
2021-10-27 23:55:30 +00:00
drh 71c3ea7523 Avoid the 1-based indexing on the WalHashLoc.aPgno[] array. Make it 0-indexed
instead.

FossilOrigin-Name: 28f5f709b4b28ba7f6f56bdd4a9e8c04d0d2df90d13d6df1a589fa4a65163f4d
2021-10-27 20:23:59 +00:00
drh 5f25627a1c Improve the comment on walIndexPage() to more accurately describe the
post-conditions.

FossilOrigin-Name: b619e936455f4001b543a9a58dea2ac9ebd598327d6be01130ca6e7e9764ffe6
2021-10-27 19:57:59 +00:00
drh 9b2adcc3d1 New assert()s to help prove correctness in sqlite3VdbeMemExpandBlob().
FossilOrigin-Name: 7238d58051bfdcea8f7a4aeab89145849d0659c987df9063aacafe97be6657fe
2021-10-27 19:05:04 +00:00
drh f76d287742 Fix the build for various the OMIT-everything compile-time option. No impact
on regular builds.

FossilOrigin-Name: 947805719bc8629619af5358ad50a6365c01f8d9ceabfe8e4df947696d3819b3
2021-10-27 17:15:08 +00:00
drh 90385ddcf1 Fix a harmless compiler warning in memdb.c.
FossilOrigin-Name: 22fdc658a7cc6d2c50957f92c19de74c9ac7d7d3498731d73e035b99a82bc406
2021-10-27 15:19:01 +00:00
drh be2d6fdd71 Fix a harmless compiler warning in fuzzcheck.
FossilOrigin-Name: 1cfb7e8a095e1e24df5117aa7be97470d8ce91837ff83dabebac53fafee0b09c
2021-10-27 15:16:30 +00:00
drh 662bebb6bd Change fuzzcheck so that it accepts binary dbsql files.
FossilOrigin-Name: c87a2426b81f22bd21543aa2408625ae472d8fe6cbe6b04145937066e61123c9
2021-10-27 13:16:33 +00:00
drh 075201e50f Add the --script option to fuzzcheck.
FossilOrigin-Name: 5a9676bd4945ca098652780515e94d04859e73588d9db5558ab42f8b068a9ddb
2021-10-27 12:05:28 +00:00
drh 48b4bf269c Enhance fuzzcheck so that if an argument is an ordinary disk file (not
a database) it is read in and processed as a script.

FossilOrigin-Name: 978dc89df521f5855678128b3c0eb503c67c1b97ddb297076e5f2c03d6297605
2021-10-26 22:36:41 +00:00
drh 9ce554baf7 Improved CLI error messages.
FossilOrigin-Name: 8443a2724f463bd2e14ea3aa337e8987104f63365767ca2b0993f3f3196cff95
2021-10-26 17:36:26 +00:00
drh 60a2fc8244 Merge multi-module test logic improvements from trunk.
FossilOrigin-Name: e00a44ac10d68b7bdaff1d9c237b598696eddc2d7392574aee1a95d94b4f165a
2021-10-19 19:26:27 +00:00
drh 7bf3d01a83 Merge trunk enhancements into the autovacuum-pages-callback branch.
FossilOrigin-Name: c26c9e5040ef4c52f2a99597e3a7c3eabd52c905d874fc76ca10fd54b749fa97
2021-10-19 18:00:05 +00:00
drh 1bbfc6744c Demostrate a prototype sqlite3_autovacuum_pages() interface.
FossilOrigin-Name: bb6f2b8b486c225043bc64e5f74ff6bbad6c5d1f337f0c81eeb6172b087bb943
2021-10-15 23:02:27 +00:00
29 changed files with 848 additions and 152 deletions
+1 -1
View File
@@ -111,7 +111,7 @@ static const char jsonIsSpace[] = {
# endif
# define testcase(X)
#endif
#if defined(NDEBUG)
#if !defined(SQLITE_DEBUG) && !defined(SQLITE_COVERAGE_TEST)
# define VVA(X)
#else
# define VVA(X) X
+33 -35
View File
@@ -1,5 +1,5 @@
C Add\sphase\sand\serror\snumber\sto\sCLI\serror\smessages.
D 2021-10-26T16:57:09.903
C Fix\sa\sminor\stypo\sin\sa\scomment.
D 2021-11-02T10:54:39.370
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -306,7 +306,7 @@ F ext/misc/fileio.c 57fefd0efc535e62bb8b07fa146875171481da81a759bbfbe2fc91bab900
F ext/misc/fossildelta.c 1240b2d3e52eab1d50c160c7fe1902a9bd210e052dc209200a750bbf885402d5
F ext/misc/fuzzer.c eae560134f66333e9e1ca4c8ffea75df42056e2ce8456734565dbe1c2a92bf3d
F ext/misc/ieee754.c 91a5594071143a4ab79c638fe9f059af1db09932faf2e704c3e29216a7d4f511
F ext/misc/json1.c 2ff65a8f97c9b8ae03124fe89a1b74197e68958882cb533daac8a694d1b81c57
F ext/misc/json1.c 1ad9d8f04f60f7a7c99e6a22ecf84d8f9bc0881782bed6c3d3a7bc6bf0213e2d
F ext/misc/memstat.c 3017a0832c645c0f8c773435620d663855f04690172316bd127270d1a7523d4d
F ext/misc/memtrace.c 7c0d115d2ef716ad0ba632c91e05bd119cb16c1aedf3bec9f06196ead2d5537b
F ext/misc/memvfs.c 7dffa8cc89c7f2d73da4bd4ccea1bcbd2bd283e3bb4cea398df7c372a197291b
@@ -490,7 +490,7 @@ F src/auth.c f4fa91b6a90bbc8e0d0f738aa284551739c9543a367071f55574681e0f24f8cf
F src/backup.c 3014889fa06e20e6adfa0d07b60097eec1f6e5b06671625f476a714d2356513d
F src/bitvec.c 7c849aac407230278445cb069bebc5f89bf2ddd87c5ed9459b070a9175707b3d
F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6
F src/btree.c 004c647dfb5332ee4b56385f3ac264ebea781cb00f7a1561a48f4a45b78fed61
F src/btree.c 2c8a52a7fd84b1aec4a79e7861b6368aecbf011a43247cc7d9a2946c7f0ae5ea
F src/btree.h 74d64b8f28cfa4a894d14d4ed64fa432cd697b98b61708d4351482ae15913e22
F src/btreeInt.h ee9348c4cb9077243b049edc93a82c1f32ca48baeabf2140d41362b9f9139ff7
F src/build.c 8bdda90f9b1189c7b0813575171b3c6b2d74b3ade57c11cb4383776781ea9335
@@ -501,7 +501,7 @@ F src/date.c fa928630fecf1d436cdc7a7a5c950c781709023ca782c21b7a43cc7361a9451e
F src/dbpage.c 8a01e865bf8bc6d7b1844b4314443a6436c07c3efe1d488ed89e81719047833a
F src/dbstat.c 861e08690fcb0f2ee1165eff0060ea8d4f3e2ea10f80dab7d32ad70443a6ff2d
F src/delete.c 0c151975fa99560767d7747f9b60543d0093d9f8b89f13d2d6058e9c83ad19e7
F src/expr.c 529f7eca2821e874a375b1b318e697d62cb28f56069677c93f587f2de5dceb54
F src/expr.c b882787df249b7de2f62c5c240ca8af2111839c761f1a5e9b8f501f940a9d92e
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
F src/fkey.c 187b67af20c5795953a592832c5d985e4313fe503ebd8f95e3e9e9ad5a730bb5
F src/func.c 1cfb09d7ffca81238eccefdb0293e1f5b7cfebbd1816dfad5ec6024742a7496b
@@ -510,17 +510,17 @@ F src/hash.c 8d7dda241d0ebdafb6ffdeda3149a412d7df75102cecfc1021c98d6219823b19
F src/hash.h 3340ab6e1d13e725571d7cee6d3e3135f0779a7d8e76a9ce0a85971fa3953c51
F src/hwtime.h cb1d7e3e1ed94b7aa6fde95ae2c2daccc3df826be26fc9ed7fd90d1750ae6144
F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
F src/insert.c b32e2dcbca838cb8acd4777a59243db4bcea53089e3181b0ea3e4dc75b43aeff
F src/insert.c 3f2892de7820d8e0b34a90bff8a3e2f879bc528683fa2ebb9e779ae56b64b741
F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
F src/loadext.c 0aa9e7f08e168e3874cb54984408e3976dafdf5616d511952c425b5ac088ea3e
F src/main.c bfe067d61ebbd0e6eb023f1fb6b353021e621cf1657e061d629064a740bfbf6f
F src/loadext.c e1dcff1c916bf6834e150b492eddda5d9792453182d2ad64294d2266b6e93c4c
F src/main.c 546dd2418c4f5d59aced76c68e55290735feb420ee305051fbd55ab8fff0d255
F src/malloc.c ef796bcc0e81d845d59a469f1cf235056caf9024172fd524e32136e65593647b
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de
F src/mem2.c c8bfc9446fd0798bddd495eb5d9dbafa7d4b7287d8c22d50a83ac9daa26d8a75
F src/mem3.c 30301196cace2a085cbedee1326a49f4b26deff0af68774ca82c1f7c06fda4f6
F src/mem5.c 9bf955937b07f8c32541c8a9991f33ce3173d944
F src/memdb.c ca36b36c497558abe8bf1fa6b6ad974db2275312ce30fc44e578e160688a7503
F src/memdb.c a6c2bb1257c3398b4dd058f81888d647472b140bb1d262d47be50606eed75d55
F src/memjournal.c a85f0dc5c02a42453d0bc3819ecfb5666cb6433e5deefcd93ccbe05c9f088b83
F src/msvc.h 3a15918220367a8876be3fa4f2abe423a861491e84b864fb2b7426bf022a28f8
F src/mutex.c 5e3409715552348732e97b9194abe92fdfcd934cfb681df4ba0ab87ac6c18d25
@@ -529,7 +529,7 @@ F src/mutex_noop.c 9d4309c075ba9cc7249e19412d3d62f7f94839c4
F src/mutex_unix.c dd2b3f1cc1863079bc1349ac0fec395a500090c4fe4e11ab775310a49f2f956d
F src/mutex_w32.c caa50e1c0258ac4443f52e00fe8aaea73b6d0728bd8856bedfff822cae418541
F src/notify.c 89a97dc854c3aa62ad5f384ef50c5a4a11d70fcc69f86de3e991573421130ed6
F src/os.c 91fc69f95ef0528368174dca20f01e1d8f82934f719e1cb50fd0260b18c028a6
F src/os.c b1c4f2d485961e9a5b6b648c36687d25047c252222e9660b7cc25a6e1ea436ab
F src/os.h 26890f540b475598cd9881dcc68931377b8d429d3ea3e2eeb64470cde64199f8
F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85
F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586
@@ -550,16 +550,16 @@ F src/random.c 097dc8b31b8fba5a9aca1697aeb9fd82078ec91be734c16bffda620ced7ab83c
F src/resolve.c ae65c88f5d0d4bc0052b203773d407efa2387c2bd6b202f87178006c7bb8632c
F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92
F src/select.c 32d25b5af6c708aa63373c78c2e59681910387a7a78c08ec3086cadc77d41627
F src/shell.c.in 6aefb37d9c87da9e33ae7d3541d07a24c8b74a4bc7b805a2a367d92fe5709108
F src/sqlite.h.in f0c1ecb5af508aa8e970cd8bc0ec851e6c380b81825038d458846c2fcdfcef50
F src/shell.c.in de92da03b04734618508a968d719e30e4c4bcc53ec7f341cdbf6a3d68ce9721c
F src/sqlite.h.in 99786216caf1c57aa3d70f95a7f84566dff6a9eeb50174799ea3b387eafd2a22
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h e97f4e9b509408fea4c4e9bef5a41608dfac343b4d3c7a990dedde1e19af9510
F src/sqliteInt.h 317bbdf926ec7c391fb00bcaa1f82799836a1151568bd9d343f43c2cdf1a48b9
F src/sqlite3ext.h d8f6f67ae9ad990a70dd03c093bcdc8883e159ff4bfd16a496f8fb80c6840b5a
F src/sqliteInt.h 02f7ccc971d67d8641707f219b9c304113d43a9a128b73a39d1fcaa036c885b7
F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a31657
F src/status.c 4b8bc2a6905163a38b739854a35b826c737333fab5b1f8e03fa7eb9a4799c4c1
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
F src/tclsqlite.c 428e813dabf82804bc13196af35a0c3c6ef4347fe557fa6717c5c66bba6e8520
F src/test1.c 63761c2be2607f1b425fde991beda48aed384f8d67f2b4ee549174c88b433009
F src/test1.c bd1c3c2637db35c0a69513e008c0e6a177b360ccae7689e0bf69f15b55e24bae
F src/test2.c 3efb99ab7f1fc8d154933e02ae1378bac9637da5
F src/test3.c 61798bb0d38b915067a8c8e03f5a534b431181f802659a6616f9b4ff7d872644
F src/test4.c 7c4420e01c577b5c4add2cb03119743b1a357543d347773b9e717195ea967159
@@ -588,7 +588,7 @@ F src/test_journal.c a0b9709b2f12b1ec819eea8a1176f283bca6d688a6d4a502bd6fd79786f
F src/test_loadext.c 337056bae59f80b9eb00ba82088b39d0f4fe6dfd
F src/test_malloc.c 21121ea85b49ec0bdb69995847cef9036ef9beca3ce63bbb776e4ea2ecc44b97
F src/test_md5.c 7268e1e8c399d4a5e181b64ac20e1e6f3bc4dd9fc87abac02db145a3d951fa8c
F src/test_multiplex.c 2ccf35551c094e353af20b0cdfac053a37bf3e96e10e7cf9f4abd1d279890a78
F src/test_multiplex.c 1b23782212a01349fac382913ef82b8de4ae8a4cb46556602c2ee733edabbbc9
F src/test_multiplex.h 5436d03f2d0501d04f3ed50a75819e190495b635
F src/test_mutex.c abf486e91bd65e2448027d4bb505e7cce6ba110e1afb9bd348d1996961cadf0d
F src/test_onefile.c f31e52e891c5fef6709b9fcef54ce660648a34172423a9cbdf4cbce3ba0049f4
@@ -620,20 +620,20 @@ F src/update.c 69c4c10bc6873a80c0a77cb578f9fc60ee90003d03f9530bc3370fa24615772d
F src/upsert.c 8789047a8f0a601ea42fa0256d1ba3190c13746b6ba940fe2d25643a7e991937
F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0
F src/util.c 30df8356e231dad33be10bb27897655002668343280004ba28c734489414a167
F src/vacuum.c 454973a59fb20bb982efc2df568a098616db6328a0491b6e84e2e07f7333db45
F src/vdbe.c a80943ed189ed5f4215636bde0aa7901319b051baffc0706f93a786bdf49ffcf
F src/vacuum.c 6c38ddc52f0619865c91dae9c441d4d48bf3040d7dc1bc5b22da1e45547ed0b3
F src/vdbe.c 54089e5ebb02d35e52d6b3d51061b79b8923c70e839df4ca4ff7bd9bcb9b9708
F src/vdbe.h 25dabb25c7e157b84e59260cfb5b466c3ac103ede9f36f4db371332c47601abe
F src/vdbeInt.h 38206c8dd6b60ff03d9fd4f626b1b4fd0eef7cdc44f2fc2c1973b0f932a3f26b
F src/vdbeapi.c 7b83468feb1d42a09d4c2e5241a3eaa3d1f138e289a843cba9fd3f1dad95ca67
F src/vdbeaux.c a57c760d1897f1b72f6fae26983df363db7a2c42d88721187e907f2c84862b42
F src/vdbeblob.c 292e96c01c4219fca71d74e1002906d43eb232af4bd83f7552a3faec741f3eb8
F src/vdbemem.c 8be0af1060012520381d3296fcb1718e80cd5b99ce04f51f7e1c4dba4072caac
F src/vdbesort.c 04292f8c569dc9ad2afc1d56d118f2cfab36ca65a3f02eef0b5b92bda01560be
F src/vdbemem.c 71a449c57be10a66a8a5620e5c5a67ebb9ca70121556dc631ffd4c4458708d8c
F src/vdbesort.c 513b481c8bab4a6578c92194a60cf3bc3b48736e4a53f8d2d7918121c5b594e7
F src/vdbetrace.c fe0bc29ebd4e02c8bc5c1945f1d2e6be5927ec12c06d89b03ef2a4def34bf823
F src/vdbevtab.c f99b275366c5fc5e2d99f734729880994ab9500bdafde7fae3b02d562b9d323c
F src/vtab.c d07cc24dd84b0b51bf05adb187b0d2e6b0cac56cfbc0197995a26d4f8fa5c7e2
F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
F src/wal.c 2be08331d798237ad5d7ae0b252700ffb2b63189cb18d993496d009a93e2f81c
F src/wal.c 6ae14d4797f31c67fc2be659d24fbc6e1a6f5f423bdfb5ef831ea171bce42320
F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a
F src/walker.c f890a3298418d7cba3b69b8803594fdc484ea241206a8dfa99db6dd36f8cbb3b
F src/where.c ecabef93b0f14442a73eca205fc960428984d75fbdc7d60226b7fc9cac127187
@@ -705,7 +705,8 @@ F test/autoindex2.test 12ef578928102baaa0dc23ad397601a2f4ecb0df
F test/autoindex3.test 2d13958a5617e987624a428d7aed91bf51f322b49b476e3573fadec697ce6da5
F test/autoindex4.test 49d3cd791a9baa16fb461d7ea3de80d019a819cf
F test/autoindex5.test 2ee94f033b87ca0160e08d81034c507aff8e230df2627f0304fa309b2fee19a3
F test/autovacuum.test 0831cd34e14695d297187f7f6519265e3121c5b0a1720e548e86829e796129e9
F test/autovacuum.test 00671369bbf96c6a49989a9425f5b78b94075d6a4b031e5e00000c2c32f365df
F test/autovacuum2.test 76f7eb4fe6a6bf6d33a196a7141dba98886d2fb53a268d7feca285d5da4759d7
F test/autovacuum_ioerr2.test 8a367b224183ad801e0e24dcb7d1501f45f244b4
F test/avfs.test 0c3a38e03cccb0fc3127838462dc05dc3f4c1480d770c084b388304c25de3652
F test/avtrans.test b7dc25459ecbd86c6fa9c606ee3068f59d81e225118617dcf2bbb6ded2ade89e
@@ -1055,7 +1056,7 @@ F test/fuzz3.test 9c813e6613b837cb7a277b0383cd66bfa07042b4cf0317157c35852f30043c
F test/fuzz4.test c229bcdb45518a89e1d208a21343e061503460ac69fae1539320a89f572eb634
F test/fuzz_common.tcl b7197de6ed1ee8250a4f82d67876f4561b42ee8cbbfc6160dcb66331bad3f830
F test/fuzz_malloc.test f348276e732e814802e39f042b1f6da6362a610af73a528d8f76898fde6b22f2
F test/fuzzcheck.c 5773a888c10080da4a3174b19136631a787735a0ee44aa1bc0078384b2caeb13
F test/fuzzcheck.c 7a07718e3c017f31e88b56a891bb79a3eb42a413a811fd65b89a7b09fdd1adbd
F test/fuzzdata1.db d36e88741b4f23bcbaaf55b006290669d03c6c891cf13c7b3a53bc1b097b693f
F test/fuzzdata2.db 128b3feeb78918d075c9b14b48610145a0dd4c8d6f1ca7c2870c7e425f5bf31f
F test/fuzzdata3.db c6586d3e3cef0fbc18108f9bb649aa77bfc38aba
@@ -1063,7 +1064,7 @@ F test/fuzzdata4.db b502c7d5498261715812dd8b3c2005bad08b3a26e6489414bd13926cd3e4
F test/fuzzdata5.db e35f64af17ec48926481cfaf3b3855e436bd40d1cfe2d59a9474cb4b748a52a5
F test/fuzzdata6.db 92a80e4afc172c24f662a10a612d188fb272de4a9bd19e017927c95f737de6d7
F test/fuzzdata7.db 0166b56fd7a6b9636a1d60ef0a060f86ddaecf99400a666bb6e5bbd7199ad1f2
F test/fuzzdata8.db e12b57c30566b9511ed8760eeccfb23e6361db9c43092032252e922ed942d67c
F test/fuzzdata8.db ea80e98f115387b052effb7194899cc9780a81f15606bc4641051342352020cc
F test/fuzzer1.test 3d4c4b7e547aba5e5511a2991e3e3d07166cfbb8
F test/fuzzer2.test a85ef814ce071293bce1ad8dffa217cbbaad4c14
F test/fuzzerfault.test f64c4aef4c9e9edf1d6dc0d3f1e65dcc81e67c996403c88d14f09b74807a42bc
@@ -1222,7 +1223,7 @@ F test/mmap3.test b3c297e78e6a8520aafcc1a8f140535594c9086e
F test/mmap4.test 2e2b4e32555b58da15176e6fe750f17c9dcf7f93
F test/mmapfault.test d4c9eff9cd8c2dc14bc43e71e042f175b0a26fe3
F test/mmapwarm.test 2272005969cd17a910077bd5082f70bc1fefad9a875afec7fc9af483898ecaf3
F test/multiplex.test dc0d67b66f84b484a83cb8bbdf3f0a7f49562ccd
F test/multiplex.test d74c034e52805f6de8cc5432cef8c9eb774bb64ec29b83a22effc8ca4dac1f08
F test/multiplex2.test 580ca5817c7edbe4cc68fa150609c9473393003a
F test/multiplex3.test d228f59eac91839a977eac19f21d053f03e4d101
F test/multiplex4.test e8ae4c4bd70606a5727743241f13b5701990abe4
@@ -1380,10 +1381,10 @@ F test/shell1.test c354008b27c904f0166c2138abd7382013ea070b41114114ecbdfb32c726a
F test/shell2.test f00a0501c00583cbc46f7510e1d713366326b2b3e63d06d15937284171a8787c
F test/shell3.test cb4b835a901742c9719437a89171172ecc4a8823ad97349af8e4e841e6f82566
F test/shell4.test 3ed6c4b42fd695efcbc25d69ef759dbb15855ca8e52ba6c5ee076f8b435f48be
F test/shell5.test 84a30b55722a95a5b72989e691c469a999ca7591e7aa00b7fabc783ea5c9a6fe
F test/shell5.test 6e4aa0e531dcb8dcf74b7920a2a7442c6712d4dff8422bbc81f768f9dee8a0e3
F test/shell6.test 1ceb51b2678c472ba6cf1e5da96679ce8347889fe2c3bf93a0e0fa73f00b00d3
F test/shell7.test 115132f66d0463417f408562cc2cf534f6bbc6d83a6d50f0072a9eb171bae97f
F test/shell8.test 96be02ea0c21f05b24c1883d7b711a1fa8525a68ab7b636aacf6057876941013
F test/shell8.test 388471d16e4de767333107e30653983f186232c0e863f4490bb230419e830aae
F test/shmlock.test 3dbf017d34ab0c60abe6a44e447d3552154bd0c87b41eaf5ceacd408dd13fda5
F test/shortread1.test bb591ef20f0fd9ed26d0d12e80eee6d7ac8897a3
F test/show_speedtest1_rtree.tcl 32e6c5f073d7426148a6936a0408f4b5b169aba5
@@ -1681,7 +1682,7 @@ F test/uri.test 3481026f00ade6dfe8adb7acb6e1e47b04369568
F test/uri2.test 9d3ba7a53ee167572d53a298ee4a5d38ec4a8fb7
F test/userauth01.test e740a2697a7b40d7c5003a7d7edaee16acd349a9
F test/utf16align.test 54cd35a27c005a9b6e7815d887718780b6a462ae
F test/vacuum-into.test 48f4cec354fb6f27c98ef58d2fe49a11b71ff131af0cd9140efacc9858b9f670
F test/vacuum-into.test c4c25dcf8ca909e33c1f5f0bb0f54b990c2c1dcbee7a4995843e79e40681a894
F test/vacuum.test ce91c39f7f91a4273bf620efad21086b5aa6ef1d
F test/vacuum2.test 9fd45ce6ce29f5614c249e03938d3567c06a9e772d4f155949f8eafe2d8af520
F test/vacuum3.test 77ecdd54592b45a0bcb133339f99f1ae0ae94d0d
@@ -1929,10 +1930,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P 4b41535b096dec4b15a85e657102a72d4288728da6103f3fdcbe0e6f244c673a
R 0e943f95c783da0ea080484e06b0d01a
T *branch * detail_cli_errors
T *sym-detail_cli_errors *
T -sym-trunk *
U larrybr
Z 75e901f51a636f4c844fe34247eb3a80
P 13fb74ac5e7578ab612af2ccc8147569d60dc35af84f496bcc5d648d223d6d6e
R 4ce534086d91ce8438a18251677b33c8
U drh
Z fc893d2685db3ae6f19a712413bc458d
+1 -1
View File
@@ -1 +1 @@
7f87a298688c37bbad8fd2e1cf0e8fbcc36f0c211dcfa3685298525648dbe21b
06a5bf4348d3125bb5407fe9b7d451800b113a91fd1a9dff7d840e2317a7284d
+40 -13
View File
@@ -3939,16 +3939,18 @@ int sqlite3BtreeIncrVacuum(Btree *p){
/*
** This routine is called prior to sqlite3PagerCommit when a transaction
** is committed for an auto-vacuum database.
**
** If SQLITE_OK is returned, then *pnTrunc is set to the number of pages
** the database file should be truncated to during the commit process.
** i.e. the database has been reorganized so that only the first *pnTrunc
** pages are in use.
*/
static int autoVacuumCommit(BtShared *pBt){
static int autoVacuumCommit(Btree *p){
int rc = SQLITE_OK;
Pager *pPager = pBt->pPager;
VVA_ONLY( int nRef = sqlite3PagerRefcount(pPager); )
Pager *pPager;
BtShared *pBt;
sqlite3 *db;
VVA_ONLY( int nRef );
assert( p!=0 );
pBt = p->pBt;
pPager = pBt->pPager;
VVA_ONLY( nRef = sqlite3PagerRefcount(pPager); )
assert( sqlite3_mutex_held(pBt->mutex) );
invalidateAllOverflowCache(pBt);
@@ -3956,6 +3958,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 nVac; /* Number of pages to vacuum */
Pgno iFree; /* The next page to be freed */
Pgno nOrig; /* Database size before freeing */
@@ -3969,18 +3972,42 @@ static int autoVacuumCommit(BtShared *pBt){
}
nFree = get4byte(&pBt->pPage1->aData[36]);
nFin = finalDbSize(pBt, nOrig, nFree);
db = p->db;
if( db->xAutovacPages ){
int iDb;
for(iDb=0; ALWAYS(iDb<db->nDb); iDb++){
if( db->aDb[iDb].pBt==p ) break;
}
nVac = db->xAutovacPages(
db->pAutovacPagesArg,
db->aDb[iDb].zDbSName,
nOrig,
nFree,
pBt->pageSize
);
if( nVac>nFree ){
nVac = nFree;
}
if( nVac==0 ){
return SQLITE_OK;
}
}else{
nVac = nFree;
}
nFin = finalDbSize(pBt, nOrig, nVac);
if( nFin>nOrig ) return SQLITE_CORRUPT_BKPT;
if( nFin<nOrig ){
rc = saveAllCursors(pBt, 0, 0);
}
for(iFree=nOrig; iFree>nFin && rc==SQLITE_OK; iFree--){
rc = incrVacuumStep(pBt, nFin, iFree, 1);
rc = incrVacuumStep(pBt, nFin, iFree, nVac==nFree);
}
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);
if( nVac==nFree ){
put4byte(&pBt->pPage1->aData[32], 0);
put4byte(&pBt->pPage1->aData[36], 0);
}
put4byte(&pBt->pPage1->aData[28], nFin);
pBt->bDoTruncate = 1;
pBt->nPage = nFin;
@@ -4031,7 +4058,7 @@ int sqlite3BtreeCommitPhaseOne(Btree *p, const char *zSuperJrnl){
sqlite3BtreeEnter(p);
#ifndef SQLITE_OMIT_AUTOVACUUM
if( pBt->autoVacuum ){
rc = autoVacuumCommit(pBt);
rc = autoVacuumCommit(p);
if( rc!=SQLITE_OK ){
sqlite3BtreeLeave(p);
return rc;
+1 -1
View File
@@ -1748,7 +1748,7 @@ Select *sqlite3SelectDup(sqlite3 *db, const Select *pDup, int flags){
return pRet;
}
#else
Select *sqlite3SelectDup(sqlite3 *db, Select *p, int flags){
Select *sqlite3SelectDup(sqlite3 *db, const Select *p, int flags){
assert( p==0 );
return 0;
}
+5 -3
View File
@@ -2327,7 +2327,8 @@ void sqlite3GenerateConstraintChecks(
assert( onError==OE_Replace );
nConflictCk = sqlite3VdbeCurrentAddr(v) - addrConflictCk;
assert( nConflictCk>0 );
assert( nConflictCk>0 || db->mallocFailed );
testcase( nConflictCk<=0 );
testcase( nConflictCk>1 );
if( regTrigCnt ){
sqlite3MultiWrite(pParse);
@@ -2613,8 +2614,9 @@ int sqlite3OpenTableAndIndices(
assert( op==OP_OpenWrite || p5==0 );
if( IsVirtual(pTab) ){
/* This routine is a no-op for virtual tables. Leave the output
** variables *piDataCur and *piIdxCur uninitialized so that valgrind
** can detect if they are used by mistake in the caller. */
** variables *piDataCur and *piIdxCur set to illegal cursor numbers
** for improved error detection. */
*piDataCur = *piIdxCur = -999;
return 0;
}
iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
+2
View File
@@ -483,6 +483,8 @@ static const sqlite3_api_routines sqlite3Apis = {
/* Version 3.36.1 and later */
sqlite3_changes64,
sqlite3_total_changes64,
/* Version 3.37.0 and later */
sqlite3_autovacuum_pages,
};
/* True if x is the directory separator character
+31
View File
@@ -1403,6 +1403,9 @@ void sqlite3LeaveMutexAndCloseZombie(sqlite3 *db){
** structure?
*/
sqlite3DbFree(db, db->aDb[1].pSchema);
if( db->xAutovacDestr ){
db->xAutovacDestr(db->pAutovacPagesArg);
}
sqlite3_mutex_leave(db->mutex);
db->eOpenState = SQLITE_STATE_CLOSED;
sqlite3_mutex_free(db->mutex);
@@ -2304,6 +2307,34 @@ void *sqlite3_preupdate_hook(
}
#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */
/*
** Register a function to be invoked prior to each autovacuum that
** determines the number of pages to vacuum.
*/
int sqlite3_autovacuum_pages(
sqlite3 *db, /* Attach the hook to this database */
unsigned int (*xCallback)(void*,const char*,u32,u32,u32),
void *pArg, /* Argument to the function */
void (*xDestructor)(void*) /* Destructor for pArg */
){
#ifdef SQLITE_ENABLE_API_ARMOR
if( !sqlite3SafetyCheckOk(db) ){
if( xDestructor ) xDestructor(pArg);
return SQLITE_MISUSE_BKPT;
}
#endif
sqlite3_mutex_enter(db->mutex);
if( db->xAutovacDestr ){
db->xAutovacDestr(db->pAutovacPagesArg);
}
db->xAutovacPages = xCallback;
db->pAutovacPagesArg = pArg;
db->xAutovacDestr = xDestructor;
sqlite3_mutex_leave(db->mutex);
return SQLITE_OK;
}
#ifndef SQLITE_OMIT_WAL
/*
** The sqlite3_wal_hook() callback registered by sqlite3_wal_autocheckpoint().
+1
View File
@@ -505,6 +505,7 @@ static int memdbOpen(
MemFile *pFile = (MemFile*)pFd;
MemStore *p = 0;
int szName;
UNUSED_PARAMETER(pVfs);
memset(pFile, 0, sizeof(*pFile));
szName = sqlite3Strlen30(zName);
+3
View File
@@ -316,12 +316,15 @@ int sqlite3OsOpenMalloc(
rc = sqlite3OsOpen(pVfs, zFile, pFile, flags, pOutFlags);
if( rc!=SQLITE_OK ){
sqlite3_free(pFile);
*ppFile = 0;
}else{
*ppFile = pFile;
}
}else{
*ppFile = 0;
rc = SQLITE_NOMEM_BKPT;
}
assert( *ppFile!=0 || rc!=SQLITE_OK );
return rc;
}
void sqlite3OsCloseFree(sqlite3_file *pFile){
+84 -19
View File
@@ -3965,6 +3965,7 @@ static const char *(azHelp[]) = {
" -c, --create Create a new archive",
" -u, --update Add or update files with changed mtime",
" -i, --insert Like -u but always add even if unchanged",
" -r, --remove Remove files from archive",
" -t, --list List contents of archive",
" -x, --extract Extract files from archive",
" Optional arguments:",
@@ -3972,6 +3973,7 @@ static const char *(azHelp[]) = {
" -f FILE, --file FILE Use archive FILE (default is current db)",
" -a FILE, --append FILE Open FILE using the apndvfs VFS",
" -C DIR, --directory DIR Read/extract files from directory DIR",
" -g, --glob Use glob matching for names in archive",
" -n, --dryrun Show the SQL that would have occurred",
" Examples:",
" .ar -cf ARCHIVE foo bar # Create ARCHIVE from files foo and bar",
@@ -6132,6 +6134,7 @@ struct ArCommand {
u8 bZip; /* True if the archive is a ZIP */
u8 bDryRun; /* True if --dry-run */
u8 bAppend; /* True if --append */
u8 bGlob; /* True if --glob */
u8 fromCmdLine; /* Run from -A instead of .archive */
int nArg; /* Number of command arguments */
char *zSrcTable; /* "sqlar", "zipfile($file)" or "zip" */
@@ -6179,21 +6182,24 @@ static int arErrorMsg(ArCommand *pAr, const char *zFmt, ...){
#define AR_CMD_EXTRACT 4
#define AR_CMD_LIST 5
#define AR_CMD_HELP 6
#define AR_CMD_REMOVE 7
/*
** Other (non-command) switches.
*/
#define AR_SWITCH_VERBOSE 7
#define AR_SWITCH_FILE 8
#define AR_SWITCH_DIRECTORY 9
#define AR_SWITCH_APPEND 10
#define AR_SWITCH_DRYRUN 11
#define AR_SWITCH_VERBOSE 8
#define AR_SWITCH_FILE 9
#define AR_SWITCH_DIRECTORY 10
#define AR_SWITCH_APPEND 11
#define AR_SWITCH_DRYRUN 12
#define AR_SWITCH_GLOB 13
static int arProcessSwitch(ArCommand *pAr, int eSwitch, const char *zArg){
switch( eSwitch ){
case AR_CMD_CREATE:
case AR_CMD_EXTRACT:
case AR_CMD_LIST:
case AR_CMD_REMOVE:
case AR_CMD_UPDATE:
case AR_CMD_INSERT:
case AR_CMD_HELP:
@@ -6206,6 +6212,9 @@ static int arProcessSwitch(ArCommand *pAr, int eSwitch, const char *zArg){
case AR_SWITCH_DRYRUN:
pAr->bDryRun = 1;
break;
case AR_SWITCH_GLOB:
pAr->bGlob = 1;
break;
case AR_SWITCH_VERBOSE:
pAr->bVerbose = 1;
break;
@@ -6244,6 +6253,7 @@ static int arParseCommand(
{ "extract", 'x', AR_CMD_EXTRACT, 0 },
{ "insert", 'i', AR_CMD_INSERT, 0 },
{ "list", 't', AR_CMD_LIST, 0 },
{ "remove", 'r', AR_CMD_REMOVE, 0 },
{ "update", 'u', AR_CMD_UPDATE, 0 },
{ "help", 'h', AR_CMD_HELP, 0 },
{ "verbose", 'v', AR_SWITCH_VERBOSE, 0 },
@@ -6251,6 +6261,7 @@ static int arParseCommand(
{ "append", 'a', AR_SWITCH_APPEND, 1 },
{ "directory", 'C', AR_SWITCH_DIRECTORY, 1 },
{ "dryrun", 'n', AR_SWITCH_DRYRUN, 0 },
{ "glob", 'g', AR_SWITCH_GLOB, 0 },
};
int nSwitch = sizeof(aSwitch) / sizeof(struct ArSwitch);
struct ArSwitch *pEnd = &aSwitch[nSwitch];
@@ -6367,11 +6378,13 @@ static int arParseCommand(
/*
** This function assumes that all arguments within the ArCommand.azArg[]
** array refer to archive members, as for the --extract or --list commands.
** It checks that each of them are present. If any specified file is not
** present in the archive, an error is printed to stderr and an error
** code returned. Otherwise, if all specified arguments are present in
** the archive, SQLITE_OK is returned.
** array refer to archive members, as for the --extract, --list or --remove
** commands. It checks that each of them are "present". If any specified
** file is not present in the archive, an error is printed to stderr and an
** error code returned. Otherwise, if all specified arguments are present
** in the archive, SQLITE_OK is returned. Here, "present" means either an
** exact equality when pAr->bGlob is false or a "name GLOB pattern" match
** when pAr->bGlob is true.
**
** This function strips any trailing '/' characters from each argument.
** This is consistent with the way the [tar] command seems to work on
@@ -6382,11 +6395,11 @@ static int arCheckEntries(ArCommand *pAr){
if( pAr->nArg ){
int i, j;
sqlite3_stmt *pTest = 0;
const char *zSel = (pAr->bGlob)
? "SELECT name FROM %s WHERE glob($name,name)"
: "SELECT name FROM %s WHERE name=$name";
shellPreparePrintf(pAr->db, &rc, &pTest,
"SELECT name FROM %s WHERE name=$name",
pAr->zSrcTable
);
shellPreparePrintf(pAr->db, &rc, &pTest, zSel, pAr->zSrcTable);
j = sqlite3_bind_parameter_index(pTest, "$name");
for(i=0; i<pAr->nArg && rc==SQLITE_OK; i++){
char *z = pAr->azArg[i];
@@ -6414,14 +6427,16 @@ static int arCheckEntries(ArCommand *pAr){
** identify all archive members that match the command arguments held
** in (*pAr). Leave this WHERE clause in (*pzWhere) before returning.
** The caller is responsible for eventually calling sqlite3_free() on
** any non-NULL (*pzWhere) value.
** any non-NULL (*pzWhere) value. Here, "match" means strict equality
** when pAr->bGlob is false and GLOB match when pAr->bGlob is true.
*/
static void arWhereClause(
int *pRc,
ArCommand *pAr,
ArCommand *pAr,
char **pzWhere /* OUT: New WHERE clause */
){
char *zWhere = 0;
const char *zSameOp = (pAr->bGlob)? "GLOB" : "=";
if( *pRc==SQLITE_OK ){
if( pAr->nArg==0 ){
zWhere = sqlite3_mprintf("1");
@@ -6431,8 +6446,8 @@ static void arWhereClause(
for(i=0; i<pAr->nArg; i++){
const char *z = pAr->azArg[i];
zWhere = sqlite3_mprintf(
"%z%s name = '%q' OR substr(name,1,%d) = '%q/'",
zWhere, zSep, z, strlen30(z)+1, z
"%z%s name %s '%q' OR substr(name,1,%d) %s '%q/'",
zWhere, zSep, zSameOp, z, strlen30(z)+1, zSameOp, z
);
if( zWhere==0 ){
*pRc = SQLITE_NOMEM;
@@ -6486,6 +6501,47 @@ static int arListCommand(ArCommand *pAr){
}
/*
** Implementation of .ar "Remove" command.
*/
static int arRemoveCommand(ArCommand *pAr){
int rc = 0;
char *zSql = 0;
char *zWhere = 0;
if( pAr->nArg ){
/* Verify that args actually exist within the archive before proceeding.
** And formulate a WHERE clause to match them. */
rc = arCheckEntries(pAr);
arWhereClause(&rc, pAr, &zWhere);
}
if( rc==SQLITE_OK ){
zSql = sqlite3_mprintf("DELETE FROM %s WHERE %s;",
pAr->zSrcTable, zWhere);
if( pAr->bDryRun ){
utf8_printf(pAr->p->out, "%s\n", zSql);
}else{
char *zErr = 0;
rc = sqlite3_exec(pAr->db, "SAVEPOINT ar;", 0, 0, 0);
if( rc==SQLITE_OK ){
rc = sqlite3_exec(pAr->db, zSql, 0, 0, &zErr);
if( rc!=SQLITE_OK ){
sqlite3_exec(pAr->db, "ROLLBACK TO ar; RELEASE ar;", 0, 0, 0);
}else{
rc = sqlite3_exec(pAr->db, "RELEASE ar;", 0, 0, 0);
}
}
if( zErr ){
utf8_printf(stdout, "ERROR: %s\n", zErr);
sqlite3_free(zErr);
}
}
}
sqlite3_free(zWhere);
sqlite3_free(zSql);
return rc;
}
/*
** Implementation of .ar "eXtract" command.
*/
@@ -6738,7 +6794,7 @@ static int arDotCommand(
int flags;
if( cmd.bAppend ) eDbType = SHELL_OPEN_APPENDVFS;
if( cmd.eCmd==AR_CMD_CREATE || cmd.eCmd==AR_CMD_INSERT
|| cmd.eCmd==AR_CMD_UPDATE ){
|| cmd.eCmd==AR_CMD_REMOVE || cmd.eCmd==AR_CMD_UPDATE ){
flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE;
}else{
flags = SQLITE_OPEN_READONLY;
@@ -6794,6 +6850,10 @@ static int arDotCommand(
rc = arCreateOrUpdateCommand(&cmd, 1, 0);
break;
case AR_CMD_REMOVE:
rc = arRemoveCommand(&cmd);
break;
default:
assert( cmd.eCmd==AR_CMD_UPDATE );
rc = arCreateOrUpdateCommand(&cmd, 1, 1);
@@ -8282,6 +8342,11 @@ static int do_meta_command(char *zLine, ShellState *p){
failIfSafeMode(p, "cannot run .import in safe mode");
memset(&sCtx, 0, sizeof(sCtx));
sCtx.z = sqlite3_malloc64(120);
if( sCtx.z==0 ){
import_cleanup(&sCtx);
shell_out_of_memory();
}
if( p->mode==MODE_Ascii ){
xRead = ascii_read_one_field;
}else{
+66
View File
@@ -6406,6 +6406,72 @@ sqlite3_stmt *sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt);
void *sqlite3_commit_hook(sqlite3*, int(*)(void*), void*);
void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*);
/*
** CAPI3REF: Autovacuum Compaction Amount Callback
** METHOD: sqlite3
**
** ^The sqlite3_autovacuum_pages(D,C,P,X) interface registers a callback
** function C that is invoked prior to each autovacuum of the database
** file. ^The callback is passed a copy of the generic data pointer (P),
** the schema-name of the attached database that is being autovacuumed,
** the the size of the database file in pages, the number of free pages,
** and the number of bytes per page, respectively. The callback should
** return the number of free pages that should be removed by the
** autovacuum. ^If the callback returns zero, then no autovacuum happens.
** ^If the value returned is greater than or equal to the number of
** free pages, then a complete autovacuum happens.
**
** <p>^If there are multiple ATTACH-ed database files that are being
** modified as part of a transaction commit, then the autovacuum pages
** callback is invoked separately for each file.
**
** <p><b>The callback is not reentrant.</b> The callback function should
** not attempt to invoke any other SQLite interface. If it does, bad
** things may happen, including segmentation faults and corrupt database
** files. The callback function should be a simple function that
** does some arithmetic on its input parameters and returns a result.
**
** ^The X parameter to sqlite3_autovacuum_pages(D,C,P,X) is an optional
** destructor for the P parameter. ^If X is not NULL, then X(P) is
** invoked whenever the database connection closes or when the callback
** is overwritten by another invocation of sqlite3_autovacuum_pages().
**
** <p>^There is only one autovacuum pages callback per database connection.
** ^Each call to the sqlite3_autovacuum_pages() interface overrides all
** previous invocations for that database connection. ^If the callback
** argument (C) to sqlite3_autovacuum_pages(D,C,P,X) is a NULL pointer,
** then the autovacuum steps callback is cancelled. The return value
** from sqlite3_autovacuum_pages() is normally SQLITE_OK, but might
** be some other error code if something goes wrong. The current
** implementation will only return SQLITE_OK or SQLITE_MISUSE, but other
** return codes might be added in future releases.
**
** <p>If no autovacuum pages callback is specified (the usual case) or
** a NULL pointer is provided for the callback,
** then the default behavior is to vacuum all free pages. So, in other
** words, the default behavior is the same as if the callback function
** were something like this:
**
** <blockquote><pre>
** &nbsp; unsigned int demonstration_autovac_pages_callback(
** &nbsp; void *pClientData,
** &nbsp; const char *zSchema,
** &nbsp; unsigned int nDbPage,
** &nbsp; unsigned int nFreePage,
** &nbsp; unsigned int nBytePerPage
** &nbsp; ){
** &nbsp; return nFreePage;
** &nbsp; }
** </pre></blockquote>
*/
int sqlite3_autovacuum_pages(
sqlite3 *db,
unsigned int(*)(void*,const char*,unsigned int,unsigned int,unsigned int),
void*,
void(*)(void*)
);
/*
** CAPI3REF: Data Change Notification Callbacks
** METHOD: sqlite3
+9
View File
@@ -340,6 +340,10 @@ struct sqlite3_api_routines {
/* Version 3.36.1 and later */
sqlite3_int64 (*changes64)(sqlite3*);
sqlite3_int64 (*total_changes64)(sqlite3*);
/* Version 3.37.0 and later */
int (*autovacuum_pages)(sqlite3*,
unsigned int(*)(void*,const char*,unsigned int,unsigned int,unsigned int),
void*, void(*)(void*));
};
/*
@@ -646,6 +650,11 @@ typedef int (*sqlite3_loadext_entry)(
#define sqlite3_database_file_object sqlite3_api->database_file_object
/* Version 3.34.0 and later */
#define sqlite3_txn_state sqlite3_api->txn_state
/* Version 3.36.1 and later */
#define sqlite3_changes64 sqlite3_api->changes64
#define sqlite3_total_changes64 sqlite3_api->total_changes64
* Version 3.37.0 and later */
#define sqlite3_autovacuum_pages sqlite3_api->autovacuum_pages
#endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */
#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
+3
View File
@@ -1566,6 +1566,9 @@ struct sqlite3 {
void (*xRollbackCallback)(void*); /* Invoked at every commit. */
void *pUpdateArg;
void (*xUpdateCallback)(void*,int, const char*,const char*,sqlite_int64);
void *pAutovacPagesArg; /* Client argument to autovac_pages */
void (*xAutovacDestr)(void*); /* Destructor for pAutovacPAgesArg */
unsigned int (*xAutovacPages)(void*,const char*,u32,u32,u32);
Parse *pParse; /* Current parse */
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
void *pPreUpdateArg; /* First argument to xPreUpdateCallback */
+91
View File
@@ -8233,6 +8233,96 @@ static int SQLITE_TCLAPI test_decode_hexdb(
return TCL_OK;
}
/*
** Client data for the autovacuum_pages callback.
*/
struct AutovacPageData {
Tcl_Interp *interp;
char *zScript;
};
typedef struct AutovacPageData AutovacPageData;
/*
** Callback functions for sqlite3_autovacuum_pages
*/
static unsigned int test_autovacuum_pages_callback(
void *pClientData,
const char *zSchema,
unsigned int nFilePages,
unsigned int nFreePages,
unsigned int nBytePerPage
){
AutovacPageData *pData = (AutovacPageData*)pClientData;
Tcl_DString str;
unsigned int x;
char zBuf[100];
Tcl_DStringInit(&str);
Tcl_DStringAppend(&str, pData->zScript, -1);
Tcl_DStringAppendElement(&str, zSchema);
sqlite3_snprintf(sizeof(zBuf), zBuf, "%u", nFilePages);
Tcl_DStringAppendElement(&str, zBuf);
sqlite3_snprintf(sizeof(zBuf), zBuf, "%u", nFreePages);
Tcl_DStringAppendElement(&str, zBuf);
sqlite3_snprintf(sizeof(zBuf), zBuf, "%u", nBytePerPage);
Tcl_DStringAppendElement(&str, zBuf);
Tcl_ResetResult(pData->interp);
Tcl_Eval(pData->interp, Tcl_DStringValue(&str));
Tcl_DStringFree(&str);
x = nFreePages;
(void)Tcl_GetIntFromObj(0, Tcl_GetObjResult(pData->interp), (int*)&x);
return x;
}
/*
** Usage: sqlite3_autovacuum_pages DB SCRIPT
**
** Add an autovacuum-pages callback to database connection DB. The callback
** will invoke SCRIPT, after appending parameters.
**
** If SCRIPT is an empty string or is omitted, then the callback is
** cancelled.
*/
static int SQLITE_TCLAPI test_autovacuum_pages(
void * clientData,
Tcl_Interp *interp,
int objc,
Tcl_Obj *CONST objv[]
){
AutovacPageData *pData;
sqlite3 *db;
int rc;
const char *zScript;
if( objc!=2 && objc!=3 ){
Tcl_WrongNumArgs(interp, 1, objv, "DB ?SCRIPT?");
return TCL_ERROR;
}
if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
zScript = objc==3 ? Tcl_GetString(objv[2]) : 0;
if( zScript ){
size_t nScript = strlen(zScript);
pData = sqlite3_malloc64( sizeof(*pData) + nScript + 1 );
if( pData==0 ){
Tcl_AppendResult(interp, "out of memory", (void*)0);
return TCL_ERROR;
}
pData->interp = interp;
pData->zScript = (char*)&pData[1];
memcpy(pData->zScript, zScript, nScript+1);
rc = sqlite3_autovacuum_pages(db,test_autovacuum_pages_callback,
pData, sqlite3_free);
}else{
rc = sqlite3_autovacuum_pages(db, 0, 0, 0);
}
if( rc ){
char zBuf[1000];
sqlite3_snprintf(sizeof(zBuf), zBuf,
"sqlite3_autovacuum_pages() returns %d", rc);
Tcl_AppendResult(interp, zBuf, (void*)0);
return TCL_ERROR;
}
return TCL_OK;
}
/*
** Register commands with the TCL interpreter.
@@ -8524,6 +8614,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
{ "atomic_batch_write", test_atomic_batch_write, 0 },
{ "sqlite3_mmap_warm", test_mmap_warm, 0 },
{ "sqlite3_config_sorterref", test_config_sorterref, 0 },
{ "sqlite3_autovacuum_pages", test_autovacuum_pages, 0 },
{ "decode_hexdb", test_decode_hexdb, 0 },
{ "test_write_db", test_write_db, 0 },
{ "sqlite3_register_cksumvfs", test_register_cksumvfs, 0 },
+72 -19
View File
@@ -962,26 +962,79 @@ static int multiplexFileControl(sqlite3_file *pConn, int op, void *pArg){
** element is the argument to the pragma or NULL if the pragma has no
** argument.
*/
if( aFcntl[1] && sqlite3_stricmp(aFcntl[1],"multiplex_truncate")==0 ){
if( aFcntl[2] && aFcntl[2][0] ){
if( sqlite3_stricmp(aFcntl[2], "on")==0
|| sqlite3_stricmp(aFcntl[2], "1")==0 ){
pGroup->bTruncate = 1;
}else
if( sqlite3_stricmp(aFcntl[2], "off")==0
|| sqlite3_stricmp(aFcntl[2], "0")==0 ){
pGroup->bTruncate = 0;
}
}
/* EVIDENCE-OF: R-27806-26076 The handler for an SQLITE_FCNTL_PRAGMA
** file control can optionally make the first element of the char**
** argument point to a string obtained from sqlite3_mprintf() or the
** equivalent and that string will become the result of the pragma
** or the error message if the pragma fails.
if( aFcntl[1] && sqlite3_strnicmp(aFcntl[1],"multiplex_",10)==0 ){
sqlite3_int64 sz = 0;
(void)multiplexFileSize(pConn, &sz);
/*
** PRAGMA multiplex_truncate=BOOLEAN;
** PRAGMA multiplex_truncate;
**
** Turn the multiplexor truncate feature on or off. Return either
** "on" or "off" to indicate the new setting. If the BOOLEAN argument
** is omitted, just return the current value for the truncate setting.
*/
aFcntl[0] = sqlite3_mprintf(pGroup->bTruncate ? "on" : "off");
rc = SQLITE_OK;
break;
if( sqlite3_stricmp(aFcntl[1],"multiplex_truncate")==0 ){
if( aFcntl[2] && aFcntl[2][0] ){
if( sqlite3_stricmp(aFcntl[2], "on")==0
|| sqlite3_stricmp(aFcntl[2], "1")==0 ){
pGroup->bTruncate = 1;
}else
if( sqlite3_stricmp(aFcntl[2], "off")==0
|| sqlite3_stricmp(aFcntl[2], "0")==0 ){
pGroup->bTruncate = 0;
}
}
/* EVIDENCE-OF: R-27806-26076 The handler for an SQLITE_FCNTL_PRAGMA
** file control can optionally make the first element of the char**
** argument point to a string obtained from sqlite3_mprintf() or the
** equivalent and that string will become the result of the pragma
** or the error message if the pragma fails.
*/
aFcntl[0] = sqlite3_mprintf(pGroup->bTruncate ? "on" : "off");
rc = SQLITE_OK;
break;
}
/*
** PRAGMA multiplex_enabled;
**
** Return 0 or 1 depending on whether the multiplexor is enabled or
** disabled, respectively.
*/
if( sqlite3_stricmp(aFcntl[1],"multiplex_enabled")==0 ){
aFcntl[0] = sqlite3_mprintf("%d", pGroup->bEnabled!=0);
rc = SQLITE_OK;
break;
}
/*
** PRAGMA multiplex_chunksize;
**
** Return the chunksize for the multiplexor, or no-op if the
** multiplexor is not active.
*/
if( sqlite3_stricmp(aFcntl[1],"multiplex_chunksize")==0
&& pGroup->bEnabled
){
aFcntl[0] = sqlite3_mprintf("%u", pGroup->szChunk);
rc = SQLITE_OK;
break;
}
/*
** PRAGMA multiplex_filecount;
**
** Return the number of disk files currently in use by the
** multiplexor. This should be the total database size size
** divided by the chunksize and rounded up.
*/
if( sqlite3_stricmp(aFcntl[1],"multiplex_filecount")==0 ){
int n = 0;
int ii;
for(ii=0; ii<pGroup->nReal; ii++){
if( pGroup->aReal[ii].p!=0 ) n++;
}
aFcntl[0] = sqlite3_mprintf("%d", n);
rc = SQLITE_OK;
break;
}
}
/* If the multiplexor does not handle the pragma, pass it through
** into the default case. */
+3 -1
View File
@@ -250,7 +250,9 @@ SQLITE_NOINLINE int sqlite3RunVacuum(
/* Do not attempt to change the page size for a WAL database */
if( sqlite3PagerGetJournalMode(sqlite3BtreePager(pMain))
==PAGER_JOURNALMODE_WAL ){
==PAGER_JOURNALMODE_WAL
&& pOut==0
){
db->nextPagesize = 0;
}
+3 -1
View File
@@ -3656,6 +3656,7 @@ case OP_Transaction: {
assert( pOp->p2>=0 && pOp->p2<=2 );
assert( pOp->p1>=0 && pOp->p1<db->nDb );
assert( DbMaskTest(p->btreeMask, pOp->p1) );
assert( rc==SQLITE_OK );
if( pOp->p2 && (db->flags & SQLITE_QueryOnly)!=0 ){
rc = SQLITE_READONLY;
goto abort_due_to_error;
@@ -3699,7 +3700,8 @@ case OP_Transaction: {
}
}
assert( pOp->p5==0 || pOp->p4type==P4_INT32 );
if( pOp->p5
if( rc==SQLITE_OK
&& pOp->p5
&& (iMeta!=pOp->p3
|| db->aDb[pOp->p1].pSchema->iGeneration!=pOp->p4.i)
){
+2
View File
@@ -374,6 +374,8 @@ int sqlite3VdbeMemExpandBlob(Mem *pMem){
if( sqlite3VdbeMemGrow(pMem, nByte, 1) ){
return SQLITE_NOMEM_BKPT;
}
assert( pMem->z!=0 );
assert( sqlite3DbMallocSize(pMem->db,pMem->z) >= nByte );
memset(&pMem->z[pMem->n], 0, pMem->u.nZero);
pMem->n += pMem->u.nZero;
+1
View File
@@ -2007,6 +2007,7 @@ static int vdbeIncrMergerNew(
vdbeMergeEngineFree(pMerger);
rc = SQLITE_NOMEM_BKPT;
}
assert( *ppOut!=0 || rc!=SQLITE_OK );
return rc;
}
+35 -27
View File
@@ -620,9 +620,13 @@ struct WalIterator {
** so. It is safe to enlarge the wal-index if pWal->writeLock is true
** or pWal->exclusiveMode==WAL_HEAPMEMORY_MODE.
**
** If this call is successful, *ppPage is set to point to the wal-index
** page and SQLITE_OK is returned. If an error (an OOM or VFS error) occurs,
** then an SQLite error code is returned and *ppPage is set to 0.
** Three possible result scenarios:
**
** (1) rc==SQLITE_OK and *ppPage==Requested-Wal-Index-Page
** (2) rc>=SQLITE_ERROR and *ppPage==NULL
** (3) rc==SQLITE_OK and *ppPage==NULL // only if iPage==0
**
** Scenario (3) can only occur when pWal->writeLock is false and iPage==0
*/
static SQLITE_NOINLINE int walIndexPageRealloc(
Wal *pWal, /* The WAL context */
@@ -655,7 +659,9 @@ static SQLITE_NOINLINE int walIndexPageRealloc(
rc = sqlite3OsShmMap(pWal->pDbFd, iPage, WALINDEX_PGSZ,
pWal->writeLock, (void volatile **)&pWal->apWiData[iPage]
);
assert( pWal->apWiData[iPage]!=0 || rc!=SQLITE_OK || pWal->writeLock==0 );
assert( pWal->apWiData[iPage]!=0
|| rc!=SQLITE_OK
|| (pWal->writeLock==0 && iPage==0) );
testcase( pWal->apWiData[iPage]==0 && rc==SQLITE_OK );
if( rc==SQLITE_OK ){
if( iPage>0 && sqlite3FaultSim(600) ) rc = SQLITE_NOMEM;
@@ -994,8 +1000,8 @@ struct WalHashLoc {
** slot in the hash table is set to N, it refers to frame number
** (pLoc->iZero+N) in the log.
**
** Finally, set pLoc->aPgno so that pLoc->aPgno[1] is the page number of the
** first frame indexed by the hash table, frame (pLoc->iZero+1).
** Finally, set pLoc->aPgno so that pLoc->aPgno[0] is the page number of the
** first frame indexed by the hash table, frame (pLoc->iZero).
*/
static int walHashGet(
Wal *pWal, /* WAL handle */
@@ -1007,7 +1013,7 @@ static int walHashGet(
rc = walIndexPage(pWal, iHash, &pLoc->aPgno);
assert( rc==SQLITE_OK || iHash>0 );
if( rc==SQLITE_OK ){
if( pLoc->aPgno ){
pLoc->aHash = (volatile ht_slot *)&pLoc->aPgno[HASHTABLE_NPAGE];
if( iHash==0 ){
pLoc->aPgno = &pLoc->aPgno[WALINDEX_HDR_SIZE/sizeof(u32)];
@@ -1015,7 +1021,8 @@ static int walHashGet(
}else{
pLoc->iZero = HASHTABLE_NPAGE_ONE + (iHash-1)*HASHTABLE_NPAGE;
}
pLoc->aPgno = &pLoc->aPgno[-1];
}else if( NEVER(rc==SQLITE_OK) ){
rc = SQLITE_ERROR;
}
return rc;
}
@@ -1097,8 +1104,9 @@ static void walCleanupHash(Wal *pWal){
/* Zero the entries in the aPgno array that correspond to frames with
** frame numbers greater than pWal->hdr.mxFrame.
*/
nByte = (int)((char *)sLoc.aHash - (char *)&sLoc.aPgno[iLimit+1]);
memset((void *)&sLoc.aPgno[iLimit+1], 0, nByte);
nByte = (int)((char *)sLoc.aHash - (char *)&sLoc.aPgno[iLimit]);
assert( nByte>=0 );
memset((void *)&sLoc.aPgno[iLimit], 0, nByte);
#ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT
/* Verify that the every entry in the mapping region is still reachable
@@ -1107,11 +1115,11 @@ static void walCleanupHash(Wal *pWal){
if( iLimit ){
int j; /* Loop counter */
int iKey; /* Hash key */
for(j=1; j<=iLimit; j++){
for(j=0; j<iLimit; j++){
for(iKey=walHash(sLoc.aPgno[j]);sLoc.aHash[iKey];iKey=walNextHash(iKey)){
if( sLoc.aHash[iKey]==j ) break;
if( sLoc.aHash[iKey]==j+1 ) break;
}
assert( sLoc.aHash[iKey]==j );
assert( sLoc.aHash[iKey]==j+1 );
}
}
#endif /* SQLITE_ENABLE_EXPENSIVE_ASSERT */
@@ -1143,9 +1151,9 @@ static int walIndexAppend(Wal *pWal, u32 iFrame, u32 iPage){
** entire hash table and aPgno[] array before proceeding.
*/
if( idx==1 ){
int nByte = (int)((u8 *)&sLoc.aHash[HASHTABLE_NSLOT]
- (u8 *)&sLoc.aPgno[1]);
memset((void*)&sLoc.aPgno[1], 0, nByte);
int nByte = (int)((u8*)&sLoc.aHash[HASHTABLE_NSLOT] - (u8*)sLoc.aPgno);
assert( nByte>=0 );
memset((void*)sLoc.aPgno, 0, nByte);
}
/* If the entry in aPgno[] is already set, then the previous writer
@@ -1154,9 +1162,9 @@ static int walIndexAppend(Wal *pWal, u32 iFrame, u32 iPage){
** Remove the remnants of that writers uncommitted transaction from
** the hash-table before writing any new entries.
*/
if( sLoc.aPgno[idx] ){
if( sLoc.aPgno[idx-1] ){
walCleanupHash(pWal);
assert( !sLoc.aPgno[idx] );
assert( !sLoc.aPgno[idx-1] );
}
/* Write the aPgno[] array entry and the hash-table slot. */
@@ -1164,7 +1172,7 @@ static int walIndexAppend(Wal *pWal, u32 iFrame, u32 iPage){
for(iKey=walHash(iPage); sLoc.aHash[iKey]; iKey=walNextHash(iKey)){
if( (nCollide--)==0 ) return SQLITE_CORRUPT_BKPT;
}
sLoc.aPgno[idx] = iPage;
sLoc.aPgno[idx-1] = iPage;
AtomicStore(&sLoc.aHash[iKey], (ht_slot)idx);
#ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT
@@ -1185,19 +1193,18 @@ static int walIndexAppend(Wal *pWal, u32 iFrame, u32 iPage){
*/
if( (idx&0x3ff)==0 ){
int i; /* Loop counter */
for(i=1; i<=idx; i++){
for(i=0; i<idx; i++){
for(iKey=walHash(sLoc.aPgno[i]);
sLoc.aHash[iKey];
iKey=walNextHash(iKey)){
if( sLoc.aHash[iKey]==i ) break;
if( sLoc.aHash[iKey]==i+1 ) break;
}
assert( sLoc.aHash[iKey]==i );
assert( sLoc.aHash[iKey]==i+1 );
}
}
#endif /* SQLITE_ENABLE_EXPENSIVE_ASSERT */
}
return rc;
}
@@ -1318,7 +1325,8 @@ static int walIndexRecover(Wal *pWal){
u32 iFirst = 1 + (iPg==0?0:HASHTABLE_NPAGE_ONE+(iPg-1)*HASHTABLE_NPAGE);
u32 nHdr, nHdr32;
rc = walIndexPage(pWal, iPg, (volatile u32**)&aShare);
if( rc ) break;
assert( aShare!=0 || rc!=SQLITE_OK );
if( aShare==0 ) break;
pWal->apWiData[iPg] = aPrivate;
for(iFrame=iFirst; iFrame<=iLast; iFrame++){
@@ -1815,7 +1823,6 @@ static int walIteratorInit(Wal *pWal, u32 nBackfill, WalIterator **pp){
int nEntry; /* Number of entries in this segment */
ht_slot *aIndex; /* Sorted index for this segment */
sLoc.aPgno++;
if( (i+1)==nSegment ){
nEntry = (int)(iLast - sLoc.iZero);
}else{
@@ -2954,7 +2961,8 @@ int sqlite3WalSnapshotRecover(Wal *pWal){
rc = walHashGet(pWal, walFramePage(i), &sLoc);
if( rc!=SQLITE_OK ) break;
pgno = sLoc.aPgno[i-sLoc.iZero];
assert( i - sLoc.iZero - 1 >=0 );
pgno = sLoc.aPgno[i-sLoc.iZero-1];
iDbOff = (i64)(pgno-1) * szPage;
if( iDbOff+szPage<=szDb ){
@@ -3187,7 +3195,7 @@ int sqlite3WalFindFrame(
iKey = walHash(pgno);
while( (iH = AtomicLoad(&sLoc.aHash[iKey]))!=0 ){
u32 iFrame = iH + sLoc.iZero;
if( iFrame<=iLast && iFrame>=pWal->minFrame && sLoc.aPgno[iH]==pgno ){
if( iFrame<=iLast && iFrame>=pWal->minFrame && sLoc.aPgno[iH-1]==pgno ){
assert( iFrame>iRead || CORRUPT_DB );
iRead = iFrame;
}
+1 -2
View File
@@ -9,9 +9,8 @@
#
#***********************************************************************
# This file implements regression tests for SQLite library. The
# focus of this file is testing the SELECT statement.
# focus of this file is testing the autovacuum feature.
#
# $Id: autovacuum.test,v 1.29 2009/04/06 17:50:03 danielk1977 Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
+87
View File
@@ -0,0 +1,87 @@
# 2021-10-15
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library. The
# focus of this file is testing the sqlite3_autovacuum_pages() interface
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
# If this build of the library does not support auto-vacuum, omit this
# whole file.
ifcapable {!autovacuum || !pragma} {
finish_test
return
}
# Demonstrate basic sqlite3_autovacuum_pages functionality
#
do_execsql_test autovacuum2-1.0 {
PRAGMA page_size=1024;
PRAGMA auto_vacuum=FULL;
CREATE TABLE t1(x);
VACUUM;
INSERT INTO t1(x) VALUES(zeroblob(10000));
PRAGMA page_count;
} {12}
proc autovac_page_callback {schema filesize freesize pagesize} {
global autovac_callback_data
lappend autovac_callback_data $schema $filesize $freesize $pagesize
return [expr {$freesize/2}]
}
sqlite3_autovacuum_pages db autovac_page_callback
set autovac_callback_data {}
do_execsql_test autovacuum2-1.1 {
BEGIN;
DELETE FROM t1;
PRAGMA freelist_count;
PRAGMA page_count;
} {9 12}
do_execsql_test autovacuum2-1.2 {
COMMIT;
} {}
do_test autovacuum2-1.3 {
set autovac_callback_data
} {main 12 9 1024}
do_execsql_test autovacuum2-1.4 {
PRAGMA freelist_count;
PRAGMA page_count;
} {5 8}
do_execsql_test autovacuum2-1.5 {
PRAGMA integrity_check;
} {ok}
# Disable the autovacuum-pages callback. Then do any transaction.
# The database should shrink to minimal size
#
sqlite3_autovacuum_pages db
do_execsql_test autovacuum2-1.10 {
CREATE TABLE t2(x);
PRAGMA freelist_count;
} {0}
# Rig the autovacuum-pages callback to always return zero. No
# autovacuum will happen.
#
proc autovac_page_callback_off {schema filesize freesize pagesize} {
return 0
}
sqlite3_autovacuum_pages db autovac_page_callback_off
do_execsql_test autovacuum2-1.20 {
BEGIN;
INSERT INTO t1(x) VALUES(zeroblob(10000));
DELETE FROM t1;
PRAGMA freelist_count;
COMMIT;
PRAGMA freelist_count;
} {9 9}
finish_test
+188 -26
View File
@@ -302,6 +302,108 @@ static VFile *createVFile(const char *zName, int sz, unsigned char *pData){
return pNew;
}
/* Return true if the line is all zeros */
static int allZero(unsigned char *aLine){
int i;
for(i=0; i<16 && aLine[i]==0; i++){}
return i==16;
}
/*
** Render a database and query as text that can be input into
** the CLI.
*/
static void renderDbSqlForCLI(
FILE *out, /* Write to this file */
const char *zFile, /* Name of the database file */
unsigned char *aDb, /* Database content */
int nDb, /* Number of bytes in aDb[] */
unsigned char *zSql, /* SQL content */
int nSql /* Bytes of SQL */
){
fprintf(out, ".print ******* %s *******\n", zFile);
if( nDb>100 ){
int i, j; /* Loop counters */
int pgsz; /* Size of each page */
int lastPage = 0; /* Last page number shown */
int iPage; /* Current page number */
unsigned char *aLine; /* Single line to display */
unsigned char buf[16]; /* Fake line */
unsigned char bShow[256]; /* Characters ok to display */
memset(bShow, '.', sizeof(bShow));
for(i=' '; i<='~'; i++){
if( i!='{' && i!='}' && i!='"' && i!='\\' ) bShow[i] = i;
}
pgsz = (aDb[16]<<8) | aDb[17];
if( pgsz==0 ) pgsz = 65536;
if( pgsz<512 || (pgsz&(pgsz-1))!=0 ) pgsz = 4096;
fprintf(out,".open --hexdb\n");
fprintf(out,"| size %d pagesize %d filename %s\n",nDb,pgsz,zFile);
for(i=0; i<nDb; i += 16){
if( i+16>nDb ){
memset(buf, 0, sizeof(buf));
memcpy(buf, aDb+i, nDb-i);
aLine = buf;
}else{
aLine = aDb + i;
}
if( allZero(aLine) ) continue;
iPage = i/pgsz + 1;
if( lastPage!=iPage ){
fprintf(out,"| page %d offset %d\n", iPage, (iPage-1)*pgsz);
lastPage = iPage;
}
fprintf(out,"| %5d:", i-(iPage-1)*pgsz);
for(j=0; j<16; j++) fprintf(out," %02x", aLine[j]);
fprintf(out," ");
for(j=0; j<16; j++){
unsigned char c = (unsigned char)aLine[j];
fputc( bShow[c], stdout);
}
fputc('\n', stdout);
}
fprintf(out,"| end %s\n", zFile);
}else{
fprintf(out,".open :memory:\n");
}
fprintf(out,".testctrl prng_seed 1 db\n");
fprintf(out,".testctrl internal_functions\n");
fprintf(out,"%.*s", nSql, zSql);
if( nSql>0 && zSql[nSql-1]!='\n' ) fprintf(out, "\n");
}
/*
** Read the complete content of a file into memory. Add a 0x00 terminator
** and return a pointer to the result.
**
** The file content is held in memory obtained from sqlite_malloc64() which
** should be freed by the caller.
*/
static char *readFile(const char *zFilename, long *sz){
FILE *in;
long nIn;
unsigned char *pBuf;
*sz = 0;
if( zFilename==0 ) return 0;
in = fopen(zFilename, "rb");
if( in==0 ) return 0;
fseek(in, 0, SEEK_END);
*sz = nIn = ftell(in);
rewind(in);
pBuf = sqlite3_malloc64( nIn+1 );
if( pBuf && 1==fread(pBuf, nIn, 1, in) ){
pBuf[nIn] = 0;
fclose(in);
return (char*)pBuf;
}
sqlite3_free(pBuf);
*sz = 0;
fclose(in);
return 0;
}
/*
** Implementation of the "readfile(X)" SQL function. The entire content
@@ -313,25 +415,15 @@ static void readfileFunc(
int argc,
sqlite3_value **argv
){
const char *zName;
FILE *in;
long nIn;
void *pBuf;
const char *zName = (const char*)sqlite3_value_text(argv[0]);
zName = (const char*)sqlite3_value_text(argv[0]);
if( zName==0 ) return;
in = fopen(zName, "rb");
if( in==0 ) return;
fseek(in, 0, SEEK_END);
nIn = ftell(in);
rewind(in);
pBuf = sqlite3_malloc64( nIn );
if( pBuf && 1==fread(pBuf, nIn, 1, in) ){
pBuf = readFile(zName, &nIn);
if( pBuf ){
sqlite3_result_blob(context, pBuf, nIn, sqlite3_free);
}else{
sqlite3_free(pBuf);
}
fclose(in);
}
/*
@@ -855,7 +947,13 @@ static int runDbSql(sqlite3 *db, const char *zSql){
}
/* Invoke this routine to run a single test case */
int runCombinedDbSqlInput(const uint8_t *aData, size_t nByte, int iTimeout){
int runCombinedDbSqlInput(
const uint8_t *aData, /* Combined DB+SQL content */
size_t nByte, /* Size of aData in bytes */
int iTimeout, /* Use this timeout */
int bScript, /* If true, just render CLI output */
int iSqlId /* SQL identifier */
){
int rc; /* SQLite API return value */
int iSql; /* Index in aData[] of start of SQL */
unsigned char *aDb = 0; /* Decoded database content */
@@ -881,6 +979,14 @@ int runCombinedDbSqlInput(const uint8_t *aData, size_t nByte, int iTimeout){
iSql = decodeDatabase((unsigned char*)aData, (int)nByte, &aDb, &nDb);
if( iSql<0 ) return 0;
nSql = (int)(nByte - iSql);
if( bScript ){
char zName[100];
sqlite3_snprintf(sizeof(zName),zName,"dbsql%06d.db",iSqlId);
renderDbSqlForCLI(stdout, zName, aDb, nDb,
(unsigned char*)(aData+iSql), nSql);
sqlite3_free(aDb);
return 0;
}
if( eVerbosity>=3 ){
printf(
"****** %d-byte input, %d-byte database, %d-byte script "
@@ -984,7 +1090,7 @@ testrun_finished:
if( rc!=SQLITE_OK ){
fprintf(stdout, "sqlite3_close() returns %d\n", rc);
}
if( eVerbosity>=2 ){
if( eVerbosity>=2 && !bScript ){
fprintf(stdout, "Peak memory usages: %f MB\n",
sqlite3_memory_highwater(1) / 1000000.0);
}
@@ -1458,6 +1564,7 @@ static void showHelp(void){
" -q|--quiet Reduced output\n"
" --rebuild Rebuild and vacuum the database file\n"
" --result-trace Show the results of each SQL command\n"
" --script Output CLI script instead of running tests\n"
" --skip N Skip the first N test cases\n"
" --spinner Use a spinner to show progress\n"
" --sqlid N Use only SQL where sqlid=N\n"
@@ -1487,6 +1594,7 @@ int main(int argc, char **argv){
int vdbeLimitFlag = 0; /* --limit-vdbe */
int infoFlag = 0; /* --info */
int nSkip = 0; /* --skip */
int bScript = 0; /* --script */
int bSpinner = 0; /* True for --spinner */
int timeoutTest = 0; /* undocumented --timeout-test flag */
int runFlags = 0; /* Flags sent to runSql() */
@@ -1585,7 +1693,7 @@ int main(int argc, char **argv){
}else
if( strcmp(z,"load-dbsql")==0 ){
zInsSql = "INSERT INTO xsql(sqltext)"
"VALUES(CAST(readtextfile(?1) AS text))";
"VALUES(readfile(?1))";
iFirstInsArg = i+1;
openFlags4Data = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE;
dbSqlOnly = 1;
@@ -1621,6 +1729,9 @@ int main(int argc, char **argv){
if( strcmp(z,"result-trace")==0 ){
runFlags |= SQL_OUTPUT;
}else
if( strcmp(z,"script")==0 ){
bScript = 1;
}else
if( strcmp(z,"skip")==0 ){
if( i>=argc-1 ) fatalError("missing arguments on %s", argv[i]);
nSkip = atoi(argv[++i]);
@@ -1669,6 +1780,16 @@ int main(int argc, char **argv){
}
return 0;
}else
if( strcmp(z,"is-dbsql")==0 ){
i++;
for(i++; i<argc; i++){
long nData;
char *aData = readFile(argv[i], &nData);
printf("%d %s\n", isDbSql((unsigned char*)aData,nData), argv[i]);
sqlite3_free(aData);
}
exit(0);
}else
{
fatalError("unknown option: %s", argv[i]);
}
@@ -1690,12 +1811,21 @@ int main(int argc, char **argv){
/* Process each source database separately */
for(iSrcDb=0; iSrcDb<nSrcDb; iSrcDb++){
char *zRawData = 0;
long nRawData = 0;
g.zDbFile = azSrcDb[iSrcDb];
rc = sqlite3_open_v2(azSrcDb[iSrcDb], &db,
openFlags4Data, pDfltVfs->zName);
if( rc==SQLITE_OK ){
rc = sqlite3_exec(db, "SELECT count(*) FROM sqlite_schema", 0, 0, 0);
}
if( rc ){
fatalError("cannot open source database %s - %s",
azSrcDb[iSrcDb], sqlite3_errmsg(db));
sqlite3_close(db);
zRawData = readFile(azSrcDb[iSrcDb], &nRawData);
if( zRawData==0 ){
fatalError("input file \"%s\" is not recognized\n", azSrcDb[iSrcDb]);
}
sqlite3_open(":memory:", &db);
}
/* Print the description, if there is one */
@@ -1730,6 +1860,7 @@ int main(int argc, char **argv){
sqlite3_finalize(pStmt);
printf("\n");
sqlite3_close(db);
sqlite3_free(zRawData);
continue;
}
@@ -1754,6 +1885,21 @@ int main(int argc, char **argv){
sqlite3_free(zSql);
if( rc ) fatalError("cannot change description: %s", sqlite3_errmsg(db));
}
if( zRawData ){
zInsSql = "INSERT INTO xsql(sqltext) VALUES(?1)";
rc = sqlite3_prepare_v2(db, zInsSql, -1, &pStmt, 0);
if( rc ) fatalError("cannot prepare statement [%s]: %s",
zInsSql, sqlite3_errmsg(db));
sqlite3_bind_text(pStmt, 1, zRawData, nRawData, SQLITE_STATIC);
sqlite3_step(pStmt);
rc = sqlite3_reset(pStmt);
if( rc ) fatalError("insert failed for %s", argv[i]);
sqlite3_finalize(pStmt);
rebuild_database(db, dbSqlOnly);
zInsSql = 0;
sqlite3_free(zRawData);
zRawData = 0;
}
ossFuzzThisDb = ossFuzz;
/* If the CONFIG(name,value) table exists, read db-specific settings
@@ -1884,7 +2030,7 @@ int main(int argc, char **argv){
}
/* Print the description, if there is one */
if( !quietFlag ){
if( !quietFlag && !bScript ){
zDbName = azSrcDb[iSrcDb];
i = (int)strlen(zDbName) - 1;
while( i>0 && zDbName[i-1]!='/' && zDbName[i-1]!='\\' ){ i--; }
@@ -1941,12 +2087,16 @@ int main(int argc, char **argv){
/* Run a test using each SQL script against each database.
*/
if( !verboseFlag && !quietFlag && !bSpinner ) printf("%s:", zDbName);
if( !verboseFlag && !quietFlag && !bSpinner && !bScript ){
printf("%s:", zDbName);
}
for(pSql=g.pFirstSql; pSql; pSql=pSql->pNext){
tmStart = timeOfDay();
if( isDbSql(pSql->a, pSql->sz) ){
sqlite3_snprintf(sizeof(g.zTestName), g.zTestName, "sqlid=%d",pSql->id);
if( bSpinner ){
if( bScript ){
/* No progress output */
}else if( bSpinner ){
int nTotal =g.nSql;
int idx = pSql->seq;
printf("\r%s: %d/%d ", zDbName, idx, nTotal);
@@ -1967,10 +2117,10 @@ int main(int argc, char **argv){
if( nSkip>0 ){
nSkip--;
}else{
runCombinedDbSqlInput(pSql->a, pSql->sz, iTimeout);
runCombinedDbSqlInput(pSql->a, pSql->sz, iTimeout, bScript, pSql->id);
}
nTest++;
if( bTimer ){
if( bTimer && !bScript ){
sqlite3_int64 tmEnd = timeOfDay();
printf("%lld %s\n", tmEnd - tmStart, g.zTestName);
}
@@ -1983,7 +2133,9 @@ int main(int argc, char **argv){
const char *zVfs = "inmem";
sqlite3_snprintf(sizeof(g.zTestName), g.zTestName, "sqlid=%d,dbid=%d",
pSql->id, pDb->id);
if( bSpinner ){
if( bScript ){
/* No progress output */
}else if( bSpinner ){
int nTotal = g.nDb*g.nSql;
int idx = pSql->seq*g.nDb + pDb->id - 1;
printf("\r%s: %d/%d ", zDbName, idx, nTotal);
@@ -2005,6 +2157,14 @@ int main(int argc, char **argv){
nSkip--;
continue;
}
if( bScript ){
char zName[100];
sqlite3_snprintf(sizeof(zName), zName, "db%06d.db",
pDb->id>1 ? pDb->id : pSql->id);
renderDbSqlForCLI(stdout, zName,
pDb->a, pDb->sz, pSql->a, pSql->sz);
continue;
}
createVFile("main.db", pDb->sz, pDb->a);
sqlite3_randomness(0,0);
if( ossFuzzThisDb ){
@@ -2077,7 +2237,9 @@ int main(int argc, char **argv){
}
}
}
if( bSpinner ){
if( bScript ){
/* No progress output */
}else if( bSpinner ){
int nTotal = g.nDb*g.nSql;
printf("\r%s: %d/%d \n", zDbName, nTotal, nTotal);
}else if( !quietFlag && !verboseFlag ){
@@ -2093,7 +2255,7 @@ int main(int argc, char **argv){
} /* End loop over all source databases */
if( !quietFlag ){
if( !quietFlag && !bScript ){
sqlite3_int64 iElapse = timeOfDay() - iBegin;
printf("fuzzcheck: 0 errors out of %d tests in %d.%03d seconds\n"
"SQLite %s %s\n",
BIN
View File
Binary file not shown.
+17
View File
@@ -182,6 +182,11 @@ do_test multiplex-2.1.3 { file size [multiplex_name test.x 0] } {4096}
do_test multiplex-2.1.4 {
execsql { INSERT INTO t1 VALUES(3, randomblob(1100)) }
} {}
do_execsql_test multiplex-2.1.5 {
PRAGMA multiplex_enabled;
PRAGMA multiplex_filecount;
PRAGMA multiplex_chunksize;
} {1 1 2147418112}
do_test multiplex-2.2.1 {
execsql { INSERT INTO t1 VALUES(3, randomblob(1100)) }
@@ -267,6 +272,18 @@ do_test multiplex-2.5.8 {
do_test multiplex-2.5.9 { file size [multiplex_name test.x 0] } [list $g_chunk_size]
do_test multiplex-2.5.10 { file size [multiplex_name test.x 1] } [list $g_chunk_size]
do_execsql_test multiplex-2.5.11 {
PRAGMA multiplex_enabled;
PRAGMA multiplex_filecount;
PRAGMA multiplex_chunksize;
} {1 3 65536}
sqlite3 db test.x
do_execsql_test multiplex-2.5.12 {
PRAGMA multiplex_filecount;
PRAGMA multiplex_chunksize;
} {3 65536}
do_test multiplex-2.5.99 {
db close
+15
View File
@@ -456,4 +456,19 @@ CREATE TABLE t7(a, b, c);
db eval { SELECT * FROM t7 ORDER BY a }
} {1 2 3 4 5 {} 6 7 8}
do_test shell5-4.3 {
forcedelete shell5.csv
set fd [open shell5.csv w]
puts $fd ",,"
puts $fd "1,2,3"
close $fd
catchcmd test.db [string trim {
.mode csv
CREATE TABLE t8(a, b, c);
.import -skip 1 shell5.csv t8
.nullvalue #
}]
db eval { SELECT * FROM t8 }
} {1 2 3}
finish_test
+22 -3
View File
@@ -44,6 +44,10 @@ proc populate_dir {dirname spec} {
}
}
proc dir_content {dirname} {
lsort [glob -nocomplain $dirname/*]
}
proc dir_to_list {dirname {n -1}} {
if {$n<0} {set n [llength [file split $dirname]]}
@@ -170,8 +174,23 @@ foreach {tn tcl} {
}
}
finish_test
do_test 2.1.1 {
populate_dir ar2 {
file1 "abcd"
file2 "efgh"
junk1 "j1"
junk2 "j2"
dir1/file3 "ijkl"
}
populate_dir ar4 {
file2 "efgh"
}
catchcmd shell8.db {.ar -c}
catchcmd shell8.db {.ar -C ar2 -i .}
catchcmd shell8.db {.ar -r ./file2 ./dir1}
catchcmd shell8.db {.ar -g -r ./ju*2}
catchcmd shell8.db {.ar -C ar4 -x .}
regsub -all {ar4} [dir_content ar4] ar2
} {ar2/file1 ar2/file2 ar2/junk1}
finish_test
+31
View File
@@ -100,4 +100,35 @@ do_test vacuum-into-510 {
db2 close
db close
# Change the page-size on a VACUUM INTO even if the original
# database is in WAL mode.
#
forcedelete test.db
forcedelete test.db2
do_test vacuum-into-600 {
sqlite3 db test.db
db eval {
PRAGMA page_size=4096;
PRAGMA journal_mode=WAL;
CREATE TABLE t1(a);
INSERT INTO t1 VALUES(19);
CREATE INDEX t1a ON t1(a);
PRAGMA integrity_check;
}
} {wal ok}
do_execsql_test vacuum-into-610 {
PRAGMA page_size;
} {4096}
do_execsql_test vacuum-into-620 {
PRAGMA page_size=1024;
VACUUM INTO 'test.db2';
} {}
do_test vacuum-into-630 {
sqlite3 db test.db2
db eval {
PRAGMA page_size;
PRAGMA integrity_check;
}
} {1024 ok}
finish_test