Compare commits

..

169 Commits

Author SHA1 Message Date
drh 6193d49cdf Use replace() instead of char() to quote newline and return characters in
strings in the output of .dump, to avoid excess expression complexity.

FossilOrigin-Name: 4c2b572969ea2ed2a925444ecfa356aa877018cbb9c4f57d081ab4b535cd1dd0
2017-04-07 11:45:58 +00:00
dan 54e2efcd2f Fix the ".lint fkey" shell command for cases where the child key is also an
INTEGER PRIMARY KEY.

FossilOrigin-Name: 48826b222c110a90996a84605318ea6b1e502b8c5129f4d561f8350dbdbcd264
2017-04-06 14:56:26 +00:00
dan 50da9382f9 Fix the ".lint fkey" shell tool command so that it works for foreign keys that
refer implicitly to primary key columns with non-BINARY default collation
sequences.

FossilOrigin-Name: 327eff25ba2420267cc8dc49dd3c3aab45f4bf9e060d1ad480e25d016d21f3ba
2017-04-06 12:06:56 +00:00
drh 6948ed5977 Remove a confusing and pointless sentence from the documentation for the
sqlite3_interrupt() interface.

FossilOrigin-Name: c5f1a2b6eb3df879d247a22b3f92f4f74fcf4f0d219450abc420ae6d02481324
2017-04-05 13:44:40 +00:00
drh dbd6a7dc06 Split off sqlite3DbFreeNN() from sqlite3DbFree() and use it in cases where
we know that the argument to be freed is never NULL.

FossilOrigin-Name: ad90e8bb5e47945607c8fb47b6ade8cfc52a9b684805cc40132629be0ecc14cc
2017-04-05 12:39:49 +00:00
drh ac48b751e2 Save a few bytes and a few CPU cycles in sqlite3ExprListDelete() routine.
FossilOrigin-Name: 9e6c939144a129b36bb119120442a4a021e00187783da211315d4bb13acd7c3a
2017-04-05 11:57:56 +00:00
drh f4dd26c5a0 Remove a conditional made unreachable by the previous ExprList enhancement.
FossilOrigin-Name: a1cf44763277b6c745b5b5509ca9129b6c3231608b4d1c8aec2815b64b5a2a07
2017-04-05 11:49:06 +00:00
drh 43606175e2 Combine the ExprList_item objects and the ExprList wrapper into a single
memory allocation, for improved performance and reduced footprint.

FossilOrigin-Name: 2b6560ad88b92820c383bcdc1e30c06f8b081ef7c6d9b1af71d2bb76c83e35cd
2017-04-05 11:32:13 +00:00
drh 32d0eba4c2 Attempt to remove bash-isms from configure.ac. Use -O0 with --enable-debug.
FossilOrigin-Name: 71ed35ccf7c0f6c49118a44cf6621f46b9ea883e4a74d51b8b1ade6d9a95413a
2017-04-05 10:54:14 +00:00
dan 75f9558808 Fix a problem causing "PRAGMA integrity_check" to disable the xfer
optimization for subsequent VACUUM operations on tables with one or more CHECK
constraints. This could result in VACUUM producing slightly larger database
files.

FossilOrigin-Name: e5bb7db51cdfd8124c60329782798cea398733545594dab55cb892b2a08c4d29
2017-04-04 19:58:54 +00:00
drh 628dfe163f Avoid an unnecessary call to sqlite3WhereGetMask() inside of whereShortCut().
FossilOrigin-Name: 5c11f4303f6a33d6358f451244551be63baf9afe5630332e60b349215e20a3af
2017-04-03 14:07:08 +00:00
dan cfb3235752 Do not attempt to run sync2.test with SQLITE_DISABLE_DIRSYNC builds.
FossilOrigin-Name: 658f08ce84b45f057843263961f6c47a322f841764134ec38f35719f0f2042d7
2017-04-03 13:59:22 +00:00
drh 761f691d0e Force a schema load prior to "PRAGMA optimize".
FossilOrigin-Name: 86897c24c0b35ffea8df72d86a099addf67de210c6568aaba22ef92f1a60c3cf
2017-04-03 13:33:51 +00:00
drh 1cc3a36d90 Fix typos in the documentation for OP_Column.
FossilOrigin-Name: 777b43e64ffb2fb80ba7b705c129c133bf9787993a66cde1759dc070b324b4b4
2017-04-03 13:17:31 +00:00
drh caab5f42db Slightly smaller and faster implementation for vdbeSorterCompareInt().
FossilOrigin-Name: 84fa069c5bdfe41d03d03875c9157cc6785150b677c04e40b8916ba5af073dc8
2017-04-03 12:04:39 +00:00
drh 8e633b3ba9 Remove an unnecessary setting of the Mem.enc field for the output of the
OP_Record opcode, for a performance improvement and size reduction.

FossilOrigin-Name: e6e36b288fdf21b7ff7f0bf85d2225b6505f54367b183c302c93c34a4a40b8b5
2017-04-01 20:44:26 +00:00
drh 662c50e067 Minor performance enhancements to the OP_Affinity opcode.
FossilOrigin-Name: c45cd3b947c0f03a688f827fddb4629a986788f0dd98d5ef899f11e68ff1c202
2017-04-01 20:14:01 +00:00
drh 96a7e28df6 Remove an unnecessary clearing of the Vdbe.iCurrentTime value.
FossilOrigin-Name: fcd2acdd6075aa9a7a66ce254eba77485f7b2804127e109c0309173488cd4b87
2017-04-01 19:45:20 +00:00
drh b808d77771 Faster implementation for sqlite3VdbeIntValue() and sqlite3VdbeRealValue().
FossilOrigin-Name: 8698df60c23d4dcc80b58352c14ae80ec238cac496f8a87bd72a96fef61cc63f
2017-04-01 11:59:36 +00:00
drh b6017a44c5 Remove unused fields from the BtCursor object.
FossilOrigin-Name: 1c0d82e0786ed22d07d774b8b166340fad97bcaab6016e395c469bcfcb7c77a3
2017-04-01 11:40:05 +00:00
drh 75e96b3100 Save a 78 bytes of code space and a million CPU cycles in speedtest1 by
storing the cell index for the leaf page in the BtCursor object in its own
field (BtCursor.ix), rather than as an entry in the BtCursor.aiIdx array.

FossilOrigin-Name: 2452f0617d1085689264b5f66681788cfe9e3b1a7b318307c93942b702a443df
2017-04-01 00:20:06 +00:00
drh 53b2459a36 Declare the Lemon-generated parser object as itself. (Duh)
FossilOrigin-Name: c8000e94cca59dabf83d6cb75b40441aaf793d29880582dc4baa17246449b5fe
2017-03-30 17:13:37 +00:00
drh 52105783fd Increase the version number for the next development cycle.
FossilOrigin-Name: 9e550ccc29f317422dae3a4bb89a78b839330825fecd40a01d1a2acc719cef79
2017-03-30 16:51:35 +00:00
drh ecc0f84d08 Ensure that the stack space used to hold the Lemon-generated parser object
is always 8-byte aligned.

FossilOrigin-Name: 1279de0b70cabf39899d92ece8852a780fd800bf3154971537b3427e5bd3ca50
2017-03-30 16:37:05 +00:00
mistachkin b3d3bea31d When compiling with MSVC, disable extra SELECT/WHERE tracing for dynamically built shells.
FossilOrigin-Name: a68919425c528b887e66b588a73a619f0506cb06855350e0ec8f844acf64d8f7
2017-03-29 23:22:18 +00:00
drh 9ca431aef8 Avoid unnecessary blob handle invalidation when changes are made to an
unrelated table.

FossilOrigin-Name: 4a01880b62706c12d6f16f7c2b5c8b0dc67a9a8a0a48c5b42451e1a133e85611
2017-03-29 18:03:50 +00:00
drh 4eb8d7fa89 Slightly smaller and faster implementation of pcache1InitBulk().
FossilOrigin-Name: 06c2b685e15b3ee045a3e7ea018701392771c7664e59a51c9aba87cdefeb37af
2017-03-29 17:06:14 +00:00
dan 9f549d548d Fix some tests in malloc5.test to account for the sqlite3_release_memory()
change in the previous commit.

FossilOrigin-Name: d336858dfcfb9539c43582b1443911df825f9af7146957734bc6f01c8f4d98e3
2017-03-29 16:55:23 +00:00
drh bf96228754 Fix the sqlite3_release_memory() interface so that it works even if
SQLITE_DEFAULT_PCACHE_INITSZ is non-zero.

FossilOrigin-Name: 5d902b7fea3144bf57f02aca87b9795fdcec4774310ade6ef01f37d206c3d74f
2017-03-29 15:18:40 +00:00
drh 0d8d9c9eff Add the new sqlite3_set_last_insert_rowid() interface to the extension
loader thunk.

FossilOrigin-Name: 8469fc0d48d6af0accef9b8a84e08ad2ca32351907510d177b4ca4815c1ea7cb
2017-03-25 19:16:41 +00:00
dan b9cd86a091 Do not run tests for ".dump --preserve-rowids" when testing
SQLITE_OMIT_VIRTUALTABLE builds.

FossilOrigin-Name: 55df410b2cd27dc4c7670bcc1196fa3a0e9e601fc24c42e53d6b0a26ee3e4b45
2017-03-25 18:31:42 +00:00
drh 34ad36bf81 Disable the new --preserve-rowids option on the CLI ".dump" command if
compiled with SQLITE_OMIT_VIRTUALTABLE.

FossilOrigin-Name: bd5bbe4eece9051cc8c27d834d22fb243d34f261641984555d02a27b7038d4f6
2017-03-25 18:15:05 +00:00
drh 3e7d012eb1 Make the default value for SQLITE_DEFAULT_SYNCHRONOUS a simple integer
literal, so that it does not show up goofy in the output of
"PRAGMA compile_options;".

FossilOrigin-Name: 833ab3212addc340ca8004e8d6a06cc5e51bf256f43dc73d87fbe67518a4891b
2017-03-25 18:03:26 +00:00
drh 2fb79e9b04 Fix two harmless compiler warnings.
FossilOrigin-Name: 32be9c3faaafd736da3f49d475dc9279af4e4ba38070b60033d898345080acf0
2017-03-25 12:08:11 +00:00
drh ba7cce317b Fix a harmless compiler warning in the JSON1 extension.
FossilOrigin-Name: c2c3dd84534bb5ea81c974847b74a166c9cba1545fc749ce625929f303bf22e4
2017-03-24 19:45:05 +00:00
drh 18333efd51 Previous check-in was not correct. This is a better fix for the OP_Once
problem of ticket [06796225f59c057cd120f1].

FossilOrigin-Name: 8194dd2814b0b3f8cffbcb16306f55aabf1c1508b9d27fa806f92f0e6ecd7631
2017-03-24 18:38:41 +00:00
drh ab087d4e67 Fix the OP_Once opcode so that it works correctly for recursive triggers.
Ticket [06796225f59c057cd120f1].

FossilOrigin-Name: 2556014514f36808e6d18b25722eae0daeeb8fbb5d18af13a9698ea6c6db1679
2017-03-24 17:59:56 +00:00
drh f9e91972c9 Add the RFC-7396 Appendix A test cases for json_patch().
FossilOrigin-Name: c5441d2df2526723f72610cc14dd243223663979e67ecdd76fe06fcd366f2b29
2017-03-24 13:31:47 +00:00
drh 29c9969871 Fix an error in the new json_patch() routine discovered by Ralf Junker.
FossilOrigin-Name: 9d5350418b2f6113e0b50c57e8a872006f27753067baf08ffdfa7943c0c9a148
2017-03-24 12:35:17 +00:00
drh adc117d40e Add the json_patch() SQL function to the JSON1 extension.
FossilOrigin-Name: 476088482024e411e2549b1697cdaf0124294c79d43f508c71c4eb66906a56fc
2017-03-23 23:44:55 +00:00
drh 37f03dfb1f Change the name of the json_merge_patch() function to just json_patch().
FossilOrigin-Name: 04d4100445a3373986ee962618bc03ec304f6ba2f867c8e9eee415daffb593fc
2017-03-23 20:33:49 +00:00
drh db528529bf Improvement to the amalgamation configure.ac file contributed by
Bob Friesenhahn.

FossilOrigin-Name: bf28a55d8185e370fea39de297c37387f852f43fac0a316e5900e633f99b367f
2017-03-23 19:51:38 +00:00
dan 8fe3e9d882 Do not run test file autoanalyze1.test if OMIT_VIRTUALTABLE is defined.
FossilOrigin-Name: e1d06a573ee56bf6a14e4dc8086d6a4df1464f2914834cf4596a0a406688f608
2017-03-23 17:22:09 +00:00
dan a77edc69ee Remove an invalid assert() statement failing when VACUUMing a database that
contains an index on a column explicitly declared "COLLATE BINARY".

FossilOrigin-Name: 9f2e04d3c3526b5ff60d941aa6d5446f602cab37cb93972937f39eefabd6868d
2017-03-23 17:03:35 +00:00
drh 1fe162fd0c Avoid redundant edits in the json_merge_patch() function.
FossilOrigin-Name: 4a8e6437dd610c5376a07867a73e5a7e2ea90357a018e1788ecce6f4e10bc939
2017-03-23 12:56:44 +00:00
drh 0002d246a9 Fix harmless compiler warnings in the new json_merge_patch() logic.
FossilOrigin-Name: 5d2cf5a2f8afd88d041d89b3936042ce5a43629d23c48738cb2791b24da3e6af
2017-03-23 00:46:15 +00:00
drh bb7aa2d85e Various fixes to the json_merge_patch() function.
FossilOrigin-Name: f49fd2554b0723eb7cf2fd765d655c6820833ee7e5f7d7629d98c27a6fffa1d9
2017-03-23 00:13:52 +00:00
drh f07b249f92 Change the name of the new function to "json_merge_patch()".
FossilOrigin-Name: 53bf70f37bbca319ea35f70849e2a34ae628a504486158fdad5c4bb7431c68e0
2017-03-22 21:45:20 +00:00
drh 633647af75 Initial implementation of the json_mergepatch(A,B) SQL function.
FossilOrigin-Name: a267444039af519f088dd8f8ee33f686cc3071c087677075af2364ebc2587514
2017-03-22 21:24:31 +00:00
drh 701ff6ad2d Fix harmless compiler warnings in the shell.
FossilOrigin-Name: a786829783ef65ef270ca360712364cbd47a540d31ed1547d50808aad698bea7
2017-03-22 12:51:34 +00:00
drh 918938f9c2 New simplified memory initialization for MacOS.
FossilOrigin-Name: 055b36f1c1593bb123f7319a07c476143d71af052b5b8d34afcd0d500f197882
2017-03-21 20:17:24 +00:00
drh 49297c86d2 Fix an incorrect assert in the ANALYZE logic for STAT4 on WITHOUT ROWID
tables.

FossilOrigin-Name: ad741976c8c29bcc94f9ea9ed7deb580bb00c8a81d1a7fba1a4e03849728433d
2017-03-21 18:56:52 +00:00
dan 119fc11eb0 Add short script ext/fts3/tool/fts3cov.sh. To help measure test-coverage of
fts3 source code.

FossilOrigin-Name: ee9588e873ffebcaa177957950cbb14924e154c391ed7f687116065064ff11b0
2017-03-21 17:19:31 +00:00
dan a14b7e02e9 Do not run sync2.test as part of the "inmemory_journal" permutation.
FossilOrigin-Name: 9f680bc7c47f8391adba6ea2b4b2cb6a5a041e22753543d5224da6656c3762fe
2017-03-21 10:45:38 +00:00
drh 174f855306 Add the --native-malloc option to fuzzcheck. Fix ossfuzz.c and fuzzcheck.c
so that they both deallocate the temp_store_directory before closing.

FossilOrigin-Name: 0dd18ec882bb28a87629d6d8dfeb5ea5d82833634b3781a7d14b917272c4dfa0
2017-03-20 22:58:27 +00:00
drh 16f0582c1b Fix the fuzzcheck program so that it can create new databases again.
FossilOrigin-Name: 021e8874a7d1bb94debae3ae04f83056a8573148ffc872cd76a186a2d22d0296
2017-03-20 20:42:21 +00:00
dan 74869e5e52 Avoid passing NULL as the second argument to memcpy() in fts3.
FossilOrigin-Name: 49b93d972de9649abfd6235b65dda1c9d468956671e50704afde6181ffa56dea
2017-03-20 19:35:30 +00:00
dan 6b904f5e01 Avoid a technically undefined right-shift of a signed value in rtree.c.
FossilOrigin-Name: a144875fe44ff3a30bab299d50b7dbec2ee21f8c73e692a71ee1f7c54b5f0c76
2017-03-20 19:26:27 +00:00
dan 920c83f18f Fix some problems in fts3 found by address-sanitizer.
FossilOrigin-Name: 16a8e84fa7f67a467f824bdd7f72cbd6a6e95dab8cc7aa1e0e751720b98f3e31
2017-03-20 18:53:32 +00:00
drh 5f42995a0a Avoid the possibility of signed integer overflow with oversized precisions
in %d conversions in the printf() implementation.

FossilOrigin-Name: ef3a7c877a7549b351aafd983cfa96c863eb2641b6218bdd5cb563f659f879d8
2017-03-20 16:34:18 +00:00
dan 5b3a3b359a Do not run sync2.test as part of the "journaltest" permutation, as it uses
"PRAGMA synchronous = off".

FossilOrigin-Name: 285005a9bcb210bb2a9aa9fed6a19d4b78641a6e7622d469bd0d2a365b2c0735
2017-03-20 16:06:48 +00:00
drh 7adbcffcb9 Ensure that a "--" prefix is added to sqlite3_trace_v2() output for nested
SQL statements.

FossilOrigin-Name: 673a7b67c4828acaea3baebea500ef1f8ae763588b0d9c9f2ad6ed5ceb3cfee2
2017-03-20 15:29:28 +00:00
dan 154cc74601 Only run sync2.test on unix, as it depends on instrumentation in os_unix.c.
FossilOrigin-Name: ecb9321e18dd72ea18d197c61c4d69500e9c4282c0eac67822cb40b2710a2815
2017-03-20 15:11:40 +00:00
drh 978896e0eb Fix the check.test script so that it works on Windows.
FossilOrigin-Name: 8822eb5d790bf8d4302c3f2dc05ab672193b309fb11771c4b3eea8a77f37e299
2017-03-20 14:44:07 +00:00
drh d3d52ef147 Documentation fix: SQLITE_SOURCE_ID is a now a SHA3-256 hash.
FossilOrigin-Name: 2aa22509e7c8a1f09b16e4544c95d0b77503daed1f83106ccc18dee8bd9487a4
2017-03-20 13:03:39 +00:00
drh a80e160634 Only do the specialized MacOS single-core zone_malloc initialization if
compiled with the SQLITE_MIGHT_BE_SINGLE_CORE flag.  This avoids a (harmless)
warning about OSAtomicCompareAndSwapPtrBarrier() being deprecated.

FossilOrigin-Name: 4e6a03d9e12b120d15946b025f97a97697cb8e8af543c238ffda220c9e3f28f4
2017-03-18 13:59:46 +00:00
drh 46acfc2b47 Fix an error in the newly revised documentation for SQLITE_LIMIT_VDBE_OP.
No changes to code.

FossilOrigin-Name: f4cf8635e6fec6f04075cc067aaa71abc4f71739068e0ad2c44609dcb8691009
2017-03-17 23:08:11 +00:00
drh 544cab7651 Set a reasonable limit on the number of opcodes in a prepared statement
for ossfuzz.c.  This should prevent timeouts in OSS-Fuzz when it generates
totally unreasonable queries.

FossilOrigin-Name: f74899ed2c78019abb406432a74dcd42a0ff8d9add005f8544dc4a8905f232eb
2017-03-17 22:51:28 +00:00
drh 1cb0266dcb Begin enforcing the SQLITE_LIMIT_VDBE_OP. The documentation warned that this
day might come.

FossilOrigin-Name: ef5914617088cbf89bfae88f63ea959a07f02dff387ddc2b43948ad99c6a97b8
2017-03-17 22:50:16 +00:00
drh f53524b4f7 Add the --show-errors and --show-max-delay command-line options to the
ossshell test program.

FossilOrigin-Name: 626bdca98e0cd78ae873d97e75bb7d544ca18759c9f1e67f4adf03daca7fe5bf
2017-03-17 14:59:40 +00:00
drh 59d705ab80 Fix the Makefile.in so that it builds the ossshell test program correctly.
FossilOrigin-Name: 36f5602ec9fb8e404c5250e18b1db877ac7bee643918b94afd51808134ea7900
2017-03-17 14:15:06 +00:00
dan 1f9144ed41 Fix a buffer overread in debugging routine sqlite3VdbeMemPrettyPrint().
Problem discovered by OSS-Fuzz.

FossilOrigin-Name: f336fba7d7d41b91a5000d01dddf785821fa79ea31dbd8d1f769d55f7e871896
2017-03-17 13:59:06 +00:00
drh a3b2da9889 Fix a problem in the enhanced PRAGMA integrity_check where it verifies
CHECK constraints: Do not be confused by the reuse of the Table.pCheck field
by VIEWs with named columns.  Problem discovered by OSS-Fuzz.

FossilOrigin-Name: 019dd3d5ba4a596c4ec3b5f0de8402c72196af0faca9138edbc0f1f4957cae60
2017-03-17 03:21:14 +00:00
dan af3332989f If the user has not set it explicitly, set the "PRAGMA synchronous" setting to
SQLITE_DEFAULT_SYNCHRONOUS when a database connection changes from wal to
rollback journal mode.

FossilOrigin-Name: 5c604479fda06714500959e121c719d1b6c8e54d1658eb9f560a4af95b7c5829
2017-03-16 18:55:21 +00:00
dan fc8f4b658c Fix a typo causing the build to fail if SQLITE_DEFAULT_SYNCHRONOUS==SQLITE_DEFAULT_WAL_SYNCHRONOUS.
FossilOrigin-Name: df39adeaa4d73a3d4ec831843b8ec7fd449f8b2137bdc7d7c320958d00e98db6
2017-03-16 18:54:42 +00:00
dan f5da7dbb07 If the user has not set it explicitly, set the "PRAGMA synchronous" setting to
SQLITE_DEFAULT_SYNCHRONOUS when a database connection changes from wal to
rollback journal mode.

FossilOrigin-Name: 78030c0f52aa39fb2ab32c75c56e6bcefe6382b8df28b1909e3c911e42dbeca3
2017-03-16 18:14:39 +00:00
drh b30574bcae Simplified OOM detection in the instr() SQL function.
FossilOrigin-Name: 6d85eb5736781b43aa674d9544c7523b849b4e634f371702f8764b33e22e1e9f
2017-03-16 14:28:52 +00:00
drh 85c2dc0ae6 Fix an uninitialized variable reference in the text generator
for "PRAGMA vdbe_trace=ON" output.
Problem discovered by OSS-Fuzz.

FossilOrigin-Name: e3d487162d1596ce125644f754ed9531ef4412f31f6837c3e31b7542b90602fe
2017-03-16 13:30:58 +00:00
drh 970ea372c4 Fix a problem in the "showdb" utility that prevents it from correctly
decoding cells with no content beyond the record header.

FossilOrigin-Name: eb7680a1c047b2a33d6a0c9733fafaee11272377c627af10bbd541b6b7ed952b
2017-03-16 13:14:03 +00:00
dan 116b56a2cc Fix a crash that could follow an OOM condition in the instr() SQL function.
FossilOrigin-Name: 6e59e903e4e956617bddef0b94e5cae02d724ac8145940b57ab5b0f628759736
2017-03-16 12:11:07 +00:00
drh 6f25936c9c Updates to README files under the ext/ hierarchy. No changes to code.
FossilOrigin-Name: 029bc5d224bcbdcca2307710539b133c39e2a27b971c28b294a1f517b80cb418
2017-03-15 20:27:46 +00:00
drh 6295ff1d3e Add the "Obtaining The Code" subsection in the top-level README.md file.
No changes to code.

FossilOrigin-Name: b1b1aa8b69aa80c83aec3380565f0b4ec0b6a6e033537becee098872da362e9a
2017-03-15 19:11:29 +00:00
drh a5d75ba9ea Mention the ".selftest" command in the ".help" output of the CLI.
FossilOrigin-Name: 37f766dbad1f99ff86dd1b771bf443036e928e5b4d8abe55bbe4acf3362c7be2
2017-03-15 14:20:34 +00:00
drh 7553c82894 Make "PRAGMA temp.synchronous=N" a no-op to ensure that the TEMP schema
always has synchronous=OFF.  This fixes an issue discovered by OSS-Fuzz.

FossilOrigin-Name: bcf6bb08d8b07d3c4567bcd367f8d4011ce8baad28c25d4e8870bdf347dd48bd
2017-03-15 14:04:03 +00:00
drh 9c4527e57d Improved header comment on the shathree.c extension. No changes to code.
FossilOrigin-Name: 84f2e3d5f611b35de16684956d842df6c93d858e8187f17eb27452758a752c57
2017-03-15 13:47:39 +00:00
mistachkin 943d825b54 Updates to the MSVC makefiles.
FossilOrigin-Name: 1e4b9e7c9ee32b985c440bf3eb65bbdf28055566e66b6feba438143a3ad8dd07
2017-03-14 15:27:56 +00:00
drh 29df8d1fc2 Add the dbdump.c extension that implements functionality similar to the
".dump" command of the CLI, though in a separate library.

FossilOrigin-Name: 2b9980a292d7f0d995b77d9b3fb217bb2206f6d452e036ac502fa06561af4c12
2017-03-13 22:10:05 +00:00
drh 4b34eb3bf5 Add dbdump.exe to the MSVC makefile.
FossilOrigin-Name: 59241a50ad1d6fe9f5804b73b3467dcd407d359ccbdcb9d72f2f6d94c90c1f40
2017-03-13 22:02:01 +00:00
drh d3bc75fb94 Fixes to the dump logic. All appears to be working in preliminary tests.
FossilOrigin-Name: 007b11e301d444361c8eff8734dc2fb968a64343c177ff30cec74a0cf76099e8
2017-03-13 21:49:48 +00:00
drh 473af4fe03 First draft of the complete dbdump.c library.
FossilOrigin-Name: 84ea4fcc52d0af02648c52989c2e69f4961071e1620382555ec59a39161a7a7d
2017-03-13 21:26:41 +00:00
drh 688633cb9e Infrastructure for an extension C-library to implement sqlite3_db_dump() and
a corresponding "dbdump" command-line utility - both of which do the same
work as the ".dump" command of the CLI.

FossilOrigin-Name: 74c5ace498f72d7f5495203678bedd0bc540211131a4e4db7b62115d5322a288
2017-03-13 19:26:34 +00:00
drh d3bb79bd0f In the output of the ".dump" command in the CLI, quote newline and
carriage-return characters using the char() function, so that they do not
get eaten by end-of-line processing logic in the OS or in other command-line
utilities and/or libraries.

FossilOrigin-Name: 68f6dc7af1013f296a11db14c007cc13cc3fe56832848bfed835ed8f74dcc676
2017-03-13 18:24:06 +00:00
drh 510b7ff536 Fix the sqlite3TreeViewSelect() routine so that it works with a null pointer
to the Select object.

FossilOrigin-Name: 9034cf7efc603864f51e931c7dc4fbbc2d01904e951e78c88d4d80f9936250e8
2017-03-13 17:37:13 +00:00
dan c3becddb75 Fix a segfault that could occur following an OOM error in the
flattenSubquery() routine.

FossilOrigin-Name: c6dda3f752c184f441624c9993e77d5031063d79a0e177b6e25a9886514a742e
2017-03-13 14:30:40 +00:00
drh bbc0177460 In the OSSFuzz test module, invoke the progress handler much more frequently
so that timeouts are detected punctually even if the test script is running
opcodes that individually take a long time (for example, an OP_Function opcode
that invokes "randomblob(1.5e6)").

FossilOrigin-Name: f3b6959c04c4ef7b8ff03582b867012a869d52b4a90a0d7ab079ee4c21be5464
2017-03-13 13:45:29 +00:00
drh ba28b5ab0a Fix a possible NULL pointer dereference in following an OOM error
in sqlite3ExprIsInteger(). Problem found by OSS-Fuzz.

FossilOrigin-Name: 5ec655e8e817c1ed3bfb2e576745a7cef441494ad7baf1bf9f8895e98ac19c5a
2017-03-12 20:28:44 +00:00
drh 1ed1e616f7 Remove an obsolete assert() in the IN operator code generation.
FossilOrigin-Name: 18bf6aca2ac86478fd12d5020f3a41cfd2bd2dc3defe2298411f79ad308a6f73
2017-03-12 19:39:00 +00:00
drh 202230ef5c Make sure the translateColumnToCopy() routine in the query planner does not
try to access an array that failed to be fully allocated due to a prior OOM.
This fixes an issue discovered by OSSFuzz.

FossilOrigin-Name: 3299a26160c239255608d1e2b15a221e28b18a3d
2017-03-11 13:02:59 +00:00
drh 708b22b1e3 The output of the ".dump" command in the CLI quotes newline and carriage-return
characters using "char(10)" and "char(13)".

FossilOrigin-Name: 8b2954dd8376e2de985cf5dedeb6eec32c430505
2017-03-11 01:56:41 +00:00
drh 891d6b4e9e Increase the number of significant digits in floating point literals on
".dump" output from the shell.

FossilOrigin-Name: 7359fcacaadc349f520536311dcd1d0b5cea7673
2017-03-11 00:46:57 +00:00
dan 1ba30db8bd Remove the rbu_round_trip.tcl script. It is now part of project "test-dbs".
FossilOrigin-Name: b5bf2957677e8f2acd7426b302229a966de08fd9
2017-03-10 18:36:34 +00:00
drh a6bf20b587 Fix an error in the SQLITE_MAX_MEMORY implementation resulting from a bad
merge.  Update the OSSFuzz interface so that it times out after running
the byte-code engine for 10 seconds.

FossilOrigin-Name: f8560c60d10c0365b33342ab05b5a953987b0471
2017-03-10 17:03:11 +00:00
drh 1e45c7db56 Add the -DSQLITE_MAX_MEMORY=N compile-time option. The default is no limit.
FossilOrigin-Name: eabd4ef498a0f0d97d65e321c4d06ab90523ed61
2017-03-10 16:22:40 +00:00
drh e43d6aee45 Add the SQLITE_MAX_MEMORY compile-time option that provides a hard upper bound
on the amount of memory that SQLite will use, per process.

FossilOrigin-Name: 77dfe2abdae88dea81217f352d87e5ba2c822715
2017-03-10 15:55:54 +00:00
drh a2df53bd61 Enhance the ".stats" dot-command in the CLI to use sqlite3_status64() instead
of sqlite3_status().

FossilOrigin-Name: 118f5c0564fef70cbd06fc0d9dbb2baec162cc39
2017-03-10 14:36:10 +00:00
drh f157d10f9f Improvements to ".selftest --init". Tests are number in increments of 10
starting with 100.  The tests are generated inside a SAVEPOINT.  Errors are
reported during test generation.  Tests can be appended to existing tests.
Add a test case to verify the schema.

FossilOrigin-Name: b044b152aac2ec606750940ea816ad4a4aef8eb6
2017-03-10 01:05:38 +00:00
drh fb546afb4d Remove the test/dbselftest.c program. In its place, add the ".selftest"
command to the CLI.  The new CLI version is .selftest is slightly different
in that it uses SHA3 hashing instead of SHA1, so the new is subtly 
incompatible with the old.

FossilOrigin-Name: f4fcd46f08ba59d2a3e772cad98383129f648386
2017-03-09 22:00:33 +00:00
drh f8563c00b2 Fix the ".dump" command to correctly extract tail data from corrupt
WITHOUT ROWID tables.

FossilOrigin-Name: 6c627e50622d8bcd25ec7d5503f3fafd725673a8
2017-03-09 18:13:52 +00:00
drh e6e1d124db Begin moving separate boolean variables in the ShellState object of the CLI
into the shellFlgs bitmask.

FossilOrigin-Name: 50eec5d9aa38fab1a85d788356ffdaf6c35d9ece
2017-03-09 13:50:49 +00:00
drh f80d4ff59f Make sure the database connection is open prior to running the ".sha3sum"
command.

FossilOrigin-Name: 2ea300fb8f7c497f3f092dc91f4305d8431c27d9
2017-03-08 18:06:20 +00:00
drh 3ee83efec1 In the ".sha3sum" command, if there is a LIKE pattern, show the hashes for
each table separately.  Without a LIKE pattern, show a single hash over the
entire database.

FossilOrigin-Name: 30f878832820ce7ccc4627c4f0f98fbe82f8b0f6
2017-03-08 17:56:54 +00:00
drh 1554bc8a2e Add the ".sha3sum" command to the CLI - used to compute a cryptographic hash
of the <em>content</em> of a database file or of individual tables with in
that file.

FossilOrigin-Name: fc663799075a22b0a61a6a114116bb2d1b96d4ab
2017-03-08 16:10:34 +00:00
drh 4146b4e34a Improved comments explaining the sha3_query() format. Fix a performance #ifdef
error in the sha3 implementation.

FossilOrigin-Name: 54ef7abd7f5b16f4b29c9519d283e142c9340fbf
2017-03-08 15:03:12 +00:00
drh acc83d2e4f Add the shathree.c extension for implementing SHA3() and SHA3_QUERY() SQL
functions.

FossilOrigin-Name: f7ca9193ddafd3676406bdfeb1b7d21182c2a3c1
2017-03-08 13:50:40 +00:00
drh f42d318002 In the CLI, avoid unnecessary identifier quoting in the ".dump" output.
Also add new ".dump" test cases.

FossilOrigin-Name: de65f907610a59e64cbf2214789c11f7117a86a6
2017-03-08 12:25:18 +00:00
drh e611f14471 Add the --preserve-rowids option to the ".dump" command in the CLI.
FossilOrigin-Name: c60aee24714a47ce12ee2a4dcefb9f55211d3761
2017-03-08 11:44:00 +00:00
dan 5cc95ebf37 Add test script ext/rbu/rbu_round_trip.tcl. Uses "dbselftest" to test that
"rbu" and "sqldiff" work together.

FossilOrigin-Name: 961e79da73b4550b3e5b0f9a617133a76485db67
2017-03-07 20:03:25 +00:00
drh 9b38d6660f Performance optimization in the tokenizer/parser loop.
FossilOrigin-Name: 2cb71583d631cd417acbeebbb4ee950573a9deef
2017-03-07 14:38:52 +00:00
drh 567bd44917 Minor comment typo fixes. No changes to code.
FossilOrigin-Name: 01cd9fb176cde30658233e36aad44e4a5519612e
2017-03-07 12:18:23 +00:00
drh a92b81f487 More size and speed improvements in the expression name resolver.
FossilOrigin-Name: e0a3d39f51a50420bae97e2bc9a8c01a5b0d3db8
2017-03-07 03:40:48 +00:00
drh 3cf48e3e89 Small size reduction and performance increase in the name resolver routine
for expressions.

FossilOrigin-Name: 1a3554e1d71b666325ff377fae5329d79ce5c05f
2017-03-07 03:25:52 +00:00
drh 59dbe3a5ef Make the default MASK argument for "PRAGMA optimize" be 0xfffe, to allow for
future expansion of up to 14 new default-on optimizations.

FossilOrigin-Name: 73019a8bba29fd07f73559cd00d5346fa822b439
2017-03-06 23:51:16 +00:00
drh e1f1c0802c Fix a typo in a comment. No changes to code.
FossilOrigin-Name: ec529bf11b16c801ea438e57d208ff7e4cedf1f9
2017-03-06 20:44:13 +00:00
drh cc98b1fc89 Add an initial implementation of the "PRAGMA optimize" command.
FossilOrigin-Name: 137aeb2b160888100bc1e871b00860149e5f6196
2017-03-06 17:33:58 +00:00
drh 063d57039e Merge updates from trunk.
FossilOrigin-Name: 5f7fc79aa06ca9b79664c50c3c277c98a74ff9a0
2017-03-06 11:39:34 +00:00
drh 2996796dcf If a reprepare is needed after binding to a variable with a number larger
than 32, set only the high-order bit of the Vdbe.expmask rather than setting
all bits.  This could potentially result in fewer false-positive reprepares.

FossilOrigin-Name: 45797feefe90cb7da53256b0c42fdaa1221d0a27
2017-03-03 21:51:40 +00:00
drh f3f883fcd7 Remove an redundant function call from the date/time function implementation.
FossilOrigin-Name: 4a04c48a311b19ba5e566877dc5baff543c41aba
2017-03-03 21:36:26 +00:00
drh 35a0925a23 Fix another corner-case for the 'start of ...' modifier in the date/time
functions.  Related to ticket [6097cb92745327a1].

FossilOrigin-Name: 8831f4393dda42b3434e7767968caea84bbca2af
2017-03-03 20:43:43 +00:00
dan 30741eb0d3 Fix a case introduced by [4cd2a967] where a corrupt database could cause a buffer overwrite.
FossilOrigin-Name: 5d0455fece514552ad7f283d56526f53d7c688bd
2017-03-03 20:02:53 +00:00
dan 0e9b43ff85 Before beginning an incremental checkpoint in RBU, sync the directory
containing the target database file. This ensures that the new directory entry
created by renaming the *-oal file to *-wal is synced to disk.

FossilOrigin-Name: 915a9a28783fbb2f4c0794eb4264ce8c0b9d42f7
2017-03-03 16:51:46 +00:00
drh 9715f7f033 Fix a bug in the 'start of ...' date/time modifiers when they follow a
julian day number.  Fix for ticket [6097cb92745327a1].

FossilOrigin-Name: 081dbcfb6d82528cefecb36c4491fa6e1a790b17
2017-03-02 23:40:21 +00:00
dan 1d62a66230 Fix another RBU case similar to the previous. This one for systems where the
sector-size is larger than the page-size.

FossilOrigin-Name: 4012bb3aa91927156ba149caa4e5c622b0729d79
2017-03-02 16:56:48 +00:00
dan cb1b0a693a When saving the state of an RBU update in the incremental-checkpoint phase,
sync the database file. Otherwise, if a power failure occurs and the RBU
update resumed following system recovery, the database may become corrupt.

FossilOrigin-Name: edee6a80e1cc7e6a2b8c3c7f76dd794fc8ab9a72
2017-03-02 14:51:47 +00:00
drh 1cfaf8eafb Add an optional bitmask of allowed optimizations on the "PRAGMA optimize"
command.  The 0x01 bit is Debug Mode.

FossilOrigin-Name: a35388eef4096c1856b025dbd90143409d4a72d3
2017-03-02 14:17:21 +00:00
drh 8d990b34db Merge recent trunk enhancements.
FossilOrigin-Name: c60cdb47612c05c252613e50a8ac10635469fdfe
2017-03-02 13:22:04 +00:00
drh 76adb23980 Make sure the Vdbe.expmask value is set correctly in sqlite3VdbeSwap().
This fixes a problem introduced by [a8fd7052].

FossilOrigin-Name: 29f54b899e5cf22ece98ab41c39c41d75a4b228d
2017-03-02 13:13:30 +00:00
dan 2147221c36 Fix a use-after-free problem in the shell tool code that could occur if an SQL
statement were executed after an ".open" command with invalid options.

FossilOrigin-Name: ac760db0727209db0a816e112ea5f47e54d54dac
2017-03-01 11:30:27 +00:00
mistachkin 6e5688d375 Make PATH handling more robust in the batch tools for MSVC.
FossilOrigin-Name: 23a8917e848a999533bc66467f7cb2f4f3d45bc1
2017-02-27 17:16:27 +00:00
dan 81415257ec Improve performance of fts5 writes by writing the "averages" record once at
the end of each transaction instead of every time the table is updated.

FossilOrigin-Name: 2b210d691462b463796e7948399133c296e89ebf
2017-02-27 17:06:56 +00:00
dan 8a89d834d6 Add an sqlite3_set_last_insert_rowid() method. Use it to work around fts4 and
fts5 modifying the last-insert-rowid unintuitively from within commit
processing.

FossilOrigin-Name: 952a3906b30a818e4574bb85f57150577d04f74e
2017-02-27 16:15:29 +00:00
dan 9c58b63c18 Add an sqlite3_set_last_insert_rowid() method. Use it to work around fts4 and
fts5 modifying the last-insert-rowid unintuitively from within commit
processing.

FossilOrigin-Name: fe41bb5632a5d438acfd682809f1bd12315b970a
2017-02-27 14:52:48 +00:00
dan 2efd3488ba Remove references to special handling in virtual table methods from the
documentation for sqlite3_last_insert_rowid().

FossilOrigin-Name: 660f9569d76e4ff1f5bd4f37f640e6a4fc2cf87d
2017-02-27 12:23:52 +00:00
dan 70cdf38232 Add an 'extern "C"' block to header file sqlite3userauth.h.
FossilOrigin-Name: ffd61fb449a510b2fc90caf86b266733051cc365
2017-02-25 20:57:46 +00:00
dan 5328181db1 Optimize defragmentPage() in the case where the page contains either one or
two free-blocks and a small number of fragmented bytes.

FossilOrigin-Name: 4cd2a9672c59ea4b3b4cf3d2f139af3c18a8e833
2017-02-25 17:47:31 +00:00
dan 3b2ede1f03 Tweak the code on this branch to detect b-tree page corruption in the same cases as the trunk.
FossilOrigin-Name: f9863b39d96dce6cb5e49a5f3a445ff3d897a951
2017-02-25 16:24:02 +00:00
dan e6d065a81e Optimize defragmentPage() in the case where the page contains either one or
two free-blocks and a small number of fragmented bytes.

FossilOrigin-Name: 202b1c0276aec6b8da64d3277de1ad91c9d62d80
2017-02-24 19:58:22 +00:00
dan bda4cb876c Save a few bytes and a few cycles by setting Vdbe.expmask to zero for
statements prepared using legacy interface sqlite3_prepare().

FossilOrigin-Name: a8fd705258643863493476f8b42ee981608a339f
2017-02-23 16:30:16 +00:00
drh 555227bec0 Add two NEVER() operators in the sqlite3BtreeRowCountEst() routine.
FossilOrigin-Name: 7a959f6d1ea038988cdb4c02d6f37abaec2580a0
2017-02-23 02:15:33 +00:00
drh bce0414844 Do a single OP_Expire at the very end of "PRAGMA optimize", and omit the
OP_Expire on ANALYZE commands invoked by the pragma.

FossilOrigin-Name: 188300a337c87b7ee0dd1f4b9a4f1bd80e70cca4
2017-02-23 00:58:36 +00:00
drh 2ead47cb49 Change the name of the analyze_as_needed pragma to "optimize". Enhance the
comment (which will become documentation, assuming these changes land on trunk)
to explain that the optimize pragma is likely to be enhanced in various ways
in future releases and that applications should not depend upon the current
behavior.

FossilOrigin-Name: 9fced545a6f80c55d6dc4a6106cb2d3569566b3e
2017-02-22 20:24:10 +00:00
drh 114ce7a4b1 Merge integrity_check and other improvements from trunk.
FossilOrigin-Name: fe073905081b421405ca425ca03c5b8b0ff5f2c8
2017-02-22 19:49:54 +00:00
dan 24d772cc27 Move a branch condition in analyze.c inside an #ifdef SQLITE_ENABLE_STAT4 block.
FossilOrigin-Name: d6afd98de3ee8b714dfd6477ead955096f623972
2017-02-22 19:41:16 +00:00
dan bd1d270ec9 Improve the performance of ANALYZE when SQLITE_ENABLE_STAT4 is defined.
FossilOrigin-Name: 737a82444065752785c643b1d29ca097c828effb
2017-02-22 19:27:51 +00:00
drh 6bd166b81e Improvements to PRAGMA integrity_check.
Verify CHECK constraints.
Verify NOT NULL constraints even on table that lack indexes.
Verify CHECK and NOT NULL constraints with PRAGMA quick_check.

FossilOrigin-Name: aa02bd3c95e374008b930d296c88dfafaf11c65a
2017-02-22 18:53:13 +00:00
drh 66accfc56b Cleanup and simplification of the output row count limit control of
PRAGMA integrity_check.

FossilOrigin-Name: 5af7d72ed9ec758283d78ceb46627d72021c1c60
2017-02-22 18:04:42 +00:00
drh 8b174f2916 Fix integrity_check so that it verifies NOT NULL constraints even for tables
that have no indexes.  Enhance quick_check so that it verifies NOT NULL and
CHECK constraints.

FossilOrigin-Name: 5264844b069cdc20f456acee9f5b2b97c986120d
2017-02-22 15:11:36 +00:00
drh 8a284dcefe Enhance "PRAGMA integrity_check" so that it verifies CHECK constraints.
FossilOrigin-Name: 549bae0856004ff65b505175460abd598b30fe57
2017-02-22 14:15:37 +00:00
dan 1325adf5e9 In sqlite3VdbeHalt(), return as soon as possible if
Vdbe.magic!=VDBE_MAGIC_RUN. This makes sqlite3_reset() slightly faster in some
cases.

FossilOrigin-Name: 80adc0cb4ed7bacc54b15ac8b5b205403939c8c4
2017-02-21 21:24:05 +00:00
dan f0e808c60b Fix an FTS5 problem that could cause a crash when certain queries were
interrupted using sqlite3_interrupt().

FossilOrigin-Name: e400909f313c317b7b67be6eb867ed61df7383dc
2017-02-21 17:52:58 +00:00
drh e324782254 Very small enhancement to dispatch speed for SQL functions.
FossilOrigin-Name: 3c3228ed16ed8a72630bd56bb9192ee3c7f82093
2017-02-21 15:27:22 +00:00
drh ad67e66dca Merge fixes from trunk.
FossilOrigin-Name: ff213f2ef5bf96754a2264685d25546d8b5ccf0a
2017-02-20 13:11:07 +00:00
drh 99d5b4cde6 Updated comments. No code changes.
FossilOrigin-Name: e842ad391e62df273a5b1ed569d42ea46d03a99b
2017-02-18 22:52:40 +00:00
drh 4a54bb5794 Add the OP_SqlExec opcode and use it to implement "PRAGMA analyze_as_needed",
invoking ANALYZE subcommands as necessary.  This simplifies the implementation.

FossilOrigin-Name: d386015f5e7ecdd951d70db56b7bbd858be7ad90
2017-02-18 15:58:52 +00:00
drh dfe11bae99 Fix errors in the table resize detection.
FossilOrigin-Name: 4229caec0b60a1617b9d5ff94b47271cbd7be1e0
2017-02-18 02:42:54 +00:00
drh 182e84c116 In the analyze_as_needed pragma, avoid running unnecessary OP_LoadAnalysis
and OP_Expire opcodes.  Make the analyze_as_needed pragma responsive to the
schema name.

FossilOrigin-Name: 882599a4a7ea92c9e7752e0745475508e58a11c3
2017-02-18 02:19:02 +00:00
drh 5e98e838da The analyze_as_needed pragma now responds to table size growth and will
automatically rerun the analysis after each 10x size increase.

FossilOrigin-Name: bfbdd07409688fac4ccddbab3639745f6152e23d
2017-02-17 19:24:06 +00:00
drh 72052a73a3 Add the "PRAGMA analyze_as_needed" command.
FossilOrigin-Name: e93db2373127d31d33ec46ef918fa9386bb664a6
2017-02-17 16:26:34 +00:00
drh a3928dd7be Set the TF_StatsUsed flag on tables when the query planner outcome is
affected by the sqlite_stat1 data.  Also, change the column names of the
"PRAGMA stats" command so that they are not keywords.

FossilOrigin-Name: fb2b8ae8310e4ea4b42354bbf36c3084a9d5c6d7
2017-02-17 15:26:36 +00:00
drh 33bec3f5e8 Enhance the Index and Table objects so that they remember if their stats come
from the sqlite_stat1 table.  Make the "PRAGMA stats" an SQLITE_DEBUG only
pragma.  Add the flags column to "PRAGMA stats".  These are all preliminary
steps toward a "PRAGMA analyze_ifneeded;" feature.

FossilOrigin-Name: 85026c8ee143bbd46565660fff8346ef81421546
2017-02-17 13:38:15 +00:00
98 changed files with 5889 additions and 1877 deletions
+7 -6
View File
@@ -566,6 +566,7 @@ SHELL_OPT += -DSQLITE_ENABLE_EXPLAIN_COMMENTS
SHELL_OPT += -DSQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
FUZZERSHELL_OPT = -DSQLITE_ENABLE_JSON1
FUZZCHECK_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5 -DSQLITE_OSS_FUZZ
FUZZCHECK_OPT += -DSQLITE_MAX_MEMORY=50000000
FUZZCHECK_SRC = $(TOP)/test/fuzzcheck.c $(TOP)/test/ossfuzz.c
DBFUZZ_OPT =
@@ -620,7 +621,8 @@ fuzzcheck$(TEXE): $(FUZZCHECK_SRC) sqlite3.c sqlite3.h
$(LTLINK) -o $@ $(FUZZCHECK_OPT) $(FUZZCHECK_SRC) sqlite3.c $(TLIBS)
ossshell$(TEXE): $(TOP)/test/ossfuzz.c $(TOP)/test/ossshell.c sqlite3.c sqlite3.h
$(LTLINK) -o $@ $(FUZZCHECK_OPT) $(TOP)/test/ossshell.c sqlite3.c sqlite3.h $(TLIBS)
$(LTLINK) -o $@ $(FUZZCHECK_OPT) $(TOP)/test/ossshell.c \
$(TOP)/test/ossfuzz.c sqlite3.c $(TLIBS)
dbfuzz$(TEXE): $(TOP)/test/dbfuzz.c sqlite3.c sqlite3.h
$(LTLINK) -o $@ $(DBFUZZ_OPT) $(TOP)/test/dbfuzz.c sqlite3.c $(TLIBS)
@@ -1153,6 +1155,10 @@ sqlite3_analyzer.c: sqlite3.c $(TOP)/src/tclsqlite.c $(TOP)/tool/spaceanal.tcl
sqlite3_analyzer$(TEXE): sqlite3_analyzer.c
$(LTLINK) sqlite3_analyzer.c -o $@ $(LIBTCL) $(TLIBS)
dbdump$(TEXE): $(TOP)/ext/misc/dbdump.c sqlite3.lo
$(LTLINK) -DDBDUMP_STANDALONE -o $@ \
$(TOP)/ext/misc/dbdump.c sqlite3.lo $(TLIBS)
showdb$(TEXE): $(TOP)/tool/showdb.c sqlite3.lo
$(LTLINK) -o $@ $(TOP)/tool/showdb.c sqlite3.lo $(TLIBS)
@@ -1185,11 +1191,6 @@ KV_OPT += -DSQLITE_DIRECT_OVERFLOW_READ
kvtest$(TEXE): $(TOP)/test/kvtest.c sqlite3.c
$(LTLINK) $(KV_OPT) -o $@ $(TOP)/test/kvtest.c sqlite3.c $(TLIBS)
DBSELFTEST_OPT += -DSQLITE_ENABLE_RTREE -DSQLITE_ENABLE_FTS4
dbselftest$(TEXE): $(TOP)/test/dbselftest.c sqlite3.c
$(LTLINK) $(DBSELFTEST_OPT) -o $@ $(TOP)/test/dbselftest.c sqlite3.c $(TLIBS)
rbu$(EXE): $(TOP)/ext/rbu/rbu.c $(TOP)/ext/rbu/sqlite3rbu.c sqlite3.lo
$(LTLINK) -I. -o $@ $(TOP)/ext/rbu/rbu.c sqlite3.lo $(TLIBS)
+10 -3
View File
@@ -745,8 +745,11 @@ RCC = $(RCC) -DSQLITE_ENABLE_API_ARMOR=1
!IF $(DEBUG)>2
TCC = $(TCC) -DSQLITE_DEBUG=1
TCC = $(TCC) -DSQLITE_ENABLE_WHERETRACE -DSQLITE_ENABLE_SELECTTRACE
RCC = $(RCC) -DSQLITE_DEBUG=1
!IF $(DYNAMIC_SHELL)==0
TCC = $(TCC) -DSQLITE_ENABLE_WHERETRACE -DSQLITE_ENABLE_SELECTTRACE
RCC = $(RCC) -DSQLITE_ENABLE_WHERETRACE -DSQLITE_ENABLE_SELECTTRACE
!ENDIF
!ENDIF
!IF $(DEBUG)>4 || $(OSTRACE)!=0
@@ -1510,7 +1513,7 @@ SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_SHELL_JSON1 -DSQLITE_ENABLE_
#
MPTESTER_COMPILE_OPTS = -DSQLITE_SHELL_JSON1 -DSQLITE_ENABLE_FTS5
FUZZERSHELL_COMPILE_OPTS = -DSQLITE_ENABLE_JSON1
FUZZCHECK_COMPILE_OPTS = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5 -DSQLITE_OSS_FUZZ
FUZZCHECK_COMPILE_OPTS = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5 -DSQLITE_OSS_FUZZ -DSQLITE_MAX_MEMORY=50000000
FUZZCHECK_SRC = $(TOP)\test\fuzzcheck.c $(TOP)\test\ossfuzz.c
OSSSHELL_SRC = $(TOP)\test\ossshell.c $(TOP)\test\ossfuzz.c
DBFUZZ_COMPILE_OPTS = -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION
@@ -2178,6 +2181,10 @@ sqlite3_analyzer.exe: sqlite3_analyzer.c $(LIBRESOBJS)
$(LTLINK) $(NO_WARN) -DBUILD_sqlite -I$(TCLINCDIR) sqlite3_analyzer.c \
/link $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LTLIBS) $(TLIBS)
dbdump.exe: $(TOP)\ext\misc\dbdump.c $(SQLITE3C) $(SQLITE3H)
$(LTLINK) $(NO_WARN) -DDBDUMP_STANDALONE $(TOP)\ext\misc\dbdump.c $(SQLITE3C) \
/link $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LTLIBS)
testloadext.lo: $(TOP)\src\test_loadext.c
$(LTCOMPILE) $(NO_WARN) -c $(TOP)\src\test_loadext.c
@@ -2256,7 +2263,7 @@ clean:
del /Q tclsqlite3.exe $(SQLITETCLH) $(SQLITETCLDECLSH) 2>NUL
del /Q testloadext.dll 2>NUL
del /Q testfixture.exe test.db 2>NUL
del /Q LogEst.exe fts3view.exe rollback-test.exe showdb.exe 2>NUL
del /Q LogEst.exe fts3view.exe rollback-test.exe showdb.exe dbdump.exe 2>NUL
del /Q changeset.exe 2>NUL
del /Q showjournal.exe showstat4.exe showwal.exe speedtest1.exe 2>NUL
del /Q mptester.exe wordcount.exe rbu.exe srcck1.exe 2>NUL
+56 -14
View File
@@ -8,6 +8,48 @@ If you are reading this on a Git mirror someplace, you are doing it wrong.
The [official repository](https://www.sqlite.org/src/) is better. Go there
now.
## Obtaining The Code
SQLite sources are managed using the
[Fossil](https://www.fossil-scm.org/), a distributed version control system
that was specifically designed to support SQLite development.
If you do not want to use Fossil, you can download tarballs or ZIP
archives as follows:
* Lastest trunk check-in:
<https://www.sqlite.org/src/tarball/sqlite.tar.gz> or
<https://www.sqlite.org/src/zip/sqlite.zip>.
* Latest release:
<https://www.sqlite.org/src/tarball/sqlite.tar.gz?r=release> or
<https://www.sqlite.org/src/zip/sqlite.zip?r=release>.
* For other check-ins, substitute an appropriate branch name or
tag or hash prefix for "release" in the URLs of the previous
bullet. Or browse the [timeline](https://www.sqlite.org/src/timeline)
to locate the check-in desired, click on its information page link,
then click on the "Tarball" or "ZIP Archive" links on the information
page.
If you do want to use Fossil to check out the source tree,
first install Fossil version 2.0 or later.
(Source tarballs and precompiled binaries available
[here](https://www.fossil-scm.org/fossil/uv/download.html).)
Then run commands like this:
mkdir ~/sqlite
cd ~/sqlite
fossil clone https://www.sqlite.org/src sqlite.fossil
fossil open sqlite.fossil
After setting up a repository using the steps above, you can always
update to the lastest version using:
fossil update trunk ;# latest trunk check-in
fossil update release ;# latest official release
Or type "fossil ui" to get a web-based user interface.
## Compiling
First create a directory in which to place
@@ -18,13 +60,13 @@ script found at the root of the source tree. Then run "make".
For example:
tar xzf sqlite.tar.gz ;# Unpack the source tree into "sqlite"
mkdir bld ;# Build will occur in a sibling directory
cd bld ;# Change to the build directory
../sqlite/configure ;# Run the configure script
make ;# Run the makefile.
make sqlite3.c ;# Build the "amalgamation" source file
make test ;# Run some tests (requires Tcl)
tar xzf sqlite.tar.gz ;# Unpack the source tree into "sqlite"
mkdir bld ;# Build will occur in a sibling directory
cd bld ;# Change to the build directory
../sqlite/configure ;# Run the configure script
make ;# Run the makefile.
make sqlite3.c ;# Build the "amalgamation" source file
make test ;# Run some tests (requires Tcl)
See the makefile for additional targets.
@@ -43,13 +85,13 @@ with the provided "Makefile.msc" to build one of the supported targets.
For example:
mkdir bld
cd bld
nmake /f Makefile.msc TOP=..\sqlite
nmake /f Makefile.msc sqlite3.c TOP=..\sqlite
nmake /f Makefile.msc sqlite3.dll TOP=..\sqlite
nmake /f Makefile.msc sqlite3.exe TOP=..\sqlite
nmake /f Makefile.msc test TOP=..\sqlite
mkdir bld
cd bld
nmake /f Makefile.msc TOP=..\sqlite
nmake /f Makefile.msc sqlite3.c TOP=..\sqlite
nmake /f Makefile.msc sqlite3.dll TOP=..\sqlite
nmake /f Makefile.msc sqlite3.exe TOP=..\sqlite
nmake /f Makefile.msc test TOP=..\sqlite
There are several build options that can be set via the NMAKE command
line. For example, to build for WinRT, simply add "FOR_WINRT=1" argument
+1 -1
View File
@@ -1 +1 @@
3.18.0
3.19.0
+4
View File
@@ -645,6 +645,10 @@ RCC = $(RCC) -DSQLITE_ENABLE_API_ARMOR=1
!IF $(DEBUG)>2
TCC = $(TCC) -DSQLITE_DEBUG=1
RCC = $(RCC) -DSQLITE_DEBUG=1
!IF $(DYNAMIC_SHELL)==0
TCC = $(TCC) -DSQLITE_ENABLE_WHERETRACE -DSQLITE_ENABLE_SELECTTRACE
RCC = $(RCC) -DSQLITE_ENABLE_WHERETRACE -DSQLITE_ENABLE_SELECTTRACE
!ENDIF
!ENDIF
!IF $(DEBUG)>4 || $(OSTRACE)!=0
+2 -2
View File
@@ -55,9 +55,9 @@ AS_IF([ test x"$enable_editline" != xno ],[
LIBS=""
AC_SEARCH_LIBS([readline],[edit],[
AC_DEFINE([HAVE_EDITLINE],1,Define to use BSD editline)
READLINE_LIBS=$LIBS
READLINE_LIBS="$LIBS -ltinfo"
enable_readline=no
])
],[],[-ltinfo])
AS_UNSET(ac_cv_search_readline)
LIBS=$sLIBS
])
Vendored
+19 -19
View File
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.69 for sqlite 3.18.0.
# Generated by GNU Autoconf 2.69 for sqlite 3.19.0.
#
#
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
@@ -726,8 +726,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='sqlite'
PACKAGE_TARNAME='sqlite'
PACKAGE_VERSION='3.18.0'
PACKAGE_STRING='sqlite 3.18.0'
PACKAGE_VERSION='3.19.0'
PACKAGE_STRING='sqlite 3.19.0'
PACKAGE_BUGREPORT=''
PACKAGE_URL=''
@@ -1463,7 +1463,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
\`configure' configures sqlite 3.18.0 to adapt to many kinds of systems.
\`configure' configures sqlite 3.19.0 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1528,7 +1528,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
short | recursive ) echo "Configuration of sqlite 3.18.0:";;
short | recursive ) echo "Configuration of sqlite 3.19.0:";;
esac
cat <<\_ACEOF
@@ -1652,7 +1652,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
sqlite configure 3.18.0
sqlite configure 3.19.0
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2071,7 +2071,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
It was created by sqlite $as_me 3.18.0, which was
It was created by sqlite $as_me 3.19.0, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -11252,7 +11252,7 @@ else
fi
if test "${use_debug}" = "yes" ; then
TARGET_DEBUG="-DSQLITE_DEBUG=1 -DSQLITE_ENABLE_SELECTTRACE -DSQLITE_ENABLE_WHERETRACE"
TARGET_DEBUG="-DSQLITE_DEBUG=1 -DSQLITE_ENABLE_SELECTTRACE -DSQLITE_ENABLE_WHERETRACE -O0"
else
TARGET_DEBUG="-DNDEBUG"
fi
@@ -11356,7 +11356,7 @@ fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to support MEMSYS5" >&5
$as_echo_n "checking whether to support MEMSYS5... " >&6; }
if test "${enable_memsys5}" = "yes"; then
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_MEMSYS5"
OPT_FEATURE_FLAGS="$(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_MEMSYS5"
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
else
@@ -11373,7 +11373,7 @@ fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to support MEMSYS3" >&5
$as_echo_n "checking whether to support MEMSYS3... " >&6; }
if test "${enable_memsys3}" = "yes" -a "${enable_memsys5}" = "no"; then
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_MEMSYS3"
OPT_FEATURE_FLAGS="$(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_MEMSYS3"
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
else
@@ -11391,7 +11391,7 @@ else
fi
if test "${enable_fts3}" = "yes" ; then
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_FTS3"
OPT_FEATURE_FLAGS="$(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_FTS3"
fi
# Check whether --enable-fts4 was given.
if test "${enable_fts4+set}" = set; then :
@@ -11401,7 +11401,7 @@ else
fi
if test "${enable_fts4}" = "yes" ; then
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_FTS4"
OPT_FEATURE_FLAGS="$(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_FTS4"
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing log" >&5
$as_echo_n "checking for library containing log... " >&6; }
if ${ac_cv_search_log+:} false; then :
@@ -11467,7 +11467,7 @@ else
fi
if test "${enable_fts5}" = "yes" ; then
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_FTS5"
OPT_FEATURE_FLAGS="$(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_FTS5"
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing log" >&5
$as_echo_n "checking for library containing log... " >&6; }
if ${ac_cv_search_log+:} false; then :
@@ -11536,7 +11536,7 @@ else
fi
if test "${enable_json1}" = "yes" ; then
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_JSON1"
OPT_FEATURE_FLAGS="$(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_JSON1"
fi
#########
@@ -11549,7 +11549,7 @@ else
fi
if test "${enable_rtree}" = "yes" ; then
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_RTREE"
OPT_FEATURE_FLAGS="$(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_RTREE"
fi
#########
@@ -11562,8 +11562,8 @@ else
fi
if test "${enable_session}" = "yes" ; then
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_SESSION"
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_PREUPDATE_HOOK"
OPT_FEATURE_FLAGS="$(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_SESSION"
OPT_FEATURE_FLAGS="$(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_PREUPDATE_HOOK"
fi
#########
@@ -12151,7 +12151,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
This file was extended by sqlite $as_me 3.18.0, which was
This file was extended by sqlite $as_me 3.19.0, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -12217,7 +12217,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
sqlite config.status 3.18.0
sqlite config.status 3.19.0
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
+10 -10
View File
@@ -560,7 +560,7 @@ AC_SEARCH_LIBS(fdatasync, [rt])
AC_ARG_ENABLE(debug, AC_HELP_STRING([--enable-debug],[enable debugging & verbose explain]),
[use_debug=$enableval],[use_debug=no])
if test "${use_debug}" = "yes" ; then
TARGET_DEBUG="-DSQLITE_DEBUG=1 -DSQLITE_ENABLE_SELECTTRACE -DSQLITE_ENABLE_WHERETRACE"
TARGET_DEBUG="-DSQLITE_DEBUG=1 -DSQLITE_ENABLE_SELECTTRACE -DSQLITE_ENABLE_WHERETRACE -O0"
else
TARGET_DEBUG="-DNDEBUG"
fi
@@ -596,7 +596,7 @@ AC_ARG_ENABLE(memsys5,
[enable_memsys5=yes],[enable_memsys5=no])
AC_MSG_CHECKING([whether to support MEMSYS5])
if test "${enable_memsys5}" = "yes"; then
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_MEMSYS5"
OPT_FEATURE_FLAGS="$(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_MEMSYS5"
AC_MSG_RESULT([yes])
else
AC_MSG_RESULT([no])
@@ -606,7 +606,7 @@ AC_ARG_ENABLE(memsys3,
[enable_memsys3=yes],[enable_memsys3=no])
AC_MSG_CHECKING([whether to support MEMSYS3])
if test "${enable_memsys3}" = "yes" -a "${enable_memsys5}" = "no"; then
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_MEMSYS3"
OPT_FEATURE_FLAGS="$(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_MEMSYS3"
AC_MSG_RESULT([yes])
else
AC_MSG_RESULT([no])
@@ -618,20 +618,20 @@ AC_ARG_ENABLE(fts3, AC_HELP_STRING([--enable-fts3],
[Enable the FTS3 extension]),
[enable_fts3=yes],[enable_fts3=no])
if test "${enable_fts3}" = "yes" ; then
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_FTS3"
OPT_FEATURE_FLAGS="$(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_FTS3"
fi
AC_ARG_ENABLE(fts4, AC_HELP_STRING([--enable-fts4],
[Enable the FTS4 extension]),
[enable_fts4=yes],[enable_fts4=no])
if test "${enable_fts4}" = "yes" ; then
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_FTS4"
OPT_FEATURE_FLAGS="$(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_FTS4"
AC_SEARCH_LIBS([log],[m])
fi
AC_ARG_ENABLE(fts5, AC_HELP_STRING([--enable-fts5],
[Enable the FTS5 extension]),
[enable_fts5=yes],[enable_fts5=no])
if test "${enable_fts5}" = "yes" ; then
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_FTS5"
OPT_FEATURE_FLAGS="$(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_FTS5"
AC_SEARCH_LIBS([log],[m])
fi
@@ -641,7 +641,7 @@ AC_ARG_ENABLE(json1, AC_HELP_STRING([--enable-json1],
[Enable the JSON1 extension]),
[enable_json1=yes],[enable_json1=no])
if test "${enable_json1}" = "yes" ; then
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_JSON1"
OPT_FEATURE_FLAGS="$(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_JSON1"
fi
#########
@@ -650,7 +650,7 @@ AC_ARG_ENABLE(rtree, AC_HELP_STRING([--enable-rtree],
[Enable the RTREE extension]),
[enable_rtree=yes],[enable_rtree=no])
if test "${enable_rtree}" = "yes" ; then
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_RTREE"
OPT_FEATURE_FLAGS="$(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_RTREE"
fi
#########
@@ -659,8 +659,8 @@ AC_ARG_ENABLE(session, AC_HELP_STRING([--enable-session],
[Enable the SESSION extension]),
[enable_session=yes],[enable_session=no])
if test "${enable_session}" = "yes" ; then
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_SESSION"
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_PREUPDATE_HOOK"
OPT_FEATURE_FLAGS="$(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_SESSION"
OPT_FEATURE_FLAGS="$(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_PREUPDATE_HOOK"
fi
#########
+8
View File
@@ -0,0 +1,8 @@
## Loadable Extensions
Various [loadable extensions](https://www.sqlite.org/loadext.html) for
SQLite are found in subfolders.
Most subfolders are dedicated to a single loadable extension (for
example FTS5, or RTREE). But the misc/ subfolder contains a collection
of smaller single-file extensions.
-2
View File
@@ -1,2 +0,0 @@
Version loadable extensions to SQLite are found in subfolders
of this folder.
+10 -4
View File
@@ -349,8 +349,9 @@ int sqlite3Fts3PutVarint(char *p, sqlite_int64 v){
** Return the number of bytes read, or 0 on error.
** The value is stored in *v.
*/
int sqlite3Fts3GetVarint(const char *p, sqlite_int64 *v){
const char *pStart = p;
int sqlite3Fts3GetVarint(const char *pBuf, sqlite_int64 *v){
const unsigned char *p = (const unsigned char*)pBuf;
const unsigned char *pStart = p;
u32 a;
u64 b;
int shift;
@@ -1397,7 +1398,9 @@ static int fts3InitVtab(
char *z;
int n = 0;
z = (char *)sqlite3Fts3NextToken(aCol[iCol], &n);
memcpy(zCsr, z, n);
if( n>0 ){
memcpy(zCsr, z, n);
}
zCsr[n] = '\0';
sqlite3Fts3Dequote(zCsr);
p->azColumn[iCol] = zCsr;
@@ -3408,8 +3411,10 @@ static int fts3SyncMethod(sqlite3_vtab *pVtab){
const u32 nMinMerge = 64; /* Minimum amount of incr-merge work to do */
Fts3Table *p = (Fts3Table*)pVtab;
int rc = sqlite3Fts3PendingTermsFlush(p);
int rc;
i64 iLastRowid = sqlite3_last_insert_rowid(p->db);
rc = sqlite3Fts3PendingTermsFlush(p);
if( rc==SQLITE_OK
&& p->nLeafAdd>(nMinMerge/16)
&& p->nAutoincrmerge && p->nAutoincrmerge!=0xff
@@ -3424,6 +3429,7 @@ static int fts3SyncMethod(sqlite3_vtab *pVtab){
if( A>(int)nMinMerge ) rc = sqlite3Fts3Incrmerge(p, A, p->nAutoincrmerge);
}
sqlite3Fts3SegmentsClose(p);
sqlite3_set_last_insert_rowid(p->db, iLastRowid);
return rc;
}
+13 -13
View File
@@ -136,16 +136,16 @@ static int unicodeAddExceptions(
){
const unsigned char *z = (const unsigned char *)zIn;
const unsigned char *zTerm = &z[nIn];
int iCode;
unsigned int iCode;
int nEntry = 0;
assert( bAlnum==0 || bAlnum==1 );
while( z<zTerm ){
READ_UTF8(z, zTerm, iCode);
assert( (sqlite3FtsUnicodeIsalnum(iCode) & 0xFFFFFFFE)==0 );
if( sqlite3FtsUnicodeIsalnum(iCode)!=bAlnum
&& sqlite3FtsUnicodeIsdiacritic(iCode)==0
assert( (sqlite3FtsUnicodeIsalnum((int)iCode) & 0xFFFFFFFE)==0 );
if( sqlite3FtsUnicodeIsalnum((int)iCode)!=bAlnum
&& sqlite3FtsUnicodeIsdiacritic((int)iCode)==0
){
nEntry++;
}
@@ -162,13 +162,13 @@ static int unicodeAddExceptions(
z = (const unsigned char *)zIn;
while( z<zTerm ){
READ_UTF8(z, zTerm, iCode);
if( sqlite3FtsUnicodeIsalnum(iCode)!=bAlnum
&& sqlite3FtsUnicodeIsdiacritic(iCode)==0
if( sqlite3FtsUnicodeIsalnum((int)iCode)!=bAlnum
&& sqlite3FtsUnicodeIsdiacritic((int)iCode)==0
){
int i, j;
for(i=0; i<nNew && aNew[i]<iCode; i++);
for(i=0; i<nNew && aNew[i]<(int)iCode; i++);
for(j=nNew; j>i; j--) aNew[j] = aNew[j-1];
aNew[i] = iCode;
aNew[i] = (int)iCode;
nNew++;
}
}
@@ -318,7 +318,7 @@ static int unicodeNext(
){
unicode_cursor *pCsr = (unicode_cursor *)pC;
unicode_tokenizer *p = ((unicode_tokenizer *)pCsr->base.pTokenizer);
int iCode = 0;
unsigned int iCode = 0;
char *zOut;
const unsigned char *z = &pCsr->aInput[pCsr->iOff];
const unsigned char *zStart = z;
@@ -330,7 +330,7 @@ static int unicodeNext(
** the input. */
while( z<zTerm ){
READ_UTF8(z, zTerm, iCode);
if( unicodeIsAlnum(p, iCode) ) break;
if( unicodeIsAlnum(p, (int)iCode) ) break;
zStart = z;
}
if( zStart>=zTerm ) return SQLITE_DONE;
@@ -350,7 +350,7 @@ static int unicodeNext(
/* Write the folded case of the last character read to the output */
zEnd = z;
iOut = sqlite3FtsUnicodeFold(iCode, p->bRemoveDiacritic);
iOut = sqlite3FtsUnicodeFold((int)iCode, p->bRemoveDiacritic);
if( iOut ){
WRITE_UTF8(zOut, iOut);
}
@@ -358,8 +358,8 @@ static int unicodeNext(
/* If the cursor is not at EOF, read the next character */
if( z>=zTerm ) break;
READ_UTF8(z, zTerm, iCode);
}while( unicodeIsAlnum(p, iCode)
|| sqlite3FtsUnicodeIsdiacritic(iCode)
}while( unicodeIsAlnum(p, (int)iCode)
|| sqlite3FtsUnicodeIsdiacritic((int)iCode)
);
/* Set the output variables and return. */
+10 -11
View File
@@ -127,9 +127,9 @@ int sqlite3FtsUnicodeIsalnum(int c){
0xFFFFFFFF, 0xFC00FFFF, 0xF8000001, 0xF8000001,
};
if( c<128 ){
return ( (aAscii[c >> 5] & (1 << (c & 0x001F)))==0 );
}else if( c<(1<<22) ){
if( (unsigned int)c<128 ){
return ( (aAscii[c >> 5] & ((unsigned int)1 << (c & 0x001F)))==0 );
}else if( (unsigned int)c<(1<<22) ){
unsigned int key = (((unsigned int)c)<<10) | 0x000003FF;
int iRes = 0;
int iHi = sizeof(aEntry)/sizeof(aEntry[0]) - 1;
@@ -322,16 +322,17 @@ int sqlite3FtsUnicodeFold(int c, int bRemoveDiacritic){
int ret = c;
assert( c>=0 );
assert( sizeof(unsigned short)==2 && sizeof(unsigned char)==1 );
if( c<128 ){
if( c>='A' && c<='Z' ) ret = c + ('a' - 'A');
}else if( c<65536 ){
const struct TableEntry *p;
int iHi = sizeof(aEntry)/sizeof(aEntry[0]) - 1;
int iLo = 0;
int iRes = -1;
assert( c>aEntry[0].iCode );
while( iHi>=iLo ){
int iTest = (iHi + iLo) / 2;
int cmp = (c - aEntry[iTest].iCode);
@@ -342,14 +343,12 @@ int sqlite3FtsUnicodeFold(int c, int bRemoveDiacritic){
iHi = iTest-1;
}
}
assert( iRes<0 || c>=aEntry[iRes].iCode );
if( iRes>=0 ){
const struct TableEntry *p = &aEntry[iRes];
if( c<(p->iCode + p->nRange) && 0==(0x01 & p->flags & (p->iCode ^ c)) ){
ret = (c + (aiOff[p->flags>>1])) & 0x0000FFFF;
assert( ret>0 );
}
assert( iRes>=0 && c>=aEntry[iRes].iCode );
p = &aEntry[iRes];
if( c<(p->iCode + p->nRange) && 0==(0x01 & p->flags & (p->iCode ^ c)) ){
ret = (c + (aiOff[p->flags>>1])) & 0x0000FFFF;
assert( ret>0 );
}
if( bRemoveDiacritic ) ret = remove_diacritic(ret);
+4 -1
View File
@@ -4956,11 +4956,14 @@ int sqlite3Fts3Incrmerge(Fts3Table *p, int nMerge, int nMin){
** Convert the text beginning at *pz into an integer and return
** its value. Advance *pz to point to the first character past
** the integer.
**
** This function used for parameters to merge= and incrmerge=
** commands.
*/
static int fts3Getint(const char **pz){
const char *z = *pz;
int i = 0;
while( (*z)>='0' && (*z)<='9' ) i = 10*i + *(z++) - '0';
while( (*z)>='0' && (*z)<='9' && i<214748363 ) i = 10*i + *(z++) - '0';
*pz = z;
return i;
}
+16
View File
@@ -0,0 +1,16 @@
#!/bin/sh
set -e
srcdir=`dirname $(dirname $(dirname $(dirname $0)))`
./testfixture $srcdir/test/fts3.test --output=fts3cov-out.txt
echo ""
for f in `ls $srcdir/ext/fts3/*.c`
do
f=`basename $f`
echo -ne "$f: "
gcov -b $f | grep Taken | sed 's/Taken at least once://'
done
+1 -1
View File
@@ -227,7 +227,7 @@ proc print_isalnum {zFunc lRange} {
an_print_ascii_bitmap $lRange
puts {
if( (unsigned int)c<128 ){
return ( (aAscii[c >> 5] & (1 << (c & 0x001F)))==0 );
return ( (aAscii[c >> 5] & ((unsigned int)1 << (c & 0x001F)))==0 );
}else if( (unsigned int)c<(1<<22) ){
unsigned int key = (((unsigned int)c)<<10) | 0x000003FF;
int iRes = 0;
+13 -2
View File
@@ -1110,7 +1110,10 @@ static int fts5ExprNodeNext_OR(
|| (bFromValid && fts5RowidCmp(pExpr, p1->iRowid, iFrom)<0)
){
int rc = fts5ExprNodeNext(pExpr, p1, bFromValid, iFrom);
if( rc!=SQLITE_OK ) return rc;
if( rc!=SQLITE_OK ){
pNode->bNomatch = 0;
return rc;
}
}
}
}
@@ -1141,7 +1144,10 @@ static int fts5ExprNodeTest_AND(
if( cmp>0 ){
/* Advance pChild until it points to iLast or laster */
rc = fts5ExprNodeNext(pExpr, pChild, 1, iLast);
if( rc!=SQLITE_OK ) return rc;
if( rc!=SQLITE_OK ){
pAnd->bNomatch = 0;
return rc;
}
}
/* If the child node is now at EOF, so is the parent AND node. Otherwise,
@@ -1180,6 +1186,8 @@ static int fts5ExprNodeNext_AND(
int rc = fts5ExprNodeNext(pExpr, pNode->apChild[0], bFromValid, iFrom);
if( rc==SQLITE_OK ){
rc = fts5ExprNodeTest_AND(pExpr, pNode);
}else{
pNode->bNomatch = 0;
}
return rc;
}
@@ -1222,6 +1230,9 @@ static int fts5ExprNodeNext_NOT(
if( rc==SQLITE_OK ){
rc = fts5ExprNodeTest_NOT(pExpr, pNode);
}
if( rc!=SQLITE_OK ){
pNode->bNomatch = 0;
}
return rc;
}
+10 -15
View File
@@ -545,11 +545,6 @@ int sqlite3Fts5StorageDelete(Fts5Storage *p, i64 iDel, sqlite3_value **apVal){
}
}
/* Write the averages record */
if( rc==SQLITE_OK ){
rc = fts5StorageSaveTotals(p);
}
return rc;
}
@@ -753,11 +748,6 @@ int sqlite3Fts5StorageIndexInsert(
}
sqlite3_free(buf.p);
/* Write the averages record */
if( rc==SQLITE_OK ){
rc = fts5StorageSaveTotals(p);
}
return rc;
}
@@ -1092,12 +1082,17 @@ int sqlite3Fts5StorageRowCount(Fts5Storage *p, i64 *pnRow){
** Flush any data currently held in-memory to disk.
*/
int sqlite3Fts5StorageSync(Fts5Storage *p, int bCommit){
if( bCommit && p->bTotalsValid ){
int rc = fts5StorageSaveTotals(p);
p->bTotalsValid = 0;
if( rc!=SQLITE_OK ) return rc;
int rc = SQLITE_OK;
i64 iLastRowid = sqlite3_last_insert_rowid(p->pConfig->db);
if( p->bTotalsValid ){
rc = fts5StorageSaveTotals(p);
if( bCommit ) p->bTotalsValid = 0;
}
return sqlite3Fts5IndexSync(p->pIndex, bCommit);
if( rc==SQLITE_OK ){
rc = sqlite3Fts5IndexSync(p->pIndex, bCommit);
}
sqlite3_set_last_insert_rowid(p->pConfig->db, iLastRowid);
return rc;
}
int sqlite3Fts5StorageRollback(Fts5Storage *p){
+87
View File
@@ -0,0 +1,87 @@
# 2016 February 2
#
# 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 is focused on OOM errors.
#
source [file join [file dirname [info script]] fts5_common.tcl]
source $testdir/malloc_common.tcl
set testprefix fts5faultA
# If SQLITE_ENABLE_FTS3 is defined, omit this file.
ifcapable !fts5 {
finish_test
return
}
foreach_detail_mode $testprefix {
if {"%DETAIL%"=="none"} continue
do_execsql_test 1.0 {
CREATE VIRTUAL TABLE o1 USING fts5(a, b, c, detail=%DETAIL%);
INSERT INTO o1(o1, rank) VALUES('pgsz', 32);
WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<60 )
INSERT INTO o1 SELECT 'A', 'B', 'C' FROM s;
WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<60 )
INSERT INTO o1 SELECT 'C', 'A', 'B' FROM s;
WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<60 )
INSERT INTO o1 SELECT 'B', 'C', 'A' FROM s;
}
do_faultsim_test 1 -faults int* -prep {
sqlite3 db test.db
} -body {
execsql { SELECT count(*) FROM o1('a') }
} -test {
faultsim_test_result {0 180} {1 {vtable constructor failed: o1}}
}
do_faultsim_test 2 -faults int* -prep {
sqlite3 db test.db
} -body {
execsql { SELECT * FROM o1('a:a AND {b c}:b') ORDER BY rank }
expr 1
} -test {
faultsim_test_result {0 1} {1 {vtable constructor failed: o1}}
}
do_faultsim_test 3 -faults int* -prep {
sqlite3 db test.db
} -body {
execsql { SELECT * FROM o1('{b c}:b NOT a:a') ORDER BY rank }
expr 1
} -test {
faultsim_test_result {0 1} {1 {vtable constructor failed: o1}}
}
do_faultsim_test 4 -faults int* -prep {
sqlite3 db test.db
} -body {
execsql { SELECT * FROM o1('b:b OR a:a') }
expr 1
} -test {
faultsim_test_result {0 1} {1 {vtable constructor failed: o1}}
}
do_faultsim_test 5 -faults int* -prep {
sqlite3 db test.db
} -body {
execsql { SELECT count(*) FROM o1('c:b') }
expr 1
} -test {
faultsim_test_result {0 1} {1 {vtable constructor failed: o1}}
}
}
finish_test
+73
View File
@@ -0,0 +1,73 @@
# 2017 Feb 27
#
# 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.
#
#***********************************************************************
#
# Tests of the last_insert_rowid functionality with fts5.
#
source [file join [file dirname [info script]] fts5_common.tcl]
set testprefix fts5lastrowid
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
ifcapable !fts5 {
finish_test
return
}
do_execsql_test 1.0 {
CREATE VIRTUAL TABLE t1 USING fts5(str);
}
do_execsql_test 1.1 {
INSERT INTO t1 VALUES('one string');
INSERT INTO t1 VALUES('two string');
INSERT INTO t1 VALUES('three string');
SELECT last_insert_rowid();
} {3}
do_execsql_test 1.2 {
BEGIN;
INSERT INTO t1 VALUES('one string');
INSERT INTO t1 VALUES('two string');
INSERT INTO t1 VALUES('three string');
COMMIT;
SELECT last_insert_rowid();
} {6}
do_execsql_test 1.3 {
INSERT INTO t1(rowid, str) VALUES(-22, 'some more text');
SELECT last_insert_rowid();
} {-22}
do_execsql_test 1.4 {
BEGIN;
INSERT INTO t1(rowid, str) VALUES(45, 'some more text');
INSERT INTO t1(rowid, str) VALUES(46, 'some more text');
INSERT INTO t1(rowid, str) VALUES(222, 'some more text');
SELECT last_insert_rowid();
COMMIT;
SELECT last_insert_rowid();
} {222 222}
do_execsql_test 1.5 {
CREATE TABLE x1(x);
INSERT INTO x1 VALUES('john'), ('paul'), ('george'), ('ringo');
INSERT INTO t1 SELECT x FROM x1;
SELECT last_insert_rowid();
} {226}
do_execsql_test 1.6 {
INSERT INTO t1(rowid, str) SELECT rowid+10, x FROM x1;
SELECT last_insert_rowid();
} {14}
finish_test
+40
View File
@@ -0,0 +1,40 @@
## Miscellaneous Extensions
This folder contains a collection of smaller loadable extensions.
See <https://www.sqlite.org/loadext.html> for instructions on how
to compile and use loadable extensions.
Each extension in this folder is implemented in a single file of C code.
Each source file contains a description in its header comment. See the
header comments for details about each extension. Additional notes are
as follows:
* **carray.c** &mdash; This module implements the
[carray](https://www.sqlite.org/carray.html) table-valued function.
It is a good example of how to go about implementing a custom
[table-valued function](https://www.sqlite.org/vtab.html#tabfunc2).
* **dbdump.c** &mdash; This is not actually a loadable extension, but
rather a library that implements an approximate equivalent to the
".dump" command of the
[command-line shell](https://www.sqlite.org/cli.html).
* **memvfs.c** &mdash; This file implements a custom
[VFS](https://www.sqlite.org/vfs.html) that stores an entire database
file in a single block of RAM. It serves as a good example of how
to implement a simple custom VFS.
* **rot13.c** &mdash; This file implements the very simple rot13()
substitution function. This file makes a good template for implementing
new custom SQL functions for SQLite.
* **series.c** &mdash; This is an implementation of the
"generate_series" [virtual table](https://www.sqlite.org/vtab.html).
It can make a good template for new custom virtual table implementations.
* **shathree.c** &mdash; An implementation of the sha3() and
sha3_query() SQL functions. The file is named "shathree.c" instead
of "sha3.c" because the default entry point names in SQLite are based
on the source filename with digits removed, so if we used the name
"sha3.c" then the entry point would conflict with the prior "sha1.c"
extension.
+717
View File
@@ -0,0 +1,717 @@
/*
** 2016-03-13
**
** 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 a C-language subroutine that converts the content
** of an SQLite database into UTF-8 text SQL statements that can be used
** to exactly recreate the original database. ROWID values are preserved.
**
** A prototype of the implemented subroutine is this:
**
** int sqlite3_db_dump(
** sqlite3 *db,
** const char *zSchema,
** const char *zTable,
** void (*xCallback)(void*, const char*),
** void *pArg
** );
**
** The db parameter is the database connection. zSchema is the schema within
** that database which is to be dumped. Usually the zSchema is "main" but
** can also be "temp" or any ATTACH-ed database. If zTable is not NULL, then
** only the content of that one table is dumped. If zTable is NULL, then all
** tables are dumped.
**
** The generate text is passed to xCallback() in multiple calls. The second
** argument to xCallback() is a copy of the pArg parameter. The first
** argument is some of the output text that this routine generates. The
** signature to xCallback() is designed to make it compatible with fputs().
**
** The sqlite3_db_dump() subroutine returns SQLITE_OK on success or some error
** code if it encounters a problem.
**
** If this file is compiled with -DDBDUMP_STANDALONE then a "main()" routine
** is included so that this routine becomes a command-line utility. The
** command-line utility takes two or three arguments which are the name
** of the database file, the schema, and optionally the table, forming the
** first three arguments of a single call to the library routine.
*/
#include "sqlite3.h"
#include <stdarg.h>
#include <string.h>
#include <ctype.h>
/*
** The state of the dump process.
*/
typedef struct DState DState;
struct DState {
sqlite3 *db; /* The database connection */
int nErr; /* Number of errors seen so far */
int rc; /* Error code */
int writableSchema; /* True if in writable_schema mode */
int (*xCallback)(const char*,void*); /* Send output here */
void *pArg; /* Argument to xCallback() */
};
/*
** A variable length string to which one can append text.
*/
typedef struct DText DText;
struct DText {
char *z; /* The text */
int n; /* Number of bytes of content in z[] */
int nAlloc; /* Number of bytes allocated to z[] */
};
/*
** Initialize and destroy a DText object
*/
static void initText(DText *p){
memset(p, 0, sizeof(*p));
}
static void freeText(DText *p){
sqlite3_free(p->z);
initText(p);
}
/* zIn is either a pointer to a NULL-terminated string in memory obtained
** from malloc(), or a NULL pointer. The string pointed to by zAppend is
** added to zIn, and the result returned in memory obtained from malloc().
** zIn, if it was not NULL, is freed.
**
** If the third argument, quote, is not '\0', then it is used as a
** quote character for zAppend.
*/
static void appendText(DText *p, char const *zAppend, char quote){
int len;
int i;
int nAppend = (int)(strlen(zAppend) & 0x3fffffff);
len = nAppend+p->n+1;
if( quote ){
len += 2;
for(i=0; i<nAppend; i++){
if( zAppend[i]==quote ) len++;
}
}
if( p->n+len>=p->nAlloc ){
char *zNew;
p->nAlloc = p->nAlloc*2 + len + 20;
zNew = sqlite3_realloc(p->z, p->nAlloc);
if( zNew==0 ){
freeText(p);
return;
}
p->z = zNew;
}
if( quote ){
char *zCsr = p->z+p->n;
*zCsr++ = quote;
for(i=0; i<nAppend; i++){
*zCsr++ = zAppend[i];
if( zAppend[i]==quote ) *zCsr++ = quote;
}
*zCsr++ = quote;
p->n = (int)(zCsr - p->z);
*zCsr = '\0';
}else{
memcpy(p->z+p->n, zAppend, nAppend);
p->n += nAppend;
p->z[p->n] = '\0';
}
}
/*
** Attempt to determine if identifier zName needs to be quoted, either
** because it contains non-alphanumeric characters, or because it is an
** SQLite keyword. Be conservative in this estimate: When in doubt assume
** that quoting is required.
**
** Return '"' if quoting is required. Return 0 if no quoting is required.
*/
static char quoteChar(const char *zName){
/* All SQLite keywords, in alphabetical order */
static const char *azKeywords[] = {
"ABORT", "ACTION", "ADD", "AFTER", "ALL", "ALTER", "ANALYZE", "AND", "AS",
"ASC", "ATTACH", "AUTOINCREMENT", "BEFORE", "BEGIN", "BETWEEN", "BY",
"CASCADE", "CASE", "CAST", "CHECK", "COLLATE", "COLUMN", "COMMIT",
"CONFLICT", "CONSTRAINT", "CREATE", "CROSS", "CURRENT_DATE",
"CURRENT_TIME", "CURRENT_TIMESTAMP", "DATABASE", "DEFAULT", "DEFERRABLE",
"DEFERRED", "DELETE", "DESC", "DETACH", "DISTINCT", "DROP", "EACH",
"ELSE", "END", "ESCAPE", "EXCEPT", "EXCLUSIVE", "EXISTS", "EXPLAIN",
"FAIL", "FOR", "FOREIGN", "FROM", "FULL", "GLOB", "GROUP", "HAVING", "IF",
"IGNORE", "IMMEDIATE", "IN", "INDEX", "INDEXED", "INITIALLY", "INNER",
"INSERT", "INSTEAD", "INTERSECT", "INTO", "IS", "ISNULL", "JOIN", "KEY",
"LEFT", "LIKE", "LIMIT", "MATCH", "NATURAL", "NO", "NOT", "NOTNULL",
"NULL", "OF", "OFFSET", "ON", "OR", "ORDER", "OUTER", "PLAN", "PRAGMA",
"PRIMARY", "QUERY", "RAISE", "RECURSIVE", "REFERENCES", "REGEXP",
"REINDEX", "RELEASE", "RENAME", "REPLACE", "RESTRICT", "RIGHT",
"ROLLBACK", "ROW", "SAVEPOINT", "SELECT", "SET", "TABLE", "TEMP",
"TEMPORARY", "THEN", "TO", "TRANSACTION", "TRIGGER", "UNION", "UNIQUE",
"UPDATE", "USING", "VACUUM", "VALUES", "VIEW", "VIRTUAL", "WHEN", "WHERE",
"WITH", "WITHOUT",
};
int i, lwr, upr, mid, c;
if( !isalpha((unsigned char)zName[0]) && zName[0]!='_' ) return '"';
for(i=0; zName[i]; i++){
if( !isalnum((unsigned char)zName[i]) && zName[i]!='_' ) return '"';
}
lwr = 0;
upr = sizeof(azKeywords)/sizeof(azKeywords[0]) - 1;
while( lwr<=upr ){
mid = (lwr+upr)/2;
c = sqlite3_stricmp(azKeywords[mid], zName);
if( c==0 ) return '"';
if( c<0 ){
lwr = mid+1;
}else{
upr = mid-1;
}
}
return 0;
}
/*
** Release memory previously allocated by tableColumnList().
*/
static void freeColumnList(char **azCol){
int i;
for(i=1; azCol[i]; i++){
sqlite3_free(azCol[i]);
}
/* azCol[0] is a static string */
sqlite3_free(azCol);
}
/*
** Return a list of pointers to strings which are the names of all
** columns in table zTab. The memory to hold the names is dynamically
** allocated and must be released by the caller using a subsequent call
** to freeColumnList().
**
** The azCol[0] entry is usually NULL. However, if zTab contains a rowid
** value that needs to be preserved, then azCol[0] is filled in with the
** name of the rowid column.
**
** The first regular column in the table is azCol[1]. The list is terminated
** by an entry with azCol[i]==0.
*/
static char **tableColumnList(DState *p, const char *zTab){
char **azCol = 0;
sqlite3_stmt *pStmt = 0;
char *zSql;
int nCol = 0;
int nAlloc = 0;
int nPK = 0; /* Number of PRIMARY KEY columns seen */
int isIPK = 0; /* True if one PRIMARY KEY column of type INTEGER */
int preserveRowid = 1;
int rc;
zSql = sqlite3_mprintf("PRAGMA table_info=%Q", zTab);
if( zSql==0 ) return 0;
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
sqlite3_free(zSql);
if( rc ) return 0;
while( sqlite3_step(pStmt)==SQLITE_ROW ){
if( nCol>=nAlloc-2 ){
char **azNew;
nAlloc = nAlloc*2 + nCol + 10;
azNew = sqlite3_realloc(azCol, nAlloc*sizeof(azCol[0]));
if( azNew==0 ) goto col_oom;
azCol = azNew;
azCol[0] = 0;
}
azCol[++nCol] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 1));
if( azCol[nCol]==0 ) goto col_oom;
if( sqlite3_column_int(pStmt, 5) ){
nPK++;
if( nPK==1
&& sqlite3_stricmp((const char*)sqlite3_column_text(pStmt,2),
"INTEGER")==0
){
isIPK = 1;
}else{
isIPK = 0;
}
}
}
sqlite3_finalize(pStmt);
pStmt = 0;
azCol[nCol+1] = 0;
/* The decision of whether or not a rowid really needs to be preserved
** is tricky. We never need to preserve a rowid for a WITHOUT ROWID table
** or a table with an INTEGER PRIMARY KEY. We are unable to preserve
** rowids on tables where the rowid is inaccessible because there are other
** columns in the table named "rowid", "_rowid_", and "oid".
*/
if( isIPK ){
/* If a single PRIMARY KEY column with type INTEGER was seen, then it
** might be an alise for the ROWID. But it might also be a WITHOUT ROWID
** table or a INTEGER PRIMARY KEY DESC column, neither of which are
** ROWID aliases. To distinguish these cases, check to see if
** there is a "pk" entry in "PRAGMA index_list". There will be
** no "pk" index if the PRIMARY KEY really is an alias for the ROWID.
*/
zSql = sqlite3_mprintf("SELECT 1 FROM pragma_index_list(%Q)"
" WHERE origin='pk'", zTab);
if( zSql==0 ) goto col_oom;
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
sqlite3_free(zSql);
if( rc ){
freeColumnList(azCol);
return 0;
}
rc = sqlite3_step(pStmt);
sqlite3_finalize(pStmt);
pStmt = 0;
preserveRowid = rc==SQLITE_ROW;
}
if( preserveRowid ){
/* Only preserve the rowid if we can find a name to use for the
** rowid */
static char *azRowid[] = { "rowid", "_rowid_", "oid" };
int i, j;
for(j=0; j<3; j++){
for(i=1; i<=nCol; i++){
if( sqlite3_stricmp(azRowid[j],azCol[i])==0 ) break;
}
if( i>nCol ){
/* At this point, we know that azRowid[j] is not the name of any
** ordinary column in the table. Verify that azRowid[j] is a valid
** name for the rowid before adding it to azCol[0]. WITHOUT ROWID
** tables will fail this last check */
int rc;
rc = sqlite3_table_column_metadata(p->db,0,zTab,azRowid[j],0,0,0,0,0);
if( rc==SQLITE_OK ) azCol[0] = azRowid[j];
break;
}
}
}
return azCol;
col_oom:
sqlite3_finalize(pStmt);
freeColumnList(azCol);
p->nErr++;
p->rc = SQLITE_NOMEM;
return 0;
}
/*
** Send mprintf-formatted content to the output callback.
*/
static void output_formatted(DState *p, const char *zFormat, ...){
va_list ap;
char *z;
va_start(ap, zFormat);
z = sqlite3_vmprintf(zFormat, ap);
va_end(ap);
p->xCallback(z, p->pArg);
sqlite3_free(z);
}
/*
** Output the given string as a quoted string using SQL quoting conventions.
**
** The "\n" and "\r" characters are converted to char(10) and char(13)
** to prevent them from being transformed by end-of-line translators.
*/
static void output_quoted_string(DState *p, const unsigned char *z){
int i;
char c;
int inQuote = 0;
int bStarted = 0;
for(i=0; (c = z[i])!=0 && c!='\'' && c!='\n' && c!='\r'; i++){}
if( c==0 ){
output_formatted(p, "'%s'", z);
return;
}
while( *z ){
for(i=0; (c = z[i])!=0 && c!='\n' && c!='\r' && c!='\''; i++){}
if( c=='\'' ) i++;
if( i ){
if( !inQuote ){
if( bStarted ) p->xCallback("||", p->pArg);
p->xCallback("'", p->pArg);
inQuote = 1;
}
output_formatted(p, "%.*s", i, z);
z += i;
bStarted = 1;
}
if( c=='\'' ){
p->xCallback("'", p->pArg);
continue;
}
if( inQuote ){
p->xCallback("'", p->pArg);
inQuote = 0;
}
if( c==0 ){
break;
}
for(i=0; (c = z[i])=='\r' || c=='\n'; i++){
if( bStarted ) p->xCallback("||", p->pArg);
output_formatted(p, "char(%d)", c);
bStarted = 1;
}
z += i;
}
if( inQuote ) p->xCallback("'", p->pArg);
}
/*
** This is an sqlite3_exec callback routine used for dumping the database.
** Each row received by this callback consists of a table name,
** the table type ("index" or "table") and SQL to create the table.
** This routine should print text sufficient to recreate the table.
*/
static int dump_callback(void *pArg, int nArg, char **azArg, char **azCol){
int rc;
const char *zTable;
const char *zType;
const char *zSql;
DState *p = (DState*)pArg;
sqlite3_stmt *pStmt;
(void)azCol;
if( nArg!=3 ) return 1;
zTable = azArg[0];
zType = azArg[1];
zSql = azArg[2];
if( strcmp(zTable, "sqlite_sequence")==0 ){
p->xCallback("DELETE FROM sqlite_sequence;\n", p->pArg);
}else if( sqlite3_strglob("sqlite_stat?", zTable)==0 ){
p->xCallback("ANALYZE sqlite_master;\n", p->pArg);
}else if( strncmp(zTable, "sqlite_", 7)==0 ){
return 0;
}else if( strncmp(zSql, "CREATE VIRTUAL TABLE", 20)==0 ){
if( !p->writableSchema ){
p->xCallback("PRAGMA writable_schema=ON;\n", p->pArg);
p->writableSchema = 1;
}
output_formatted(p,
"INSERT INTO sqlite_master(type,name,tbl_name,rootpage,sql)"
"VALUES('table','%q','%q',0,'%q');",
zTable, zTable, zSql);
return 0;
}else{
if( sqlite3_strglob("CREATE TABLE ['\"]*", zSql)==0 ){
p->xCallback("CREATE TABLE IF NOT EXISTS ", p->pArg);
p->xCallback(zSql+13, p->pArg);
}else{
p->xCallback(zSql, p->pArg);
}
p->xCallback(";\n", p->pArg);
}
if( strcmp(zType, "table")==0 ){
DText sSelect;
DText sTable;
char **azCol;
int i;
int nCol;
azCol = tableColumnList(p, zTable);
if( azCol==0 ) return 0;
initText(&sTable);
appendText(&sTable, "INSERT INTO ", 0);
/* Always quote the table name, even if it appears to be pure ascii,
** in case it is a keyword. Ex: INSERT INTO "table" ... */
appendText(&sTable, zTable, quoteChar(zTable));
/* If preserving the rowid, add a column list after the table name.
** In other words: "INSERT INTO tab(rowid,a,b,c,...) VALUES(...)"
** instead of the usual "INSERT INTO tab VALUES(...)".
*/
if( azCol[0] ){
appendText(&sTable, "(", 0);
appendText(&sTable, azCol[0], 0);
for(i=1; azCol[i]; i++){
appendText(&sTable, ",", 0);
appendText(&sTable, azCol[i], quoteChar(azCol[i]));
}
appendText(&sTable, ")", 0);
}
appendText(&sTable, " VALUES(", 0);
/* Build an appropriate SELECT statement */
initText(&sSelect);
appendText(&sSelect, "SELECT ", 0);
if( azCol[0] ){
appendText(&sSelect, azCol[0], 0);
appendText(&sSelect, ",", 0);
}
for(i=1; azCol[i]; i++){
appendText(&sSelect, azCol[i], quoteChar(azCol[i]));
if( azCol[i+1] ){
appendText(&sSelect, ",", 0);
}
}
nCol = i;
if( azCol[0]==0 ) nCol--;
freeColumnList(azCol);
appendText(&sSelect, " FROM ", 0);
appendText(&sSelect, zTable, quoteChar(zTable));
rc = sqlite3_prepare_v2(p->db, sSelect.z, -1, &pStmt, 0);
if( rc!=SQLITE_OK ){
p->nErr++;
if( p->rc==SQLITE_OK ) p->rc = rc;
}else{
while( SQLITE_ROW==sqlite3_step(pStmt) ){
p->xCallback(sTable.z, p->pArg);
for(i=0; i<nCol; i++){
if( i ) p->xCallback(",", p->pArg);
switch( sqlite3_column_type(pStmt,i) ){
case SQLITE_INTEGER: {
output_formatted(p, "%lld", sqlite3_column_int64(pStmt,i));
break;
}
case SQLITE_FLOAT: {
double r = sqlite3_column_double(pStmt,i);
output_formatted(p, "%!.20g", r);
break;
}
case SQLITE_NULL: {
p->xCallback("NULL", p->pArg);
break;
}
case SQLITE_TEXT: {
output_quoted_string(p, sqlite3_column_text(pStmt,i));
break;
}
case SQLITE_BLOB: {
int nByte = sqlite3_column_bytes(pStmt,i);
unsigned char *a = (unsigned char*)sqlite3_column_blob(pStmt,i);
int j;
p->xCallback("x'", p->pArg);
for(j=0; j<nByte; j++){
char zWord[3];
zWord[0] = "0123456789abcdef"[(a[j]>>4)&15];
zWord[1] = "0123456789abcdef"[a[j]&15];
zWord[2] = 0;
p->xCallback(zWord, p->pArg);
}
p->xCallback("'", p->pArg);
break;
}
}
}
p->xCallback(");\n", p->pArg);
}
}
sqlite3_finalize(pStmt);
freeText(&sTable);
freeText(&sSelect);
}
return 0;
}
/*
** Execute a query statement that will generate SQL output. Print
** the result columns, comma-separated, on a line and then add a
** semicolon terminator to the end of that line.
**
** If the number of columns is 1 and that column contains text "--"
** then write the semicolon on a separate line. That way, if a
** "--" comment occurs at the end of the statement, the comment
** won't consume the semicolon terminator.
*/
static void output_sql_from_query(
DState *p, /* Query context */
const char *zSelect, /* SELECT statement to extract content */
...
){
sqlite3_stmt *pSelect;
int rc;
int nResult;
int i;
const char *z;
char *zSql;
va_list ap;
va_start(ap, zSelect);
zSql = sqlite3_vmprintf(zSelect, ap);
va_end(ap);
if( zSql==0 ){
p->rc = SQLITE_NOMEM;
p->nErr++;
return;
}
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pSelect, 0);
sqlite3_free(zSql);
if( rc!=SQLITE_OK || !pSelect ){
output_formatted(p, "/**** ERROR: (%d) %s *****/\n", rc,
sqlite3_errmsg(p->db));
p->nErr++;
return;
}
rc = sqlite3_step(pSelect);
nResult = sqlite3_column_count(pSelect);
while( rc==SQLITE_ROW ){
z = (const char*)sqlite3_column_text(pSelect, 0);
p->xCallback(z, p->pArg);
for(i=1; i<nResult; i++){
p->xCallback(",", p->pArg);
p->xCallback((const char*)sqlite3_column_text(pSelect,i), p->pArg);
}
if( z==0 ) z = "";
while( z[0] && (z[0]!='-' || z[1]!='-') ) z++;
if( z[0] ){
p->xCallback("\n;\n", p->pArg);
}else{
p->xCallback(";\n", p->pArg);
}
rc = sqlite3_step(pSelect);
}
rc = sqlite3_finalize(pSelect);
if( rc!=SQLITE_OK ){
output_formatted(p, "/**** ERROR: (%d) %s *****/\n", rc,
sqlite3_errmsg(p->db));
if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++;
}
}
/*
** Run zQuery. Use dump_callback() as the callback routine so that
** the contents of the query are output as SQL statements.
**
** If we get a SQLITE_CORRUPT error, rerun the query after appending
** "ORDER BY rowid DESC" to the end.
*/
static void run_schema_dump_query(
DState *p,
const char *zQuery,
...
){
char *zErr = 0;
char *z;
va_list ap;
va_start(ap, zQuery);
z = sqlite3_vmprintf(zQuery, ap);
va_end(ap);
sqlite3_exec(p->db, z, dump_callback, p, &zErr);
sqlite3_free(z);
if( zErr ){
output_formatted(p, "/****** %s ******/\n", zErr);
sqlite3_free(zErr);
p->nErr++;
zErr = 0;
}
}
/*
** Convert an SQLite database into SQL statements that will recreate that
** database.
*/
int sqlite3_db_dump(
sqlite3 *db, /* The database connection */
const char *zSchema, /* Which schema to dump. Usually "main". */
const char *zTable, /* Which table to dump. NULL means everything. */
int (*xCallback)(const char*,void*), /* Output sent to this callback */
void *pArg /* Second argument of the callback */
){
DState x;
memset(&x, 0, sizeof(x));
x.rc = sqlite3_exec(db, "BEGIN", 0, 0, 0);
if( x.rc ) return x.rc;
x.db = db;
x.xCallback = xCallback;
x.pArg = pArg;
xCallback("PRAGMA foreign_keys=OFF;\nBEGIN TRANSACTION;\n", pArg);
if( zTable==0 ){
run_schema_dump_query(&x,
"SELECT name, type, sql FROM \"%w\".sqlite_master "
"WHERE sql NOT NULL AND type=='table' AND name!='sqlite_sequence'",
zSchema
);
run_schema_dump_query(&x,
"SELECT name, type, sql FROM \"%w\".sqlite_master "
"WHERE name=='sqlite_sequence'", zSchema
);
output_sql_from_query(&x,
"SELECT sql FROM sqlite_master "
"WHERE sql NOT NULL AND type IN ('index','trigger','view')", 0
);
}else{
run_schema_dump_query(&x,
"SELECT name, type, sql FROM \"%w\".sqlite_master "
"WHERE tbl_name=%Q COLLATE nocase AND type=='table'"
" AND sql NOT NULL",
zSchema, zTable
);
output_sql_from_query(&x,
"SELECT sql FROM \"%w\".sqlite_master "
"WHERE sql NOT NULL"
" AND type IN ('index','trigger','view')"
" AND tbl_name=%Q COLLATE nocase",
zSchema, zTable
);
}
if( x.writableSchema ){
xCallback("PRAGMA writable_schema=OFF;\n", pArg);
}
xCallback(x.nErr ? "ROLLBACK; -- due to errors\n" : "COMMIT;\n", pArg);
sqlite3_exec(db, "COMMIT", 0, 0, 0);
return x.rc;
}
/* The generic subroutine is above. The code the follows implements
** the command-line interface.
*/
#ifdef DBDUMP_STANDALONE
#include <stdio.h>
/*
** Command-line interface
*/
int main(int argc, char **argv){
sqlite3 *db;
const char *zDb;
const char *zSchema;
const char *zTable = 0;
int rc;
if( argc<2 || argc>4 ){
fprintf(stderr, "Usage: %s DATABASE ?SCHEMA? ?TABLE?\n", argv[0]);
return 1;
}
zDb = argv[1];
zSchema = argc>=3 ? argv[2] : "main";
zTable = argc==4 ? argv[3] : 0;
rc = sqlite3_open(zDb, &db);
if( rc ){
fprintf(stderr, "Cannot open \"%s\": %s\n", zDb, sqlite3_errmsg(db));
sqlite3_close(db);
return 1;
}
rc = sqlite3_db_dump(db, zSchema, zTable,
(int(*)(const char*,void*))fputs, (void*)stdout);
if( rc ){
fprintf(stderr, "Error: sqlite3_db_dump() returns %d\n", rc);
}
sqlite3_close(db);
return rc!=SQLITE_OK;
}
#endif /* DBDUMP_STANDALONE */
+138 -20
View File
@@ -138,9 +138,10 @@ static const char * const jsonType[] = {
#define JNODE_RAW 0x01 /* Content is raw, not JSON encoded */
#define JNODE_ESCAPE 0x02 /* Content is text with \ escapes */
#define JNODE_REMOVE 0x04 /* Do not output */
#define JNODE_REPLACE 0x08 /* Replace with JsonNode.iVal */
#define JNODE_APPEND 0x10 /* More ARRAY/OBJECT entries at u.iAppend */
#define JNODE_LABEL 0x20 /* Is a label of an object */
#define JNODE_REPLACE 0x08 /* Replace with JsonNode.u.iReplace */
#define JNODE_PATCH 0x10 /* Patch with JsonNode.u.pPatch */
#define JNODE_APPEND 0x20 /* More ARRAY/OBJECT entries at u.iAppend */
#define JNODE_LABEL 0x40 /* Is a label of an object */
/* A single node of parsed JSON
@@ -148,12 +149,13 @@ static const char * const jsonType[] = {
struct JsonNode {
u8 eType; /* One of the JSON_ type values */
u8 jnFlags; /* JNODE flags */
u8 iVal; /* Replacement value when JNODE_REPLACE */
u32 n; /* Bytes of content, or number of sub-nodes */
union {
const char *zJContent; /* Content for INT, REAL, and STRING */
u32 iAppend; /* More terms for ARRAY and OBJECT */
u32 iKey; /* Key for ARRAY objects in json_tree() */
u32 iReplace; /* Replacement content for JNODE_REPLACE */
JsonNode *pPatch; /* Node chain of patch for JNODE_PATCH */
} u;
};
@@ -410,6 +412,13 @@ static void jsonRenderNode(
JsonString *pOut, /* Write JSON here */
sqlite3_value **aReplace /* Replacement values */
){
if( pNode->jnFlags & (JNODE_REPLACE|JNODE_PATCH) ){
if( pNode->jnFlags & JNODE_REPLACE ){
jsonAppendValue(pOut, aReplace[pNode->u.iReplace]);
return;
}
pNode = pNode->u.pPatch;
}
switch( pNode->eType ){
default: {
assert( pNode->eType==JSON_NULL );
@@ -441,12 +450,7 @@ static void jsonRenderNode(
jsonAppendChar(pOut, '[');
for(;;){
while( j<=pNode->n ){
if( pNode[j].jnFlags & (JNODE_REMOVE|JNODE_REPLACE) ){
if( pNode[j].jnFlags & JNODE_REPLACE ){
jsonAppendSeparator(pOut);
jsonAppendValue(pOut, aReplace[pNode[j].iVal]);
}
}else{
if( (pNode[j].jnFlags & JNODE_REMOVE)==0 ){
jsonAppendSeparator(pOut);
jsonRenderNode(&pNode[j], pOut, aReplace);
}
@@ -468,11 +472,7 @@ static void jsonRenderNode(
jsonAppendSeparator(pOut);
jsonRenderNode(&pNode[j], pOut, aReplace);
jsonAppendChar(pOut, ':');
if( pNode[j+1].jnFlags & JNODE_REPLACE ){
jsonAppendValue(pOut, aReplace[pNode[j+1].iVal]);
}else{
jsonRenderNode(&pNode[j+1], pOut, aReplace);
}
jsonRenderNode(&pNode[j+1], pOut, aReplace);
}
j += 1 + jsonNodeSize(&pNode[j+1]);
}
@@ -699,7 +699,6 @@ static int jsonParseAddNode(
p = &pParse->aNode[pParse->nNode];
p->eType = (u8)eType;
p->jnFlags = 0;
p->iVal = 0;
p->n = n;
p->u.zJContent = zContent;
return pParse->nNode++;
@@ -1165,6 +1164,25 @@ static void jsonWrongNumArgs(
sqlite3_free(zMsg);
}
/*
** Mark all NULL entries in the Object passed in as JNODE_REMOVE.
*/
static void jsonRemoveAllNulls(JsonNode *pNode){
int i, n;
assert( pNode->eType==JSON_OBJECT );
n = pNode->n;
for(i=2; i<=n; i += jsonNodeSize(&pNode[i])+1){
switch( pNode[i].eType ){
case JSON_NULL:
pNode[i].jnFlags |= JNODE_REMOVE;
break;
case JSON_OBJECT:
jsonRemoveAllNulls(&pNode[i]);
break;
}
}
}
/****************************************************************************
** SQL functions used for testing and debugging
@@ -1357,6 +1375,105 @@ static void jsonExtractFunc(
jsonParseReset(&x);
}
/* This is the RFC 7396 MergePatch algorithm.
*/
static JsonNode *jsonMergePatch(
JsonParse *pParse, /* The JSON parser that contains the TARGET */
int iTarget, /* Node of the TARGET in pParse */
JsonNode *pPatch /* The PATCH */
){
u32 i, j;
u32 iRoot;
JsonNode *pTarget;
if( pPatch->eType!=JSON_OBJECT ){
return pPatch;
}
assert( iTarget>=0 && iTarget<pParse->nNode );
pTarget = &pParse->aNode[iTarget];
assert( (pPatch->jnFlags & JNODE_APPEND)==0 );
if( pTarget->eType!=JSON_OBJECT ){
jsonRemoveAllNulls(pPatch);
return pPatch;
}
iRoot = iTarget;
for(i=1; i<pPatch->n; i += jsonNodeSize(&pPatch[i+1])+1){
u32 nKey;
const char *zKey;
assert( pPatch[i].eType==JSON_STRING );
assert( pPatch[i].jnFlags & JNODE_LABEL );
nKey = pPatch[i].n;
zKey = pPatch[i].u.zJContent;
assert( (pPatch[i].jnFlags & JNODE_RAW)==0 );
for(j=1; j<pTarget->n; j += jsonNodeSize(&pTarget[j+1])+1 ){
assert( pTarget[j].eType==JSON_STRING );
assert( pTarget[j].jnFlags & JNODE_LABEL );
assert( (pPatch[i].jnFlags & JNODE_RAW)==0 );
if( pTarget[j].n==nKey && strncmp(pTarget[j].u.zJContent,zKey,nKey)==0 ){
if( pTarget[j+1].jnFlags & (JNODE_REMOVE|JNODE_PATCH) ) break;
if( pPatch[i+1].eType==JSON_NULL ){
pTarget[j+1].jnFlags |= JNODE_REMOVE;
}else{
JsonNode *pNew = jsonMergePatch(pParse, iTarget+j+1, &pPatch[i+1]);
if( pNew==0 ) return 0;
pTarget = &pParse->aNode[iTarget];
if( pNew!=&pTarget[j+1] ){
pTarget[j+1].u.pPatch = pNew;
pTarget[j+1].jnFlags |= JNODE_PATCH;
}
}
break;
}
}
if( j>=pTarget->n && pPatch[i+1].eType!=JSON_NULL ){
int iStart, iPatch;
iStart = jsonParseAddNode(pParse, JSON_OBJECT, 2, 0);
jsonParseAddNode(pParse, JSON_STRING, nKey, zKey);
iPatch = jsonParseAddNode(pParse, JSON_TRUE, 0, 0);
if( pParse->oom ) return 0;
jsonRemoveAllNulls(pPatch);
pTarget = &pParse->aNode[iTarget];
pParse->aNode[iRoot].jnFlags |= JNODE_APPEND;
pParse->aNode[iRoot].u.iAppend = iStart - iRoot;
iRoot = iStart;
pParse->aNode[iPatch].jnFlags |= JNODE_PATCH;
pParse->aNode[iPatch].u.pPatch = &pPatch[i+1];
}
}
return pTarget;
}
/*
** Implementation of the json_mergepatch(JSON1,JSON2) function. Return a JSON
** object that is the result of running the RFC 7396 MergePatch() algorithm
** on the two arguments.
*/
static void jsonPatchFunc(
sqlite3_context *ctx,
int argc,
sqlite3_value **argv
){
JsonParse x; /* The JSON that is being patched */
JsonParse y; /* The patch */
JsonNode *pResult; /* The result of the merge */
UNUSED_PARAM(argc);
if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return;
if( jsonParse(&y, ctx, (const char*)sqlite3_value_text(argv[1])) ){
jsonParseReset(&x);
return;
}
pResult = jsonMergePatch(&x, 0, y.aNode);
assert( pResult!=0 || x.oom );
if( pResult ){
jsonReturnJson(pResult, ctx, 0);
}else{
sqlite3_result_error_nomem(ctx);
}
jsonParseReset(&x);
jsonParseReset(&y);
}
/*
** Implementation of the json_object(NAME,VALUE,...) function. Return a JSON
** object that contains all name/value given in arguments. Or if any name
@@ -1460,11 +1577,11 @@ static void jsonReplaceFunc(
if( x.nErr ) goto replace_err;
if( pNode ){
pNode->jnFlags |= (u8)JNODE_REPLACE;
pNode->iVal = (u8)(i+1);
pNode->u.iReplace = i + 1;
}
}
if( x.aNode[0].jnFlags & JNODE_REPLACE ){
sqlite3_result_value(ctx, argv[x.aNode[0].iVal]);
sqlite3_result_value(ctx, argv[x.aNode[0].u.iReplace]);
}else{
jsonReturnJson(x.aNode, ctx, argv);
}
@@ -1514,11 +1631,11 @@ static void jsonSetFunc(
goto jsonSetDone;
}else if( pNode && (bApnd || bIsSet) ){
pNode->jnFlags |= (u8)JNODE_REPLACE;
pNode->iVal = (u8)(i+1);
pNode->u.iReplace = i + 1;
}
}
if( x.aNode[0].jnFlags & JNODE_REPLACE ){
sqlite3_result_value(ctx, argv[x.aNode[0].iVal]);
sqlite3_result_value(ctx, argv[x.aNode[0].u.iReplace]);
}else{
jsonReturnJson(x.aNode, ctx, argv);
}
@@ -2161,6 +2278,7 @@ int sqlite3Json1Init(sqlite3 *db){
{ "json_extract", -1, 0, jsonExtractFunc },
{ "json_insert", -1, 0, jsonSetFunc },
{ "json_object", -1, 0, jsonObjectFunc },
{ "json_patch", 2, 0, jsonPatchFunc },
{ "json_quote", 1, 0, jsonQuoteFunc },
{ "json_remove", -1, 0, jsonRemoveFunc },
{ "json_replace", -1, 0, jsonReplaceFunc },
+714
View File
@@ -0,0 +1,714 @@
/*
** 2017-03-08
**
** 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 SQLite extension implements a functions that compute SHA1 hashes.
** Two SQL functions are implemented:
**
** sha3(X,SIZE)
** sha3_query(Y,SIZE)
**
** The sha3(X) function computes the SHA3 hash of the input X, or NULL if
** X is NULL.
**
** The sha3_query(Y) function evalutes all queries in the SQL statements of Y
** and returns a hash of their results.
**
** The SIZE argument is optional. If omitted, the SHA3-256 hash algorithm
** is used. If SIZE is included it must be one of the integers 224, 256,
** 384, or 512, to determine SHA3 hash variant that is computed.
*/
#include "sqlite3ext.h"
SQLITE_EXTENSION_INIT1
#include <assert.h>
#include <string.h>
#include <stdarg.h>
typedef sqlite3_uint64 u64;
/******************************************************************************
** The Hash Engine
*/
/*
** Macros to determine whether the machine is big or little endian,
** and whether or not that determination is run-time or compile-time.
**
** For best performance, an attempt is made to guess at the byte-order
** using C-preprocessor macros. If that is unsuccessful, or if
** -DSHA3_BYTEORDER=0 is set, then byte-order is determined
** at run-time.
*/
#ifndef SHA3_BYTEORDER
# if defined(i386) || defined(__i386__) || defined(_M_IX86) || \
defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || \
defined(_M_AMD64) || defined(_M_ARM) || defined(__x86) || \
defined(__arm__)
# define SHA3_BYTEORDER 1234
# elif defined(sparc) || defined(__ppc__)
# define SHA3_BYTEORDER 4321
# else
# define SHA3_BYTEORDER 0
# endif
#endif
/*
** State structure for a SHA3 hash in progress
*/
typedef struct SHA3Context SHA3Context;
struct SHA3Context {
union {
u64 s[25]; /* Keccak state. 5x5 lines of 64 bits each */
unsigned char x[1600]; /* ... or 1600 bytes */
} u;
unsigned nRate; /* Bytes of input accepted per Keccak iteration */
unsigned nLoaded; /* Input bytes loaded into u.x[] so far this cycle */
unsigned ixMask; /* Insert next input into u.x[nLoaded^ixMask]. */
};
/*
** A single step of the Keccak mixing function for a 1600-bit state
*/
static void KeccakF1600Step(SHA3Context *p){
int i;
u64 B0, B1, B2, B3, B4;
u64 C0, C1, C2, C3, C4;
u64 D0, D1, D2, D3, D4;
static const u64 RC[] = {
0x0000000000000001ULL, 0x0000000000008082ULL,
0x800000000000808aULL, 0x8000000080008000ULL,
0x000000000000808bULL, 0x0000000080000001ULL,
0x8000000080008081ULL, 0x8000000000008009ULL,
0x000000000000008aULL, 0x0000000000000088ULL,
0x0000000080008009ULL, 0x000000008000000aULL,
0x000000008000808bULL, 0x800000000000008bULL,
0x8000000000008089ULL, 0x8000000000008003ULL,
0x8000000000008002ULL, 0x8000000000000080ULL,
0x000000000000800aULL, 0x800000008000000aULL,
0x8000000080008081ULL, 0x8000000000008080ULL,
0x0000000080000001ULL, 0x8000000080008008ULL
};
# define A00 (p->u.s[0])
# define A01 (p->u.s[1])
# define A02 (p->u.s[2])
# define A03 (p->u.s[3])
# define A04 (p->u.s[4])
# define A10 (p->u.s[5])
# define A11 (p->u.s[6])
# define A12 (p->u.s[7])
# define A13 (p->u.s[8])
# define A14 (p->u.s[9])
# define A20 (p->u.s[10])
# define A21 (p->u.s[11])
# define A22 (p->u.s[12])
# define A23 (p->u.s[13])
# define A24 (p->u.s[14])
# define A30 (p->u.s[15])
# define A31 (p->u.s[16])
# define A32 (p->u.s[17])
# define A33 (p->u.s[18])
# define A34 (p->u.s[19])
# define A40 (p->u.s[20])
# define A41 (p->u.s[21])
# define A42 (p->u.s[22])
# define A43 (p->u.s[23])
# define A44 (p->u.s[24])
# define ROL64(a,x) ((a<<x)|(a>>(64-x)))
for(i=0; i<24; i+=4){
C0 = A00^A10^A20^A30^A40;
C1 = A01^A11^A21^A31^A41;
C2 = A02^A12^A22^A32^A42;
C3 = A03^A13^A23^A33^A43;
C4 = A04^A14^A24^A34^A44;
D0 = C4^ROL64(C1, 1);
D1 = C0^ROL64(C2, 1);
D2 = C1^ROL64(C3, 1);
D3 = C2^ROL64(C4, 1);
D4 = C3^ROL64(C0, 1);
B0 = (A00^D0);
B1 = ROL64((A11^D1), 44);
B2 = ROL64((A22^D2), 43);
B3 = ROL64((A33^D3), 21);
B4 = ROL64((A44^D4), 14);
A00 = B0 ^((~B1)& B2 );
A00 ^= RC[i];
A11 = B1 ^((~B2)& B3 );
A22 = B2 ^((~B3)& B4 );
A33 = B3 ^((~B4)& B0 );
A44 = B4 ^((~B0)& B1 );
B2 = ROL64((A20^D0), 3);
B3 = ROL64((A31^D1), 45);
B4 = ROL64((A42^D2), 61);
B0 = ROL64((A03^D3), 28);
B1 = ROL64((A14^D4), 20);
A20 = B0 ^((~B1)& B2 );
A31 = B1 ^((~B2)& B3 );
A42 = B2 ^((~B3)& B4 );
A03 = B3 ^((~B4)& B0 );
A14 = B4 ^((~B0)& B1 );
B4 = ROL64((A40^D0), 18);
B0 = ROL64((A01^D1), 1);
B1 = ROL64((A12^D2), 6);
B2 = ROL64((A23^D3), 25);
B3 = ROL64((A34^D4), 8);
A40 = B0 ^((~B1)& B2 );
A01 = B1 ^((~B2)& B3 );
A12 = B2 ^((~B3)& B4 );
A23 = B3 ^((~B4)& B0 );
A34 = B4 ^((~B0)& B1 );
B1 = ROL64((A10^D0), 36);
B2 = ROL64((A21^D1), 10);
B3 = ROL64((A32^D2), 15);
B4 = ROL64((A43^D3), 56);
B0 = ROL64((A04^D4), 27);
A10 = B0 ^((~B1)& B2 );
A21 = B1 ^((~B2)& B3 );
A32 = B2 ^((~B3)& B4 );
A43 = B3 ^((~B4)& B0 );
A04 = B4 ^((~B0)& B1 );
B3 = ROL64((A30^D0), 41);
B4 = ROL64((A41^D1), 2);
B0 = ROL64((A02^D2), 62);
B1 = ROL64((A13^D3), 55);
B2 = ROL64((A24^D4), 39);
A30 = B0 ^((~B1)& B2 );
A41 = B1 ^((~B2)& B3 );
A02 = B2 ^((~B3)& B4 );
A13 = B3 ^((~B4)& B0 );
A24 = B4 ^((~B0)& B1 );
C0 = A00^A20^A40^A10^A30;
C1 = A11^A31^A01^A21^A41;
C2 = A22^A42^A12^A32^A02;
C3 = A33^A03^A23^A43^A13;
C4 = A44^A14^A34^A04^A24;
D0 = C4^ROL64(C1, 1);
D1 = C0^ROL64(C2, 1);
D2 = C1^ROL64(C3, 1);
D3 = C2^ROL64(C4, 1);
D4 = C3^ROL64(C0, 1);
B0 = (A00^D0);
B1 = ROL64((A31^D1), 44);
B2 = ROL64((A12^D2), 43);
B3 = ROL64((A43^D3), 21);
B4 = ROL64((A24^D4), 14);
A00 = B0 ^((~B1)& B2 );
A00 ^= RC[i+1];
A31 = B1 ^((~B2)& B3 );
A12 = B2 ^((~B3)& B4 );
A43 = B3 ^((~B4)& B0 );
A24 = B4 ^((~B0)& B1 );
B2 = ROL64((A40^D0), 3);
B3 = ROL64((A21^D1), 45);
B4 = ROL64((A02^D2), 61);
B0 = ROL64((A33^D3), 28);
B1 = ROL64((A14^D4), 20);
A40 = B0 ^((~B1)& B2 );
A21 = B1 ^((~B2)& B3 );
A02 = B2 ^((~B3)& B4 );
A33 = B3 ^((~B4)& B0 );
A14 = B4 ^((~B0)& B1 );
B4 = ROL64((A30^D0), 18);
B0 = ROL64((A11^D1), 1);
B1 = ROL64((A42^D2), 6);
B2 = ROL64((A23^D3), 25);
B3 = ROL64((A04^D4), 8);
A30 = B0 ^((~B1)& B2 );
A11 = B1 ^((~B2)& B3 );
A42 = B2 ^((~B3)& B4 );
A23 = B3 ^((~B4)& B0 );
A04 = B4 ^((~B0)& B1 );
B1 = ROL64((A20^D0), 36);
B2 = ROL64((A01^D1), 10);
B3 = ROL64((A32^D2), 15);
B4 = ROL64((A13^D3), 56);
B0 = ROL64((A44^D4), 27);
A20 = B0 ^((~B1)& B2 );
A01 = B1 ^((~B2)& B3 );
A32 = B2 ^((~B3)& B4 );
A13 = B3 ^((~B4)& B0 );
A44 = B4 ^((~B0)& B1 );
B3 = ROL64((A10^D0), 41);
B4 = ROL64((A41^D1), 2);
B0 = ROL64((A22^D2), 62);
B1 = ROL64((A03^D3), 55);
B2 = ROL64((A34^D4), 39);
A10 = B0 ^((~B1)& B2 );
A41 = B1 ^((~B2)& B3 );
A22 = B2 ^((~B3)& B4 );
A03 = B3 ^((~B4)& B0 );
A34 = B4 ^((~B0)& B1 );
C0 = A00^A40^A30^A20^A10;
C1 = A31^A21^A11^A01^A41;
C2 = A12^A02^A42^A32^A22;
C3 = A43^A33^A23^A13^A03;
C4 = A24^A14^A04^A44^A34;
D0 = C4^ROL64(C1, 1);
D1 = C0^ROL64(C2, 1);
D2 = C1^ROL64(C3, 1);
D3 = C2^ROL64(C4, 1);
D4 = C3^ROL64(C0, 1);
B0 = (A00^D0);
B1 = ROL64((A21^D1), 44);
B2 = ROL64((A42^D2), 43);
B3 = ROL64((A13^D3), 21);
B4 = ROL64((A34^D4), 14);
A00 = B0 ^((~B1)& B2 );
A00 ^= RC[i+2];
A21 = B1 ^((~B2)& B3 );
A42 = B2 ^((~B3)& B4 );
A13 = B3 ^((~B4)& B0 );
A34 = B4 ^((~B0)& B1 );
B2 = ROL64((A30^D0), 3);
B3 = ROL64((A01^D1), 45);
B4 = ROL64((A22^D2), 61);
B0 = ROL64((A43^D3), 28);
B1 = ROL64((A14^D4), 20);
A30 = B0 ^((~B1)& B2 );
A01 = B1 ^((~B2)& B3 );
A22 = B2 ^((~B3)& B4 );
A43 = B3 ^((~B4)& B0 );
A14 = B4 ^((~B0)& B1 );
B4 = ROL64((A10^D0), 18);
B0 = ROL64((A31^D1), 1);
B1 = ROL64((A02^D2), 6);
B2 = ROL64((A23^D3), 25);
B3 = ROL64((A44^D4), 8);
A10 = B0 ^((~B1)& B2 );
A31 = B1 ^((~B2)& B3 );
A02 = B2 ^((~B3)& B4 );
A23 = B3 ^((~B4)& B0 );
A44 = B4 ^((~B0)& B1 );
B1 = ROL64((A40^D0), 36);
B2 = ROL64((A11^D1), 10);
B3 = ROL64((A32^D2), 15);
B4 = ROL64((A03^D3), 56);
B0 = ROL64((A24^D4), 27);
A40 = B0 ^((~B1)& B2 );
A11 = B1 ^((~B2)& B3 );
A32 = B2 ^((~B3)& B4 );
A03 = B3 ^((~B4)& B0 );
A24 = B4 ^((~B0)& B1 );
B3 = ROL64((A20^D0), 41);
B4 = ROL64((A41^D1), 2);
B0 = ROL64((A12^D2), 62);
B1 = ROL64((A33^D3), 55);
B2 = ROL64((A04^D4), 39);
A20 = B0 ^((~B1)& B2 );
A41 = B1 ^((~B2)& B3 );
A12 = B2 ^((~B3)& B4 );
A33 = B3 ^((~B4)& B0 );
A04 = B4 ^((~B0)& B1 );
C0 = A00^A30^A10^A40^A20;
C1 = A21^A01^A31^A11^A41;
C2 = A42^A22^A02^A32^A12;
C3 = A13^A43^A23^A03^A33;
C4 = A34^A14^A44^A24^A04;
D0 = C4^ROL64(C1, 1);
D1 = C0^ROL64(C2, 1);
D2 = C1^ROL64(C3, 1);
D3 = C2^ROL64(C4, 1);
D4 = C3^ROL64(C0, 1);
B0 = (A00^D0);
B1 = ROL64((A01^D1), 44);
B2 = ROL64((A02^D2), 43);
B3 = ROL64((A03^D3), 21);
B4 = ROL64((A04^D4), 14);
A00 = B0 ^((~B1)& B2 );
A00 ^= RC[i+3];
A01 = B1 ^((~B2)& B3 );
A02 = B2 ^((~B3)& B4 );
A03 = B3 ^((~B4)& B0 );
A04 = B4 ^((~B0)& B1 );
B2 = ROL64((A10^D0), 3);
B3 = ROL64((A11^D1), 45);
B4 = ROL64((A12^D2), 61);
B0 = ROL64((A13^D3), 28);
B1 = ROL64((A14^D4), 20);
A10 = B0 ^((~B1)& B2 );
A11 = B1 ^((~B2)& B3 );
A12 = B2 ^((~B3)& B4 );
A13 = B3 ^((~B4)& B0 );
A14 = B4 ^((~B0)& B1 );
B4 = ROL64((A20^D0), 18);
B0 = ROL64((A21^D1), 1);
B1 = ROL64((A22^D2), 6);
B2 = ROL64((A23^D3), 25);
B3 = ROL64((A24^D4), 8);
A20 = B0 ^((~B1)& B2 );
A21 = B1 ^((~B2)& B3 );
A22 = B2 ^((~B3)& B4 );
A23 = B3 ^((~B4)& B0 );
A24 = B4 ^((~B0)& B1 );
B1 = ROL64((A30^D0), 36);
B2 = ROL64((A31^D1), 10);
B3 = ROL64((A32^D2), 15);
B4 = ROL64((A33^D3), 56);
B0 = ROL64((A34^D4), 27);
A30 = B0 ^((~B1)& B2 );
A31 = B1 ^((~B2)& B3 );
A32 = B2 ^((~B3)& B4 );
A33 = B3 ^((~B4)& B0 );
A34 = B4 ^((~B0)& B1 );
B3 = ROL64((A40^D0), 41);
B4 = ROL64((A41^D1), 2);
B0 = ROL64((A42^D2), 62);
B1 = ROL64((A43^D3), 55);
B2 = ROL64((A44^D4), 39);
A40 = B0 ^((~B1)& B2 );
A41 = B1 ^((~B2)& B3 );
A42 = B2 ^((~B3)& B4 );
A43 = B3 ^((~B4)& B0 );
A44 = B4 ^((~B0)& B1 );
}
}
/*
** Initialize a new hash. iSize determines the size of the hash
** in bits and should be one of 224, 256, 384, or 512. Or iSize
** can be zero to use the default hash size of 256 bits.
*/
static void SHA3Init(SHA3Context *p, int iSize){
memset(p, 0, sizeof(*p));
if( iSize>=128 && iSize<=512 ){
p->nRate = (1600 - ((iSize + 31)&~31)*2)/8;
}else{
p->nRate = (1600 - 2*256)/8;
}
#if SHA3_BYTEORDER==1234
/* Known to be little-endian at compile-time. No-op */
#elif SHA3_BYTEORDER==4321
p->ixMask = 7; /* Big-endian */
#else
{
static unsigned int one = 1;
if( 1==*(unsigned char*)&one ){
/* Little endian. No byte swapping. */
p->ixMask = 0;
}else{
/* Big endian. Byte swap. */
p->ixMask = 7;
}
}
#endif
}
/*
** Make consecutive calls to the SHA3Update function to add new content
** to the hash
*/
static void SHA3Update(
SHA3Context *p,
const unsigned char *aData,
unsigned int nData
){
unsigned int i = 0;
#if SHA3_BYTEORDER==1234
if( (p->nLoaded % 8)==0 && ((aData - (const unsigned char*)0)&7)==0 ){
for(; i+7<nData; i+=8){
p->u.s[p->nLoaded/8] ^= *(u64*)&aData[i];
p->nLoaded += 8;
if( p->nLoaded>=p->nRate ){
KeccakF1600Step(p);
p->nLoaded = 0;
}
}
}
#endif
for(; i<nData; i++){
#if SHA3_BYTEORDER==1234
p->u.x[p->nLoaded] ^= aData[i];
#elif SHA3_BYTEORDER==4321
p->u.x[p->nLoaded^0x07] ^= aData[i];
#else
p->u.x[p->nLoaded^p->ixMask] ^= aData[i];
#endif
p->nLoaded++;
if( p->nLoaded==p->nRate ){
KeccakF1600Step(p);
p->nLoaded = 0;
}
}
}
/*
** After all content has been added, invoke SHA3Final() to compute
** the final hash. The function returns a pointer to the binary
** hash value.
*/
static unsigned char *SHA3Final(SHA3Context *p){
unsigned int i;
if( p->nLoaded==p->nRate-1 ){
const unsigned char c1 = 0x86;
SHA3Update(p, &c1, 1);
}else{
const unsigned char c2 = 0x06;
const unsigned char c3 = 0x80;
SHA3Update(p, &c2, 1);
p->nLoaded = p->nRate - 1;
SHA3Update(p, &c3, 1);
}
for(i=0; i<p->nRate; i++){
p->u.x[i+p->nRate] = p->u.x[i^p->ixMask];
}
return &p->u.x[p->nRate];
}
/* End of the hashing logic
*****************************************************************************/
/*
** Implementation of the sha3(X,SIZE) function.
**
** Return a BLOB which is the SIZE-bit SHA3 hash of X. The default
** size is 256. If X is a BLOB, it is hashed as is.
** For all other non-NULL types of input, X is converted into a UTF-8 string
** and the string is hashed without the trailing 0x00 terminator. The hash
** of a NULL value is NULL.
*/
static void sha3Func(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
SHA3Context cx;
int eType = sqlite3_value_type(argv[0]);
int nByte = sqlite3_value_bytes(argv[0]);
int iSize;
if( argc==1 ){
iSize = 256;
}else{
iSize = sqlite3_value_int(argv[1]);
if( iSize!=224 && iSize!=256 && iSize!=384 && iSize!=512 ){
sqlite3_result_error(context, "SHA3 size should be one of: 224 256 "
"384 512", -1);
return;
}
}
if( eType==SQLITE_NULL ) return;
SHA3Init(&cx, iSize);
if( eType==SQLITE_BLOB ){
SHA3Update(&cx, sqlite3_value_blob(argv[0]), nByte);
}else{
SHA3Update(&cx, sqlite3_value_text(argv[0]), nByte);
}
sqlite3_result_blob(context, SHA3Final(&cx), iSize/8, SQLITE_TRANSIENT);
}
/* Compute a string using sqlite3_vsnprintf() with a maximum length
** of 50 bytes and add it to the hash.
*/
static void hash_step_vformat(
SHA3Context *p, /* Add content to this context */
const char *zFormat,
...
){
va_list ap;
int n;
char zBuf[50];
va_start(ap, zFormat);
sqlite3_vsnprintf(sizeof(zBuf),zBuf,zFormat,ap);
va_end(ap);
n = (int)strlen(zBuf);
SHA3Update(p, (unsigned char*)zBuf, n);
}
/*
** Implementation of the sha3_query(SQL,SIZE) function.
**
** This function compiles and runs the SQL statement(s) given in the
** argument. The results are hashed using a SIZE-bit SHA3. The default
** size is 256.
**
** The format of the byte stream that is hashed is summarized as follows:
**
** S<n>:<sql>
** R
** N
** I<int>
** F<ieee-float>
** B<size>:<bytes>
** T<size>:<text>
**
** <sql> is the original SQL text for each statement run and <n> is
** the size of that text. The SQL text is UTF-8. A single R character
** occurs before the start of each row. N means a NULL value.
** I mean an 8-byte little-endian integer <int>. F is a floating point
** number with an 8-byte little-endian IEEE floating point value <ieee-float>.
** B means blobs of <size> bytes. T means text rendered as <size>
** bytes of UTF-8. The <n> and <size> values are expressed as an ASCII
** text integers.
**
** For each SQL statement in the X input, there is one S segment. Each
** S segment is followed by zero or more R segments, one for each row in the
** result set. After each R, there are one or more N, I, F, B, or T segments,
** one for each column in the result set. Segments are concatentated directly
** with no delimiters of any kind.
*/
static void sha3QueryFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
sqlite3 *db = sqlite3_context_db_handle(context);
const char *zSql = (const char*)sqlite3_value_text(argv[0]);
sqlite3_stmt *pStmt = 0;
int nCol; /* Number of columns in the result set */
int i; /* Loop counter */
int rc;
int n;
const char *z;
SHA3Context cx;
int iSize;
if( argc==1 ){
iSize = 256;
}else{
iSize = sqlite3_value_int(argv[1]);
if( iSize!=224 && iSize!=256 && iSize!=384 && iSize!=512 ){
sqlite3_result_error(context, "SHA3 size should be one of: 224 256 "
"384 512", -1);
return;
}
}
if( zSql==0 ) return;
SHA3Init(&cx, iSize);
while( zSql[0] ){
rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zSql);
if( rc ){
char *zMsg = sqlite3_mprintf("error SQL statement [%s]: %s",
zSql, sqlite3_errmsg(db));
sqlite3_finalize(pStmt);
sqlite3_result_error(context, zMsg, -1);
sqlite3_free(zMsg);
return;
}
if( !sqlite3_stmt_readonly(pStmt) ){
char *zMsg = sqlite3_mprintf("non-query: [%s]", sqlite3_sql(pStmt));
sqlite3_finalize(pStmt);
sqlite3_result_error(context, zMsg, -1);
sqlite3_free(zMsg);
return;
}
nCol = sqlite3_column_count(pStmt);
z = sqlite3_sql(pStmt);
n = (int)strlen(z);
hash_step_vformat(&cx,"S%d:",n);
SHA3Update(&cx,(unsigned char*)z,n);
/* Compute a hash over the result of the query */
while( SQLITE_ROW==sqlite3_step(pStmt) ){
SHA3Update(&cx,(const unsigned char*)"R",1);
for(i=0; i<nCol; i++){
switch( sqlite3_column_type(pStmt,i) ){
case SQLITE_NULL: {
SHA3Update(&cx, (const unsigned char*)"N",1);
break;
}
case SQLITE_INTEGER: {
sqlite3_uint64 u;
int j;
unsigned char x[9];
sqlite3_int64 v = sqlite3_column_int64(pStmt,i);
memcpy(&u, &v, 8);
for(j=8; j>=1; j--){
x[j] = u & 0xff;
u >>= 8;
}
x[0] = 'I';
SHA3Update(&cx, x, 9);
break;
}
case SQLITE_FLOAT: {
sqlite3_uint64 u;
int j;
unsigned char x[9];
double r = sqlite3_column_double(pStmt,i);
memcpy(&u, &r, 8);
for(j=8; j>=1; j--){
x[j] = u & 0xff;
u >>= 8;
}
x[0] = 'F';
SHA3Update(&cx,x,9);
break;
}
case SQLITE_TEXT: {
int n2 = sqlite3_column_bytes(pStmt, i);
const unsigned char *z2 = sqlite3_column_text(pStmt, i);
hash_step_vformat(&cx,"T%d:",n2);
SHA3Update(&cx, z2, n2);
break;
}
case SQLITE_BLOB: {
int n2 = sqlite3_column_bytes(pStmt, i);
const unsigned char *z2 = sqlite3_column_blob(pStmt, i);
hash_step_vformat(&cx,"B%d:",n2);
SHA3Update(&cx, z2, n2);
break;
}
}
}
}
sqlite3_finalize(pStmt);
}
sqlite3_result_blob(context, SHA3Final(&cx), iSize/8, SQLITE_TRANSIENT);
}
#ifdef _WIN32
__declspec(dllexport)
#endif
int sqlite3_shathree_init(
sqlite3 *db,
char **pzErrMsg,
const sqlite3_api_routines *pApi
){
int rc = SQLITE_OK;
SQLITE_EXTENSION_INIT2(pApi);
(void)pzErrMsg; /* Unused parameter */
rc = sqlite3_create_function(db, "sha3", 1, SQLITE_UTF8, 0,
sha3Func, 0, 0);
if( rc==SQLITE_OK ){
rc = sqlite3_create_function(db, "sha3", 2, SQLITE_UTF8, 0,
sha3Func, 0, 0);
}
if( rc==SQLITE_OK ){
rc = sqlite3_create_function(db, "sha3_query", 1, SQLITE_UTF8, 0,
sha3QueryFunc, 0, 0);
}
if( rc==SQLITE_OK ){
rc = sqlite3_create_function(db, "sha3_query", 2, SQLITE_UTF8, 0,
sha3QueryFunc, 0, 0);
}
return rc;
}
+106
View File
@@ -0,0 +1,106 @@
# 2017 March 02
#
# 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.
#
#***********************************************************************
#
if {![info exists testdir]} {
set testdir [file join [file dirname [info script]] .. .. test]
}
source $testdir/tester.tcl
set ::testprefix rbucrash2
db close
forcedelete test.db-oal rbu.db
sqlite3_shutdown
sqlite3_config_uri 1
reset_db
# Set up a target database and an rbu update database. The target
# db is the usual "test.db", the rbu db is "test.db2".
#
forcedelete test.db2
do_execsql_test 1.0 {
CREATE TABLE t1(a, b, c, PRIMARY KEY(a), UNIQUE(b));
INSERT INTO t1 VALUES(1, 2, 3);
INSERT INTO t1 VALUES(4, 5, 6);
INSERT INTO t1 VALUES(7, 8, 9);
ATTACH 'test.db2' AS rbu;
CREATE TABLE rbu.data_t1(a, b, c, rbu_control);
INSERT INTO data_t1 VALUES('one', randomblob(3500), NULL, 0);
INSERT INTO data_t1 VALUES('two', randomblob(3500), NULL, 0);
INSERT INTO data_t1 VALUES('three', randomblob(3500), NULL, 0);
INSERT INTO data_t1 VALUES('four', randomblob(3500), NULL, 0);
INSERT INTO data_t1 VALUES('five', randomblob(3500), NULL, 0);
INSERT INTO data_t1 VALUES('six', randomblob(3500), NULL, 0);
}
db_save_and_close
proc do_rbu_crash_test2 {tn script} {
foreach {f blksz} {
test.db 512
test.db2 512
test.db 4096
test.db2 4096
} {
set bDone 0
for {set iDelay 1} {$bDone==0} {incr iDelay} {
forcedelete test.db2 test.db2-journal test.db test.db-oal test.db-wal
db_restore
set res [
crashsql -file $f -delay $iDelay -tclbody $script -dflt 1 -opendb {} \
-blocksize $blksz {}
]
set bDone 1
if {$res == "1 {child process exited abnormally}"} {
set bDone 0
} elseif {$res != "0 {}"} {
error "unexected catchsql result: $res"
}
sqlite3rbu rbu test.db test.db2
while {[rbu step]=="SQLITE_OK"} {}
rbu close
sqlite3 db test.db
do_execsql_test $tn.delay=$iDelay.f=$f.blksz=$blksz {
PRAGMA integrity_check;
} {ok}
db close
}
}
}
for {set x 1} {$x < 10} {incr x} {
do_rbu_crash_test2 1.$x {
sqlite3rbu rbu test.db test.db2
while {[rbu step]=="SQLITE_OK"} {
rbu savestate
}
rbu close
}
}
for {set x 1} {$x < 2} {incr x} {
do_rbu_crash_test2 2.$x {
sqlite3rbu rbu test.db test.db2
while {[rbu step]=="SQLITE_OK"} {
rbu close
sqlite3rbu rbu test.db test.db2
}
rbu close
}
}
finish_test
+2
View File
@@ -40,6 +40,7 @@ proc create_rbu1 {filename} {
do_execsql_test 1.0 {
PRAGMA page_size = 4096;
CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
}
@@ -266,6 +267,7 @@ foreach bReopen {0 1} {
do_test 3.$bReopen.1.0 {
reset_db
execsql {
PRAGMA page_size = 4096;
CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
CREATE TABLE t2(a INTEGER PRIMARY KEY, b);
CREATE TABLE t3(a INTEGER PRIMARY KEY, b);
+50 -3
View File
@@ -356,6 +356,7 @@ struct sqlite3rbu {
RbuObjIter objiter; /* Iterator for skipping through tbl/idx */
const char *zVfsName; /* Name of automatically created rbu vfs */
rbu_file *pTargetFd; /* File handle open on target db */
int nPagePerSector; /* Pages per sector for pTargetFd */
i64 iOalSz;
i64 nPhaseOneStep;
@@ -2620,6 +2621,23 @@ static void rbuSetupCheckpoint(sqlite3rbu *p, RbuState *pState){
if( p->nFrame==0 || (pState && pState->iWalCksum!=p->iWalCksum) ){
p->rc = SQLITE_DONE;
p->eStage = RBU_STAGE_DONE;
}else{
int nSectorSize;
sqlite3_file *pDb = p->pTargetFd->pReal;
sqlite3_file *pWal = p->pTargetFd->pWalFd->pReal;
assert( p->nPagePerSector==0 );
nSectorSize = pDb->pMethods->xSectorSize(pDb);
if( nSectorSize>p->pgsz ){
p->nPagePerSector = nSectorSize / p->pgsz;
}else{
p->nPagePerSector = 1;
}
/* Call xSync() on the wal file. This causes SQLite to sync the
** directory in which the target database and the wal file reside, in
** case it has not been synced since the rename() call in
** rbuMoveOalFile(). */
p->rc = pWal->pMethods->xSync(pWal, SQLITE_SYNC_NORMAL);
}
}
}
@@ -3275,9 +3293,26 @@ int sqlite3rbu_step(sqlite3rbu *p){
p->rc = SQLITE_DONE;
}
}else{
RbuFrame *pFrame = &p->aFrame[p->nStep];
rbuCheckpointFrame(p, pFrame);
p->nStep++;
/* At one point the following block copied a single frame from the
** wal file to the database file. So that one call to sqlite3rbu_step()
** checkpointed a single frame.
**
** However, if the sector-size is larger than the page-size, and the
** application calls sqlite3rbu_savestate() or close() immediately
** after this step, then rbu_step() again, then a power failure occurs,
** then the database page written here may be damaged. Work around
** this by checkpointing frames until the next page in the aFrame[]
** lies on a different disk sector to the current one. */
u32 iSector;
do{
RbuFrame *pFrame = &p->aFrame[p->nStep];
iSector = (pFrame->iDbPage-1) / p->nPagePerSector;
rbuCheckpointFrame(p, pFrame);
p->nStep++;
}while( p->nStep<p->nFrame
&& iSector==((p->aFrame[p->nStep].iDbPage-1) / p->nPagePerSector)
&& p->rc==SQLITE_OK
);
}
p->nProgress++;
}
@@ -3718,6 +3753,12 @@ int sqlite3rbu_close(sqlite3rbu *p, char **pzErrmsg){
p->rc = sqlite3_exec(p->dbMain, "COMMIT", 0, 0, &p->zErrmsg);
}
/* Sync the db file if currently doing an incremental checkpoint */
if( p->rc==SQLITE_OK && p->eStage==RBU_STAGE_CKPT ){
sqlite3_file *pDb = p->pTargetFd->pReal;
p->rc = pDb->pMethods->xSync(pDb, SQLITE_SYNC_NORMAL);
}
rbuSaveState(p, p->eStage);
if( p->rc==SQLITE_OK && p->eStage==RBU_STAGE_OAL ){
@@ -3842,6 +3883,12 @@ int sqlite3rbu_savestate(sqlite3rbu *p){
if( rc==SQLITE_OK ) rc = sqlite3_exec(p->dbMain, "COMMIT", 0, 0, 0);
}
/* Sync the db file */
if( rc==SQLITE_OK && p->eStage==RBU_STAGE_CKPT ){
sqlite3_file *pDb = p->pTargetFd->pReal;
rc = pDb->pMethods->xSync(pDb, SQLITE_SYNC_NORMAL);
}
p->rc = rc;
rbuSaveState(p, p->eStage);
rc = p->rc;
+9 -9
View File
@@ -458,15 +458,15 @@ static i64 readInt64(u8 *p){
memcpy(&x, p, 8);
return x;
#else
return (
(((i64)p[0]) << 56) +
(((i64)p[1]) << 48) +
(((i64)p[2]) << 40) +
(((i64)p[3]) << 32) +
(((i64)p[4]) << 24) +
(((i64)p[5]) << 16) +
(((i64)p[6]) << 8) +
(((i64)p[7]) << 0)
return (i64)(
(((u64)p[0]) << 56) +
(((u64)p[1]) << 48) +
(((u64)p[2]) << 40) +
(((u64)p[3]) << 32) +
(((u64)p[4]) << 24) +
(((u64)p[5]) << 16) +
(((u64)p[6]) << 8) +
(((u64)p[7]) << 0)
);
#endif
}
+8
View File
@@ -21,6 +21,10 @@
*/
#ifdef SQLITE_USER_AUTHENTICATION
#ifdef __cplusplus
extern "C" {
#endif
/*
** If a database contains the SQLITE_USER table, then the
** sqlite3_user_authenticate() interface must be invoked with an
@@ -85,4 +89,8 @@ int sqlite3_user_delete(
const char *zUsername /* Username to remove */
);
#ifdef __cplusplus
} /* end of the 'extern "C"' block */
#endif
#endif /* SQLITE_USER_AUTHENTICATION */
+5 -5
View File
@@ -477,10 +477,9 @@ SHELL_OPT += -DSQLITE_ENABLE_EXPLAIN_COMMENTS
SHELL_OPT += -DSQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
FUZZERSHELL_OPT = -DSQLITE_ENABLE_JSON1
FUZZCHECK_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5
FUZZCHECK_OPT += -DSQLITE_MAX_MEMORY=50000000
DBFUZZ_OPT =
KV_OPT = -DSQLITE_THREADSAFE=0 -DSQLITE_DIRECT_OVERFLOW_READ
DBSELFTEST_OPT = -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION
DBSELFTEST_OPT += -DSQLITE_ENABLE_RTREE -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_FTS5
ST_OPT = -DSQLITE_THREADSAFE=0
# This is the default Makefile target. The objects listed here
@@ -762,6 +761,10 @@ sqlite3_analyzer.c: sqlite3.c $(TOP)/src/tclsqlite.c $(TOP)/tool/spaceanal.tcl
sqlite3_analyzer$(EXE): sqlite3_analyzer.c
$(TCCX) $(TCL_FLAGS) sqlite3_analyzer.c -o $@ $(LIBTCL) $(THREADLIB)
dbdump$(EXE): $(TOP)/ext/misc/dbdump.c sqlite3.o
$(TCCX) -DDBDUMP_STANDALONE -o dbdump$(EXE) \
$(TOP)/ext/misc/dbdump.c sqlite3.o $(THREADLIB)
# Rules to build the 'testfixture' application.
#
TESTFIXTURE_FLAGS = -DSQLITE_TEST=1 -DSQLITE_CRASH_TEST=1
@@ -902,9 +905,6 @@ speedtest1$(EXE): $(TOP)/test/speedtest1.c sqlite3.c
kvtest$(EXE): $(TOP)/test/kvtest.c sqlite3.c
$(TCCX) -I. $(KV_OPT) -o kvtest$(EXE) $(TOP)/test/kvtest.c sqlite3.c $(THREADLIB)
dbselftest$(EXE): $(TOP)/test/dbselftest.c sqlite3.c
$(TCCX) -I. $(DBSELFTEST_OPT) -o dbselftest$(EXE) $(TOP)/test/dbselftest.c sqlite3.c $(THREADLIB)
rbu$(EXE): $(TOP)/ext/rbu/rbu.c $(TOP)/ext/rbu/sqlite3rbu.c sqlite3.o
$(TCC) -I. -o rbu$(EXE) $(TOP)/ext/rbu/rbu.c sqlite3.o \
$(THREADLIB)
+101 -87
View File
@@ -1,20 +1,20 @@
C Proof\sof\sconcept\sfor\sa\s"PRAGMA\svdbe_cycle_limit=N"\scommand.\s\sWhen\sN>0,\ninvoke\ssqlite3_interrupt()\swhenever\sany\sbyte\scode\sprogram\suses\smore\sthan\nN\svirtual\smachine\scycles.
D 2017-02-21T13:29:18.463
F Makefile.in edb6bcdd37748d2b1c3422ff727c748df7ffe918
C Use\sreplace()\sinstead\sof\schar()\sto\squote\snewline\sand\sreturn\scharacters\sin\nstrings\sin\sthe\soutput\sof\s.dump,\sto\savoid\sexcess\sexpression\scomplexity.
D 2017-04-07T11:45:58.111
F Makefile.in 1cc758ce3374a32425e4d130c2fe7b026b20de5b8843243de75f087c0a2661fb
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
F Makefile.msc a89ea37ab5928026001569f056973b9059492fe2
F README.md 8ecc12493ff9f820cdea6520a9016001cb2e59b7
F VERSION 3605fa447e4623f5ff4a6adc97b1fde9a257b8f2
F Makefile.msc a4c0613a18663bda56d8cf76079ab6590a7c3602e54befb4bbdef76bcaa38b6a
F README.md 2b15fae33852f2f53996774c21fb41e1d94181c4401a0e43ac93e11f2cc901b9
F VERSION 0a0e02e16b44ea735b40118fc844311b2ab0d35b25fbeda5120aee62f973f663
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2
F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90
F art/sqlite370.jpg d512473dae7e378a67e28ff96a34da7cb331def2
F autoconf/INSTALL 83e4a25da9fd053c7b3665eaaaf7919707915903
F autoconf/Makefile.am 1a47d071e3d5435f8f7ebff7eb6703848bbd65d4
F autoconf/Makefile.msc 3de603bcec5c07462801a20fd7dc1b871400af99
F autoconf/Makefile.msc 1fba0d762d115509d4fce7e333305cee172d521aaacec8bbf7aad5503605d3fb
F autoconf/README.first 6c4f34fe115ff55d4e8dbfa3cecf04a0188292f7
F autoconf/README.txt 4f04b0819303aabaa35fff5f7b257fb0c1ef95f1
F autoconf/configure.ac cacf2616abf6e4a569bde2ef365c143caeec40bc
F autoconf/configure.ac 2893b823ecc86cea13739f6c8109a41392254d1db08235c5615e0af5722c8578
F autoconf/tea/Makefile.in b438a7020446c8a8156e8d97c8914a04833da6fd
F autoconf/tea/README 3e9a3c060f29a44344ab50aec506f4db903fb873
F autoconf/tea/aclocal.m4 52c47aac44ce0ddb1f918b6993e8beb8eee88f43
@@ -30,13 +30,13 @@ F autoconf/tea/win/rules.vc c511f222b80064096b705dbeb97060ee1d6b6d63
F config.guess 226d9a188c6196f3033ffc651cbc9dcee1a42977
F config.h.in 6376abec766e9a0785178b1823b5a587e9f1ccbc
F config.sub 9ebe4c3b3dab6431ece34f16828b594fb420da55
F configure b15d030a8ae2e672d76c97b6667dacb98934a467 x
F configure.ac 605173e829ab64514ed89f9b53d0da1739d7b0a0
F configure bddf7d1d945894b724e2b16a1266359a40abec2c798c95b4409a7ebf771c38ef x
F configure.ac 901e8db2c211e8b655e51ee24f2b8faa33407acde87effc47f70380f3b04e452
F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
F doc/lemon.html b5a3c07d33ecb8e019ce8f7660fe2dbbad9d7977
F doc/pager-invariants.txt 27fed9a70ddad2088750c4a2b493b63853da2710
F doc/vfs-shm.txt e101f27ea02a8387ce46a05be2b1a902a021d37a
F ext/README.txt 913a7bd3f4837ab14d7e063304181787658b14e1
F ext/README.md fd5f78013b0a2bc6f0067afb19e6ad040e89a10179b4f6f03eee58fac5f169bd
F ext/async/README.txt e12275968f6fde133a80e04387d0e839b0c51f91
F ext/async/sqlite3async.c 0f3070cc3f5ede78f2b9361fb3b629ce200d7d74
F ext/async/sqlite3async.h f489b080af7e72aec0e1ee6f1d98ab6cf2e4dcef
@@ -70,7 +70,7 @@ F ext/fts3/README.content fdc666a70d5257a64fee209f97cf89e0e6e32b51
F ext/fts3/README.syntax a19711dc5458c20734b8e485e75fb1981ec2427a
F ext/fts3/README.tokenizers e0a8b81383ea60d0334d274fadf305ea14a8c314
F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d
F ext/fts3/fts3.c c4d7eecb12de9749851bcab6e5ca616a5803047a
F ext/fts3/fts3.c f0d5de1bc2155ba7cd7c0c1a751779a3a8857fa34d5c12f3b233a23fa2e79ea2
F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe
F ext/fts3/fts3Int.h eb2502000148e80913b965db3e59f29251266d0a
F ext/fts3/fts3_aux.c 9edc3655fcb287f0467d0a4b886a01c6185fe9f1
@@ -86,15 +86,16 @@ F ext/fts3/fts3_tokenize_vtab.c a27593ab19657166f6fa5ec073b678cc29a75860
F ext/fts3/fts3_tokenizer.c a22bf311a71f3efa9d7012d8cc48fc9b0f3dace7
F ext/fts3/fts3_tokenizer.h 64c6ef6c5272c51ebe60fc607a896e84288fcbc3
F ext/fts3/fts3_tokenizer1.c 5c98225a53705e5ee34824087478cf477bdb7004
F ext/fts3/fts3_unicode.c a93f5edc0aff44ef8b06d7cb55b52026541ca145
F ext/fts3/fts3_unicode2.c c3d01968d497bd7001e7dc774ba75b372738c057
F ext/fts3/fts3_write.c c3863f23b6b4623c8b9d5cf31c12ce4469f78ca9
F ext/fts3/fts3_unicode.c 525a3bd9a7564603c5c061b7de55403a565307758a94600e8a2f6b00d1c40d9d
F ext/fts3/fts3_unicode2.c cc04fc672bfd42b1e650398cb0bf71f64f9aae032cfe75bbcfe75b9cf966029c
F ext/fts3/fts3_write.c a51d48d646974ee2fb4b17fcd5da0416a5759a32dcacc2cce2ba00d5a767848e
F ext/fts3/fts3speed.tcl b54caf6a18d38174f1a6e84219950d85e98bb1e9
F ext/fts3/mkfts3amal.tcl 252ecb7fe6467854f2aa237bf2c390b74e71f100
F ext/fts3/tool/fts3cov.sh c331d006359456cf6f8f953e37f2b9c7d568f3863f00bb5f7eb87fea4ac01b73
F ext/fts3/tool/fts3view.c 202801a2056995b763864d60c2dee744d46f1677
F ext/fts3/unicode/CaseFolding.txt 8c678ca52ecc95e16bc7afc2dbf6fc9ffa05db8c
F ext/fts3/unicode/UnicodeData.txt cd07314edb62d49fde34debdaf92fa2aa69011e7
F ext/fts3/unicode/mkunicode.tcl 2debed3f582d77b3fdd0b8830880250021571fd8
F ext/fts3/unicode/mkunicode.tcl ab0543a3b2399092ea2dd75df1bef333405b0d7f6b8c4951a0fbb60e780cb69f
F ext/fts3/unicode/parseunicode.tcl da577d1384810fb4e2b209bf3313074353193e95
F ext/fts5/extract_api_docs.tcl a36e54ec777172ddd3f9a88daf593b00848368e0
F ext/fts5/fts5.h 62f3e33ceeb9a428db139f9c012186b371da1cc7
@@ -102,11 +103,11 @@ F ext/fts5/fts5Int.h c629b24d2b92b99596f3b8e82289fddca06df6e1
F ext/fts5/fts5_aux.c 67acf8d51723cf28ffc3828210ba662df4b8d267
F ext/fts5/fts5_buffer.c 4c1502d4c956cd092c89ce4480867f9d8bf325cd
F ext/fts5/fts5_config.c 5af9c360e99669d29f06492c370892394aba0857
F ext/fts5/fts5_expr.c 33f0e8063ac7360bcd71c0ff0dcbacdc05fffe50
F ext/fts5/fts5_expr.c c6ecc2280162a3714d15dce2a8f2299f748b627c
F ext/fts5/fts5_hash.c 880998e596b60f078348d48732ca4ad9a90caad2
F ext/fts5/fts5_index.c f67032a9a529ba52a545e6e3ab970764199c05d4
F ext/fts5/fts5_main.c f85281445dcf8be32d18841c93a6f90fe27dbfe2
F ext/fts5/fts5_storage.c de0ed8a06738bde433afe11e92295ceaffbc4e58
F ext/fts5/fts5_storage.c 8f0e65cb33bde8f449e1c9b4be4600d18b4da6e9
F ext/fts5/fts5_tcl.c 4a901f00c8553740dba63511603f5527d741c26a
F ext/fts5/fts5_test_mi.c 783b86697ebf773c18fc109992426c0173a055bc
F ext/fts5/fts5_test_tok.c db08af63673c3a7d39f053b36fd6e065017706be
@@ -160,10 +161,12 @@ F ext/fts5/test/fts5fault8.test 6785af34bd1760de74e2824ea9c161965af78f85
F ext/fts5/test/fts5fault9.test e10e395428a9ea0596ebe752ff7123d16ab78e08
F ext/fts5/test/fts5faultA.test fa5d59c0ff62b7125cd14eee38ded1c46e15a7ea
F ext/fts5/test/fts5faultB.test 7f3bba790fa172073ac314f9b8ed197390b61eca
F ext/fts5/test/fts5faultD.test cc5d1225556e356615e719c612e845d41bff7d5a
F ext/fts5/test/fts5full.test 6f6143af0c6700501d9fd597189dfab1555bb741
F ext/fts5/test/fts5fuzz1.test bece4695fc169b61ab236ada7931c6e4942cbef9
F ext/fts5/test/fts5hash.test 06f9309ccb4d5050a131594e9e47d0b21456837d
F ext/fts5/test/fts5integrity.test f5e4f8d284385875068ad0f3e894ce43e9de835d
F ext/fts5/test/fts5lastrowid.test 4fac1aba696dd6c956e03b0cf91f6f1f3aaec494
F ext/fts5/test/fts5matchinfo.test f7dde99697bcb310ea8faa8eb2714d9f4dfc0e1b
F ext/fts5/test/fts5merge.test 9f65f090d214ff865c56bef4f864aaa1182af6e3
F ext/fts5/test/fts5merge2.test a6da3c16d694235938d1939f503cfa53f0943d75
@@ -204,16 +207,18 @@ F ext/fts5/tool/showfts5.tcl d54da0e067306663e2d5d523965ca487698e722c
F ext/icu/README.txt d9fbbad0c2f647c3fdf715fc9fd64af53aedfc43
F ext/icu/icu.c 84900472a088a3a172c6c079f58a1d3a1952c332
F ext/icu/sqliteicu.h 728867a802baa5a96de7495e9689a8e01715ef37
F ext/misc/README.md 8e008c8d2b02e09096b31dfba033253ac27c6c06a18aa5826e299fa7601d90b2
F ext/misc/amatch.c 211108e201105e4bb0c076527b8cfd34330fc234
F ext/misc/carray.c 40c27641010a4dc67e3690bdb7c9d36ca58b3c2d
F ext/misc/closure.c 0d2a038df8fbae7f19de42e7c7d71f2e4dc88704
F ext/misc/compress.c 122faa92d25033d6c3f07c39231de074ab3d2e83
F ext/misc/csv.c 531a46cbad789fca0aa9db69a0e6c8ac9e68767d
F ext/misc/dbdump.c 34174d537318027b159e3341105866c05a4149376ede59988c82280bed144e6d
F ext/misc/eval.c f971962e92ebb8b0a4e6b62949463ee454d88fa2
F ext/misc/fileio.c d4171c815d6543a9edef8308aab2951413cd8d0f
F ext/misc/fuzzer.c 7c64b8197bb77b7d64eff7cac7848870235d4c25
F ext/misc/ieee754.c f190d0cc5182529acb15babd177781be1ac1718c
F ext/misc/json1.c 552a7d730863419e05dc947265b28bd411680e2e
F ext/misc/json1.c 92b9e404bd79cc76d3ef2b3a9e37bf775700f7d645466fd41d2e8742e3fa16fb
F ext/misc/memvfs.c e5225bc22e79dde6b28380f3a068ddf600683a33
F ext/misc/nextchar.c 35c8b8baacb96d92abbb34a83a997b797075b342
F ext/misc/percentile.c 92699c8cd7d517ff610e6037e56506f8904dae2e
@@ -223,6 +228,7 @@ F ext/misc/rot13.c 1ac6f95f99b575907b9b09c81a349114cf9be45a
F ext/misc/scrub.c 1c5bfb8b0cd18b602fcb55755e84abf0023ac2fb
F ext/misc/series.c e11e534ada797d5b816d7e7a93c022306563ca35
F ext/misc/sha1.c 0b9e9b855354910d3ca467bf39099d570e73db56
F ext/misc/shathree.c fa185d7aee0ad0aca5e091b4a2db7baff11796170e5793b5de99e511a13af448
F ext/misc/showauth.c 732578f0fe4ce42d577e1c86dc89dd14a006ab52
F ext/misc/spellfix.c a4723b6aff748a417b5091b68a46443265c40f0d
F ext/misc/totype.c 4a167594e791abeed95e0a8db028822b5e8fe512
@@ -248,6 +254,7 @@ F ext/rbu/rbuB.test c25bc325b8072a766e56bb76c001866b405925c2
F ext/rbu/rbuC.test efe47db508a0269b683cb2a1913a425ffd39a831
F ext/rbu/rbu_common.tcl a38e8e2d4a50fd6aaf151633714c1b1d2fae3ead
F ext/rbu/rbucrash.test 8d2ed5d4b05fef6c00c2a6b5f7ead71fa172a695
F ext/rbu/rbucrash2.test b2ecbdd7bb72c88bd217c65bd00dafa07f7f2d4d
F ext/rbu/rbudiff.test 3e605cf624d00d04d0fb1316a3acec4fbe3b3ac5
F ext/rbu/rbudor.test 99b05cc0df613e962c2c8085cfb05686a09cf315
F ext/rbu/rbufault.test cc0be8d5d392d98b0c2d6a51be377ea989250a89
@@ -255,16 +262,16 @@ F ext/rbu/rbufault2.test 9a7f19edd6ea35c4c9f807d8a3db0a03a5670c06
F ext/rbu/rbufault3.test 54a399888ac4af44c68f9f58afbed23149428bca
F ext/rbu/rbufault4.test 34e70701cbec51571ffbd9fbf9d4e0f2ec495ca7
F ext/rbu/rbufts.test 828cd689da825f0a7b7c53ffc1f6f7fdb6fa5bda
F ext/rbu/rbuprogress.test e3e25fb7622641b8f2df7c6b7a7eb6fddfc46a4b
F ext/rbu/rbuprogress.test 1849d4e0e50616edf5ce75ce7db86622e656b5cf
F ext/rbu/rburesume.test 8acb77f4a422ff55acfcfc9cc15a5cb210b1de83
F ext/rbu/rbusave.test 0f43b6686084f426ddd040b878426452fd2c2f48
F ext/rbu/rbuvacuum.test 4a977447c15c2581ab668781d9ef4294382530e0
F ext/rbu/rbuvacuum2.test 2074ab14fe66e1c7e7210c62562650dcd215bbaa
F ext/rbu/sqlite3rbu.c bb0de6cdbdb14a7d55a097238a434b7e99caf318
F ext/rbu/sqlite3rbu.c 2a89efba9eeba8e6c89a498dc195e8efbdde2694
F ext/rbu/sqlite3rbu.h 6fb6294c34a9ca93b5894a33bca530c6f08decba
F ext/rbu/test_rbu.c 5aa22616afac6f71ebd3d9bc9bf1006cfabcca88
F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761
F ext/rtree/rtree.c 3f3a595dba485e340246fa2c8ba330a6b9768b00
F ext/rtree/rtree.c 0acd285bfacc347579a5df9fe947212fb99e2775a40c43f027c3a16936c58e7e
F ext/rtree/rtree.h 834dbcb82dc85b2481cde6a07cdadfddc99e9b9e
F ext/rtree/rtree1.test 42dadfc7b44a436cd74a1bebc0b9b689e4eaf7ec
F ext/rtree/rtree2.test acbb3a4ce0f4fbc2c304d2b4b784cfa161856bba
@@ -312,13 +319,13 @@ F ext/session/sessionwor.test 2f3744236dc8b170a695b7d8ddc8c743c7e79fdc
F ext/session/sqlite3session.c 13642d9c754cc18f17e141f82860d269e2adf920
F ext/session/sqlite3session.h d4db650adfcc7a4360e9f12a09c2d117b1db6b53
F ext/session/test_session.c eb0bd6c1ea791c1d66ee4ef94c16500dad936386
F ext/userauth/sqlite3userauth.h 19cb6f0e31316d0ee4afdfb7a85ef9da3333a220
F ext/userauth/sqlite3userauth.h 7f3ea8c4686db8e40b0a0e7a8e0b00fac13aa7a3
F ext/userauth/user-auth.txt e6641021a9210364665fe625d067617d03f27b04
F ext/userauth/userauth.c 3410be31283abba70255d71fd24734e017a4497f
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60
F main.mk 08e0b151abb46353c677ac4974b50c6077f85eee
F main.mk 9abb506e717887d57f754bae139b85c1a06d6f2ac25b589f3e792e310567f278
F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
@@ -331,38 +338,38 @@ F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
F src/alter.c 3b23977620ce9662ac54443f65b87ba996e36121
F src/analyze.c ac7a5d7e3cee07d074697904e00e4a8ab7b2b4f5
F src/analyze.c 0d0ccf7520a201d8747ea2f02c92c26e26f801bc161f714f27b9f7630dde0421
F src/attach.c 8c476f8bd5d2afe11d925f890d30e527e5b0ce43
F src/auth.c 930b376a9c56998557367e6f7f8aaeac82a2a792
F src/backup.c faf17e60b43233c214aae6a8179d24503a61e83b
F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33
F src/btmutex.c 0e9ce2d56159b89b9bc8e197e023ee11e39ff8ca
F src/btree.c 3ae66974881e74df9909093818b4c3428f8d7982
F src/btree.h e6d352808956ec163a17f832193a3e198b3fb0ac
F src/btreeInt.h cd55d39d9916270837a88c12e701047cba0729b0
F src/build.c 9e799f1edd910dfa8a0bc29bd390d35d310596af
F src/btree.c 24ae5472bd0b53b4130ecdda389deb621af721d1fcb50890b878102b00bd10fa
F src/btree.h bf64dfeeddeebdb775a5eba0098bbc00d073290d
F src/btreeInt.h a392d353104b4add58b4a59cb185f5d5693dde832c565b77d8d4c343ed98f610
F src/build.c 4026a9c554b233e50c5e9ad46963e676cf54dd2306d952aa1eaa07a1bc9ce14f
F src/callback.c 2e76147783386374bf01b227f752c81ec872d730
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
F src/ctime.c a9984df73898c042a5cfc8f9d8e7723d02bc35c9
F src/date.c dc3f1391d9297f8c748132813aaffcb117090d6e
F src/ctime.c 47d91a25ad8f199a71a5b1b7b169d6dd0d6e98c5719eca801568798743d1161c
F src/date.c ee676e7694dfadbdd2fde1a258a71be8360ba5ae
F src/dbstat.c 19ee7a4e89979d4df8e44cfac7a8f905ec89b77d
F src/delete.c 0d9d5549d42e79ce4d82ff1db1e6c81e36d2f67c
F src/expr.c 8a29e9b72d4b642189999c41782cd6c5bc43512f
F src/expr.c 6bce2cbdd822963cf28e782938a96274cc37f18ac28dec7a4e35ccac09f66ce8
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
F src/fkey.c 2e9aabe1aee76273aff8a84ee92c464e095400ae
F src/func.c c67273e1ec08abbdcc14c189892a3ff6eeece86b
F src/func.c 9d52522cc8ae7f5cdadfe14594262f1618bc1f86083c4cd6da861b4cf5af6174
F src/global.c 4a34512d82fc5aa13c802db06bcfff5e1d3de955
F src/hash.c 63d0ee752a3b92d4695b2b1f5259c4621b2cfebd
F src/hash.h ab34c5c54a9e9de2e790b24349ba5aab3dbb4fd4
F src/hwtime.h 747c1bbe9df21a92e9c50f3bbec1de841dc5e5da
F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
F src/insert.c 3ed64afc49c0a2221e397b9f65d231ffbef506fe
F src/insert.c d4bb3a135948553d18cf992f76f7ed7b18aa0327f250607b5a6671e55d9947d5
F src/legacy.c e88ed13c2d531decde75d42c2e35623fb9ce3cb0
F src/loadext.c a68d8d1d14cf7488bb29dc5311cb1ce9a4404258
F src/main.c e207b81542d13b9f13d61e78ca441f9781f055b0
F src/malloc.c d0a1474236486165bcb349af82e2a6560178bf7b
F src/loadext.c a72909474dadce771d3669bf84bf689424f6f87d471fee898589c3ef9b2acfd9
F src/main.c 158326243c5ddc8b98a1e983fa488650cf76d760
F src/malloc.c e20bb2b48abec52d3faf01cce12e8b4f95973755fafec98d45162dfdab111978
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c fd7cd6fe21d46fe0a4186367dd8dc26d87b787eb
F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de
F src/mem2.c f1940d9e91948dd6a908fbb9ce3835c36b5d83c3
F src/mem3.c 8768ac94694f31ffaf8b4d0ea5dc08af7010a35a
F src/mem5.c 9bf955937b07f8c32541c8a9991f33ce3173d944
@@ -383,24 +390,24 @@ F src/os_win.c 2a6c73eef01c51a048cc4ddccd57f981afbec18a
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
F src/pager.c ff1232b3088a39806035ecfac4fffeb22717d80b
F src/pager.h f2a99646c5533ffe11afa43e9e0bea74054e4efa
F src/parse.y af8830094f4aecb91cb69721f3601ad10c36abc4
F src/parse.y 48b03113704ee8bd78ee6996d81de7fbee22e105
F src/pcache.c 62835bed959e2914edd26afadfecce29ece0e870
F src/pcache.h 2cedcd8407eb23017d92790b112186886e179490
F src/pcache1.c e3967219b2a92b9edcb9324a4ba75009090d3953
F src/pragma.c 9180cce9a16e0835c6f7d0aa42d8938ce59c2011
F src/pragma.h 1ec44ee89a43e65bf70c9ef4ef066df217b9ab3f
F src/pcache1.c 1195a21fe28e223e024f900b2011e80df53793f0356a24caace4188b098540dc
F src/pragma.c 220474f113cade6a6b5bacd3e3a65eca339acbee804128bc5db13a9cad55fba5
F src/pragma.h 37a1311d0388db480388d7ec09054f7103045eff20d4971f8a433b77f40b9921
F src/prepare.c b1140c3d0cf59bc85ace00ce363153041b424b7a
F src/printf.c 67427bbee66d891fc6f6f5aada857e9cdb368c1c
F src/printf.c 8757834f1b54dae512fb25eb1acc8e94a0d15dd2290b58f2563f65973265adb2
F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
F src/resolve.c f9bc0de45a30a450da47b3766de00be89bf9be79
F src/resolve.c 3e518b962d932a997fae373366880fc028c75706
F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac
F src/select.c d12f3539f80db38b09015561b569e0eb1c4b6c5f
F src/shell.c bf976d5301be9d8a4c52852c97909cc9a41ee20d
F src/sqlite.h.in 751ff125eb159c8f92c182b8df980a5e4f50e966
F src/select.c afcf31d8ed7c890328a31d3f350467ccd273af345b24562382b398d6d9cd0664
F src/shell.c 3680725485ce5022dc683d593e8a4b95f973597d843ddb8be788d7dc24d16de9
F src/sqlite.h.in ab77e511620eebbd4ed7e4f52fae697b6870dda66c945acd2d3066f99c98e17e
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h 8648034aa702469afb553231677306cc6492a1ae
F src/sqliteInt.h 46fe8e5aee3825d77fa771216ef263dc947030e7
F src/sqliteLimit.h c0373387c287c8d0932510b5547ecde31b5da247
F src/sqlite3ext.h 58fd0676d3111d02e62e5a35992a7d3da5d3f88753acc174f2d37b774fbbdd28
F src/sqliteInt.h 6cf244eb06119b44e155717708e54f0638c35e9bd8ef59ea570eb1f093f0da44
F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b
F src/status.c a9e66593dfb28a9e746cba7153f84d49c1ddc4b1
F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34
F src/tclsqlite.c 6c2151b6d8d98e183a04466d40df8889c0574d79
@@ -409,7 +416,7 @@ F src/test2.c 3efb99ab7f1fc8d154933e02ae1378bac9637da5
F src/test3.c d03f5b5da9a2410b7a91c64b0d3306ed28ab6fee
F src/test4.c 18ec393bb4d0ad1de729f0b94da7267270f3d8e6
F src/test5.c 328aae2c010c57a9829d255dc099d6899311672d
F src/test6.c 121060d2e79a4f5047eb12b5135b23a6a7a5af01
F src/test6.c 004ad42f121f693b8cbe060d1a330678abc61620
F src/test7.c 5612e9aecf934d6df7bba6ce861fdf5ba5456010
F src/test8.c 4f4904721167b32f7a4fa8c7b32a07a673d6cc86
F src/test9.c 12e5ba554d2d1cbe0158f6ab3f7ffcd7a86ee4e5
@@ -419,7 +426,7 @@ F src/test_backup.c bf5da90c9926df0a4b941f2d92825a01bbe090a0
F src/test_bestindex.c d23f80d334c59662af69191854c76b8d3d0c8c96
F src/test_blob.c f65ac717da2618691cf9dad094e6da0219dcd208
F src/test_btree.c 8b2dc8b8848cf3a4db93f11578f075e82252a274
F src/test_config.c 83179ea845479b5be9a651d014649e3f2722a1fe
F src/test_config.c edcba290248dc18736dd814c9b95863c6762e0b35753048d8cbe5bf65f7abfbb
F src/test_delete.c af7eab5702f853fb1c62a5f7665e2234cf1ae17b
F src/test_demovfs.c a0c3bdd45ed044115c2c9f7779e56eafff18741e
F src/test_devsym.c 4e58dec2602d8e139ca08659f62a62450587cb58
@@ -429,7 +436,7 @@ F src/test_hexio.c 1d4469ca61ab202a1fcec6543f584d2407205e8d
F src/test_init.c 4413c211a94b62157ca4c145b3f27c497f03c664
F src/test_intarray.c 988fc61cb0ff539f4172c0d95f15287c92516f64
F src/test_intarray.h f3b7672f5d1056eac563c0d6ea8480a660b1475c
F src/test_journal.c d3b83f2bcb7792c709e57abddc456a2b1818643a
F src/test_journal.c 619f2aa10e0d7a5f87c0f06825bc61dfce1c6b9c7f3ad990fb13de6c3b8874a3
F src/test_loadext.c 337056bae59f80b9eb00ba82088b39d0f4fe6dfd
F src/test_malloc.c c05f6c40bd6c8bfe5f1718212f81fd5687f91766
F src/test_multiplex.c e054459f7633f3ff8ce1245da724f9a8be189e4e
@@ -454,29 +461,29 @@ F src/test_windirent.c 17f91f5f2aa1bb7328abb49414c363b5d2a9d3ff
F src/test_windirent.h 5d67483a55442e31e1bde0f4a230e6e932ad5906
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
F src/tokenize.c 25ccc63ae2c4163933221f3181c9982b47cd08d2
F src/treeview.c 4e44ade3bfe59d82005039f72e09333ce2b4162c
F src/tokenize.c 1003d6d90c6783206c711f0a9397656fa5b055209f4d092caa43bb3bf5215db5
F src/treeview.c 84d0ac737e1231702679f0289180021e19c5cc186ec413e8dcb704a887c76ec8
F src/trigger.c c9f0810043b265724fdb1bdd466894f984dfc182
F src/update.c 456d4a4656f8a03c2abc88a51b19172197400e58
F src/utf.c 699001c79f28e48e9bcdf8a463da029ea660540c
F src/util.c ca8440ede81e155d15cff7c101654f60b55a9ae6
F src/vacuum.c 1fe4555cd8c9b263afb85b5b4ee3a4a4181ad569
F src/vdbe.c 16f378640570c24442fd7191b136b5d6380f5c7b
F src/vdbe.h 59998ffd71d7caa8886bc78dafaf8caeccd4c13c
F src/vdbeInt.h 4e4b15b2e1330e1636e4e01974eab2b0b985092f
F src/vdbeapi.c 3e4a8893feeb78620f4aac4ac5b85d92255b97e1
F src/vdbeaux.c 4122458d33318ab039c4b5da1ca4e7c9221c38e4
F src/vdbe.c b070c9c81a5faff5d9fc9563c7c030e3e1adb69d835259470fd945ef61f3f9fb
F src/vdbe.h caa5346d52bae2a3c8c1dcfa60a7a4dc878a9e3865cb8239da55808b316c8158
F src/vdbeInt.h 5db089ce18c4feff8820ec6e4cac2d2c82e03d4b1d96f10a6e43832147b8dffe
F src/vdbeapi.c 5b08d82592bcff4470601fe78aaabebd50837860
F src/vdbeaux.c 0ecacf8c7ca93e430b30819b8fc9b2c1ffe88202d1437e88c08a1f0b6159c58c
F src/vdbeblob.c 359891617358deefc85bef7bcf787fa6b77facb9
F src/vdbemem.c 3b5a9a5b375458d3e12a50ae1aaa41eeec2175fd
F src/vdbesort.c eda25cb2d1727efca6f7862fea32b8aa33c0face
F src/vdbemem.c 8bb4dd22837da969bfda25ef3f92d41aaad192328f89a0951290d5e26ad7dbc4
F src/vdbesort.c e72fe02a2121386ba767ede8942e9450878b8fc873abf3d1b6824485f092570c
F src/vdbetrace.c 41963d5376f0349842b5fc4aaaaacd7d9cdc0834
F src/vtab.c 007513c2ef52472fcdea6a741683d50662e82790
F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
F src/wal.c 40c543f0a2195d1b0dc88ef12142bea690009344
F src/wal.h 06b2a0b599cc0f53ea97f497cf8c6b758c999f71
F src/walker.c 91a6df7435827e41cff6bb7df50ea00934ee78b0
F src/where.c 01baf58b72f3ddb7793cdee2871f751e3e09b35e
F src/whereInt.h c0b092180f04608d80c258174b0a14a1f9c8d02f
F src/walker.c b71a992b413b3a022572eccf29ef4b4890223791
F src/where.c 49b48b720184fdde747c468d7270feeb1b88c6a71092cea3a1aa168dc8ac0b0f
F src/whereInt.h 2d50c2b74a33be44cb68fdecee30b4d93552f1f4
F src/wherecode.c 677e95413c472c0b413023b6b69a47f40fce1b04
F src/whereexpr.c 130cdd1a43af71b19755270fb1224874cf55158c
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
@@ -521,6 +528,7 @@ F test/attachmalloc.test 3a4bfca9545bfe906a8d2e622de10fbac5b711b0
F test/auth.test c6ede04bee65637ff354b43fc1235aa560c0863e
F test/auth2.test 9eb7fce9f34bf1f50d3f366fb3e606be5a2000a1
F test/auth3.test 0d48b901cf111c14b4b1b5205c7d28f1a278190f
F test/autoanalyze1.test b9cc3f32a990fa56669b668d237c6d53e983554ae80c0604992e18869a0b2dec
F test/autoinc.test 6ae8fb69c9f656962464ae4e6667045d0dfc3b46
F test/autoindex1.test 14b63a9f1e405fe6d5bfc8c8d00249c2ebaf13ea
F test/autoindex2.test 12ef578928102baaa0dc23ad397601a2f4ecb0df
@@ -575,7 +583,7 @@ F test/capi3d.test 485048dc5cd07bc68011e4917ad035ad6047ab82
F test/capi3e.test 3d49c01ef2a1a55f41d73cba2b23b5059ec460fe
F test/cast.test 4c275cbdc8202d6f9c54a3596701719868ac7dc3
F test/cffault.test 9d6b20606afe712374952eec4f8fd74b1a8097ef
F test/check.test 85a84bfc4be0e83f668747211c7cd45a6721d485
F test/check.test 33a698e8c63613449d85d624a38ef669bf20331daabebe3891c9405dd6df463a
F test/close.test 83947daf3b700631f90f4850ddaab455be4af73d
F test/closure01.test b1703ba40639cfc9b295cf478d70739415eec6a4
F test/coalesce.test cee0dccb9fbd2d494b77234bccf9dc6c6786eb91
@@ -589,7 +597,7 @@ F test/collate7.test 8ec29d98f3ee4ccebce6e16ce3863fb6b8c7b868
F test/collate8.test cd9b3d3f999b8520ffaa7cc1647061fc5bab1334
F test/collate9.test 3adcc799229545940df2f25308dd1ad65869145a
F test/collateA.test b8218ab90d1fa5c59dcf156efabb1b2599c580d6
F test/collateB.test 8ec2accd2d7166c1eff0d2a39bc90262c6f89632
F test/collateB.test 1e68906951b846570f29f20102ed91d29e634854ee47454d725f2151ecac0b95
F test/colmeta.test 2c765ea61ee37bc43bbe6d6047f89004e6508eb1
F test/colname.test 08948a4809d22817e0e5de89c7c0a8bd90cb551b
F test/conflict.test 029faa2d81a0d1cafb5f88614beb663d972c01db
@@ -615,6 +623,7 @@ F test/corruptG.test adf79b669cbfd19e28c8191a610d083ae53a6d51
F test/corruptH.test 79801d97ec5c2f9f3c87739aa1ec2eb786f96454
F test/corruptI.test 075fe1d75aa1d84e2949be56b6264376c41502e4
F test/corruptJ.test 4d5ccc4bf959464229a836d60142831ef76a5aa4
F test/corruptK.test 814a59ec699d8546b4e29005fba3d16e933ef2fe
F test/cost.test 1eedbfd868f806f3fa08ff072b04cf270dcf61c8
F test/count.test cb2e0f934c6eb33670044520748d2ecccd46259c
F test/coveridxscan.test b629e896b14df2f000a99b8d170d80589c46562c
@@ -634,9 +643,8 @@ F test/csv01.test e0ba3caaa57e4c667a0b45977689fb8082f14348
F test/ctime.test ff6c38e822459d6ca743c34901caf57740b08b54
F test/cursorhint.test 7bc346788390475e77a345da2b92270d04d35856
F test/cursorhint2.test 8457e93d97f665f23f97cdbc8477d16e3480331b
F test/date.test a6a5a48b90907bca9fbcc79a30be5a715c1ab2fc
F test/date.test 9b73bbeb1b82d9c1f44dec5cf563bf7da58d2373
F test/dbfuzz.c 73047c920d6210e5912c87cdffd9a1c281d4252e
F test/dbselftest.c b2e6cfac59066dbcb7334b66304bb15a5508dd42
F test/dbstatus.test 73149851b3aff14fc6db478e58f9083a66422cf5
F test/dbstatus2.test e93ab03bfae6d62d4d935f20de928c19ca0ed0ab
F test/default.test 0cb49b1c315a0d81c81d775e407f66906a2a604d
@@ -805,6 +813,7 @@ F test/fts4growth.test e5390da74619cacc389711bac9349640b32c4f9a
F test/fts4growth2.test 13ad4e76451af6e6906c95cdc725d01b00044269
F test/fts4incr.test 4e353a0bd886ea984e56fce9e77724fc923b8d0d
F test/fts4langid.test 65a7332c9bc257919e259a304aa8a38c41655b9d
F test/fts4lastrowid.test fa5e157955a3121615ef3e16ff5196e96c9e1e64
F test/fts4merge.test d2b39f6b1bd4a9738a13540e2d044cba11c43d47
F test/fts4merge2.test 5faa558d1b672f82b847d2a337465fa745e46891
F test/fts4merge3.test 8d9ccb4a3d41c4c617a149d6c4b13ad02de797d0
@@ -825,7 +834,7 @@ F test/fuzz2.test 76dc35b32b6d6f965259508508abce75a6c4d7e1
F test/fuzz3.test b47377143f0c80f91ed29d722861077ff34415d5
F test/fuzz_common.tcl a87dfbb88c2a6b08a38e9a070dabd129e617b45b
F test/fuzz_malloc.test 328f70aaca63adf29b4c6f06505ed0cf57ca7c26
F test/fuzzcheck.c a87e6067a8d19844bade916841cb76150ecf24a2
F test/fuzzcheck.c 2152602232c96d9c790eff3013e1369ce59de3203fa0b75bc613531448454e61
F test/fuzzdata1.db 7ee3227bad0e7ccdeb08a9e6822916777073c664
F test/fuzzdata2.db f03a420d3b822cc82e4f894ca957618fbe9c4973
F test/fuzzdata3.db c6586d3e3cef0fbc18108f9bb649aa77bfc38aba
@@ -874,7 +883,7 @@ F test/init.test 15c823093fdabbf7b531fe22cf037134d09587a7
F test/insert.test 38742b5e9601c8f8d76e9b7555f7270288c2d371
F test/insert2.test 4d14b8f1b810a41995f6286b64a6943215d52208
F test/insert3.test 1b7db95a03ad9c5013fdf7d6722b6cd66ee55e30
F test/insert4.test a20432f1c0fbbcff8f11d0e6ab4acb8c9db58023
F test/insert4.test 46bead5f39e181850ee56adcf49d3a3157c460c52249211714612ac89fe34835
F test/insert5.test 394f96728d1258f406fe5f5aeb0aaf29487c39a6
F test/instr.test 9a8802f28437d8ade53fedfc47b2ca599b4e48ba
F test/instrfault.test 0f870b218ea17cd477bb19ed330eecdb460dd53a
@@ -904,6 +913,7 @@ F test/jrnlmode3.test 556b447a05be0e0963f4311e95ab1632b11c9eaa
F test/json101.test c0897616f32d95431f37fd291cb78742181980ac
F test/json102.test bf3fe7a706d30936a76a0f7a0375e1e8e73aff5a
F test/json103.test c5f6b85e69de05f6b3195f9f9d5ce9cd179099a0
F test/json104.test 877d5845f6303899b7889ea5dd1bea99076e3100574d5c536082245c5805dcaa
F test/keyword1.test 37ef6bba5d2ed5b07ecdd6810571de2956599dff
F test/kvtest.c b9a9822dda05a1aa481215a52e2fc93cd8b22ee5
F test/lastinsert.test 42e948fd6442f07d60acbd15d33fb86473e0ef63
@@ -929,7 +939,7 @@ F test/make-where7.tcl 05c16b5d4f5d6512881dfec560cb793915932ef9
F test/malloc.test 21c213365f2cca95ab2d7dc078dc8525f96065f8
F test/malloc3.test e3b32c724b5a124b57cb0ed177f675249ad0c66a
F test/malloc4.test 957337613002b7058a85116493a262f679f3a261
F test/malloc5.test 192d0b5ee1d023a07d5164c34cf47d010da73da1
F test/malloc5.test a591be066ebc6ad34adaa4b38939a037a59ebd80ad681e79dedac7b4a9e7bc09
F test/malloc6.test 2f039d9821927eacae43e1831f815e157659a151
F test/malloc7.test 7c68a32942858bc715284856c5507446bba88c3a
F test/malloc8.test 9b7a3f8cb9cf0b12fff566e80a980b1767bd961d
@@ -947,6 +957,7 @@ F test/mallocI.test 6c23a71df077fa5d387be90e7e669c5b368ca38a
F test/mallocJ.test b5d1839da331d96223e5f458856f8ffe1366f62e
F test/mallocK.test 27cb5566a6e5f2d76f9d4aa2eca45524401fd61e
F test/mallocL.test fb311ff80afddf3b1a75e52289081f4754d901dc
F test/mallocM.test 78bbe9d3da84a5c679123cdb40d7b2010b18fc46e13897e4f253c6ba6fbff134
F test/malloc_common.tcl aac62499b76be719fac31e7a3e54a7fd53272e7f
F test/manydb.test 28385ae2087967aa05c38624cec7d96ec74feb3e
F test/mem5.test c6460fba403c5703141348cd90de1c294188c68f
@@ -1000,8 +1011,8 @@ F test/orderby7.test 3d1383d52ade5b9eb3a173b3147fdd296f0202da
F test/orderby8.test 23ef1a5d72bd3adcc2f65561c654295d1b8047bd
F test/orderby9.test 87fb9548debcc2cd141c5299002dd94672fa76a3
F test/oserror.test b32dc34f2363ef18532e3a0a7358e3e7e321974f
F test/ossfuzz.c e469138f4be3e92df6173b79b3b216ab6e17b407
F test/ossshell.c d9f1a6f43e7bab45d6be857a5800f5d4a1861db3
F test/ossfuzz.c f5abed3177f719df3c3109901fcdd26b9fb7f581c8da50fc26f3a81ddfb2c2ae
F test/ossshell.c 296ab63067841bd1b1e97b46a0b2af48ee7f69d50d1a723008bee12dd7122622
F test/ovfl.test 199c482696defceacee8c8e0e0ef36da62726b2f
F test/pager1.test 841868017e9dd3cb459b8d78862091a7d9cff21d
F test/pager2.test 67b8f40ae98112bcdba1f2b2d03ea83266418c71
@@ -1016,11 +1027,12 @@ F test/parser1.test 391b9bf9a229547a129c61ac345ed1a6f5eb1854
F test/pcache.test c8acbedd3b6fd0f9a7ca887a83b11d24a007972b
F test/pcache2.test af7f3deb1a819f77a6d0d81534e97d1cf62cd442
F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff
F test/permutations.test 46ad98770d3c04ce2418cab2cc527647bfe961a7
F test/permutations.test af720e7d139e7e5417341d0f0eef2b911c0b067852138dc2f5b6a451b5725118
F test/pragma.test 1e94755164a3a3264cd39836de4bebcb7809e5f8
F test/pragma2.test e5d5c176360c321344249354c0c16aec46214c9f
F test/pragma3.test 14c12bc5352b1e100e0b6b44f371053a81ccf8ed
F test/pragma4.test 6e85b6eab8e61ffc9c7db59d842276674e8e3264
F test/pragmafault.test 275edaf3161771d37de60e5c2b412627ac94cef11739236bec12ed1258b240f8
F test/printf.test b3ff34e73d59124140eaf89f7672e21bc2ca5fcc
F test/printf2.test 9e6db85f81c63f2367c34a9d7db384088bd374ad
F test/progress.test ebab27f670bd0d4eb9d20d49cef96e68141d92fb
@@ -1103,12 +1115,12 @@ F test/sharedA.test 0cdf1a76dfa00e6beee66af5b534b1e8df2720f5
F test/sharedB.test 16cc7178e20965d75278f410943109b77b2e645e
F test/shared_err.test 2f2aee20db294b9924e81f6ccbe60f19e21e8506
F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304
F test/shell1.test 52ac23a345772ab0d6d3241a21a633fdaa3ed581
F test/shell1.test 50226a3a66bbd42a902e9f7698f768927eb33a56e9cfc55b7c157c38eb3e80ac
F test/shell2.test e242a9912f44f4c23c3d1d802a83e934e84c853b
F test/shell3.test 9b95ba643eaa228376f06a898fb410ee9b6e57c1
F test/shell4.test 89ad573879a745974ff2df20ff97c5d6ffffbd5d
F test/shell5.test 50a732c1c2158b1cd62cf53975ce1ea7ce6b9dc9
F test/shell6.test cff624fadf71bdb5e3a9b0f86eaf59a43c0622b1
F test/shell6.test ab1592ebe881371f651f18ee6a0df21cbfb5310f88cb832ab642d4038f679772
F test/shell7.test 07751911b294698e0c5df67bcbd29e7d2f0f2907
F test/shortread1.test bb591ef20f0fd9ed26d0d12e80eee6d7ac8897a3
F test/show_speedtest1_rtree.tcl 32e6c5f073d7426148a6936a0408f4b5b169aba5
@@ -1156,6 +1168,7 @@ F test/subtype1.test 7fe09496352f97053af1437150751be2d0a0cae8
F test/superlock.test ec94f0556b6488d97f71c79f9061ae08d9ab8f12
F test/symlink.test c9ebe7330d228249e447038276bfc8a7b22f4849
F test/sync.test 2f84bdbc2b2df1fcb0220575b4b9f8cea94b7529
F test/sync2.test 6be8ed007fa063b147773c1982b5bdba97a32badc536bdc6077eff5cf8710ece
F test/syscall.test f59ba4e25f7ba4a4c031026cc2ef8b6e4b4c639c
F test/sysfault.test c9f2b0d8d677558f74de750c75e12a5454719d04
F test/tabfunc01.test 699251cb99651415218a891384510a685c7ab012
@@ -1170,7 +1183,7 @@ F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30
F test/temptable2.test cd396beb41117a5302fff61767c35fa4270a0d5e
F test/temptable3.test d11a0974e52b347e45ee54ef1923c91ed91e4637
F test/temptrigger.test 38f0ca479b1822d3117069e014daabcaacefffcc
F test/tester.tcl 67835ac17e90055f24a9cf52e5c5bce0dd511c74
F test/tester.tcl 581f0185434daf7026ccede4c07e8d1479186ec5
F test/thread001.test 9f22fd3525a307ff42a326b6bc7b0465be1745a5
F test/thread002.test e630504f8a06c00bf8bbe68528774dd96aeb2e58
F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7
@@ -1348,6 +1361,7 @@ F test/triggerC.test 302d8995f5ffe63bbc15053abb3ef7a39cf5a092
F test/triggerD.test 8e7f3921a92a5797d472732108109e44575fa650
F test/triggerE.test 15fa63f1097db1f83dd62d121616006978063d1f
F test/triggerF.test 55b1eb13433997faac3a4948c1d8252f6c8c636b
F test/triggerG.test 175cafdc6399d85231a09e82e051b0e45a2fd1f23dd08ae715bc359716149ab6
F test/tt3_checkpoint.c 9e75cf7c1c364f52e1c47fd0f14c4340a9db0fe1
F test/tt3_index.c 39eec10a35f57672225be4d182862152896dee4a
F test/tt3_lookaside1.c 0377e202c3c2a50d688cb65ba203afeda6fafeb9
@@ -1466,10 +1480,10 @@ F test/wordcount.c 06efb84b7c48a4973c2c24ea06c93d00bce24389
F test/zeroblob.test 3857870fe681b8185654414a9bccfde80b62a0fa
F test/zerodamage.test e59a56443d6298ecf7435f618f0b27654f0c849e
F tool/GetFile.cs a15e08acb5dd7539b75ba23501581d7c2b462cb5
F tool/GetTclKit.bat f94784e3bdc2f50c539266f5467cbf1f27612cb3
F tool/GetTclKit.bat 6afa640edc7810725aec61c3076ac617c4aaf0b7
F tool/Replace.cs 02c67258801c2fb5f63231e0ac0f220b4b36ba91
F tool/addopcodes.tcl 10c889c4a65ec6c5604e4a47306fa77ff57ae189
F tool/build-all-msvc.bat 018c1b273458a90c8ba633c6f0c5654cfcb138bf x
F tool/build-all-msvc.bat c12328d06c45fec8baada5949e3d5af54bf8c887 x
F tool/build-shell.sh 950f47c6174f1eea171319438b93ba67ff5bf367
F tool/cg_anno.tcl f95b0006c52cf7f0496b506343415b6ee3cdcdd3 x
F tool/checkSpacing.c 810e51703529a204fc4e1eb060e9ab663e3c06d2
@@ -1494,7 +1508,7 @@ F tool/mkmsvcmin.tcl 95b37e202cbed873aa8ffdbb493b9db45927be2b
F tool/mkopcodec.tcl d1b6362bd3aa80d5520d4d6f3765badf01f6c43c
F tool/mkopcodeh.tcl a01d2c1d8a6205b03fc635adf3735b4c523befd3
F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e
F tool/mkpragmatab.tcl b6ef1997fbc019015cb3f1b078c38b884d1ce4b6
F tool/mkpragmatab.tcl 32bb40741df11bddc8451de9ea4d130e7b4476d8064794b1cf402ac110840fba
F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97
F tool/mksqlite3c-noext.tcl fef88397668ae83166735c41af99d79f56afaabb
F tool/mksqlite3c.tcl 06b2e6a0f21cc0a5d70fbbd136b3e0a96470645e
@@ -1509,7 +1523,7 @@ F tool/replace.tcl 60f91e8dd06ab81f74d213ecbd9c9945f32ac048
F tool/restore_jrnl.tcl 6957a34f8f1f0f8285e07536225ec3b292a9024a
F tool/rollback-test.c 9fc98427d1e23e84429d7e6d07d9094fbdec65a5
F tool/run-speed-test.sh f95d19fd669b68c4c38b6b475242841d47c66076
F tool/showdb.c c695a5d5c8110640e0d9fadf5e254da90c79c36e
F tool/showdb.c e6bc9dba233bf1b57ca0a525a2bba762db4e223de84990739db3f09c46151b1e
F tool/showjournal.c 5bad7ae8784a43d2b270d953060423b8bd480818
F tool/showlocks.c 9920bcc64f58378ff1118caead34147201f48c68
F tool/showstat4.c b14159aa062f661b394ba37b6b7b94bfb8012ab9
@@ -1556,10 +1570,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P 1589db012ef1389bf84399fccf96d143b2ac4c0f
R 927fcfe986f9d231ee2a8f2fc2e00fd4
T *branch * vdbe_cycle_limit
T *sym-vdbe_cycle_limit *
P 48826b222c110a90996a84605318ea6b1e502b8c5129f4d561f8350dbdbcd264
R 33164644836f84aff2e4df2bff5189e1
T *branch * shell-fix
T *sym-shell-fix *
T -sym-trunk *
U drh
Z 42d28699ae4b43243cadb703ee72bd58
Z d4f7ac77bbed43ce1dcbcb86734fd32f
+1 -1
View File
@@ -1 +1 @@
9626b41e6ef70631cc1867315e409a2a92ce2a53
4c2b572969ea2ed2a925444ecfa356aa877018cbb9c4f57d081ab4b535cd1dd0
+47 -31
View File
@@ -290,6 +290,7 @@ struct Stat4Accum {
Stat4Sample *aBest; /* Array of nCol best samples */
int iMin; /* Index in a[] of entry with minimum score */
int nSample; /* Current number of samples */
int nMaxEqZero; /* Max leading 0 in anEq[] for any a[] entry */
int iGet; /* Index of current sample accessed by stat_get() */
Stat4Sample *a; /* Array of mxSample Stat4Sample objects */
sqlite3 *db; /* Database connection, for malloc() */
@@ -554,6 +555,13 @@ static void sampleInsert(Stat4Accum *p, Stat4Sample *pNew, int nEqZero){
assert( IsStat4 || nEqZero==0 );
#ifdef SQLITE_ENABLE_STAT4
/* Stat4Accum.nMaxEqZero is set to the maximum number of leading 0
** values in the anEq[] array of any sample in Stat4Accum.a[]. In
** other words, if nMaxEqZero is n, then it is guaranteed that there
** are no samples with Stat4Sample.anEq[m]==0 for (m>=n). */
if( nEqZero>p->nMaxEqZero ){
p->nMaxEqZero = nEqZero;
}
if( pNew->isPSample==0 ){
Stat4Sample *pUpgrade = 0;
assert( pNew->anEq[pNew->iCol]>0 );
@@ -651,12 +659,22 @@ static void samplePushPrevious(Stat4Accum *p, int iChng){
}
}
/* Update the anEq[] fields of any samples already collected. */
/* Check that no sample contains an anEq[] entry with an index of
** p->nMaxEqZero or greater set to zero. */
for(i=p->nSample-1; i>=0; i--){
int j;
for(j=iChng; j<p->nCol; j++){
if( p->a[i].anEq[j]==0 ) p->a[i].anEq[j] = p->current.anEq[j];
for(j=p->nMaxEqZero; j<p->nCol; j++) assert( p->a[i].anEq[j]>0 );
}
/* Update the anEq[] fields of any samples already collected. */
if( iChng<p->nMaxEqZero ){
for(i=p->nSample-1; i>=0; i--){
int j;
for(j=iChng; j<p->nCol; j++){
if( p->a[i].anEq[j]==0 ) p->a[i].anEq[j] = p->current.anEq[j];
}
}
p->nMaxEqZero = iChng;
}
#endif
@@ -1186,7 +1204,7 @@ static void analyzeOneTable(
regKey = sqlite3GetTempRange(pParse, pPk->nKeyCol);
for(j=0; j<pPk->nKeyCol; j++){
k = sqlite3ColumnOfIndex(pIdx, pPk->aiColumn[j]);
assert( k>=0 && k<pTab->nCol );
assert( k>=0 && k<pIdx->nColumn );
sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, k, regKey+j);
VdbeComment((v, "%s", pTab->aCol[pPk->aiColumn[j]].zName));
}
@@ -1370,27 +1388,14 @@ void sqlite3Analyze(Parse *pParse, Token *pName1, Token *pName2){
if( i==1 ) continue; /* Do not analyze the TEMP database */
analyzeDatabase(pParse, i);
}
}else if( pName2->n==0 ){
/* Form 2: Analyze the database or table named */
iDb = sqlite3FindDb(db, pName1);
if( iDb>=0 ){
analyzeDatabase(pParse, iDb);
}else{
z = sqlite3NameFromToken(db, pName1);
if( z ){
if( (pIdx = sqlite3FindIndex(db, z, 0))!=0 ){
analyzeTable(pParse, pIdx->pTable, pIdx);
}else if( (pTab = sqlite3LocateTable(pParse, 0, z, 0))!=0 ){
analyzeTable(pParse, pTab, 0);
}
sqlite3DbFree(db, z);
}
}
}else if( pName2->n==0 && (iDb = sqlite3FindDb(db, pName1))>=0 ){
/* Analyze the schema named as the argument */
analyzeDatabase(pParse, iDb);
}else{
/* Form 3: Analyze the fully qualified table name */
/* Form 3: Analyze the table or index named as an argument */
iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pTableName);
if( iDb>=0 ){
zDb = db->aDb[iDb].zDbSName;
zDb = pName2->n ? db->aDb[iDb].zDbSName : 0;
z = sqlite3NameFromToken(db, pTableName);
if( z ){
if( (pIdx = sqlite3FindIndex(db, z, zDb))!=0 ){
@@ -1400,10 +1405,11 @@ void sqlite3Analyze(Parse *pParse, Token *pName1, Token *pName2){
}
sqlite3DbFree(db, z);
}
}
}
}
if( db->nSqlExec==0 && (v = sqlite3GetVdbe(pParse))!=0 ){
sqlite3VdbeAddOp0(v, OP_Expire);
}
v = sqlite3GetVdbe(pParse);
if( v ) sqlite3VdbeAddOp0(v, OP_Expire);
}
/*
@@ -1532,7 +1538,11 @@ static int analysisLoader(void *pData, int argc, char **argv, char **NotUsed){
#endif
pIndex->bUnordered = 0;
decodeIntArray((char*)z, nCol, aiRowEst, pIndex->aiRowLogEst, pIndex);
if( pIndex->pPartIdxWhere==0 ) pTable->nRowLogEst = pIndex->aiRowLogEst[0];
pIndex->hasStat1 = 1;
if( pIndex->pPartIdxWhere==0 ){
pTable->nRowLogEst = pIndex->aiRowLogEst[0];
pTable->tabFlags |= TF_HasStat1;
}
}else{
Index fakeIdx;
fakeIdx.szIdxRow = pTable->szTabRow;
@@ -1541,6 +1551,7 @@ static int analysisLoader(void *pData, int argc, char **argv, char **NotUsed){
#endif
decodeIntArray((char*)z, 1, 0, &pTable->nRowLogEst, &fakeIdx);
pTable->szTabRow = fakeIdx.szIdxRow;
pTable->tabFlags |= TF_HasStat1;
}
return 0;
@@ -1835,15 +1846,20 @@ int sqlite3AnalysisLoad(sqlite3 *db, int iDb){
HashElem *i;
char *zSql;
int rc = SQLITE_OK;
Schema *pSchema = db->aDb[iDb].pSchema;
assert( iDb>=0 && iDb<db->nDb );
assert( db->aDb[iDb].pBt!=0 );
/* Clear any prior statistics */
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
for(i=sqliteHashFirst(&db->aDb[iDb].pSchema->idxHash);i;i=sqliteHashNext(i)){
for(i=sqliteHashFirst(&pSchema->tblHash); i; i=sqliteHashNext(i)){
Table *pTab = sqliteHashData(i);
pTab->tabFlags &= ~TF_HasStat1;
}
for(i=sqliteHashFirst(&pSchema->idxHash); i; i=sqliteHashNext(i)){
Index *pIdx = sqliteHashData(i);
pIdx->aiRowLogEst[0] = 0;
pIdx->hasStat1 = 0;
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
sqlite3DeleteIndexSamples(db, pIdx);
pIdx->aSample = 0;
@@ -1866,9 +1882,9 @@ int sqlite3AnalysisLoad(sqlite3 *db, int iDb){
/* Set appropriate defaults on all indexes not in the sqlite_stat1 table */
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
for(i=sqliteHashFirst(&db->aDb[iDb].pSchema->idxHash);i;i=sqliteHashNext(i)){
for(i=sqliteHashFirst(&pSchema->idxHash); i; i=sqliteHashNext(i)){
Index *pIdx = sqliteHashData(i);
if( pIdx->aiRowLogEst[0]==0 ) sqlite3DefaultRowEst(pIdx);
if( !pIdx->hasStat1 ) sqlite3DefaultRowEst(pIdx);
}
/* Load the statistics from the sqlite_stat4 table. */
@@ -1878,7 +1894,7 @@ int sqlite3AnalysisLoad(sqlite3 *db, int iDb){
rc = loadStat4(db, sInfo.zDatabase);
db->lookaside.bDisable--;
}
for(i=sqliteHashFirst(&db->aDb[iDb].pSchema->idxHash);i;i=sqliteHashNext(i)){
for(i=sqliteHashFirst(&pSchema->idxHash); i; i=sqliteHashNext(i)){
Index *pIdx = sqliteHashData(i);
sqlite3_free(pIdx->aiRowEst);
pIdx->aiRowEst = 0;
+161 -72
View File
@@ -499,6 +499,7 @@ static void invalidateAllOverflowCache(BtShared *pBt){
*/
static void invalidateIncrblobCursors(
Btree *pBtree, /* The database file to check */
Pgno pgnoRoot, /* The table that might be changing */
i64 iRow, /* The rowid that might be changing */
int isClearTable /* True if all rows are being deleted */
){
@@ -509,7 +510,7 @@ static void invalidateIncrblobCursors(
for(p=pBtree->pBt->pCursor; p; p=p->pNext){
if( (p->curFlags & BTCF_Incrblob)!=0 ){
pBtree->hasIncrblobCur = 1;
if( isClearTable || p->info.nKey==iRow ){
if( p->pgnoRoot==pgnoRoot && (isClearTable || p->info.nKey==iRow) ){
p->eState = CURSOR_INVALID;
}
}
@@ -518,7 +519,7 @@ static void invalidateIncrblobCursors(
#else
/* Stub function when INCRBLOB is omitted */
#define invalidateIncrblobCursors(x,y,z)
#define invalidateIncrblobCursors(w,x,y,z)
#endif /* SQLITE_OMIT_INCRBLOB */
/*
@@ -1317,17 +1318,18 @@ static void ptrmapPutOvflPtr(MemPage *pPage, u8 *pCell, int *pRC){
/*
** Defragment the page given. All Cells are moved to the
** end of the page and all free space is collected into one
** big FreeBlk that occurs in between the header and cell
** pointer array and the cell content area.
** Defragment the page given. This routine reorganizes cells within the
** page so that there are no free-blocks on the free-block list.
**
** Parameter nMaxFrag is the maximum amount of fragmented space that may be
** present in the page after this routine returns.
**
** EVIDENCE-OF: R-44582-60138 SQLite may from time to time reorganize a
** b-tree page so that there are no freeblocks or fragment bytes, all
** unused bytes are contained in the unallocated space region, and all
** cells are packed tightly at the end of the page.
*/
static int defragmentPage(MemPage *pPage){
static int defragmentPage(MemPage *pPage, int nMaxFrag){
int i; /* Loop counter */
int pc; /* Address of the i-th cell */
int hdr; /* Offset to the page header */
@@ -1342,7 +1344,6 @@ static int defragmentPage(MemPage *pPage){
int iCellFirst; /* First allowable cell index */
int iCellLast; /* Last possible cell index */
assert( sqlite3PagerIswriteable(pPage->pDbPage) );
assert( pPage->pBt!=0 );
assert( pPage->pBt->usableSize <= SQLITE_MAX_PAGE_SIZE );
@@ -1354,9 +1355,56 @@ static int defragmentPage(MemPage *pPage){
cellOffset = pPage->cellOffset;
nCell = pPage->nCell;
assert( nCell==get2byte(&data[hdr+3]) );
usableSize = pPage->pBt->usableSize;
cbrk = usableSize;
iCellFirst = cellOffset + 2*nCell;
usableSize = pPage->pBt->usableSize;
/* This block handles pages with two or fewer free blocks and nMaxFrag
** or fewer fragmented bytes. In this case it is faster to move the
** two (or one) blocks of cells using memmove() and add the required
** offsets to each pointer in the cell-pointer array than it is to
** reconstruct the entire page. */
if( (int)data[hdr+7]<=nMaxFrag ){
int iFree = get2byte(&data[hdr+1]);
if( iFree ){
int iFree2 = get2byte(&data[iFree]);
/* pageFindSlot() has already verified that free blocks are sorted
** in order of offset within the page, and that no block extends
** past the end of the page. Provided the two free slots do not
** overlap, this guarantees that the memmove() calls below will not
** overwrite the usableSize byte buffer, even if the database page
** is corrupt. */
assert( iFree2==0 || iFree2>iFree );
assert( iFree+get2byte(&data[iFree+2]) <= usableSize );
assert( iFree2==0 || iFree2+get2byte(&data[iFree2+2]) <= usableSize );
if( 0==iFree2 || (data[iFree2]==0 && data[iFree2+1]==0) ){
u8 *pEnd = &data[cellOffset + nCell*2];
u8 *pAddr;
int sz2 = 0;
int sz = get2byte(&data[iFree+2]);
int top = get2byte(&data[hdr+5]);
if( iFree2 ){
if( iFree+sz>iFree2 ) return SQLITE_CORRUPT_BKPT;
sz2 = get2byte(&data[iFree2+2]);
assert( iFree+sz+sz2+iFree2-(iFree+sz) <= usableSize );
memmove(&data[iFree+sz+sz2], &data[iFree+sz], iFree2-(iFree+sz));
sz += sz2;
}
cbrk = top+sz;
assert( cbrk+(iFree-top) <= usableSize );
memmove(&data[cbrk], &data[top], iFree-top);
for(pAddr=&data[cellOffset]; pAddr<pEnd; pAddr+=2){
pc = get2byte(pAddr);
if( pc<iFree ){ put2byte(pAddr, pc+sz); }
else if( pc<iFree2 ){ put2byte(pAddr, pc+sz2); }
}
goto defragment_out;
}
}
}
cbrk = usableSize;
iCellLast = usableSize - 4;
for(i=0; i<nCell; i++){
u8 *pAddr; /* The i-th cell pointer */
@@ -1390,16 +1438,18 @@ static int defragmentPage(MemPage *pPage){
}
memcpy(&data[cbrk], &src[pc], size);
}
data[hdr+7] = 0;
defragment_out:
if( data[hdr+7]+cbrk-iCellFirst!=pPage->nFree ){
return SQLITE_CORRUPT_BKPT;
}
assert( cbrk>=iCellFirst );
put2byte(&data[hdr+5], cbrk);
data[hdr+1] = 0;
data[hdr+2] = 0;
data[hdr+7] = 0;
memset(&data[iCellFirst], 0, cbrk-iCellFirst);
assert( sqlite3PagerIswriteable(pPage->pDbPage) );
if( cbrk-iCellFirst!=pPage->nFree ){
return SQLITE_CORRUPT_BKPT;
}
return SQLITE_OK;
}
@@ -1537,10 +1587,10 @@ static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){
testcase( gap+2+nByte==top );
if( gap+2+nByte>top ){
assert( pPage->nCell>0 || CORRUPT_DB );
rc = defragmentPage(pPage);
rc = defragmentPage(pPage, MIN(4, pPage->nFree - (2+nByte)));
if( rc ) return rc;
top = get2byteNotZero(&data[hdr+5]);
assert( gap+nByte<=top );
assert( gap+2+nByte<=top );
}
@@ -2812,6 +2862,31 @@ int sqlite3BtreeGetAutoVacuum(Btree *p){
#endif
}
/*
** If the user has not set the safety-level for this database connection
** using "PRAGMA synchronous", and if the safety-level is not already
** set to the value passed to this function as the second parameter,
** set it so.
*/
#if SQLITE_DEFAULT_SYNCHRONOUS!=SQLITE_DEFAULT_WAL_SYNCHRONOUS
static void setDefaultSyncFlag(BtShared *pBt, u8 safety_level){
sqlite3 *db;
Db *pDb;
if( (db=pBt->db)!=0 && (pDb=db->aDb)!=0 ){
while( pDb->pBt==0 || pDb->pBt->pBt!=pBt ){ pDb++; }
if( pDb->bSyncSet==0
&& pDb->safety_level!=safety_level
&& pDb!=&db->aDb[1]
){
pDb->safety_level = safety_level;
sqlite3PagerSetFlags(pBt->pPager,
pDb->safety_level | (db->flags & PAGER_FLAGS_MASK));
}
}
}
#else
# define setDefaultSyncFlag(pBt,safety_level)
#endif
/*
** Get a reference to pPage1 of the database file. This will
@@ -2885,26 +2960,15 @@ static int lockBtree(BtShared *pBt){
if( rc!=SQLITE_OK ){
goto page1_init_failed;
}else{
#if SQLITE_DEFAULT_SYNCHRONOUS!=SQLITE_DEFAULT_WAL_SYNCHRONOUS
sqlite3 *db;
Db *pDb;
if( (db=pBt->db)!=0 && (pDb=db->aDb)!=0 ){
while( pDb->pBt==0 || pDb->pBt->pBt!=pBt ){ pDb++; }
if( pDb->bSyncSet==0
&& pDb->safety_level==SQLITE_DEFAULT_SYNCHRONOUS+1
){
pDb->safety_level = SQLITE_DEFAULT_WAL_SYNCHRONOUS+1;
sqlite3PagerSetFlags(pBt->pPager,
pDb->safety_level | (db->flags & PAGER_FLAGS_MASK));
}
}
#endif
setDefaultSyncFlag(pBt, SQLITE_DEFAULT_WAL_SYNCHRONOUS+1);
if( isOpen==0 ){
releasePage(pPage1);
return SQLITE_OK;
}
}
rc = SQLITE_NOTADB;
}else{
setDefaultSyncFlag(pBt, SQLITE_DEFAULT_SYNCHRONOUS+1);
}
#endif
@@ -4253,7 +4317,7 @@ int sqlite3BtreeCloseCursor(BtCursor *pCur){
CellInfo info;
int iPage = pCur->iPage;
memset(&info, 0, sizeof(info));
btreeParseCell(pCur->apPage[iPage], pCur->aiIdx[iPage], &info);
btreeParseCell(pCur->apPage[iPage], pCur->ix, &info);
assert( CORRUPT_DB || memcmp(&info, &pCur->info, sizeof(info))==0 );
}
#else
@@ -4263,7 +4327,7 @@ static SQLITE_NOINLINE void getCellInfo(BtCursor *pCur){
if( pCur->info.nSize==0 ){
int iPage = pCur->iPage;
pCur->curFlags |= BTCF_ValidNKey;
btreeParseCell(pCur->apPage[iPage],pCur->aiIdx[iPage],&pCur->info);
btreeParseCell(pCur->apPage[iPage],pCur->ix,&pCur->info);
}else{
assertCellInfo(pCur);
}
@@ -4470,7 +4534,7 @@ static int accessPayload(
assert( pPage );
assert( eOp==0 || eOp==1 );
assert( pCur->eState==CURSOR_VALID );
assert( pCur->aiIdx[pCur->iPage]<pPage->nCell );
assert( pCur->ix<pPage->nCell );
assert( cursorHoldsMutex(pCur) );
getCellInfo(pCur);
@@ -4657,7 +4721,7 @@ int sqlite3BtreePayload(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){
assert( cursorHoldsMutex(pCur) );
assert( pCur->eState==CURSOR_VALID );
assert( pCur->iPage>=0 && pCur->apPage[pCur->iPage] );
assert( pCur->aiIdx[pCur->iPage]<pCur->apPage[pCur->iPage]->nCell );
assert( pCur->ix<pCur->apPage[pCur->iPage]->nCell );
return accessPayload(pCur, offset, amt, (unsigned char*)pBuf, 0);
}
@@ -4719,7 +4783,7 @@ static const void *fetchPayload(
assert( pCur->eState==CURSOR_VALID );
assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
assert( cursorOwnsBtShared(pCur) );
assert( pCur->aiIdx[pCur->iPage]<pCur->apPage[pCur->iPage]->nCell );
assert( pCur->ix<pCur->apPage[pCur->iPage]->nCell );
assert( pCur->info.nSize>0 );
assert( pCur->info.pPayload>pCur->apPage[pCur->iPage]->aData || CORRUPT_DB );
assert( pCur->info.pPayload<pCur->apPage[pCur->iPage]->aDataEnd ||CORRUPT_DB);
@@ -4770,8 +4834,8 @@ static int moveToChild(BtCursor *pCur, u32 newPgno){
}
pCur->info.nSize = 0;
pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
pCur->iPage++;
pCur->aiIdx[pCur->iPage] = 0;
pCur->aiIdx[pCur->iPage++] = pCur->ix;
pCur->ix = 0;
return getAndInitPage(pBt, newPgno, &pCur->apPage[pCur->iPage],
pCur, pCur->curPagerFlags);
}
@@ -4819,6 +4883,7 @@ static void moveToParent(BtCursor *pCur){
testcase( pCur->aiIdx[pCur->iPage-1] > pCur->apPage[pCur->iPage-1]->nCell );
pCur->info.nSize = 0;
pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
pCur->ix = pCur->aiIdx[pCur->iPage-1];
releasePageNotNull(pCur->apPage[pCur->iPage--]);
}
@@ -4900,7 +4965,7 @@ static int moveToRoot(BtCursor *pCur){
}
skip_init:
pCur->aiIdx[0] = 0;
pCur->ix = 0;
pCur->info.nSize = 0;
pCur->curFlags &= ~(BTCF_AtLast|BTCF_ValidNKey|BTCF_ValidOvfl);
@@ -4934,8 +4999,8 @@ static int moveToLeftmost(BtCursor *pCur){
assert( cursorOwnsBtShared(pCur) );
assert( pCur->eState==CURSOR_VALID );
while( rc==SQLITE_OK && !(pPage = pCur->apPage[pCur->iPage])->leaf ){
assert( pCur->aiIdx[pCur->iPage]<pPage->nCell );
pgno = get4byte(findCell(pPage, pCur->aiIdx[pCur->iPage]));
assert( pCur->ix<pPage->nCell );
pgno = get4byte(findCell(pPage, pCur->ix));
rc = moveToChild(pCur, pgno);
}
return rc;
@@ -4960,11 +5025,11 @@ static int moveToRightmost(BtCursor *pCur){
assert( pCur->eState==CURSOR_VALID );
while( !(pPage = pCur->apPage[pCur->iPage])->leaf ){
pgno = get4byte(&pPage->aData[pPage->hdrOffset+8]);
pCur->aiIdx[pCur->iPage] = pPage->nCell;
pCur->ix = pPage->nCell;
rc = moveToChild(pCur, pgno);
if( rc ) return rc;
}
pCur->aiIdx[pCur->iPage] = pPage->nCell-1;
pCur->ix = pPage->nCell-1;
assert( pCur->info.nSize==0 );
assert( (pCur->curFlags & BTCF_ValidNKey)==0 );
return SQLITE_OK;
@@ -5012,7 +5077,7 @@ int sqlite3BtreeLast(BtCursor *pCur, int *pRes){
for(ii=0; ii<pCur->iPage; ii++){
assert( pCur->aiIdx[ii]==pCur->apPage[ii]->nCell );
}
assert( pCur->aiIdx[pCur->iPage]==pCur->apPage[pCur->iPage]->nCell-1 );
assert( pCur->ix==pCur->apPage[pCur->iPage]->nCell-1 );
assert( pCur->apPage[pCur->iPage]->leaf );
#endif
return SQLITE_OK;
@@ -5159,7 +5224,7 @@ int sqlite3BtreeMovetoUnpacked(
upr = pPage->nCell-1;
assert( biasRight==0 || biasRight==1 );
idx = upr>>(1-biasRight); /* idx = biasRight ? upr : (lwr+upr)/2; */
pCur->aiIdx[pCur->iPage] = (u16)idx;
pCur->ix = (u16)idx;
if( xRecordCompare==0 ){
for(;;){
i64 nCellKey;
@@ -5178,7 +5243,7 @@ int sqlite3BtreeMovetoUnpacked(
if( lwr>upr ){ c = +1; break; }
}else{
assert( nCellKey==intKey );
pCur->aiIdx[pCur->iPage] = (u16)idx;
pCur->ix = (u16)idx;
if( !pPage->leaf ){
lwr = idx;
goto moveto_next_layer;
@@ -5247,7 +5312,7 @@ int sqlite3BtreeMovetoUnpacked(
rc = SQLITE_NOMEM_BKPT;
goto moveto_finish;
}
pCur->aiIdx[pCur->iPage] = (u16)idx;
pCur->ix = (u16)idx;
rc = accessPayload(pCur, 0, nCell, (unsigned char*)pCellKey, 0);
pCur->curFlags &= ~BTCF_ValidOvfl;
if( rc ){
@@ -5269,7 +5334,7 @@ int sqlite3BtreeMovetoUnpacked(
assert( c==0 );
*pRes = 0;
rc = SQLITE_OK;
pCur->aiIdx[pCur->iPage] = (u16)idx;
pCur->ix = (u16)idx;
if( pIdxKey->errCode ) rc = SQLITE_CORRUPT;
goto moveto_finish;
}
@@ -5281,8 +5346,8 @@ int sqlite3BtreeMovetoUnpacked(
assert( lwr==upr+1 || (pPage->intKey && !pPage->leaf) );
assert( pPage->isInit );
if( pPage->leaf ){
assert( pCur->aiIdx[pCur->iPage]<pCur->apPage[pCur->iPage]->nCell );
pCur->aiIdx[pCur->iPage] = (u16)idx;
assert( pCur->ix<pCur->apPage[pCur->iPage]->nCell );
pCur->ix = (u16)idx;
*pRes = c;
rc = SQLITE_OK;
goto moveto_finish;
@@ -5293,7 +5358,7 @@ moveto_next_layer:
}else{
chldPg = get4byte(findCell(pPage, lwr));
}
pCur->aiIdx[pCur->iPage] = (u16)lwr;
pCur->ix = (u16)lwr;
rc = moveToChild(pCur, chldPg);
if( rc ) break;
}
@@ -5319,6 +5384,30 @@ int sqlite3BtreeEof(BtCursor *pCur){
return (CURSOR_VALID!=pCur->eState);
}
/*
** Return an estimate for the number of rows in the table that pCur is
** pointing to. Return a negative number if no estimate is currently
** available.
*/
i64 sqlite3BtreeRowCountEst(BtCursor *pCur){
i64 n;
u8 i;
assert( cursorOwnsBtShared(pCur) );
assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
/* Currently this interface is only called by the OP_IfSmaller
** opcode, and it that case the cursor will always be valid and
** will always point to a leaf node. */
if( NEVER(pCur->eState!=CURSOR_VALID) ) return -1;
if( NEVER(pCur->apPage[pCur->iPage]->leaf==0) ) return -1;
for(n=1, i=0; i<=pCur->iPage; i++){
n *= pCur->apPage[i]->nCell;
}
return n;
}
/*
** Advance the cursor to the next entry in the database. If
** successful then set *pRes=0. If the cursor
@@ -5370,7 +5459,7 @@ static SQLITE_NOINLINE int btreeNext(BtCursor *pCur, int *pRes){
}
pPage = pCur->apPage[pCur->iPage];
idx = ++pCur->aiIdx[pCur->iPage];
idx = ++pCur->ix;
assert( pPage->isInit );
/* If the database file is corrupt, it is possible for the value of idx
@@ -5394,7 +5483,7 @@ static SQLITE_NOINLINE int btreeNext(BtCursor *pCur, int *pRes){
}
moveToParent(pCur);
pPage = pCur->apPage[pCur->iPage];
}while( pCur->aiIdx[pCur->iPage]>=pPage->nCell );
}while( pCur->ix>=pPage->nCell );
if( pPage->intKey ){
return sqlite3BtreeNext(pCur, pRes);
}else{
@@ -5418,8 +5507,8 @@ int sqlite3BtreeNext(BtCursor *pCur, int *pRes){
*pRes = 0;
if( pCur->eState!=CURSOR_VALID ) return btreeNext(pCur, pRes);
pPage = pCur->apPage[pCur->iPage];
if( (++pCur->aiIdx[pCur->iPage])>=pPage->nCell ){
pCur->aiIdx[pCur->iPage]--;
if( (++pCur->ix)>=pPage->nCell ){
pCur->ix--;
return btreeNext(pCur, pRes);
}
if( pPage->leaf ){
@@ -5483,12 +5572,12 @@ static SQLITE_NOINLINE int btreePrevious(BtCursor *pCur, int *pRes){
pPage = pCur->apPage[pCur->iPage];
assert( pPage->isInit );
if( !pPage->leaf ){
int idx = pCur->aiIdx[pCur->iPage];
int idx = pCur->ix;
rc = moveToChild(pCur, get4byte(findCell(pPage, idx)));
if( rc ) return rc;
rc = moveToRightmost(pCur);
}else{
while( pCur->aiIdx[pCur->iPage]==0 ){
while( pCur->ix==0 ){
if( pCur->iPage==0 ){
pCur->eState = CURSOR_INVALID;
*pRes = 1;
@@ -5499,7 +5588,7 @@ static SQLITE_NOINLINE int btreePrevious(BtCursor *pCur, int *pRes){
assert( pCur->info.nSize==0 );
assert( (pCur->curFlags & (BTCF_ValidOvfl))==0 );
pCur->aiIdx[pCur->iPage]--;
pCur->ix--;
pPage = pCur->apPage[pCur->iPage];
if( pPage->intKey && !pPage->leaf ){
rc = sqlite3BtreePrevious(pCur, pRes);
@@ -5518,12 +5607,12 @@ int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){
pCur->curFlags &= ~(BTCF_AtLast|BTCF_ValidOvfl|BTCF_ValidNKey);
pCur->info.nSize = 0;
if( pCur->eState!=CURSOR_VALID
|| pCur->aiIdx[pCur->iPage]==0
|| pCur->ix==0
|| pCur->apPage[pCur->iPage]->leaf==0
){
return btreePrevious(pCur, pRes);
}
pCur->aiIdx[pCur->iPage]--;
pCur->ix--;
return SQLITE_OK;
}
@@ -7689,7 +7778,7 @@ static int balance_nonroot(
** free space needs to be up front.
*/
assert( nNew==1 || CORRUPT_DB );
rc = defragmentPage(apNew[0]);
rc = defragmentPage(apNew[0], -1);
testcase( rc!=SQLITE_OK );
assert( apNew[0]->nFree ==
(get2byte(&apNew[0]->aData[5])-apNew[0]->cellOffset-apNew[0]->nCell*2)
@@ -7845,8 +7934,8 @@ static int balance(BtCursor *pCur){
rc = balance_deeper(pPage, &pCur->apPage[1]);
if( rc==SQLITE_OK ){
pCur->iPage = 1;
pCur->ix = 0;
pCur->aiIdx[0] = 0;
pCur->aiIdx[1] = 0;
assert( pCur->apPage[1]->nOverflow );
}
}else{
@@ -8023,7 +8112,7 @@ int sqlite3BtreeInsert(
assert( pX->pKey==0 );
/* If this is an insert into a table b-tree, invalidate any incrblob
** cursors open on the row being replaced */
invalidateIncrblobCursors(p, pX->nKey, 0);
invalidateIncrblobCursors(p, pCur->pgnoRoot, pX->nKey, 0);
/* If BTREE_SAVEPOSITION is set, the cursor must already be pointing
** to a row with the same key as the new entry being inserted. */
@@ -8075,7 +8164,7 @@ int sqlite3BtreeInsert(
if( rc ) goto end_insert;
assert( szNew==pPage->xCellSize(pPage, newCell) );
assert( szNew <= MX_CELL_SIZE(pBt) );
idx = pCur->aiIdx[pCur->iPage];
idx = pCur->ix;
if( loc==0 ){
CellInfo info;
assert( idx<pPage->nCell );
@@ -8103,7 +8192,7 @@ int sqlite3BtreeInsert(
if( rc ) goto end_insert;
}else if( loc<0 && pPage->nCell>0 ){
assert( pPage->leaf );
idx = ++pCur->aiIdx[pCur->iPage];
idx = ++pCur->ix;
}else{
assert( pPage->leaf );
}
@@ -8199,12 +8288,12 @@ int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){
assert( pCur->curFlags & BTCF_WriteFlag );
assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) );
assert( !hasReadConflicts(p, pCur->pgnoRoot) );
assert( pCur->aiIdx[pCur->iPage]<pCur->apPage[pCur->iPage]->nCell );
assert( pCur->ix<pCur->apPage[pCur->iPage]->nCell );
assert( pCur->eState==CURSOR_VALID );
assert( (flags & ~(BTREE_SAVEPOSITION | BTREE_AUXDELETE))==0 );
iCellDepth = pCur->iPage;
iCellIdx = pCur->aiIdx[iCellDepth];
iCellIdx = pCur->ix;
pPage = pCur->apPage[iCellDepth];
pCell = findCell(pPage, iCellIdx);
@@ -8253,7 +8342,7 @@ int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){
/* If this is a delete operation to remove a row from a table b-tree,
** invalidate any incrblob cursors open on the row being deleted. */
if( pCur->pKeyInfo==0 ){
invalidateIncrblobCursors(p, pCur->info.nKey, 0);
invalidateIncrblobCursors(p, pCur->pgnoRoot, pCur->info.nKey, 0);
}
/* Make the page containing the entry to be deleted writable. Then free any
@@ -8321,7 +8410,7 @@ int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){
pCur->eState = CURSOR_SKIPNEXT;
if( iCellIdx>=pPage->nCell ){
pCur->skipNext = -1;
pCur->aiIdx[iCellDepth] = pPage->nCell-1;
pCur->ix = pPage->nCell-1;
}else{
pCur->skipNext = 1;
}
@@ -8580,7 +8669,7 @@ int sqlite3BtreeClearTable(Btree *p, int iTable, int *pnChange){
/* Invalidate all incrblob cursors open on table iTable (assuming iTable
** is the root of a table b-tree - if it is not, the following call is
** a no-op). */
invalidateIncrblobCursors(p, 0, 1);
invalidateIncrblobCursors(p, (Pgno)iTable, 0, 1);
rc = clearDatabasePage(pBt, (Pgno)iTable, 0, pnChange);
}
sqlite3BtreeLeave(p);
@@ -8834,16 +8923,16 @@ int sqlite3BtreeCount(BtCursor *pCur, i64 *pnEntry){
return moveToRoot(pCur);
}
moveToParent(pCur);
}while ( pCur->aiIdx[pCur->iPage]>=pCur->apPage[pCur->iPage]->nCell );
}while ( pCur->ix>=pCur->apPage[pCur->iPage]->nCell );
pCur->aiIdx[pCur->iPage]++;
pCur->ix++;
pPage = pCur->apPage[pCur->iPage];
}
/* Descend to the child node of the cell that the cursor currently
** points at. This is the right-child if (iIdx==pPage->nCell).
*/
iIdx = pCur->aiIdx[pCur->iPage];
iIdx = pCur->ix;
if( iIdx==pPage->nCell ){
rc = moveToChild(pCur, get4byte(&pPage->aData[pPage->hdrOffset+8]));
}else{
+1
View File
@@ -296,6 +296,7 @@ u32 sqlite3BtreePayloadSize(BtCursor*);
char *sqlite3BtreeIntegrityCheck(Btree*, int *aRoot, int nRoot, int, int*);
struct Pager *sqlite3BtreePager(Btree*);
i64 sqlite3BtreeRowCountEst(BtCursor*);
#ifndef SQLITE_OMIT_INCRBLOB
int sqlite3BtreePayloadChecked(BtCursor*, u32 offset, u32 amt, void*);
+4 -4
View File
@@ -517,10 +517,10 @@ struct BtCursor {
** initialized. */
i8 iPage; /* Index of current page in apPage */
u8 curIntKey; /* Value of apPage[0]->intKey */
struct KeyInfo *pKeyInfo; /* Argument passed to comparison function */
void *padding1; /* Make object size a multiple of 16 */
u16 aiIdx[BTCURSOR_MAX_DEPTH]; /* Current index in apPage[i] */
MemPage *apPage[BTCURSOR_MAX_DEPTH]; /* Pages from root to current page */
u16 ix; /* Current index for apPage[iPage] */
u16 aiIdx[BTCURSOR_MAX_DEPTH-1]; /* Current index in apPage[i] */
struct KeyInfo *pKeyInfo; /* Arg passed to comparison function */
MemPage *apPage[BTCURSOR_MAX_DEPTH]; /* Pages from root to current page */
};
/*
+6 -2
View File
@@ -1115,6 +1115,7 @@ void sqlite3AddNotNull(Parse *pParse, int onError){
p = pParse->pNewTable;
if( p==0 || NEVER(p->nCol<1) ) return;
p->aCol[p->nCol-1].notNull = (u8)onError;
p->tabFlags |= TF_HasNotNull;
}
/*
@@ -3454,6 +3455,9 @@ void sqlite3DefaultRowEst(Index *pIdx){
int nCopy = MIN(ArraySize(aVal), pIdx->nKeyCol);
int i;
/* Indexes with default row estimates should not have stat1 data */
assert( !pIdx->hasStat1 );
/* Set the first entry (number of rows in the index) to the estimated
** number of rows in the table, or half the number of rows in the table
** for a partial index. But do not let the estimate drop below 10. */
@@ -3619,7 +3623,7 @@ void sqlite3IdListDelete(sqlite3 *db, IdList *pList){
sqlite3DbFree(db, pList->a[i].zName);
}
sqlite3DbFree(db, pList->a);
sqlite3DbFree(db, pList);
sqlite3DbFreeNN(db, pList);
}
/*
@@ -3809,7 +3813,7 @@ void sqlite3SrcListDelete(sqlite3 *db, SrcList *pList){
sqlite3ExprDelete(db, pItem->pOn);
sqlite3IdListDelete(db, pItem->pUsing);
}
sqlite3DbFree(db, pList);
sqlite3DbFreeNN(db, pList);
}
/*
+6
View File
@@ -66,6 +66,12 @@ static const char * const azCompileOpt[] = {
#if defined(SQLITE_DEFAULT_MMAP_SIZE) && !defined(SQLITE_DEFAULT_MMAP_SIZE_xc)
"DEFAULT_MMAP_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_MMAP_SIZE),
#endif
#if SQLITE_DEFAULT_SYNCHRONOUS
"DEFAULT_SYNCHRONOUS=" CTIMEOPT_VAL(SQLITE_DEFAULT_SYNCHRONOUS),
#endif
#if SQLITE_DEFAULT_WAL_SYNCHRONOUS
"DEFAULT_WAL_SYNCHRONOUS=" CTIMEOPT_VAL(SQLITE_DEFAULT_WAL_SYNCHRONOUS),
#endif
#if SQLITE_DIRECT_OVERFLOW_READ
"DIRECT_OVERFLOW_READ",
#endif
+2 -1
View File
@@ -743,18 +743,19 @@ static int parseModifier(
** or month or year.
*/
if( sqlite3_strnicmp(z, "start of ", 9)!=0 ) break;
if( !p->validJD && !p->validYMD && !p->validHMS ) break;
z += 9;
computeYMD(p);
p->validHMS = 1;
p->h = p->m = 0;
p->s = 0.0;
p->rawS = 0;
p->validTZ = 0;
p->validJD = 0;
if( sqlite3_stricmp(z,"month")==0 ){
p->D = 1;
rc = 0;
}else if( sqlite3_stricmp(z,"year")==0 ){
computeYMD(p);
p->M = 1;
p->D = 1;
rc = 0;
+37 -44
View File
@@ -1038,7 +1038,7 @@ static SQLITE_NOINLINE void sqlite3ExprDeleteNN(sqlite3 *db, Expr *p){
}
if( ExprHasProperty(p, EP_MemToken) ) sqlite3DbFree(db, p->u.zToken);
if( !ExprHasProperty(p, EP_Static) ){
sqlite3DbFree(db, p);
sqlite3DbFreeNN(db, p);
}
}
void sqlite3ExprDelete(sqlite3 *db, Expr *p){
@@ -1305,15 +1305,11 @@ ExprList *sqlite3ExprListDup(sqlite3 *db, ExprList *p, int flags){
Expr *pPriorSelectCol = 0;
assert( db!=0 );
if( p==0 ) return 0;
pNew = sqlite3DbMallocRawNN(db, sizeof(*pNew) );
pNew = sqlite3DbMallocRawNN(db,
sizeof(*pNew)+sizeof(pNew->a[0])*(p->nExpr-1) );
if( pNew==0 ) return 0;
pNew->nExpr = i = p->nExpr;
if( (flags & EXPRDUP_REDUCE)==0 ) for(i=1; i<p->nExpr; i+=i){}
pNew->a = pItem = sqlite3DbMallocRawNN(db, i*sizeof(p->a[0]) );
if( pItem==0 ){
sqlite3DbFree(db, pNew);
return 0;
}
pNew->nAlloc = pNew->nExpr = p->nExpr;
pItem = pNew->a;
pOldItem = p->a;
for(i=0; i<p->nExpr; i++, pItem++, pOldItem++){
Expr *pOldExpr = pOldItem->pExpr;
@@ -1404,7 +1400,7 @@ IdList *sqlite3IdListDup(sqlite3 *db, IdList *p){
pNew->nId = p->nId;
pNew->a = sqlite3DbMallocRawNN(db, p->nId*sizeof(p->a[0]) );
if( pNew->a==0 ){
sqlite3DbFree(db, pNew);
sqlite3DbFreeNN(db, pNew);
return 0;
}
/* Note that because the size of the allocation for p->a[] is not
@@ -1475,6 +1471,7 @@ ExprList *sqlite3ExprListAppend(
ExprList *pList, /* List to which to append. Might be NULL */
Expr *pExpr /* Expression to be appended. Might be NULL */
){
struct ExprList_item *pItem;
sqlite3 *db = pParse->db;
assert( db!=0 );
if( pList==0 ){
@@ -1483,23 +1480,20 @@ ExprList *sqlite3ExprListAppend(
goto no_mem;
}
pList->nExpr = 0;
pList->a = sqlite3DbMallocRawNN(db, sizeof(pList->a[0]));
if( pList->a==0 ) goto no_mem;
}else if( (pList->nExpr & (pList->nExpr-1))==0 ){
struct ExprList_item *a;
assert( pList->nExpr>0 );
a = sqlite3DbRealloc(db, pList->a, pList->nExpr*2*sizeof(pList->a[0]));
if( a==0 ){
pList->nAlloc = 1;
}else if( pList->nExpr==pList->nAlloc ){
ExprList *pNew;
pNew = sqlite3DbRealloc(db, pList,
sizeof(*pList)+(2*pList->nAlloc - 1)*sizeof(pList->a[0]));
if( pNew==0 ){
goto no_mem;
}
pList->a = a;
}
assert( pList->a!=0 );
if( 1 ){
struct ExprList_item *pItem = &pList->a[pList->nExpr++];
memset(pItem, 0, sizeof(*pItem));
pItem->pExpr = pExpr;
pList = pNew;
pList->nAlloc *= 2;
}
pItem = &pList->a[pList->nExpr++];
memset(pItem, 0, sizeof(*pItem));
pItem->pExpr = pExpr;
return pList;
no_mem:
@@ -1556,20 +1550,19 @@ ExprList *sqlite3ExprListAppendVector(
}
}
if( pExpr->op==TK_SELECT ){
if( pList && pList->a[iFirst].pExpr ){
Expr *pFirst = pList->a[iFirst].pExpr;
assert( pFirst->op==TK_SELECT_COLUMN );
if( pExpr->op==TK_SELECT && pList ){
Expr *pFirst = pList->a[iFirst].pExpr;
assert( pFirst!=0 );
assert( pFirst->op==TK_SELECT_COLUMN );
/* Store the SELECT statement in pRight so it will be deleted when
** sqlite3ExprListDelete() is called */
pFirst->pRight = pExpr;
pExpr = 0;
/* Store the SELECT statement in pRight so it will be deleted when
** sqlite3ExprListDelete() is called */
pFirst->pRight = pExpr;
pExpr = 0;
/* Remember the size of the LHS in iTable so that we can check that
** the RHS and LHS sizes match during code generation. */
pFirst->iTable = pColumns->nId;
}
/* Remember the size of the LHS in iTable so that we can check that
** the RHS and LHS sizes match during code generation. */
pFirst->iTable = pColumns->nId;
}
vector_append_error:
@@ -1663,16 +1656,16 @@ void sqlite3ExprListCheckLength(
** Delete an entire expression list.
*/
static SQLITE_NOINLINE void exprListDeleteNN(sqlite3 *db, ExprList *pList){
int i;
struct ExprList_item *pItem;
assert( pList->a!=0 || pList->nExpr==0 );
for(pItem=pList->a, i=0; i<pList->nExpr; i++, pItem++){
int i = pList->nExpr;
struct ExprList_item *pItem = pList->a;
assert( pList->nExpr>0 );
do{
sqlite3ExprDelete(db, pItem->pExpr);
sqlite3DbFree(db, pItem->zName);
sqlite3DbFree(db, pItem->zSpan);
}
sqlite3DbFree(db, pList->a);
sqlite3DbFree(db, pList);
pItem++;
}while( --i>0 );
sqlite3DbFreeNN(db, pList);
}
void sqlite3ExprListDelete(sqlite3 *db, ExprList *pList){
if( pList ) exprListDeleteNN(db, pList);
@@ -1860,6 +1853,7 @@ int sqlite3ExprContainsSubquery(Expr *p){
*/
int sqlite3ExprIsInteger(Expr *p, int *pValue){
int rc = 0;
if( p==0 ) return 0; /* Can only happen following on OOM */
/* If an expression is an integer literal that fits in a signed 32-bit
** integer, then the EP_IntValue flag will have already been set */
@@ -2532,7 +2526,6 @@ int sqlite3CodeSubselect(
int i;
sqlite3SelectDestInit(&dest, SRT_Set, pExpr->iTable);
dest.zAffSdst = exprINAffinity(pParse, pExpr);
assert( (pExpr->iTable&0x0000FFFF)==pExpr->iTable );
pSelect->iLimit = 0;
testcase( pSelect->selFlags & SF_Distinct );
testcase( pKeyInfo==0 ); /* Caused by OOM in sqlite3KeyInfoAlloc() */
+1 -3
View File
@@ -204,15 +204,13 @@ static void instrFunc(
if( typeHaystack==SQLITE_BLOB && typeNeedle==SQLITE_BLOB ){
zHaystack = sqlite3_value_blob(argv[0]);
zNeedle = sqlite3_value_blob(argv[1]);
assert( zNeedle!=0 );
assert( zHaystack!=0 || nHaystack==0 );
isText = 0;
}else{
zHaystack = sqlite3_value_text(argv[0]);
zNeedle = sqlite3_value_text(argv[1]);
isText = 1;
if( zHaystack==0 || zNeedle==0 ) return;
}
if( zNeedle==0 || (nHaystack && zHaystack==0) ) return;
while( nNeedle<=nHaystack && memcmp(zHaystack, zNeedle, nNeedle)!=0 ){
N++;
do{
-2
View File
@@ -2227,8 +2227,6 @@ static int xferOptimization(
** sorted order. */
for(i=0; i<pSrcIdx->nColumn; i++){
const char *zColl = pSrcIdx->azColl[i];
assert( sqlite3_stricmp(sqlite3StrBINARY, zColl)!=0
|| sqlite3StrBINARY==zColl );
if( sqlite3_stricmp(sqlite3StrBINARY, zColl) ) break;
}
if( i==pSrcIdx->nColumn ){
+3 -1
View File
@@ -421,7 +421,9 @@ static const sqlite3_api_routines sqlite3Apis = {
sqlite3_system_errno,
/* Version 3.14.0 and later */
sqlite3_trace_v2,
sqlite3_expanded_sql
sqlite3_expanded_sql,
/* Version 3.18.0 and later */
sqlite3_set_last_insert_rowid
};
/*
+15
View File
@@ -921,6 +921,21 @@ sqlite_int64 sqlite3_last_insert_rowid(sqlite3 *db){
return db->lastRowid;
}
/*
** Set the value returned by the sqlite3_last_insert_rowid() API function.
*/
void sqlite3_set_last_insert_rowid(sqlite3 *db, sqlite3_int64 iRowid){
#ifdef SQLITE_ENABLE_API_ARMOR
if( !sqlite3SafetyCheckOk(db) ){
(void)SQLITE_MISUSE_BKPT;
return;
}
#endif
sqlite3_mutex_enter(db->mutex);
db->lastRowid = iRowid;
sqlite3_mutex_leave(db->mutex);
}
/*
** Return the number of changes in the most recent call to sqlite3_exec().
*/
+15 -3
View File
@@ -230,6 +230,13 @@ static void mallocWithAlarm(int n, void **pp){
** following xRoundup() call. */
nFull = sqlite3GlobalConfig.m.xRoundup(n);
#ifdef SQLITE_MAX_MEMORY
if( sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED)+nFull>SQLITE_MAX_MEMORY ){
*pp = 0;
return;
}
#endif
sqlite3StatusHighwater(SQLITE_STATUS_MALLOC_SIZE, n);
if( mem0.alarmThreshold>0 ){
sqlite3_int64 nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED);
@@ -467,11 +474,12 @@ static SQLITE_NOINLINE void measureAllocationSize(sqlite3 *db, void *p){
/*
** Free memory that might be associated with a particular database
** connection.
** connection. Calling sqlite3DbFree(D,X) for X==0 is a harmless no-op.
** The sqlite3DbFreeNN(D,X) version requires that X be non-NULL.
*/
void sqlite3DbFree(sqlite3 *db, void *p){
void sqlite3DbFreeNN(sqlite3 *db, void *p){
assert( db==0 || sqlite3_mutex_held(db->mutex) );
if( p==0 ) return;
assert( p!=0 );
if( db ){
if( db->pnBytesFreed ){
measureAllocationSize(db, p);
@@ -495,6 +503,10 @@ void sqlite3DbFree(sqlite3 *db, void *p){
sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
sqlite3_free(p);
}
void sqlite3DbFree(sqlite3 *db, void *p){
assert( db==0 || sqlite3_mutex_held(db->mutex) );
if( p ) sqlite3DbFreeNN(db, p);
}
/*
** Change the size of an existing memory allocation
+5 -12
View File
@@ -57,7 +57,9 @@
*/
#include <sys/sysctl.h>
#include <malloc/malloc.h>
#ifdef SQLITE_MIGHT_BE_SINGLE_CORE
#include <libkern/OSAtomic.h>
#endif /* SQLITE_MIGHT_BE_SINGLE_CORE */
static malloc_zone_t* _sqliteZone_;
#define SQLITE_MALLOC(x) malloc_zone_malloc(_sqliteZone_, (x))
#define SQLITE_FREE(x) malloc_zone_free(_sqliteZone_, (x));
@@ -250,19 +252,10 @@ static int sqlite3MemInit(void *NotUsed){
}else{
/* only 1 core, use our own zone to contention over global locks,
** e.g. we have our own dedicated locks */
bool success;
malloc_zone_t* newzone = malloc_create_zone(4096, 0);
malloc_set_zone_name(newzone, "Sqlite_Heap");
do{
success = OSAtomicCompareAndSwapPtrBarrier(NULL, newzone,
(void * volatile *)&_sqliteZone_);
}while(!_sqliteZone_);
if( !success ){
/* somebody registered a zone first */
malloc_destroy_zone(newzone);
}
_sqliteZone_ = malloc_create_zone(4096, 0);
malloc_set_zone_name(_sqliteZone_, "Sqlite_Heap");
}
#endif
#endif /* defined(__APPLE__) && !defined(SQLITE_WITHOUT_ZONEMALLOC) */
UNUSED_PARAMETER(NotUsed);
return SQLITE_OK;
}
+1 -1
View File
@@ -899,7 +899,7 @@ term(A) ::= INTEGER(X). {
A.pExpr = sqlite3ExprAlloc(pParse->db, TK_INTEGER, &X, 1);
A.zStart = X.z;
A.zEnd = X.z + X.n;
if( A.pExpr ) A.pExpr->flags |= EP_Leaf;
if( A.pExpr ) A.pExpr->flags |= EP_Leaf|EP_Resolved;
}
expr(A) ::= VARIABLE(X). {
if( !(X.z[0]=='#' && sqlite3Isdigit(X.z[1])) ){
+3 -4
View File
@@ -285,8 +285,7 @@ static int pcache1InitBulk(PCache1 *pCache){
sqlite3EndBenignMalloc();
if( zBulk ){
int nBulk = sqlite3MallocSize(zBulk)/pCache->szAlloc;
int i;
for(i=0; i<nBulk; i++){
do{
PgHdr1 *pX = (PgHdr1*)&zBulk[pCache->szPage];
pX->page.pBuf = zBulk;
pX->page.pExtra = &pX[1];
@@ -295,7 +294,7 @@ static int pcache1InitBulk(PCache1 *pCache){
pX->pNext = pCache->pFree;
pCache->pFree = pX;
zBulk += pCache->szAlloc;
}
}while( --nBulk );
}
return pCache->pFree!=0;
}
@@ -1211,7 +1210,7 @@ int sqlite3PcacheReleaseMemory(int nReq){
int nFree = 0;
assert( sqlite3_mutex_notheld(pcache1.grp.mutex) );
assert( sqlite3_mutex_notheld(pcache1.mutex) );
if( sqlite3GlobalConfig.nPage==0 ){
if( sqlite3GlobalConfig.pPage==0 ){
PgHdr1 *p;
pcache1EnterMutex(&pcache1.grp);
while( (nReq<0 || nFree<nReq)
+199 -70
View File
@@ -296,11 +296,19 @@ static const PragmaName *pragmaLocate(const char *zName){
}
/*
** A progress handler callback that interrupts.
** Helper subroutine for PRAGMA integrity_check:
**
** Generate code to output a single-column result row with the result
** held in register regResult. Decrement the result count and halt if
** the maximum number of result rows have been issued.
*/
static int interruptProgressHandler(void *pDb){
sqlite3_interrupt((sqlite3*)pDb);
return 1;
static int integrityCheckResultRow(Vdbe *v, int regResult){
int addr;
sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, 1);
addr = sqlite3VdbeAddOp3(v, OP_IfPos, 1, sqlite3VdbeCurrentAddr(v)+2, 1);
VdbeCoverage(v);
sqlite3VdbeAddOp2(v, OP_Halt, 0, 0);
return addr;
}
/*
@@ -744,23 +752,6 @@ void sqlite3Pragma(
}
#endif
/*
** PRAGMA vdbe_cycle_limit=N
**
** Arrange to interrupt any SQL statement that runs for more than N
** virtual machine instructions. If N is zero, allow virtual machines
** to run indefinitely.
*/
case PragTyp_VDBE_CYCLE_LIMIT: {
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
if( zRight ){
int N = sqlite3Atoi(zRight);
sqlite3_progress_handler(db, N, N>0 ? interruptProgressHandler : 0, db);
}
break;
}
#ifndef SQLITE_OMIT_PAGER_PRAGMAS
/*
** PRAGMA [schema.]cache_size
@@ -1024,7 +1015,7 @@ void sqlite3Pragma(
if( !db->autoCommit ){
sqlite3ErrorMsg(pParse,
"Safety level may not be changed inside a transaction");
}else{
}else if( iDb!=1 ){
int iLevel = (getSafetyLevel(zRight,0,1)+1) & PAGER_SYNCHRONOUS_MASK;
if( iLevel==0 ) iLevel = 1;
pDb->safety_level = iLevel;
@@ -1123,29 +1114,33 @@ void sqlite3Pragma(
}
break;
#ifdef SQLITE_DEBUG
case PragTyp_STATS: {
Index *pIdx;
HashElem *i;
pParse->nMem = 4;
pParse->nMem = 5;
sqlite3CodeVerifySchema(pParse, iDb);
for(i=sqliteHashFirst(&pDb->pSchema->tblHash); i; i=sqliteHashNext(i)){
Table *pTab = sqliteHashData(i);
sqlite3VdbeMultiLoad(v, 1, "ssii",
sqlite3VdbeMultiLoad(v, 1, "ssiii",
pTab->zName,
0,
pTab->szTabRow,
pTab->nRowLogEst);
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 4);
pTab->nRowLogEst,
pTab->tabFlags);
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 5);
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
sqlite3VdbeMultiLoad(v, 2, "sii",
sqlite3VdbeMultiLoad(v, 2, "siii",
pIdx->zName,
pIdx->szIdxRow,
pIdx->aiRowLogEst[0]);
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 4);
pIdx->aiRowLogEst[0],
pIdx->hasStat1);
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 5);
}
}
}
break;
#endif
case PragTyp_INDEX_INFO: if( zRight ){
Index *pIdx;
@@ -1402,9 +1397,17 @@ void sqlite3Pragma(
#endif
#ifndef SQLITE_OMIT_INTEGRITY_CHECK
/* Pragma "quick_check" is reduced version of
/* PRAGMA integrity_check
** PRAGMA integrity_check(N)
** PRAGMA quick_check
** PRAGMA quick_check(N)
**
** Verify the integrity of the database.
**
** The "quick_check" is reduced version of
** integrity_check designed to detect most database corruption
** without most of the overhead of a full integrity-check.
** without the overhead of cross-checking indexes. Quick_check
** is linear time wherease integrity_check is O(NlogN).
*/
case PragTyp_INTEGRITY_CHECK: {
int i, j, addr, mxErr;
@@ -1435,7 +1438,7 @@ void sqlite3Pragma(
mxErr = SQLITE_INTEGRITY_CHECK_ERROR_MAX;
}
}
sqlite3VdbeAddOp2(v, OP_Integer, mxErr, 1); /* reg[1] holds errors left */
sqlite3VdbeAddOp2(v, OP_Integer, mxErr-1, 1); /* reg[1] holds errors left */
/* Do an integrity check on each database file */
for(i=0; i<db->nDb; i++){
@@ -1450,10 +1453,6 @@ void sqlite3Pragma(
if( iDb>=0 && i!=iDb ) continue;
sqlite3CodeVerifySchema(pParse, i);
addr = sqlite3VdbeAddOp1(v, OP_IfPos, 1); /* Halt if out of errors */
VdbeCoverage(v);
sqlite3VdbeAddOp2(v, OP_Halt, 0, 0);
sqlite3VdbeJumpHere(v, addr);
/* Do an integrity check of the B-Tree
**
@@ -1493,12 +1492,12 @@ void sqlite3Pragma(
P4_DYNAMIC);
sqlite3VdbeAddOp3(v, OP_Move, 2, 4, 1);
sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 2);
sqlite3VdbeAddOp2(v, OP_ResultRow, 2, 1);
integrityCheckResultRow(v, 2);
sqlite3VdbeJumpHere(v, addr);
/* Make sure all the indices are constructed correctly.
*/
for(x=sqliteHashFirst(pTbls); x && !isQuick; x=sqliteHashNext(x)){
for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){
Table *pTab = sqliteHashData(x);
Index *pIdx, *pPk;
Index *pPrior = 0;
@@ -1506,12 +1505,14 @@ void sqlite3Pragma(
int iDataCur, iIdxCur;
int r1 = -1;
if( pTab->pIndex==0 ) continue;
if( pTab->tnum<1 ) continue; /* Skip VIEWs or VIRTUAL TABLEs */
if( pTab->pCheck==0
&& (pTab->tabFlags & TF_HasNotNull)==0
&& (pTab->pIndex==0 || isQuick)
){
continue; /* No additional checks needed for this table */
}
pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab);
addr = sqlite3VdbeAddOp1(v, OP_IfPos, 1); /* Stop if out of errors */
VdbeCoverage(v);
sqlite3VdbeAddOp2(v, OP_Halt, 0, 0);
sqlite3VdbeJumpHere(v, addr);
sqlite3ExprCacheClear(pParse);
sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenRead, 0,
1, 0, &iDataCur, &iIdxCur);
@@ -1526,24 +1527,45 @@ void sqlite3Pragma(
/* Verify that all NOT NULL columns really are NOT NULL */
for(j=0; j<pTab->nCol; j++){
char *zErr;
int jmp2, jmp3;
int jmp2;
if( j==pTab->iPKey ) continue;
if( pTab->aCol[j].notNull==0 ) continue;
sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, j, 3);
sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG);
jmp2 = sqlite3VdbeAddOp1(v, OP_NotNull, 3); VdbeCoverage(v);
sqlite3VdbeAddOp2(v, OP_AddImm, 1, -1); /* Decrement error limit */
zErr = sqlite3MPrintf(db, "NULL value in %s.%s", pTab->zName,
pTab->aCol[j].zName);
sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC);
sqlite3VdbeAddOp2(v, OP_ResultRow, 3, 1);
jmp3 = sqlite3VdbeAddOp1(v, OP_IfPos, 1); VdbeCoverage(v);
sqlite3VdbeAddOp0(v, OP_Halt);
integrityCheckResultRow(v, 3);
sqlite3VdbeJumpHere(v, jmp2);
sqlite3VdbeJumpHere(v, jmp3);
}
/* Verify CHECK constraints */
if( pTab->pCheck && (db->flags & SQLITE_IgnoreChecks)==0 ){
ExprList *pCheck = sqlite3ExprListDup(db, pTab->pCheck, 0);
if( db->mallocFailed==0 ){
int addrCkFault = sqlite3VdbeMakeLabel(v);
int addrCkOk = sqlite3VdbeMakeLabel(v);
char *zErr;
int k;
pParse->iSelfTab = iDataCur;
sqlite3ExprCachePush(pParse);
for(k=pCheck->nExpr-1; k>0; k--){
sqlite3ExprIfFalse(pParse, pCheck->a[k].pExpr, addrCkFault, 0);
}
sqlite3ExprIfTrue(pParse, pCheck->a[0].pExpr, addrCkOk,
SQLITE_JUMPIFNULL);
sqlite3VdbeResolveLabel(v, addrCkFault);
zErr = sqlite3MPrintf(db, "CHECK constraint failed in %s",
pTab->zName);
sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC);
integrityCheckResultRow(v, 3);
sqlite3VdbeResolveLabel(v, addrCkOk);
sqlite3ExprCachePop(pParse);
}
sqlite3ExprListDelete(db, pCheck);
}
/* Validate index entries for the current row */
for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
for(j=0, pIdx=pTab->pIndex; pIdx && !isQuick; pIdx=pIdx->pNext, j++){
int jmp2, jmp3, jmp4, jmp5;
int ckUniq = sqlite3VdbeMakeLabel(v);
if( pPk==pIdx ) continue;
@@ -1554,16 +1576,13 @@ void sqlite3Pragma(
/* Verify that an index entry exists for the current table row */
jmp2 = sqlite3VdbeAddOp4Int(v, OP_Found, iIdxCur+j, ckUniq, r1,
pIdx->nColumn); VdbeCoverage(v);
sqlite3VdbeAddOp2(v, OP_AddImm, 1, -1); /* Decrement error limit */
sqlite3VdbeLoadString(v, 3, "row ");
sqlite3VdbeAddOp3(v, OP_Concat, 7, 3, 3);
sqlite3VdbeLoadString(v, 4, " missing from index ");
sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 3);
jmp5 = sqlite3VdbeLoadString(v, 4, pIdx->zName);
sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 3);
sqlite3VdbeAddOp2(v, OP_ResultRow, 3, 1);
jmp4 = sqlite3VdbeAddOp1(v, OP_IfPos, 1); VdbeCoverage(v);
sqlite3VdbeAddOp0(v, OP_Halt);
jmp4 = integrityCheckResultRow(v, 3);
sqlite3VdbeJumpHere(v, jmp2);
/* For UNIQUE indexes, verify that only one entry exists with the
** current key. The entry is unique if (1) any column is NULL
@@ -1584,7 +1603,6 @@ void sqlite3Pragma(
sqlite3VdbeJumpHere(v, jmp6);
sqlite3VdbeAddOp4Int(v, OP_IdxGT, iIdxCur+j, uniqOk, r1,
pIdx->nKeyCol); VdbeCoverage(v);
sqlite3VdbeAddOp2(v, OP_AddImm, 1, -1); /* Decrement error limit */
sqlite3VdbeLoadString(v, 3, "non-unique entry in index ");
sqlite3VdbeGoto(v, jmp5);
sqlite3VdbeResolveLabel(v, uniqOk);
@@ -1595,19 +1613,18 @@ void sqlite3Pragma(
sqlite3VdbeAddOp2(v, OP_Next, iDataCur, loopTop); VdbeCoverage(v);
sqlite3VdbeJumpHere(v, loopTop-1);
#ifndef SQLITE_OMIT_BTREECOUNT
sqlite3VdbeLoadString(v, 2, "wrong # of entries in index ");
for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
if( pPk==pIdx ) continue;
addr = sqlite3VdbeCurrentAddr(v);
sqlite3VdbeAddOp2(v, OP_IfPos, 1, addr+2); VdbeCoverage(v);
sqlite3VdbeAddOp2(v, OP_Halt, 0, 0);
sqlite3VdbeAddOp2(v, OP_Count, iIdxCur+j, 3);
sqlite3VdbeAddOp3(v, OP_Eq, 8+j, addr+8, 3); VdbeCoverage(v);
sqlite3VdbeChangeP5(v, SQLITE_NOTNULL);
sqlite3VdbeAddOp2(v, OP_AddImm, 1, -1);
sqlite3VdbeLoadString(v, 3, pIdx->zName);
sqlite3VdbeAddOp3(v, OP_Concat, 3, 2, 7);
sqlite3VdbeAddOp2(v, OP_ResultRow, 7, 1);
if( !isQuick ){
sqlite3VdbeLoadString(v, 2, "wrong # of entries in index ");
for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
if( pPk==pIdx ) continue;
sqlite3VdbeAddOp2(v, OP_Count, iIdxCur+j, 3);
addr = sqlite3VdbeAddOp3(v, OP_Eq, 8+j, 0, 3); VdbeCoverage(v);
sqlite3VdbeChangeP5(v, SQLITE_NOTNULL);
sqlite3VdbeLoadString(v, 3, pIdx->zName);
sqlite3VdbeAddOp3(v, OP_Concat, 3, 2, 7);
integrityCheckResultRow(v, 7);
sqlite3VdbeJumpHere(v, addr);
}
}
#endif /* SQLITE_OMIT_BTREECOUNT */
}
@@ -1616,7 +1633,7 @@ void sqlite3Pragma(
static const int iLn = VDBE_OFFSET_LINENO(2);
static const VdbeOpList endCode[] = {
{ OP_AddImm, 1, 0, 0}, /* 0 */
{ OP_If, 1, 4, 0}, /* 1 */
{ OP_IfNotZero, 1, 4, 0}, /* 1 */
{ OP_String8, 0, 3, 0}, /* 2 */
{ OP_ResultRow, 3, 1, 0}, /* 3 */
};
@@ -1624,7 +1641,7 @@ void sqlite3Pragma(
aOp = sqlite3VdbeAddOpList(v, ArraySize(endCode), endCode, iLn);
if( aOp ){
aOp[0].p2 = -mxErr;
aOp[0].p2 = 1-mxErr;
aOp[2].p4type = P4_STATIC;
aOp[2].p4.z = "ok";
}
@@ -1849,6 +1866,118 @@ void sqlite3Pragma(
break;
}
/*
** PRAGMA optimize
** PRAGMA optimize(MASK)
** PRAGMA schema.optimize
** PRAGMA schema.optimize(MASK)
**
** Attempt to optimize the database. All schemas are optimized in the first
** two forms, and only the specified schema is optimized in the latter two.
**
** The details of optimizations performed by this pragma are expected
** to change and improve over time. Applications should anticipate that
** this pragma will perform new optimizations in future releases.
**
** The optional argument is a bitmask of optimizations to perform:
**
** 0x0001 Debugging mode. Do not actually perform any optimizations
** but instead return one line of text for each optimization
** that would have been done. Off by default.
**
** 0x0002 Run ANALYZE on tables that might benefit. On by default.
** See below for additional information.
**
** 0x0004 (Not yet implemented) Record usage and performance
** information from the current session in the
** database file so that it will be available to "optimize"
** pragmas run by future database connections.
**
** 0x0008 (Not yet implemented) Create indexes that might have
** been helpful to recent queries
**
** The default MASK is and always shall be 0xfffe. 0xfffe means perform all ** of the optimizations listed above except Debug Mode, including new
** optimizations that have not yet been invented. If new optimizations are
** ever added that should be off by default, those off-by-default
** optimizations will have bitmasks of 0x10000 or larger.
**
** DETERMINATION OF WHEN TO RUN ANALYZE
**
** In the current implementation, a table is analyzed if only if all of
** the following are true:
**
** (1) MASK bit 0x02 is set.
**
** (2) The query planner used sqlite_stat1-style statistics for one or
** more indexes of the table at some point during the lifetime of
** the current connection.
**
** (3) One or more indexes of the table are currently unanalyzed OR
** the number of rows in the table has increased by 25 times or more
** since the last time ANALYZE was run.
**
** The rules for when tables are analyzed are likely to change in
** future releases.
*/
case PragTyp_OPTIMIZE: {
int iDbLast; /* Loop termination point for the schema loop */
int iTabCur; /* Cursor for a table whose size needs checking */
HashElem *k; /* Loop over tables of a schema */
Schema *pSchema; /* The current schema */
Table *pTab; /* A table in the schema */
Index *pIdx; /* An index of the table */
LogEst szThreshold; /* Size threshold above which reanalysis is needd */
char *zSubSql; /* SQL statement for the OP_SqlExec opcode */
u32 opMask; /* Mask of operations to perform */
if( zRight ){
opMask = (u32)sqlite3Atoi(zRight);
if( (opMask & 0x02)==0 ) break;
}else{
opMask = 0xfffe;
}
iTabCur = pParse->nTab++;
for(iDbLast = zDb?iDb:db->nDb-1; iDb<=iDbLast; iDb++){
if( iDb==1 ) continue;
sqlite3CodeVerifySchema(pParse, iDb);
pSchema = db->aDb[iDb].pSchema;
for(k=sqliteHashFirst(&pSchema->tblHash); k; k=sqliteHashNext(k)){
pTab = (Table*)sqliteHashData(k);
/* If table pTab has not been used in a way that would benefit from
** having analysis statistics during the current session, then skip it.
** This also has the effect of skipping virtual tables and views */
if( (pTab->tabFlags & TF_StatsUsed)==0 ) continue;
/* Reanalyze if the table is 25 times larger than the last analysis */
szThreshold = pTab->nRowLogEst + 46; assert( sqlite3LogEst(25)==46 );
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
if( !pIdx->hasStat1 ){
szThreshold = 0; /* Always analyze if any index lacks statistics */
break;
}
}
if( szThreshold ){
sqlite3OpenTable(pParse, iTabCur, iDb, pTab, OP_OpenRead);
sqlite3VdbeAddOp3(v, OP_IfSmaller, iTabCur,
sqlite3VdbeCurrentAddr(v)+2+(opMask&1), szThreshold);
VdbeCoverage(v);
}
zSubSql = sqlite3MPrintf(db, "ANALYZE \"%w\".\"%w\"",
db->aDb[iDb].zDbSName, pTab->zName);
if( opMask & 0x01 ){
int r1 = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp4(v, OP_String8, 0, r1, 0, zSubSql, P4_DYNAMIC);
sqlite3VdbeAddOp2(v, OP_ResultRow, r1, 1);
}else{
sqlite3VdbeAddOp4(v, OP_SqlExec, 0, 0, 0, zSubSql, P4_DYNAMIC);
}
}
}
sqlite3VdbeAddOp0(v, OP_Expire);
break;
}
/*
** PRAGMA busy_timeout
** PRAGMA busy_timeout = N
+76 -77
View File
@@ -30,25 +30,25 @@
#define PragTyp_LOCKING_MODE 22
#define PragTyp_PAGE_COUNT 23
#define PragTyp_MMAP_SIZE 24
#define PragTyp_PAGE_SIZE 25
#define PragTyp_SECURE_DELETE 26
#define PragTyp_SHRINK_MEMORY 27
#define PragTyp_SOFT_HEAP_LIMIT 28
#define PragTyp_STATS 29
#define PragTyp_OPTIMIZE 25
#define PragTyp_PAGE_SIZE 26
#define PragTyp_SECURE_DELETE 27
#define PragTyp_SHRINK_MEMORY 28
#define PragTyp_SOFT_HEAP_LIMIT 29
#define PragTyp_SYNCHRONOUS 30
#define PragTyp_TABLE_INFO 31
#define PragTyp_TEMP_STORE 32
#define PragTyp_TEMP_STORE_DIRECTORY 33
#define PragTyp_THREADS 34
#define PragTyp_VDBE_CYCLE_LIMIT 35
#define PragTyp_WAL_AUTOCHECKPOINT 36
#define PragTyp_WAL_CHECKPOINT 37
#define PragTyp_ACTIVATE_EXTENSIONS 38
#define PragTyp_HEXKEY 39
#define PragTyp_KEY 40
#define PragTyp_REKEY 41
#define PragTyp_LOCK_STATUS 42
#define PragTyp_PARSER_TRACE 43
#define PragTyp_WAL_AUTOCHECKPOINT 35
#define PragTyp_WAL_CHECKPOINT 36
#define PragTyp_ACTIVATE_EXTENSIONS 37
#define PragTyp_HEXKEY 38
#define PragTyp_KEY 39
#define PragTyp_REKEY 40
#define PragTyp_LOCK_STATUS 41
#define PragTyp_PARSER_TRACE 42
#define PragTyp_STATS 43
/* Property flags associated with various pragma. */
#define PragFlg_NeedSchema 0x01 /* Force schema load before running */
@@ -72,47 +72,48 @@ static const char *const pragCName[] = {
/* 4 */ "notnull",
/* 5 */ "dflt_value",
/* 6 */ "pk",
/* 7 */ "table", /* Used by: stats */
/* 8 */ "index",
/* 9 */ "width",
/* 10 */ "height",
/* 11 */ "seqno", /* Used by: index_info */
/* 12 */ "cid",
/* 13 */ "name",
/* 14 */ "seqno", /* Used by: index_xinfo */
/* 15 */ "cid",
/* 16 */ "name",
/* 17 */ "desc",
/* 18 */ "coll",
/* 19 */ "key",
/* 20 */ "seq", /* Used by: index_list */
/* 21 */ "name",
/* 22 */ "unique",
/* 23 */ "origin",
/* 24 */ "partial",
/* 25 */ "seq", /* Used by: database_list */
/* 26 */ "name",
/* 27 */ "file",
/* 28 */ "seq", /* Used by: collation_list */
/* 29 */ "name",
/* 30 */ "id", /* Used by: foreign_key_list */
/* 31 */ "seq",
/* 32 */ "table",
/* 33 */ "from",
/* 34 */ "to",
/* 35 */ "on_update",
/* 36 */ "on_delete",
/* 37 */ "match",
/* 38 */ "table", /* Used by: foreign_key_check */
/* 39 */ "rowid",
/* 40 */ "parent",
/* 41 */ "fkid",
/* 42 */ "busy", /* Used by: wal_checkpoint */
/* 43 */ "log",
/* 44 */ "checkpointed",
/* 45 */ "timeout", /* Used by: busy_timeout */
/* 46 */ "database", /* Used by: lock_status */
/* 47 */ "status",
/* 7 */ "tbl", /* Used by: stats */
/* 8 */ "idx",
/* 9 */ "wdth",
/* 10 */ "hght",
/* 11 */ "flgs",
/* 12 */ "seqno", /* Used by: index_info */
/* 13 */ "cid",
/* 14 */ "name",
/* 15 */ "seqno", /* Used by: index_xinfo */
/* 16 */ "cid",
/* 17 */ "name",
/* 18 */ "desc",
/* 19 */ "coll",
/* 20 */ "key",
/* 21 */ "seq", /* Used by: index_list */
/* 22 */ "name",
/* 23 */ "unique",
/* 24 */ "origin",
/* 25 */ "partial",
/* 26 */ "seq", /* Used by: database_list */
/* 27 */ "name",
/* 28 */ "file",
/* 29 */ "seq", /* Used by: collation_list */
/* 30 */ "name",
/* 31 */ "id", /* Used by: foreign_key_list */
/* 32 */ "seq",
/* 33 */ "table",
/* 34 */ "from",
/* 35 */ "to",
/* 36 */ "on_update",
/* 37 */ "on_delete",
/* 38 */ "match",
/* 39 */ "table", /* Used by: foreign_key_check */
/* 40 */ "rowid",
/* 41 */ "parent",
/* 42 */ "fkid",
/* 43 */ "busy", /* Used by: wal_checkpoint */
/* 44 */ "log",
/* 45 */ "checkpointed",
/* 46 */ "timeout", /* Used by: busy_timeout */
/* 47 */ "database", /* Used by: lock_status */
/* 48 */ "status",
};
/* Definitions of all built-in pragmas */
@@ -158,7 +159,7 @@ static const PragmaName aPragmaName[] = {
{/* zName: */ "busy_timeout",
/* ePragTyp: */ PragTyp_BUSY_TIMEOUT,
/* ePragFlg: */ PragFlg_Result0,
/* ColNames: */ 45, 1,
/* ColNames: */ 46, 1,
/* iArg: */ 0 },
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
{/* zName: */ "cache_size",
@@ -195,7 +196,7 @@ static const PragmaName aPragmaName[] = {
{/* zName: */ "collation_list",
/* ePragTyp: */ PragTyp_COLLATION_LIST,
/* ePragFlg: */ PragFlg_Result0,
/* ColNames: */ 28, 2,
/* ColNames: */ 29, 2,
/* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_COMPILEOPTION_DIAGS)
@@ -230,7 +231,7 @@ static const PragmaName aPragmaName[] = {
{/* zName: */ "database_list",
/* ePragTyp: */ PragTyp_DATABASE_LIST,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0,
/* ColNames: */ 25, 3,
/* ColNames: */ 26, 3,
/* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED)
@@ -267,14 +268,14 @@ static const PragmaName aPragmaName[] = {
{/* zName: */ "foreign_key_check",
/* ePragTyp: */ PragTyp_FOREIGN_KEY_CHECK,
/* ePragFlg: */ PragFlg_NeedSchema,
/* ColNames: */ 38, 4,
/* ColNames: */ 39, 4,
/* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_FOREIGN_KEY)
{/* zName: */ "foreign_key_list",
/* ePragTyp: */ PragTyp_FOREIGN_KEY_LIST,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt,
/* ColNames: */ 30, 8,
/* ColNames: */ 31, 8,
/* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
@@ -337,17 +338,17 @@ static const PragmaName aPragmaName[] = {
{/* zName: */ "index_info",
/* ePragTyp: */ PragTyp_INDEX_INFO,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt,
/* ColNames: */ 11, 3,
/* ColNames: */ 12, 3,
/* iArg: */ 0 },
{/* zName: */ "index_list",
/* ePragTyp: */ PragTyp_INDEX_LIST,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt,
/* ColNames: */ 20, 5,
/* ColNames: */ 21, 5,
/* iArg: */ 0 },
{/* zName: */ "index_xinfo",
/* ePragTyp: */ PragTyp_INDEX_INFO,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt,
/* ColNames: */ 14, 6,
/* ColNames: */ 15, 6,
/* iArg: */ 1 },
#endif
#if !defined(SQLITE_OMIT_INTEGRITY_CHECK)
@@ -394,7 +395,7 @@ static const PragmaName aPragmaName[] = {
{/* zName: */ "lock_status",
/* ePragTyp: */ PragTyp_LOCK_STATUS,
/* ePragFlg: */ PragFlg_Result0,
/* ColNames: */ 46, 2,
/* ColNames: */ 47, 2,
/* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
@@ -413,6 +414,13 @@ static const PragmaName aPragmaName[] = {
/* ePragFlg: */ 0,
/* ColNames: */ 0, 0,
/* iArg: */ 0 },
#endif
{/* zName: */ "optimize",
/* ePragTyp: */ PragTyp_OPTIMIZE,
/* ePragFlg: */ PragFlg_Result1|PragFlg_NeedSchema,
/* ColNames: */ 0, 0,
/* iArg: */ 0 },
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
{/* zName: */ "page_count",
/* ePragTyp: */ PragTyp_PAGE_COUNT,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq,
@@ -511,11 +519,11 @@ static const PragmaName aPragmaName[] = {
/* iArg: */ SQLITE_SqlTrace },
#endif
#endif
#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) && defined(SQLITE_DEBUG)
{/* zName: */ "stats",
/* ePragTyp: */ PragTyp_STATS,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq,
/* ColNames: */ 7, 4,
/* ColNames: */ 7, 5,
/* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
@@ -563,15 +571,6 @@ static const PragmaName aPragmaName[] = {
/* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
/* ColNames: */ 0, 0,
/* iArg: */ SQLITE_VdbeAddopTrace },
#endif
#endif
{/* zName: */ "vdbe_cycle_limit",
/* ePragTyp: */ PragTyp_VDBE_CYCLE_LIMIT,
/* ePragFlg: */ PragFlg_NoColumns,
/* ColNames: */ 0, 0,
/* iArg: */ 0 },
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
#if defined(SQLITE_DEBUG)
{/* zName: */ "vdbe_debug",
/* ePragTyp: */ PragTyp_FLAG,
/* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
@@ -603,7 +602,7 @@ static const PragmaName aPragmaName[] = {
{/* zName: */ "wal_checkpoint",
/* ePragTyp: */ PragTyp_WAL_CHECKPOINT,
/* ePragFlg: */ PragFlg_NeedSchema,
/* ColNames: */ 42, 3,
/* ColNames: */ 43, 3,
/* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
@@ -614,4 +613,4 @@ static const PragmaName aPragmaName[] = {
/* iArg: */ SQLITE_WriteSchema|SQLITE_RecoveryMode },
#endif
};
/* Number of pragmas: 61 on by default, 74 total. */
/* Number of pragmas: 60 on by default, 74 total. */
+3 -2
View File
@@ -400,12 +400,13 @@ void sqlite3VXPrintf(
nOut = etBUFSIZE;
zOut = buf;
}else{
nOut = precision + 10 + precision/3;
zOut = zExtra = sqlite3Malloc( nOut );
u64 n = (u64)precision + 10 + precision/3;
zOut = zExtra = sqlite3Malloc( n );
if( zOut==0 ){
setStrAccumError(pAccum, STRACCUM_NOMEM);
return;
}
nOut = (int)n;
}
bufpt = &zOut[nOut-1];
if( xtype==etORDINAL ){
+29 -23
View File
@@ -229,7 +229,8 @@ static int lookupName(
}
/* Start at the inner-most context and move outward until a match is found */
while( pNC && cnt==0 ){
assert( pNC && cnt==0 );
do{
ExprList *pEList;
SrcList *pSrcList = pNC->pSrcList;
@@ -414,11 +415,11 @@ static int lookupName(
/* Advance to the next name context. The loop will exit when either
** we have a match (cnt>0) or when we run out of name contexts.
*/
if( cnt==0 ){
pNC = pNC->pNext;
nSubquery++;
}
}
if( cnt ) break;
pNC = pNC->pNext;
nSubquery++;
}while( pNC );
/*
** If X and Y are NULL (in other words if only the column name Z is
@@ -608,33 +609,38 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
#endif /* defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT)
&& !defined(SQLITE_OMIT_SUBQUERY) */
/* A lone identifier is the name of a column.
*/
case TK_ID: {
return lookupName(pParse, 0, 0, pExpr->u.zToken, pNC, pExpr);
}
/* A table name and column name: ID.ID
/* A column name: ID
** Or table name and column name: ID.ID
** Or a database, table and column: ID.ID.ID
**
** The TK_ID and TK_OUT cases are combined so that there will only
** be one call to lookupName(). Then the compiler will in-line
** lookupName() for a size reduction and performance increase.
*/
case TK_ID:
case TK_DOT: {
const char *zColumn;
const char *zTable;
const char *zDb;
Expr *pRight;
/* if( pSrcList==0 ) break; */
notValid(pParse, pNC, "the \".\" operator", NC_IdxExpr);
pRight = pExpr->pRight;
if( pRight->op==TK_ID ){
if( pExpr->op==TK_ID ){
zDb = 0;
zTable = pExpr->pLeft->u.zToken;
zColumn = pRight->u.zToken;
zTable = 0;
zColumn = pExpr->u.zToken;
}else{
assert( pRight->op==TK_DOT );
zDb = pExpr->pLeft->u.zToken;
zTable = pRight->pLeft->u.zToken;
zColumn = pRight->pRight->u.zToken;
notValid(pParse, pNC, "the \".\" operator", NC_IdxExpr);
pRight = pExpr->pRight;
if( pRight->op==TK_ID ){
zDb = 0;
zTable = pExpr->pLeft->u.zToken;
zColumn = pRight->u.zToken;
}else{
assert( pRight->op==TK_DOT );
zDb = pExpr->pLeft->u.zToken;
zTable = pRight->pLeft->u.zToken;
zColumn = pRight->pRight->u.zToken;
}
}
return lookupName(pParse, zDb, zTable, zColumn, pNC, pExpr);
}
+6 -4
View File
@@ -76,7 +76,7 @@ static void clearSelect(sqlite3 *db, Select *p, int bFree){
sqlite3ExprDelete(db, p->pLimit);
sqlite3ExprDelete(db, p->pOffset);
if( p->pWith ) sqlite3WithDelete(db, p->pWith);
if( bFree ) sqlite3DbFree(db, p);
if( bFree ) sqlite3DbFreeNN(db, p);
p = pPrior;
bFree = 1;
}
@@ -1055,7 +1055,7 @@ void sqlite3KeyInfoUnref(KeyInfo *p){
if( p ){
assert( p->nRef>0 );
p->nRef--;
if( p->nRef==0 ) sqlite3DbFree(p->db, p);
if( p->nRef==0 ) sqlite3DbFreeNN(p->db, p);
}
}
@@ -2900,7 +2900,7 @@ static int multiSelectOrderBy(
if( pNew==0 ) return SQLITE_NOMEM_BKPT;
pNew->flags |= EP_IntValue;
pNew->u.iValue = i;
pOrderBy = sqlite3ExprListAppend(pParse, pOrderBy, pNew);
p->pOrderBy = pOrderBy = sqlite3ExprListAppend(pParse, pOrderBy, pNew);
if( pOrderBy ) pOrderBy->a[nOrderBy++].u.x.iOrderByCol = (u16)i;
}
}
@@ -3749,7 +3749,9 @@ static int flattenSubquery(
}else{
pParent->pWhere = sqlite3ExprAnd(db, pWhere, pParent->pWhere);
}
substSelect(pParse, pParent, iParent, pSub->pEList, 0);
if( db->mallocFailed==0 ){
substSelect(pParse, pParent, iParent, pSub->pEList, 0);
}
/* The flattened query is distinct if either the inner or the
** outer query is distinct.
+1497 -246
View File
File diff suppressed because it is too large Load Diff
+39 -21
View File
@@ -114,8 +114,8 @@ extern "C" {
** system</a>. ^The SQLITE_SOURCE_ID macro evaluates to
** a string which identifies a particular check-in of SQLite
** within its configuration management system. ^The SQLITE_SOURCE_ID
** string contains the date and time of the check-in (UTC) and an SHA1
** hash of the entire source tree.
** string contains the date and time of the check-in (UTC) and a SHA1
** or SHA3-256 hash of the entire source tree.
**
** See also: [sqlite3_libversion()],
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
@@ -2040,20 +2040,30 @@ int sqlite3_extended_result_codes(sqlite3*, int onoff);
** the table has a column of type [INTEGER PRIMARY KEY] then that column
** is another alias for the rowid.
**
** ^The sqlite3_last_insert_rowid(D) interface returns the [rowid] of the
** most recent successful [INSERT] into a rowid table or [virtual table]
** on database connection D.
** ^Inserts into [WITHOUT ROWID] tables are not recorded.
** ^If no successful [INSERT]s into rowid tables
** have ever occurred on the database connection D,
** then sqlite3_last_insert_rowid(D) returns zero.
** ^The sqlite3_last_insert_rowid(D) interface usually returns the [rowid] of
** the most recent successful [INSERT] into a rowid table or [virtual table]
** on database connection D. ^Inserts into [WITHOUT ROWID] tables are not
** recorded. ^If no successful [INSERT]s into rowid tables have ever occurred
** on the database connection D, then sqlite3_last_insert_rowid(D) returns
** zero.
**
** ^(If an [INSERT] occurs within a trigger or within a [virtual table]
** method, then this routine will return the [rowid] of the inserted
** row as long as the trigger or virtual table method is running.
** But once the trigger or virtual table method ends, the value returned
** by this routine reverts to what it was before the trigger or virtual
** table method began.)^
** As well as being set automatically as rows are inserted into database
** tables, the value returned by this function may be set explicitly by
** [sqlite3_set_last_insert_rowid()]
**
** Some virtual table implementations may INSERT rows into rowid tables as
** part of committing a transaction (e.g. to flush data accumulated in memory
** to disk). In this case subsequent calls to this function return the rowid
** associated with these internal INSERT operations, which leads to
** unintuitive results. Virtual table implementations that do write to rowid
** tables in this way can avoid this problem by restoring the original
** rowid value using [sqlite3_set_last_insert_rowid()] before returning
** control to the user.
**
** ^(If an [INSERT] occurs within a trigger then this routine will
** return the [rowid] of the inserted row as long as the trigger is
** running. Once the trigger program ends, the value returned
** by this routine reverts to what it was before the trigger was fired.)^
**
** ^An [INSERT] that fails due to a constraint violation is not a
** successful [INSERT] and does not change the value returned by this
@@ -2080,6 +2090,16 @@ int sqlite3_extended_result_codes(sqlite3*, int onoff);
*/
sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*);
/*
** CAPI3REF: Set the Last Insert Rowid value.
** METHOD: sqlite3
**
** The sqlite3_set_last_insert_rowid(D, R) method allows the application to
** set the value returned by calling sqlite3_last_insert_rowid(D) to R
** without inserting a row into the database.
*/
void sqlite3_set_last_insert_rowid(sqlite3*,sqlite3_int64);
/*
** CAPI3REF: Count The Number Of Rows Modified
** METHOD: sqlite3
@@ -2191,9 +2211,6 @@ int sqlite3_total_changes(sqlite3*);
** ^A call to sqlite3_interrupt(D) that occurs when there are no running
** SQL statements is a no-op and has no effect on SQL statements
** that are started after the sqlite3_interrupt() call returns.
**
** If the database connection closes while [sqlite3_interrupt()]
** is running then bad things will likely happen.
*/
void sqlite3_interrupt(sqlite3*);
@@ -3404,9 +3421,9 @@ int sqlite3_limit(sqlite3*, int id, int newVal);
**
** [[SQLITE_LIMIT_VDBE_OP]] ^(<dt>SQLITE_LIMIT_VDBE_OP</dt>
** <dd>The maximum number of instructions in a virtual machine program
** used to implement an SQL statement. This limit is not currently
** enforced, though that might be added in some future release of
** SQLite.</dd>)^
** used to implement an SQL statement. If [sqlite3_prepare_v2()] or
** the equivalent tries to allocate space for more than this many opcodes
** in a single prepared statement, an SQLITE_NOMEM error is returned.</dd>)^
**
** [[SQLITE_LIMIT_FUNCTION_ARG]] ^(<dt>SQLITE_LIMIT_FUNCTION_ARG</dt>
** <dd>The maximum number of arguments on a function.</dd>)^
@@ -3444,6 +3461,7 @@ int sqlite3_limit(sqlite3*, int id, int newVal);
#define SQLITE_LIMIT_TRIGGER_DEPTH 10
#define SQLITE_LIMIT_WORKER_THREADS 11
/*
** CAPI3REF: Compiling An SQL Statement
** KEYWORDS: {SQL statement compiler}
+4
View File
@@ -282,6 +282,8 @@ struct sqlite3_api_routines {
/* Version 3.14.0 and later */
int (*trace_v2)(sqlite3*,unsigned,int(*)(unsigned,void*,void*,void*),void*);
char *(*expanded_sql)(sqlite3_stmt*);
/* Version 3.18.0 and later */
void (*set_last_insert_rowid)(sqlite3*,sqlite3_int64);
};
/*
@@ -540,6 +542,8 @@ typedef int (*sqlite3_loadext_entry)(
/* Version 3.14.0 and later */
#define sqlite3_trace_v2 sqlite3_api->trace_v2
#define sqlite3_expanded_sql sqlite3_api->expanded_sql
/* Version 3.18.0 and later */
#define sqlite3_set_last_insert_rowid sqlite3_api->set_last_insert_rowid
#endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */
#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
+17 -11
View File
@@ -1127,7 +1127,7 @@ typedef int VList;
** and the one-based values are used internally.
*/
#ifndef SQLITE_DEFAULT_SYNCHRONOUS
# define SQLITE_DEFAULT_SYNCHRONOUS (PAGER_SYNCHRONOUS_FULL-1)
# define SQLITE_DEFAULT_SYNCHRONOUS 2
#endif
#ifndef SQLITE_DEFAULT_WAL_SYNCHRONOUS
# define SQLITE_DEFAULT_WAL_SYNCHRONOUS SQLITE_DEFAULT_SYNCHRONOUS
@@ -1333,6 +1333,7 @@ struct sqlite3 {
u8 isTransactionSavepoint; /* True if the outermost savepoint is a TS */
u8 mTrace; /* zero or more SQLITE_TRACE flags */
u8 skipBtreeMutex; /* True if no shared-cache backends */
u8 nSqlExec; /* Number of pending OP_SqlExec opcodes */
int nextPagesize; /* Pagesize after VACUUM if >0 */
u32 magic; /* Magic number for detect library misuse */
int nChange; /* Value returned by sqlite3_changes() */
@@ -1879,15 +1880,17 @@ struct Table {
** the TF_OOOHidden attribute would apply in this case. Such tables require
** special handling during INSERT processing.
*/
#define TF_Readonly 0x01 /* Read-only system table */
#define TF_Ephemeral 0x02 /* An ephemeral table */
#define TF_HasPrimaryKey 0x04 /* Table has a primary key */
#define TF_Autoincrement 0x08 /* Integer primary key is autoincrement */
/* available for reuse: 0x10 */
#define TF_WithoutRowid 0x20 /* No rowid. PRIMARY KEY is the key */
#define TF_NoVisibleRowid 0x40 /* No user-visible "rowid" column */
#define TF_OOOHidden 0x80 /* Out-of-Order hidden columns */
#define TF_Readonly 0x0001 /* Read-only system table */
#define TF_Ephemeral 0x0002 /* An ephemeral table */
#define TF_HasPrimaryKey 0x0004 /* Table has a primary key */
#define TF_Autoincrement 0x0008 /* Integer primary key is autoincrement */
#define TF_HasStat1 0x0010 /* nRowLogEst set from sqlite_stat1 */
#define TF_WithoutRowid 0x0020 /* No rowid. PRIMARY KEY is the key */
#define TF_NoVisibleRowid 0x0040 /* No user-visible "rowid" column */
#define TF_OOOHidden 0x0080 /* Out-of-Order hidden columns */
#define TF_StatsUsed 0x0100 /* Query planner decisions affected by
** Index.aiRowLogEst[] values */
#define TF_HasNotNull 0x0200 /* Contains NOT NULL constraints */
/*
** Test to see whether or not a table is a virtual table. This is
@@ -2130,6 +2133,7 @@ struct Index {
unsigned isResized:1; /* True if resizeIndexObject() has been called */
unsigned isCovering:1; /* True if this is a covering index */
unsigned noSkipScan:1; /* Do not try to use skip-scan if true */
unsigned hasStat1:1; /* aiRowLogEst values come from sqlite_stat1 */
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
int nSample; /* Number of elements in aSample[] */
int nSampleCol; /* Size of IndexSample.anEq[] and so on */
@@ -2439,6 +2443,7 @@ struct Expr {
*/
struct ExprList {
int nExpr; /* Number of expressions on the list */
int nAlloc; /* Number of a[] slots allocated */
struct ExprList_item { /* For each expression in the list */
Expr *pExpr; /* The parse tree for this expression */
char *zName; /* Token associated with this expression */
@@ -2454,7 +2459,7 @@ struct ExprList {
} x;
int iConstExprReg; /* Register in which Expr value is cached */
} u;
} *a; /* Alloc a power of two greater or equal to nExpr */
} a[1]; /* One slot for each expression in the list */
};
/*
@@ -3472,6 +3477,7 @@ void *sqlite3Realloc(void*, u64);
void *sqlite3DbReallocOrFree(sqlite3 *, void *, u64);
void *sqlite3DbRealloc(sqlite3 *, void *, u64);
void sqlite3DbFree(sqlite3*, void*);
void sqlite3DbFreeNN(sqlite3*, void*);
int sqlite3MallocSize(void*);
int sqlite3DbMallocSize(sqlite3*, void*);
void *sqlite3ScratchMalloc(int);
+1 -1
View File
@@ -87,7 +87,7 @@
** Not currently enforced.
*/
#ifndef SQLITE_MAX_VDBE_OP
# define SQLITE_MAX_VDBE_OP 25000
# define SQLITE_MAX_VDBE_OP 250000000
#endif
/*
+11 -6
View File
@@ -315,8 +315,9 @@ static int writeListSync(CrashFile *pFile, int isCrash){
assert(pWrite->zBuf);
#ifdef TRACE_CRASHTEST
printf("Trashing %d sectors @ %lld (sector %d) (%s)\n",
1+iLast-iFirst, pWrite->iOffset, iFirst, pWrite->pFile->zName
printf("Trashing %d sectors (%d bytes) @ %lld (sector %d) (%s)\n",
1+iLast-iFirst, (1+iLast-iFirst)*g.iSectorSize,
pWrite->iOffset, iFirst, pWrite->pFile->zName
);
#endif
@@ -827,7 +828,7 @@ static int SQLITE_TCLAPI crashNowCmd(
}
/*
** tclcmd: sqlite_crash_enable ENABLE
** tclcmd: sqlite_crash_enable ENABLE ?DEFAULT?
**
** Parameter ENABLE must be a boolean value. If true, then the "crash"
** vfs is added to the system. If false, it is removed.
@@ -839,6 +840,7 @@ static int SQLITE_TCLAPI crashEnableCmd(
Tcl_Obj *CONST objv[]
){
int isEnable;
int isDefault = 0;
static sqlite3_vfs crashVfs = {
2, /* iVersion */
0, /* szOsFile */
@@ -862,14 +864,17 @@ static int SQLITE_TCLAPI crashEnableCmd(
0, /* xCurrentTimeInt64 */
};
if( objc!=2 ){
Tcl_WrongNumArgs(interp, 1, objv, "ENABLE");
if( objc!=2 && objc!=3 ){
Tcl_WrongNumArgs(interp, 1, objv, "ENABLE ?DEFAULT?");
return TCL_ERROR;
}
if( Tcl_GetBooleanFromObj(interp, objv[1], &isEnable) ){
return TCL_ERROR;
}
if( objc==3 && Tcl_GetBooleanFromObj(interp, objv[2], &isDefault) ){
return TCL_ERROR;
}
if( (isEnable && crashVfs.pAppData) || (!isEnable && !crashVfs.pAppData) ){
return TCL_OK;
@@ -880,7 +885,7 @@ static int SQLITE_TCLAPI crashEnableCmd(
crashVfs.mxPathname = pOriginalVfs->mxPathname;
crashVfs.pAppData = (void *)pOriginalVfs;
crashVfs.szOsFile = sizeof(CrashFile) + pOriginalVfs->szOsFile;
sqlite3_vfs_register(&crashVfs, 0);
sqlite3_vfs_register(&crashVfs, isDefault);
}else{
crashVfs.pAppData = 0;
sqlite3_vfs_unregister(&crashVfs);
+2
View File
@@ -740,6 +740,8 @@ Tcl_SetVar2(interp, "sqlite_options", "mergesort", "1", TCL_GLOBAL_ONLY);
LINKVAR( DEFAULT_CACHE_SIZE );
LINKVAR( DEFAULT_PAGE_SIZE );
LINKVAR( DEFAULT_FILE_FORMAT );
LINKVAR( DEFAULT_SYNCHRONOUS );
LINKVAR( DEFAULT_WAL_SYNCHRONOUS );
LINKVAR( MAX_ATTACHED );
LINKVAR( MAX_DEFAULT_PAGE_SIZE );
LINKVAR( MAX_WORKER_THREADS );
+3
View File
@@ -557,6 +557,9 @@ static int jtWrite(
u32 pgno = (u32)(iOfst/p->nPagesize + 1);
assert( (iAmt==1||iAmt==(int)p->nPagesize) &&
((iOfst+iAmt)%p->nPagesize)==0 );
/* The following assert() statements may fail if this layer is used
** with a connection in "PRAGMA synchronous=off" mode. If they
** fail with sync=normal or sync=full, this may indicate problem. */
assert( pgno<=p->nPage || p->nSync>0 );
assert( pgno>p->nPage || sqlite3BitvecTest(p->pWritable, pgno) );
}
+15 -14
View File
@@ -475,14 +475,14 @@ int sqlite3GetToken(const unsigned char *z, int *tokenType){
*/
int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){
int nErr = 0; /* Number of errors encountered */
int i; /* Loop counter */
void *pEngine; /* The LEMON-generated LALR(1) parser */
int n = 0; /* Length of the next token token */
int tokenType; /* type of the next token */
int lastTokenParsed = -1; /* type of the previous token */
sqlite3 *db = pParse->db; /* The database connection */
int mxSqlLen; /* Max length of an SQL string */
#ifdef sqlite3Parser_ENGINEALWAYSONSTACK
unsigned char zSpace[sizeof(yyParser)]; /* Space for parser engine object */
yyParser sEngine; /* Space to hold the Lemon-generated Parser object */
#endif
assert( zSql!=0 );
@@ -492,11 +492,10 @@ int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){
}
pParse->rc = SQLITE_OK;
pParse->zTail = zSql;
i = 0;
assert( pzErrMsg!=0 );
/* sqlite3ParserTrace(stdout, "parser: "); */
#ifdef sqlite3Parser_ENGINEALWAYSONSTACK
pEngine = zSpace;
pEngine = &sEngine;
sqlite3ParserInit(pEngine);
#else
pEngine = sqlite3ParserAlloc(sqlite3Malloc);
@@ -510,12 +509,10 @@ int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){
assert( pParse->nVar==0 );
assert( pParse->pVList==0 );
while( 1 ){
assert( i>=0 );
if( zSql[i]!=0 ){
pParse->sLastToken.z = &zSql[i];
pParse->sLastToken.n = sqlite3GetToken((u8*)&zSql[i],&tokenType);
i += pParse->sLastToken.n;
if( i>mxSqlLen ){
if( zSql[0]!=0 ){
n = sqlite3GetToken((u8*)zSql, &tokenType);
mxSqlLen -= n;
if( mxSqlLen<0 ){
pParse->rc = SQLITE_TOOBIG;
break;
}
@@ -529,6 +526,7 @@ int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){
}else{
tokenType = TK_SEMI;
}
zSql -= n;
}
if( tokenType>=TK_SPACE ){
assert( tokenType==TK_SPACE || tokenType==TK_ILLEGAL );
@@ -537,18 +535,21 @@ int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){
break;
}
if( tokenType==TK_ILLEGAL ){
sqlite3ErrorMsg(pParse, "unrecognized token: \"%T\"",
&pParse->sLastToken);
sqlite3ErrorMsg(pParse, "unrecognized token: \"%.*s\"", n, zSql);
break;
}
zSql += n;
}else{
pParse->sLastToken.z = zSql;
pParse->sLastToken.n = n;
sqlite3Parser(pEngine, tokenType, pParse->sLastToken, pParse);
lastTokenParsed = tokenType;
zSql += n;
if( pParse->rc!=SQLITE_OK || db->mallocFailed ) break;
}
}
assert( nErr==0 );
pParse->zTail = &zSql[i];
pParse->zTail = zSql;
#ifdef YYTRACKMAXSTACKDEPTH
sqlite3_mutex_enter(sqlite3MallocMutex());
sqlite3StatusHighwater(SQLITE_STATUS_PARSER_STACK,
@@ -603,7 +604,7 @@ int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){
while( pParse->pAinc ){
AutoincInfo *p = pParse->pAinc;
pParse->pAinc = p->pNext;
sqlite3DbFree(db, p);
sqlite3DbFreeNN(db, p);
}
while( pParse->pZombieTab ){
Table *p = pParse->pZombieTab;
+4
View File
@@ -126,6 +126,10 @@ void sqlite3TreeViewWith(TreeView *pView, const With *pWith, u8 moreToFollow){
void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 moreToFollow){
int n = 0;
int cnt = 0;
if( p==0 ){
sqlite3TreeViewLine(pView, "nil-SELECT");
return;
}
pView = sqlite3TreeViewPush(pView, moreToFollow);
if( p->pWith ){
sqlite3TreeViewWith(pView, p->pWith, 1);
+103 -37
View File
@@ -403,9 +403,7 @@ void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf){
}else{
c = 's';
}
sqlite3_snprintf(100, zCsr, "%c", c);
zCsr += sqlite3Strlen30(zCsr);
*(zCsr++) = c;
sqlite3_snprintf(100, zCsr, "%d[", pMem->n);
zCsr += sqlite3Strlen30(zCsr);
for(i=0; i<16 && i<pMem->n; i++){
@@ -417,9 +415,7 @@ void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf){
if( z<32 || z>126 ) *zCsr++ = '.';
else *zCsr++ = z;
}
sqlite3_snprintf(100, zCsr, "]%s", encnames[pMem->enc]);
zCsr += sqlite3Strlen30(zCsr);
*(zCsr++) = ']';
if( f & MEM_Zero ){
sqlite3_snprintf(100, zCsr,"+%dz",pMem->u.nZero);
zCsr += sqlite3Strlen30(zCsr);
@@ -1669,21 +1665,21 @@ case OP_Function: {
for(i=pCtx->argc-1; i>=0; i--) pCtx->argv[i] = &aMem[pOp->p2+i];
}
memAboutToChange(p, pCtx->pOut);
memAboutToChange(p, pOut);
#ifdef SQLITE_DEBUG
for(i=0; i<pCtx->argc; i++){
assert( memIsValid(pCtx->argv[i]) );
REGISTER_TRACE(pOp->p2+i, pCtx->argv[i]);
}
#endif
MemSetTypeFlag(pCtx->pOut, MEM_Null);
MemSetTypeFlag(pOut, MEM_Null);
pCtx->fErrorOrAux = 0;
(*pCtx->pFunc->xSFunc)(pCtx, pCtx->argc, pCtx->argv);/* IMP: R-24505-23230 */
/* If the function returned an error, throw an exception */
if( pCtx->fErrorOrAux ){
if( pCtx->isError ){
sqlite3VdbeError(p, "%s", sqlite3_value_text(pCtx->pOut));
sqlite3VdbeError(p, "%s", sqlite3_value_text(pOut));
rc = pCtx->isError;
}
sqlite3VdbeDeleteAuxData(db, &p->pAuxData, pCtx->iOp, pOp->p1);
@@ -1692,12 +1688,12 @@ case OP_Function: {
/* Copy the result of the function into register P3 */
if( pOut->flags & (MEM_Str|MEM_Blob) ){
sqlite3VdbeChangeEncoding(pCtx->pOut, encoding);
if( sqlite3VdbeMemTooBig(pCtx->pOut) ) goto too_big;
sqlite3VdbeChangeEncoding(pOut, encoding);
if( sqlite3VdbeMemTooBig(pOut) ) goto too_big;
}
REGISTER_TRACE(pOp->p3, pCtx->pOut);
UPDATE_MAX_BLOBSIZE(pCtx->pOut);
REGISTER_TRACE(pOp->p3, pOut);
UPDATE_MAX_BLOBSIZE(pOut);
break;
}
@@ -2336,19 +2332,39 @@ case OP_BitNot: { /* same as TK_BITNOT, in1, out2 */
/* Opcode: Once P1 P2 * * *
**
** If the P1 value is equal to the P1 value on the OP_Init opcode at
** instruction 0, then jump to P2. If the two P1 values differ, then
** set the P1 value on this opcode to equal the P1 value on the OP_Init
** and fall through.
** Fall through to the next instruction the first time this opcode is
** encountered on each invocation of the byte-code program. Jump to P2
** on the second and all subsequent encounters during the same invocation.
**
** Top-level programs determine first invocation by comparing the P1
** operand against the P1 operand on the OP_Init opcode at the beginning
** of the program. If the P1 values differ, then fall through and make
** the P1 of this opcode equal to the P1 of OP_Init. If P1 values are
** the same then take the jump.
**
** For subprograms, there is a bitmask in the VdbeFrame that determines
** whether or not the jump should be taken. The bitmask is necessary
** because the self-altering code trick does not work for recursive
** triggers.
*/
case OP_Once: { /* jump */
u32 iAddr; /* Address of this instruction */
assert( p->aOp[0].opcode==OP_Init );
VdbeBranchTaken(p->aOp[0].p1==pOp->p1, 2);
if( p->aOp[0].p1==pOp->p1 ){
goto jump_to_p2;
if( p->pFrame ){
iAddr = (int)(pOp - p->aOp);
if( (p->pFrame->aOnce[iAddr/8] & (1<<(iAddr & 7)))!=0 ){
VdbeBranchTaken(1, 2);
goto jump_to_p2;
}
p->pFrame->aOnce[iAddr/8] |= 1<<(iAddr & 7);
}else{
pOp->p1 = p->aOp[0].p1;
if( p->aOp[0].p1==pOp->p1 ){
VdbeBranchTaken(1, 2);
goto jump_to_p2;
}
}
VdbeBranchTaken(0, 2);
pOp->p1 = p->aOp[0].p1;
break;
}
@@ -2424,7 +2440,7 @@ case OP_NotNull: { /* same as TK_NOTNULL, jump, in1 */
**
** The value extracted is stored in register P3.
**
** If the column contains fewer than P2 fields, then extract a NULL. Or,
** If the record contains fewer than P2 fields, then extract a NULL. Or,
** if the P4 argument is a P4_MEM use the value of the P4 argument as
** the result.
**
@@ -2433,7 +2449,7 @@ case OP_NotNull: { /* same as TK_NOTNULL, jump, in1 */
** The first OP_Column against a pseudo-table after the value of the content
** register has changed should have this bit set.
**
** If the OPFLAG_LENGTHARG and OPFLAG_TYPEOFARG bits are set on P5 when
** If the OPFLAG_LENGTHARG and OPFLAG_TYPEOFARG bits are set on P5 then
** the result is guaranteed to only be used as the argument of a length()
** or typeof() function, respectively. The loading of large blobs can be
** skipped for length() and all content loading can be skipped for typeof().
@@ -2661,8 +2677,13 @@ case OP_Column: {
** 2. the length(X) function if X is a blob, and
** 3. if the content length is zero.
** So we might as well use bogus content rather than reading
** content from disk. */
static u8 aZero[8]; /* This is the bogus content */
** content from disk.
**
** Although sqlite3VdbeSerialGet() may read at most 8 bytes from the
** buffer passed to it, debugging function VdbeMemPrettyPrint() may
** read up to 16. So 16 bytes of bogus content is supplied.
*/
static u8 aZero[16]; /* This is the bogus content */
sqlite3VdbeSerialGet(aZero, t, pDest);
}else{
rc = sqlite3VdbeMemFromBtree(pC->uc.pCursor, aOffset[p2], len, pDest);
@@ -2689,18 +2710,18 @@ op_column_out:
*/
case OP_Affinity: {
const char *zAffinity; /* The affinity to be applied */
char cAff; /* A single character of affinity */
zAffinity = pOp->p4.z;
assert( zAffinity!=0 );
assert( pOp->p2>0 );
assert( zAffinity[pOp->p2]==0 );
pIn1 = &aMem[pOp->p1];
while( (cAff = *(zAffinity++))!=0 ){
do{
assert( pIn1 <= &p->aMem[(p->nMem+1 - p->nCursor)] );
assert( memIsValid(pIn1) );
applyAffinity(pIn1, cAff, encoding);
applyAffinity(pIn1, *(zAffinity++), encoding);
pIn1++;
}
}while( zAffinity[0] );
break;
}
@@ -2871,7 +2892,6 @@ case OP_MakeRecord: {
pOut->u.nZero = nZero;
pOut->flags |= MEM_Zero;
}
pOut->enc = SQLITE_UTF8; /* In case the blob is ever converted to text */
REGISTER_TRACE(pOp->p3, pOut);
UPDATE_MAX_BLOBSIZE(pOut);
break;
@@ -4056,7 +4076,7 @@ case OP_Found: { /* jump, in3 */
}
}
rc = sqlite3BtreeMovetoUnpacked(pC->uc.pCursor, pIdxKey, 0, 0, &res);
if( pFree ) sqlite3DbFree(db, pFree);
if( pFree ) sqlite3DbFreeNN(db, pFree);
if( rc!=SQLITE_OK ){
goto abort_due_to_error;
}
@@ -4847,6 +4867,33 @@ case OP_Last: { /* jump */
break;
}
/* Opcode: IfSmaller P1 P2 P3 * *
**
** Estimate the number of rows in the table P1. Jump to P2 if that
** estimate is less than approximately 2**(0.1*P3).
*/
case OP_IfSmaller: { /* jump */
VdbeCursor *pC;
BtCursor *pCrsr;
int res;
i64 sz;
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
pCrsr = pC->uc.pCursor;
assert( pCrsr );
rc = sqlite3BtreeFirst(pCrsr, &res);
if( rc ) goto abort_due_to_error;
if( res==0 ){
sz = sqlite3BtreeRowCountEst(pCrsr);
if( ALWAYS(sz>=0) && sqlite3LogEst((u64)sz)<pOp->p3 ) res = 1;
}
VdbeBranchTaken(res!=0,2);
if( res ) goto jump_to_p2;
break;
}
/* Opcode: SorterSort P1 P2 * * *
**
@@ -5491,6 +5538,18 @@ case OP_CreateTable: { /* out2 */
break;
}
/* Opcode: SqlExec * * * P4 *
**
** Run the SQL statement or statements specified in the P4 string.
*/
case OP_SqlExec: {
db->nSqlExec++;
rc = sqlite3_exec(db, pOp->p4.z, 0, 0, 0);
db->nSqlExec--;
if( rc ) goto abort_due_to_error;
break;
}
/* Opcode: ParseSchema P1 * * P4 *
**
** Read and parse all entries from the SQLITE_MASTER table of database P1
@@ -5535,7 +5594,7 @@ case OP_ParseSchema: {
assert( !db->mallocFailed );
rc = sqlite3_exec(db, zSql, sqlite3InitCallback, &initData, 0);
if( rc==SQLITE_OK ) rc = initData.rc;
sqlite3DbFree(db, zSql);
sqlite3DbFreeNN(db, zSql);
db->init.busy = 0;
}
}
@@ -5611,7 +5670,7 @@ case OP_DropTrigger: {
** register P1 the text of an error message describing any problems.
** If no problems are found, store a NULL in register P1.
**
** The register P3 contains the maximum number of allowed errors.
** The register P3 contains one less than the maximum number of allowed errors.
** At most reg(P3) errors will be reported.
** In other words, the analysis stops as soon as reg(P1) errors are
** seen. Reg(P1) is updated with the number of errors remaining.
@@ -5644,14 +5703,14 @@ case OP_IntegrityCk: {
assert( pOp->p5<db->nDb );
assert( DbMaskTest(p->btreeMask, pOp->p5) );
z = sqlite3BtreeIntegrityCheck(db->aDb[pOp->p5].pBt, aRoot, nRoot,
(int)pnErr->u.i, &nErr);
pnErr->u.i -= nErr;
(int)pnErr->u.i+1, &nErr);
sqlite3VdbeMemSetNull(pIn1);
if( nErr==0 ){
assert( z==0 );
}else if( z==0 ){
goto no_mem;
}else{
pnErr->u.i -= nErr-1;
sqlite3VdbeMemSetStr(pIn1, z, -1, SQLITE_UTF8, sqlite3_free);
}
UPDATE_MAX_BLOBSIZE(pIn1);
@@ -5830,7 +5889,8 @@ case OP_Program: { /* jump */
if( pProgram->nCsr==0 ) nMem++;
nByte = ROUND8(sizeof(VdbeFrame))
+ nMem * sizeof(Mem)
+ pProgram->nCsr * sizeof(VdbeCursor *);
+ pProgram->nCsr * sizeof(VdbeCursor*)
+ (pProgram->nOp + 7)/8;
pFrame = sqlite3DbMallocZero(db, nByte);
if( !pFrame ){
goto no_mem;
@@ -5881,6 +5941,8 @@ case OP_Program: { /* jump */
p->nMem = pFrame->nChildMem;
p->nCursor = (u16)pFrame->nChildCsr;
p->apCsr = (VdbeCursor **)&aMem[p->nMem];
pFrame->aOnce = (u8*)&p->apCsr[pProgram->nCsr];
memset(pFrame->aOnce, 0, (pProgram->nOp + 7)/8);
p->aOp = aOp = pProgram->aOp;
p->nOp = pProgram->nOp;
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
@@ -6910,7 +6972,11 @@ case OP_Init: { /* jump */
sqlite3_free(z);
}else
#endif
{
if( db->nVdbeExec>1 ){
char *z = sqlite3MPrintf(db, "-- %s", zTrace);
(void)db->xTrace(SQLITE_TRACE_STMT, db->pTraceArg, p, z);
sqlite3DbFree(db, z);
}else{
(void)db->xTrace(SQLITE_TRACE_STMT, db->pTraceArg, p, zTrace);
}
}
+1
View File
@@ -87,6 +87,7 @@ struct SubProgram {
int nOp; /* Elements in aOp[] */
int nMem; /* Number of memory cells required */
int nCsr; /* Number of cursors required */
u8 *aOnce; /* Array of OP_Once flags */
void *token; /* id that may be used to recursive triggers */
SubProgram *pNext; /* Next sub-program already visited */
};
+1
View File
@@ -164,6 +164,7 @@ struct VdbeFrame {
i64 *anExec; /* Event counters from parent frame */
Mem *aMem; /* Array of memory cells for parent frame */
VdbeCursor **apCsr; /* Array of Vdbe cursors for parent frame */
u8 *aOnce; /* Bitmask used by OP_Once */
void *token; /* Copy of SubProgram.token */
i64 lastRowid; /* Last insert rowid (sqlite3.lastRowid) */
AuxData *pAuxData; /* Linked list of auxdata allocations */
+8 -6
View File
@@ -154,7 +154,8 @@ int sqlite3_clear_bindings(sqlite3_stmt *pStmt){
sqlite3VdbeMemRelease(&p->aVar[i]);
p->aVar[i].flags = MEM_Null;
}
if( p->isPrepareV2 && p->expmask ){
assert( p->isPrepareV2 || p->expmask==0 );
if( p->expmask ){
p->expired = 1;
}
sqlite3_mutex_leave(mutex);
@@ -1258,9 +1259,8 @@ static int vdbeUnbind(Vdbe *p, int i){
** as if there had been a schema change, on the first sqlite3_step() call
** following any change to the bindings of that parameter.
*/
if( p->isPrepareV2 &&
((i<32 && p->expmask & ((u32)1 << i)) || p->expmask==0xffffffff)
){
assert( p->isPrepareV2 || p->expmask==0 );
if( p->expmask!=0 && (p->expmask & (i>=31 ? 0x80000000 : (u32)1<<i))!=0 ){
p->expired = 1;
}
return SQLITE_OK;
@@ -1523,10 +1523,12 @@ int sqlite3_transfer_bindings(sqlite3_stmt *pFromStmt, sqlite3_stmt *pToStmt){
if( pFrom->nVar!=pTo->nVar ){
return SQLITE_ERROR;
}
if( pTo->isPrepareV2 && pTo->expmask ){
assert( pTo->isPrepareV2 || pTo->expmask==0 );
if( pTo->expmask ){
pTo->expired = 1;
}
if( pFrom->isPrepareV2 && pFrom->expmask ){
assert( pFrom->isPrepareV2 || pFrom->expmask==0 );
if( pFrom->expmask ){
pFrom->expired = 1;
}
return sqlite3TransferBindings(pFromStmt, pToStmt);
+21 -14
View File
@@ -57,6 +57,7 @@ void sqlite3VdbeError(Vdbe *p, const char *zFormat, ...){
void sqlite3VdbeSetSql(Vdbe *p, const char *z, int n, int isPrepareV2){
assert( isPrepareV2==1 || isPrepareV2==0 );
if( p==0 ) return;
if( !isPrepareV2 ) p->expmask = 0;
#if defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_ENABLE_SQLLOG)
if( !isPrepareV2 ) return;
#endif
@@ -85,6 +86,7 @@ void sqlite3VdbeSwap(Vdbe *pA, Vdbe *pB){
pA->zSql = pB->zSql;
pB->zSql = zTmp;
pB->isPrepareV2 = pA->isPrepareV2;
pB->expmask = pA->expmask;
}
/*
@@ -115,6 +117,12 @@ static int growOpArray(Vdbe *v, int nOp){
UNUSED_PARAMETER(nOp);
#endif
/* Ensure that the size of a VDBE does not grow too large */
if( nNew > p->db->aLimit[SQLITE_LIMIT_VDBE_OP] ){
sqlite3OomFault(p->db);
return SQLITE_NOMEM;
}
assert( nOp<=(1024/sizeof(Op)) );
assert( nNew>=(p->nOpAlloc+nOp) );
pNew = sqlite3DbRealloc(p->db, v->aOp, nNew*sizeof(Op));
@@ -803,7 +811,7 @@ void sqlite3VdbeJumpHere(Vdbe *p, int addr){
*/
static void freeEphemeralFunction(sqlite3 *db, FuncDef *pDef){
if( (pDef->funcFlags & SQLITE_FUNC_EPHEM)!=0 ){
sqlite3DbFree(db, pDef);
sqlite3DbFreeNN(db, pDef);
}
}
@@ -814,11 +822,11 @@ static void vdbeFreeOpArray(sqlite3 *, Op *, int);
*/
static SQLITE_NOINLINE void freeP4Mem(sqlite3 *db, Mem *p){
if( p->szMalloc ) sqlite3DbFree(db, p->zMalloc);
sqlite3DbFree(db, p);
sqlite3DbFreeNN(db, p);
}
static SQLITE_NOINLINE void freeP4FuncCtx(sqlite3 *db, sqlite3_context *p){
freeEphemeralFunction(db, p->pFunc);
sqlite3DbFree(db, p);
sqlite3DbFreeNN(db, p);
}
static void freeP4(sqlite3 *db, int p4type, void *p4){
assert( db );
@@ -877,8 +885,8 @@ static void vdbeFreeOpArray(sqlite3 *db, Op *aOp, int nOp){
sqlite3DbFree(db, pOp->zComment);
#endif
}
sqlite3DbFreeNN(db, aOp);
}
sqlite3DbFree(db, aOp);
}
/*
@@ -1551,7 +1559,7 @@ static void releaseMemArray(Mem *p, int N){
if( p->flags&(MEM_Agg|MEM_Dyn|MEM_Frame|MEM_RowSet) ){
sqlite3VdbeMemRelease(p);
}else if( p->szMalloc ){
sqlite3DbFree(db, p->zMalloc);
sqlite3DbFreeNN(db, p->zMalloc);
p->szMalloc = 0;
}
@@ -2609,13 +2617,13 @@ int sqlite3VdbeHalt(Vdbe *p){
** one, or the complete transaction if there is no statement transaction.
*/
if( p->magic!=VDBE_MAGIC_RUN ){
return SQLITE_OK;
}
if( db->mallocFailed ){
p->rc = SQLITE_NOMEM_BKPT;
}
closeAllCursors(p);
if( p->magic!=VDBE_MAGIC_RUN ){
return SQLITE_OK;
}
checkActiveVdbeCnt(db);
/* No commit or rollback needed if the program never started or if the
@@ -2922,7 +2930,6 @@ int sqlite3VdbeReset(Vdbe *p){
}
}
#endif
p->iCurrentTime = 0;
p->magic = VDBE_MAGIC_RESET;
return p->rc & db->errMask;
}
@@ -3032,7 +3039,7 @@ void sqlite3VdbeDelete(Vdbe *p){
}
p->magic = VDBE_MAGIC_DEAD;
p->db = 0;
sqlite3DbFree(db, p);
sqlite3DbFreeNN(db, p);
}
/*
@@ -4550,8 +4557,8 @@ sqlite3_value *sqlite3VdbeGetBoundValue(Vdbe *v, int iVar, u8 aff){
*/
void sqlite3VdbeSetVarmask(Vdbe *v, int iVar){
assert( iVar>0 );
if( iVar>32 ){
v->expmask = 0xffffffff;
if( iVar>=32 ){
v->expmask |= 0x80000000;
}else{
v->expmask |= ((u32)1 << (iVar-1));
}
@@ -4591,7 +4598,7 @@ static void vdbeFreeUnpacked(sqlite3 *db, int nField, UnpackedRecord *p){
Mem *pMem = &p->aMem[i];
if( pMem->zMalloc ) sqlite3VdbeMemRelease(pMem);
}
sqlite3DbFree(db, p);
sqlite3DbFreeNN(db, p);
}
}
#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */
@@ -4658,7 +4665,7 @@ void sqlite3VdbePreUpdateHook(
for(i=0; i<pCsr->nField; i++){
sqlite3VdbeMemRelease(&preupdate.aNew[i]);
}
sqlite3DbFree(db, preupdate.aNew);
sqlite3DbFreeNN(db, preupdate.aNew);
}
}
#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */
+22 -16
View File
@@ -131,7 +131,7 @@ SQLITE_NOINLINE int sqlite3VdbeMemGrow(Mem *pMem, int n, int bPreserve){
pMem->z = pMem->zMalloc = sqlite3DbReallocOrFree(pMem->db, pMem->z, n);
bPreserve = 0;
}else{
if( pMem->szMalloc>0 ) sqlite3DbFree(pMem->db, pMem->zMalloc);
if( pMem->szMalloc>0 ) sqlite3DbFreeNN(pMem->db, pMem->zMalloc);
pMem->zMalloc = sqlite3DbMallocRaw(pMem->db, n);
}
if( pMem->zMalloc==0 ){
@@ -341,7 +341,7 @@ int sqlite3VdbeMemFinalize(Mem *pMem, FuncDef *pFunc){
ctx.pFunc = pFunc;
pFunc->xFinalize(&ctx); /* IMP: R-24505-23230 */
assert( (pMem->flags & MEM_Dyn)==0 );
if( pMem->szMalloc>0 ) sqlite3DbFree(pMem->db, pMem->zMalloc);
if( pMem->szMalloc>0 ) sqlite3DbFreeNN(pMem->db, pMem->zMalloc);
memcpy(pMem, &t, sizeof(t));
rc = ctx.isError;
}
@@ -392,7 +392,7 @@ static SQLITE_NOINLINE void vdbeMemClear(Mem *p){
vdbeMemClearExternAndSetNull(p);
}
if( p->szMalloc ){
sqlite3DbFree(p->db, p->zMalloc);
sqlite3DbFreeNN(p->db, p->zMalloc);
p->szMalloc = 0;
}
p->z = 0;
@@ -420,7 +420,7 @@ void sqlite3VdbeMemRelease(Mem *p){
** If the double is out of range of a 64-bit signed integer then
** return the closest available 64-bit signed integer.
*/
static i64 doubleToInt64(double r){
static SQLITE_NOINLINE i64 doubleToInt64(double r){
#ifdef SQLITE_OMIT_FLOATING_POINT
/* When floating-point is omitted, double and int64 are the same thing */
return r;
@@ -456,6 +456,11 @@ static i64 doubleToInt64(double r){
**
** If pMem represents a string value, its encoding might be changed.
*/
static SQLITE_NOINLINE i64 memIntValue(Mem *pMem){
i64 value = 0;
sqlite3Atoi64(pMem->z, &value, pMem->n, pMem->enc);
return value;
}
i64 sqlite3VdbeIntValue(Mem *pMem){
int flags;
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
@@ -466,10 +471,8 @@ i64 sqlite3VdbeIntValue(Mem *pMem){
}else if( flags & MEM_Real ){
return doubleToInt64(pMem->u.r);
}else if( flags & (MEM_Str|MEM_Blob) ){
i64 value = 0;
assert( pMem->z || pMem->n==0 );
sqlite3Atoi64(pMem->z, &value, pMem->n, pMem->enc);
return value;
return memIntValue(pMem);
}else{
return 0;
}
@@ -481,6 +484,12 @@ i64 sqlite3VdbeIntValue(Mem *pMem){
** value. If it is a string or blob, try to convert it to a double.
** If it is a NULL, return 0.0.
*/
static SQLITE_NOINLINE double memRealValue(Mem *pMem){
/* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */
double val = (double)0;
sqlite3AtoF(pMem->z, &val, pMem->n, pMem->enc);
return val;
}
double sqlite3VdbeRealValue(Mem *pMem){
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
assert( EIGHT_BYTE_ALIGNMENT(pMem) );
@@ -489,10 +498,7 @@ double sqlite3VdbeRealValue(Mem *pMem){
}else if( pMem->flags & MEM_Int ){
return (double)pMem->u.i;
}else if( pMem->flags & (MEM_Str|MEM_Blob) ){
/* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */
double val = (double)0;
sqlite3AtoF(pMem->z, &val, pMem->n, pMem->enc);
return val;
return memRealValue(pMem);
}else{
/* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */
return (double)0;
@@ -1117,7 +1123,7 @@ static sqlite3_value *valueNew(sqlite3 *db, struct ValueNewStat4Ctx *p){
pRec->aMem[i].db = db;
}
}else{
sqlite3DbFree(db, pRec);
sqlite3DbFreeNN(db, pRec);
pRec = 0;
}
}
@@ -1229,7 +1235,7 @@ static int valueFromFunction(
for(i=0; i<nVal; i++){
sqlite3ValueFree(apVal[i]);
}
sqlite3DbFree(db, apVal);
sqlite3DbFreeNN(db, apVal);
}
*ppVal = pVal;
@@ -1428,7 +1434,7 @@ static void recordFunc(
putVarint32(&aRet[1], iSerial);
sqlite3VdbeSerialPut(&aRet[1+nSerial], argv[0], iSerial);
sqlite3_result_blob(context, aRet, nRet, SQLITE_TRANSIENT);
sqlite3DbFree(db, aRet);
sqlite3DbFreeNN(db, aRet);
}
}
@@ -1655,7 +1661,7 @@ void sqlite3Stat4ProbeFree(UnpackedRecord *pRec){
sqlite3VdbeMemRelease(&aMem[i]);
}
sqlite3KeyInfoUnref(pRec->pKeyInfo);
sqlite3DbFree(db, pRec);
sqlite3DbFreeNN(db, pRec);
}
}
#endif /* ifdef SQLITE_ENABLE_STAT4 */
@@ -1679,7 +1685,7 @@ void sqlite3ValueSetStr(
void sqlite3ValueFree(sqlite3_value *v){
if( !v ) return;
sqlite3VdbeMemRelease((Mem *)v);
sqlite3DbFree(((Mem*)v)->db, v);
sqlite3DbFreeNN(((Mem*)v)->db, v);
}
/*
+26 -27
View File
@@ -858,37 +858,36 @@ static int vdbeSorterCompareInt(
assert( (s1>0 && s1<7) || s1==8 || s1==9 );
assert( (s2>0 && s2<7) || s2==8 || s2==9 );
if( s1>7 && s2>7 ){
if( s1==s2 ){
/* The two values have the same sign. Compare using memcmp(). */
static const u8 aLen[] = {0, 1, 2, 3, 4, 6, 8, 0, 0, 0 };
const u8 n = aLen[s1];
int i;
res = 0;
for(i=0; i<n; i++){
if( (res = v1[i] - v2[i])!=0 ){
if( ((v1[0] ^ v2[0]) & 0x80)!=0 ){
res = v1[0] & 0x80 ? -1 : +1;
}
break;
}
}
}else if( s1>7 && s2>7 ){
res = s1 - s2;
}else{
if( s1==s2 ){
if( (*v1 ^ *v2) & 0x80 ){
/* The two values have different signs */
res = (*v1 & 0x80) ? -1 : +1;
}else{
/* The two values have the same sign. Compare using memcmp(). */
static const u8 aLen[] = {0, 1, 2, 3, 4, 6, 8 };
int i;
res = 0;
for(i=0; i<aLen[s1]; i++){
if( (res = v1[i] - v2[i]) ) break;
}
}
if( s2>7 ){
res = +1;
}else if( s1>7 ){
res = -1;
}else{
if( s2>7 ){
res = +1;
}else if( s1>7 ){
res = -1;
}else{
res = s1 - s2;
}
assert( res!=0 );
res = s1 - s2;
}
assert( res!=0 );
if( res>0 ){
if( *v1 & 0x80 ) res = -1;
}else{
if( *v2 & 0x80 ) res = +1;
}
if( res>0 ){
if( *v1 & 0x80 ) res = -1;
}else{
if( *v2 & 0x80 ) res = +1;
}
}
+2 -2
View File
@@ -27,11 +27,11 @@
**
** WRC_Continue Continue descending down the tree.
**
** WRC_Prune Do not descend into child nodes. But allow
** WRC_Prune Do not descend into child nodes, but allow
** the walk to continue with sibling nodes.
**
** WRC_Abort Do no more callbacks. Unwind the stack and
** return the top-level walk call.
** return from the top-level walk call.
**
** The return value from this routine is WRC_Abort to abandon the tree walk
** and WRC_Continue to continue.
+32 -13
View File
@@ -517,14 +517,16 @@ static LogEst estLog(LogEst N){
** value stored in its output register.
*/
static void translateColumnToCopy(
Vdbe *v, /* The VDBE containing code to translate */
Parse *pParse, /* Parsing context */
int iStart, /* Translate from this opcode to the end */
int iTabCur, /* OP_Column/OP_Rowid references to this table */
int iRegister, /* The first column is in this register */
int bIncrRowid /* If non-zero, transform OP_rowid to OP_AddImm(1) */
){
Vdbe *v = pParse->pVdbe;
VdbeOp *pOp = sqlite3VdbeGetOp(v, iStart);
int iEnd = sqlite3VdbeCurrentAddr(v);
if( pParse->db->mallocFailed ) return;
for(; iStart<iEnd; iStart++, pOp++){
if( pOp->p1!=iTabCur ) continue;
if( pOp->opcode==OP_Column ){
@@ -802,7 +804,9 @@ static void constructAutomaticIndex(
if( pPartial ) sqlite3VdbeResolveLabel(v, iContinue);
if( pTabItem->fg.viaCoroutine ){
sqlite3VdbeChangeP2(v, addrCounter, regBase+n);
translateColumnToCopy(v, addrTop, pLevel->iTabCur, pTabItem->regResult, 1);
testcase( pParse->db->mallocFailed );
translateColumnToCopy(pParse, addrTop, pLevel->iTabCur,
pTabItem->regResult, 1);
sqlite3VdbeGoto(v, addrTop);
pTabItem->fg.viaCoroutine = 0;
}else{
@@ -1782,7 +1786,7 @@ static void whereLoopClearUnion(sqlite3 *db, WhereLoop *p){
p->u.vtab.idxStr = 0;
}else if( (p->wsFlags & WHERE_AUTO_INDEX)!=0 && p->u.btree.pIndex!=0 ){
sqlite3DbFree(db, p->u.btree.pIndex->zColAff);
sqlite3DbFree(db, p->u.btree.pIndex);
sqlite3DbFreeNN(db, p->u.btree.pIndex);
p->u.btree.pIndex = 0;
}
}
@@ -1792,7 +1796,7 @@ static void whereLoopClearUnion(sqlite3 *db, WhereLoop *p){
** Deallocate internal memory used by a WhereLoop object
*/
static void whereLoopClear(sqlite3 *db, WhereLoop *p){
if( p->aLTerm!=p->aLTermSpace ) sqlite3DbFree(db, p->aLTerm);
if( p->aLTerm!=p->aLTermSpace ) sqlite3DbFreeNN(db, p->aLTerm);
whereLoopClearUnion(db, p);
whereLoopInit(p);
}
@@ -1807,7 +1811,7 @@ static int whereLoopResize(sqlite3 *db, WhereLoop *p, int n){
paNew = sqlite3DbMallocRawNN(db, sizeof(p->aLTerm[0])*n);
if( paNew==0 ) return SQLITE_NOMEM_BKPT;
memcpy(paNew, p->aLTerm, sizeof(p->aLTerm[0])*p->nLSlot);
if( p->aLTerm!=p->aLTermSpace ) sqlite3DbFree(db, p->aLTerm);
if( p->aLTerm!=p->aLTermSpace ) sqlite3DbFreeNN(db, p->aLTerm);
p->aLTerm = paNew;
p->nLSlot = n;
return SQLITE_OK;
@@ -1837,7 +1841,7 @@ static int whereLoopXfer(sqlite3 *db, WhereLoop *pTo, WhereLoop *pFrom){
*/
static void whereLoopDelete(sqlite3 *db, WhereLoop *p){
whereLoopClear(db, p);
sqlite3DbFree(db, p);
sqlite3DbFreeNN(db, p);
}
/*
@@ -1858,7 +1862,7 @@ static void whereInfoFree(sqlite3 *db, WhereInfo *pWInfo){
pWInfo->pLoops = p->pNextLoop;
whereLoopDelete(db, p);
}
sqlite3DbFree(db, pWInfo);
sqlite3DbFreeNN(db, pWInfo);
}
}
@@ -2387,6 +2391,11 @@ static int whereLoopAddBtreeIndex(
continue;
}
if( IsUniqueIndex(pProbe) && saved_nEq==pProbe->nKeyCol-1 ){
pBuilder->bldFlags |= SQLITE_BLDF_UNIQUE;
}else{
pBuilder->bldFlags |= SQLITE_BLDF_INDEXED;
}
pNew->wsFlags = saved_wsFlags;
pNew->u.btree.nEq = saved_nEq;
pNew->u.btree.nBtm = saved_nBtm;
@@ -2934,7 +2943,15 @@ static int whereLoopAddBtree(
}
}
pBuilder->bldFlags = 0;
rc = whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, 0);
if( pBuilder->bldFlags==SQLITE_BLDF_INDEXED ){
/* If a non-unique index is used, or if a prefix of the key for
** unique index is used (making the index functionally non-unique)
** then the sqlite_stat1 data becomes important for scoring the
** plan */
pTab->tabFlags |= TF_StatsUsed;
}
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
sqlite3Stat4ProbeFree(pBuilder->pRec);
pBuilder->nRecValid = 0;
@@ -3236,7 +3253,7 @@ static int whereLoopAddVirtual(
}
if( p->needToFreeIdxStr ) sqlite3_free(p->idxStr);
sqlite3DbFree(pParse->db, p);
sqlite3DbFreeNN(pParse->db, p);
return rc;
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */
@@ -4091,7 +4108,7 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
if( nFrom==0 ){
sqlite3ErrorMsg(pParse, "no query solution");
sqlite3DbFree(db, pSpace);
sqlite3DbFreeNN(db, pSpace);
return SQLITE_ERROR;
}
@@ -4167,7 +4184,7 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
pWInfo->nRowOut = pFrom->nRow;
/* Free temporary memory and return success */
sqlite3DbFree(db, pSpace);
sqlite3DbFreeNN(db, pSpace);
return SQLITE_OK;
}
@@ -4245,7 +4262,8 @@ static int whereShortCut(WhereLoopBuilder *pBuilder){
if( pLoop->wsFlags ){
pLoop->nOut = (LogEst)1;
pWInfo->a[0].pWLoop = pLoop;
pLoop->maskSelf = sqlite3WhereGetMask(&pWInfo->sMaskSet, iCur);
assert( pWInfo->sMaskSet.n==1 && iCur==pWInfo->sMaskSet.ix[0] );
pLoop->maskSelf = 1; /* sqlite3WhereGetMask(&pWInfo->sMaskSet, iCur); */
pWInfo->a[0].iTabCur = iCur;
pWInfo->nRowOut = 1;
if( pWInfo->pOrderBy ) pWInfo->nOBSat = pWInfo->pOrderBy->nExpr;
@@ -4907,8 +4925,9 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
** the co-routine into OP_Copy of result contained in a register.
** OP_Rowid becomes OP_Null.
*/
if( pTabItem->fg.viaCoroutine && !db->mallocFailed ){
translateColumnToCopy(v, pLevel->addrBody, pLevel->iTabCur,
if( pTabItem->fg.viaCoroutine ){
testcase( pParse->db->mallocFailed );
translateColumnToCopy(pParse, pLevel->addrBody, pLevel->iTabCur,
pTabItem->regResult, 0);
continue;
}
+5
View File
@@ -395,8 +395,13 @@ struct WhereLoopBuilder {
UnpackedRecord *pRec; /* Probe for stat4 (if required) */
int nRecValid; /* Number of valid fields currently in pRec */
#endif
unsigned int bldFlags; /* SQLITE_BLDF_* flags */
};
/* Allowed values for WhereLoopBuider.bldFlags */
#define SQLITE_BLDF_INDEXED 0x0001 /* An index is used */
#define SQLITE_BLDF_UNIQUE 0x0002 /* All keys of a UNIQUE index used */
/*
** The WHERE clause processing routine has two halves. The
** first part does the start of the WHERE loop and the second
+123
View File
@@ -0,0 +1,123 @@
# 2017-02-17
#
# 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 tests for the logic used to estimate when
# running ANALYZE would be beneficial.
#
# Note that this test uses some hard-coded bitmask values from sqliteInt.h.
# If any of the following constants changes:
#
# define TF_HasStat1 0x0010
# define TF_StatsUsed 0x0100
#
# then some of the magic numbers in test results below might need to be
# adjusted.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
# There is nothing to test if ANALYZE is disable for this build.
# These tests also use "PRAGMA stats" which are only enabled for
# debugging builds.
#
ifcapable {!debug || !analyze || !vtab} {
finish_test
return
}
do_execsql_test autoanalyze1-100 {
-- Build up a test table with some indexes
CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c, d);
CREATE UNIQUE INDEX t1bc ON t1(b,c);
CREATE INDEX t1d ON t1(d);
WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<100)
INSERT INTO t1(a,b,c,d) SELECT x, x, x, x FROM c;
-- Verify that the hasStat1 flag is clear on on indexes
SELECT idx, flgs FROM pragma_stats
WHERE idx IS NOT NULL
ORDER BY idx;
-- Verify that the TF_HasStat1 flag is clear on the table
SELECT tbl, (flgs & 0x10)!=0 FROM pragma_stats WHERE tbl='t1' AND idx IS NULL;
} {t1bc 0 t1d 0 t1 0}
# No use of stat1 recorded so far
do_execsql_test autoanalyze1-110 {
SELECT (flgs & 0x0100)!=0 FROM pragma_stats WHERE tbl='t1' AND idx IS NULL;
} {0}
# Access using a unique index does not set the TF_StatsUsed flag.
#
do_execsql_test autoanalyze1-200 {
SELECT * FROM t1 WHERE a=55;
} {55 55 55 55}
do_execsql_test autoanalyze1-201 {
SELECT (flgs & 0x0100)!=0 FROM pragma_stats WHERE tbl='t1' AND idx IS NULL;
} {0}
do_execsql_test autoanalyze1-210 {
SELECT * FROM t1 WHERE a IN (55,199,299);
} {55 55 55 55}
do_execsql_test autoanalyze1-211 {
SELECT (flgs & 0x0100)!=0 FROM pragma_stats WHERE tbl='t1' AND idx IS NULL;
} {0}
do_execsql_test autoanalyze1-220 {
SELECT * FROM t1 WHERE (b,c)=(45,45);
} {45 45 45 45}
do_execsql_test autoanalyze1-221 {
SELECT (flgs & 0x0100)!=0 FROM pragma_stats WHERE tbl='t1' AND idx IS NULL;
} {0}
# Any use of the non-unique t1d index triggers the use of stats.
#
sqlite3 db test.db
do_execsql_test autoanalyze1-300 {
SELECT * FROM t1 WHERE d=45;
} {45 45 45 45}
do_execsql_test autoanalyze1-301 {
SELECT (flgs & 0x0100)!=0 FROM pragma_stats WHERE tbl='t1' AND idx IS NULL;
} {1}
sqlite3 db test.db
do_execsql_test autoanalyze1-310 {
SELECT * FROM t1 WHERE d=45 AND a=45;
} {45 45 45 45}
do_execsql_test autoanalyze1-311 {
SELECT (flgs & 0x0100)!=0 FROM pragma_stats WHERE tbl='t1' AND idx IS NULL;
} {0} ;# The ROWID lookup short-circuits the d=45 constraint
sqlite3 db test.db
do_execsql_test autoanalyze1-320 {
SELECT * FROM t1 WHERE d=45 AND a IN (45,46);
} {45 45 45 45}
do_execsql_test autoanalyze1-321 {
SELECT (flgs & 0x0100)!=0 FROM pragma_stats WHERE tbl='t1' AND idx IS NULL;
} {1}
# Any use of prefix of a unique index triggers the use of stats
#
sqlite3 db test.db
do_execsql_test autoanalyze1-400 {
SELECT * FROM t1 WHERE b=45;
} {45 45 45 45}
do_execsql_test autoanalyze1-401 {
SELECT (flgs & 0x0100)!=0 FROM pragma_stats WHERE tbl='t1' AND idx IS NULL;
} {1}
# The TF_StatsUsed flag is reset when the database is reopened
#
sqlite3 db test.db
do_execsql_test autoanalyze1-500 {
SELECT (flgs & 0x0100)!=0 FROM pragma_stats WHERE tbl='t1' AND idx IS NULL;
} {0}
finish_test
+17 -3
View File
@@ -309,11 +309,15 @@ do_test check-4.8 {
PRAGMA ignore_check_constraints=ON;
UPDATE t4 SET x=0, y=1;
SELECT * FROM t4;
PRAGMA integrity_check;
}
} {0 1}
} {0 1 ok}
do_execsql_test check-4.8.1 {
PRAGMA ignore_check_constraints=OFF;
PRAGMA integrity_check;
} {{CHECK constraint failed in t4}}
do_test check-4.9 {
catchsql {
PRAGMA ignore_check_constraints=OFF;
UPDATE t4 SET x=0, y=2;
}
} {1 {CHECK constraint failed: t4}}
@@ -477,6 +481,16 @@ do_catchsql_test 9.3 {
UPDATE t1 SET c=a*2 WHERE a=1;
} {1 {CHECK constraint failed: c-check}}
# Integrity check on a VIEW with columns.
#
db close
db2 close
forcedelete test.db
sqlite3 db test.db
do_execsql_test 10.1 {
CREATE TABLE t1(x);
CREATE VIEW v1(y) AS SELECT x FROM t1;
PRAGMA integrity_check;
} {ok}
finish_test
+14
View File
@@ -13,6 +13,7 @@
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix collateB
do_execsql_test collateB-1.1 {
CREATE TABLE t1(a INTEGER PRIMARY KEY);
@@ -60,4 +61,17 @@ do_execsql_test collateB-1.17 {
SELECT *,'|' FROM t1, t2, t3 WHERE b=x2 AND a=x1 AND 1=a;
} {1 11 1 11 |}
#-------------------------------------------------------------------------
# Test an assert() failure that was occuring if an index were created
# on a column explicitly declared "COLLATE binary".
reset_db
do_execsql_test 2.1 {
CREATE TABLE t4(a COLLATE binary);
CREATE INDEX i4 ON t4(a);
INSERT INTO t4 VALUES('one'), ('two'), ('three');
VACUUM;
}
integrity_check 2.2
finish_test
+113
View File
@@ -0,0 +1,113 @@
# 2017-03-03
#
# 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.
#
#***********************************************************************
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix corruptK
if {[permutation]=="mmap"} {
finish_test
return
}
# This module uses hard-coded offsets which do not work if the reserved_bytes
# value is nonzero.
if {[nonzero_reserved_bytes]} {finish_test; return;}
database_may_be_corrupt
# Initialize the database.
#
do_execsql_test 1.1 {
PRAGMA page_size=1024;
PRAGMA auto_vacuum=0;
CREATE TABLE t1(x);
INSERT INTO t1 VALUES(randomblob(20));
INSERT INTO t1 VALUES(randomblob(100)); -- make this into a free slot
INSERT INTO t1 VALUES(randomblob(27)); -- this one will be corrupt
INSERT INTO t1 VALUES(randomblob(800));
DELETE FROM t1 WHERE rowid=2; -- free the 100 byte slot
PRAGMA page_count
} {2}
# Corrupt the database so that the blob stored immediately before
# the free slot (rowid==3) has an overlarge length field. So that
# we can use sqlite3_blob_write() to manipulate the size field of
# the free slot.
#
# Then use sqlite3_blob_write() to set the size of said free slot
# to 24 bytes (instead of the actual 100).
#
# Then use the new 24 byte slot. Leaving the in-memory version of
# the page with zero free slots and a large nFree value. Then try
# to allocate another slot to get to defragmentPage().
#
do_test 1.2 {
db close
hexio_write test.db [expr 1024 + 0x360] 21
hexio_write test.db [expr 1024 + 0x363] [format %x [expr 31*2 + 12]]
sqlite3 db test.db
set fd [db incrblob t1 x 3]
fconfigure $fd -translation binary -encoding binary
seek $fd 30
puts -nonewline $fd "\x18"
close $fd
} {}
do_execsql_test 1.3 {
INSERT INTO t1 VALUES(randomblob(20));
}
do_catchsql_test 1.4 {
INSERT INTO t1 VALUES(randomblob(90));
} {1 {database disk image is malformed}}
#-------------------------------------------------------------------------
reset_db
do_execsql_test 2.1 {
PRAGMA page_size=1024;
PRAGMA auto_vacuum=0;
CREATE TABLE t1(x);
INSERT INTO t1 VALUES(randomblob(20));
INSERT INTO t1 VALUES(randomblob(20)); -- free this one
INSERT INTO t1 VALUES(randomblob(20));
INSERT INTO t1 VALUES(randomblob(20)); -- and this one
INSERT INTO t1 VALUES(randomblob(20)); -- corrupt this one.
DELETE FROM t1 WHERE rowid IN(2, 4);
PRAGMA page_count
} {2}
do_test 2.2 {
db close
hexio_write test.db [expr 1024 + 0x388] 53
hexio_write test.db [expr 1024 + 0x38A] 03812C
sqlite3 db test.db
set fd [db incrblob t1 x 5]
fconfigure $fd -translation binary -encoding binary
seek $fd 22
puts -nonewline $fd "\x5d"
close $fd
} {}
do_catchsql_test 2.3 {
INSERT INTO t1 VALUES(randomblob(900));
} {1 {database disk image is malformed}}
finish_test
+12
View File
@@ -596,5 +596,17 @@ datetest 16.29 {datetime(5373484,'-176546 months')} NULL
datetest 16.30 {datetime(5373484,'-14712 years')} {-4713-12-31 12:00:00}
datetest 16.31 {datetime(5373484,'-14713 years')} NULL
# 2017-03-02: Wrong 'start of day' computation.
# https://www.sqlite.org/src/info/6097cb92745327a1
#
datetest 17.1 {datetime(2457754, 'start of day')} {2016-12-31 00:00:00}
datetest 17.2 {datetime(2457828)} {2017-03-15 12:00:00}
datetest 17.3 {datetime(2457828,'start of day')} {2017-03-15 00:00:00}
datetest 17.4 {datetime(2457828,'start of month')} {2017-03-01 00:00:00}
datetest 17.5 {datetime(2457828,'start of year')} {2017-01-01 00:00:00}
datetest 17.6 {datetime(37,'start of year')} NULL
datetest 17.7 {datetime(38,'start of year')} {-4712-01-01 00:00:00}
finish_test
-786
View File
@@ -1,786 +0,0 @@
/*
** 2017-02-07
**
** 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 program implements an SQLite database self-verification utility.
** Usage:
**
** dbselftest DATABASE ...
**
** This program reads the "selftest" table in DATABASE, in rowid order,
** and runs each of the tests described there, reporting results at the
** end.
**
** The intent of this program is to have a set of test database files that
** can be run using future versions of SQLite in order to verify that
** legacy database files continue to be readable. In other words, the
** intent is to confirm that there have been no breaking changes in the
** file format. The program can also be used to verify that database files
** are fully compatible between different architectures.
**
** The selftest table looks like this:
**
** CREATE TABLE selftest (
** id INTEGER PRIMARY KEY, -- Run tests in ascending order
** op TEXT, -- "test", "regexp", "print", etc.
** cmdtxt TEXT, -- Usually the SQL to be run
** expected TEXT -- Expected results
** );
**
*/
#include <assert.h>
#include <string.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include "sqlite3.h"
static const char zHelp[] =
"Usage: dbselftest [OPTIONS] DBFILE ...\n"
"\n"
" --init Create the selftest table\n"
" -q Suppress most output. Errors only\n"
" -v Show extra output\n"
;
/******************************************************************************
** The following code from ext/misc/sha1.c
**
** Context for the SHA1 hash
*/
typedef struct SHA1Context SHA1Context;
struct SHA1Context {
unsigned int state[5];
unsigned int count[2];
unsigned char buffer[64];
};
#if __GNUC__ && (defined(__i386__) || defined(__x86_64__))
/*
* GCC by itself only generates left rotates. Use right rotates if
* possible to be kinder to dinky implementations with iterative rotate
* instructions.
*/
#define SHA_ROT(op, x, k) \
({ unsigned int y; asm(op " %1,%0" : "=r" (y) : "I" (k), "0" (x)); y; })
#define rol(x,k) SHA_ROT("roll", x, k)
#define ror(x,k) SHA_ROT("rorl", x, k)
#else
/* Generic C equivalent */
#define SHA_ROT(x,l,r) ((x) << (l) | (x) >> (r))
#define rol(x,k) SHA_ROT(x,k,32-(k))
#define ror(x,k) SHA_ROT(x,32-(k),k)
#endif
#define blk0le(i) (block[i] = (ror(block[i],8)&0xFF00FF00) \
|(rol(block[i],8)&0x00FF00FF))
#define blk0be(i) block[i]
#define blk(i) (block[i&15] = rol(block[(i+13)&15]^block[(i+8)&15] \
^block[(i+2)&15]^block[i&15],1))
/*
* (R0+R1), R2, R3, R4 are the different operations (rounds) used in SHA1
*
* Rl0() for little-endian and Rb0() for big-endian. Endianness is
* determined at run-time.
*/
#define Rl0(v,w,x,y,z,i) \
z+=((w&(x^y))^y)+blk0le(i)+0x5A827999+rol(v,5);w=ror(w,2);
#define Rb0(v,w,x,y,z,i) \
z+=((w&(x^y))^y)+blk0be(i)+0x5A827999+rol(v,5);w=ror(w,2);
#define R1(v,w,x,y,z,i) \
z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=ror(w,2);
#define R2(v,w,x,y,z,i) \
z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=ror(w,2);
#define R3(v,w,x,y,z,i) \
z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=ror(w,2);
#define R4(v,w,x,y,z,i) \
z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=ror(w,2);
/*
* Hash a single 512-bit block. This is the core of the algorithm.
*/
void SHA1Transform(unsigned int state[5], const unsigned char buffer[64]){
unsigned int qq[5]; /* a, b, c, d, e; */
static int one = 1;
unsigned int block[16];
memcpy(block, buffer, 64);
memcpy(qq,state,5*sizeof(unsigned int));
#define a qq[0]
#define b qq[1]
#define c qq[2]
#define d qq[3]
#define e qq[4]
/* Copy p->state[] to working vars */
/*
a = state[0];
b = state[1];
c = state[2];
d = state[3];
e = state[4];
*/
/* 4 rounds of 20 operations each. Loop unrolled. */
if( 1 == *(unsigned char*)&one ){
Rl0(a,b,c,d,e, 0); Rl0(e,a,b,c,d, 1); Rl0(d,e,a,b,c, 2); Rl0(c,d,e,a,b, 3);
Rl0(b,c,d,e,a, 4); Rl0(a,b,c,d,e, 5); Rl0(e,a,b,c,d, 6); Rl0(d,e,a,b,c, 7);
Rl0(c,d,e,a,b, 8); Rl0(b,c,d,e,a, 9); Rl0(a,b,c,d,e,10); Rl0(e,a,b,c,d,11);
Rl0(d,e,a,b,c,12); Rl0(c,d,e,a,b,13); Rl0(b,c,d,e,a,14); Rl0(a,b,c,d,e,15);
}else{
Rb0(a,b,c,d,e, 0); Rb0(e,a,b,c,d, 1); Rb0(d,e,a,b,c, 2); Rb0(c,d,e,a,b, 3);
Rb0(b,c,d,e,a, 4); Rb0(a,b,c,d,e, 5); Rb0(e,a,b,c,d, 6); Rb0(d,e,a,b,c, 7);
Rb0(c,d,e,a,b, 8); Rb0(b,c,d,e,a, 9); Rb0(a,b,c,d,e,10); Rb0(e,a,b,c,d,11);
Rb0(d,e,a,b,c,12); Rb0(c,d,e,a,b,13); Rb0(b,c,d,e,a,14); Rb0(a,b,c,d,e,15);
}
R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
/* Add the working vars back into context.state[] */
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
state[4] += e;
#undef a
#undef b
#undef c
#undef d
#undef e
}
/* Initialize a SHA1 context */
static void hash_init(SHA1Context *p){
/* SHA1 initialization constants */
p->state[0] = 0x67452301;
p->state[1] = 0xEFCDAB89;
p->state[2] = 0x98BADCFE;
p->state[3] = 0x10325476;
p->state[4] = 0xC3D2E1F0;
p->count[0] = p->count[1] = 0;
}
/* Add new content to the SHA1 hash */
static void hash_step(
SHA1Context *p, /* Add content to this context */
const unsigned char *data, /* Data to be added */
unsigned int len /* Number of bytes in data */
){
unsigned int i, j;
j = p->count[0];
if( (p->count[0] += len << 3) < j ){
p->count[1] += (len>>29)+1;
}
j = (j >> 3) & 63;
if( (j + len) > 63 ){
(void)memcpy(&p->buffer[j], data, (i = 64-j));
SHA1Transform(p->state, p->buffer);
for(; i + 63 < len; i += 64){
SHA1Transform(p->state, &data[i]);
}
j = 0;
}else{
i = 0;
}
(void)memcpy(&p->buffer[j], &data[i], len - i);
}
/* Compute a string using sqlite3_vsnprintf() and hash it */
static void hash_step_vformat(
SHA1Context *p, /* Add content to this context */
const char *zFormat,
...
){
va_list ap;
int n;
char zBuf[50];
va_start(ap, zFormat);
sqlite3_vsnprintf(sizeof(zBuf),zBuf,zFormat,ap);
va_end(ap);
n = (int)strlen(zBuf);
hash_step(p, (unsigned char*)zBuf, n);
}
/* Add padding and compute the message digest. Render the
** message digest as lower-case hexadecimal and put it into
** zOut[]. zOut[] must be at least 41 bytes long. */
static void hash_finish(
SHA1Context *p, /* The SHA1 context to finish and render */
char *zOut /* Store hexadecimal hash here */
){
unsigned int i;
unsigned char finalcount[8];
unsigned char digest[20];
static const char zEncode[] = "0123456789abcdef";
for (i = 0; i < 8; i++){
finalcount[i] = (unsigned char)((p->count[(i >= 4 ? 0 : 1)]
>> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */
}
hash_step(p, (const unsigned char *)"\200", 1);
while ((p->count[0] & 504) != 448){
hash_step(p, (const unsigned char *)"\0", 1);
}
hash_step(p, finalcount, 8); /* Should cause a SHA1Transform() */
for (i = 0; i < 20; i++){
digest[i] = (unsigned char)((p->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
}
for(i=0; i<20; i++){
zOut[i*2] = zEncode[(digest[i]>>4)&0xf];
zOut[i*2+1] = zEncode[digest[i] & 0xf];
}
zOut[i*2]= 0;
}
/*
** Implementation of the sha1(X) function.
**
** Return a lower-case hexadecimal rendering of the SHA1 hash of the
** argument X. If X is a BLOB, it is hashed as is. For all other
** types of input, X is converted into a UTF-8 string and the string
** is hash without the trailing 0x00 terminator. The hash of a NULL
** value is NULL.
*/
static void sha1Func(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
SHA1Context cx;
int eType = sqlite3_value_type(argv[0]);
int nByte = sqlite3_value_bytes(argv[0]);
char zOut[44];
assert( argc==1 );
if( eType==SQLITE_NULL ) return;
hash_init(&cx);
if( eType==SQLITE_BLOB ){
hash_step(&cx, sqlite3_value_blob(argv[0]), nByte);
}else{
hash_step(&cx, sqlite3_value_text(argv[0]), nByte);
}
hash_finish(&cx, zOut);
sqlite3_result_text(context, zOut, 40, SQLITE_TRANSIENT);
}
/*
** Run a prepared statement and compute the SHA1 hash on the
** result rows.
*/
static void sha1RunStatement(SHA1Context *pCtx, sqlite3_stmt *pStmt){
int nCol = sqlite3_column_count(pStmt);
const char *z = sqlite3_sql(pStmt);
int n = (int)strlen(z);
hash_step_vformat(pCtx,"S%d:",n);
hash_step(pCtx,(unsigned char*)z,n);
/* Compute a hash over the result of the query */
while( SQLITE_ROW==sqlite3_step(pStmt) ){
int i;
hash_step(pCtx,(const unsigned char*)"R",1);
for(i=0; i<nCol; i++){
switch( sqlite3_column_type(pStmt,i) ){
case SQLITE_NULL: {
hash_step(pCtx, (const unsigned char*)"N",1);
break;
}
case SQLITE_INTEGER: {
sqlite3_uint64 u;
int j;
unsigned char x[9];
sqlite3_int64 v = sqlite3_column_int64(pStmt,i);
memcpy(&u, &v, 8);
for(j=8; j>=1; j--){
x[j] = u & 0xff;
u >>= 8;
}
x[0] = 'I';
hash_step(pCtx, x, 9);
break;
}
case SQLITE_FLOAT: {
sqlite3_uint64 u;
int j;
unsigned char x[9];
double r = sqlite3_column_double(pStmt,i);
memcpy(&u, &r, 8);
for(j=8; j>=1; j--){
x[j] = u & 0xff;
u >>= 8;
}
x[0] = 'F';
hash_step(pCtx,x,9);
break;
}
case SQLITE_TEXT: {
int n2 = sqlite3_column_bytes(pStmt, i);
const unsigned char *z2 = sqlite3_column_text(pStmt, i);
hash_step_vformat(pCtx,"T%d:",n2);
hash_step(pCtx, z2, n2);
break;
}
case SQLITE_BLOB: {
int n2 = sqlite3_column_bytes(pStmt, i);
const unsigned char *z2 = sqlite3_column_blob(pStmt, i);
hash_step_vformat(pCtx,"B%d:",n2);
hash_step(pCtx, z2, n2);
break;
}
}
}
}
}
/*
** Run one or more statements of SQL. Compute a SHA1 hash of the output.
*/
static int sha1Exec(
sqlite3 *db, /* Run against this database connection */
const char *zSql, /* The SQL to be run */
char *zOut /* Store the SHA1 hash as hexadecimal in this buffer */
){
sqlite3_stmt *pStmt = 0; /* A prepared statement */
int rc; /* Result of an API call */
SHA1Context cx; /* The SHA1 hash context */
hash_init(&cx);
while( zSql[0] ){
rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zSql);
if( rc ){
sqlite3_finalize(pStmt);
return rc;
}
sha1RunStatement(&cx, pStmt);
sqlite3_finalize(pStmt);
}
hash_finish(&cx, zOut);
return SQLITE_OK;
}
/*
** Implementation of the sha1_query(SQL) function.
**
** This function compiles and runs the SQL statement(s) given in the
** argument. The results are hashed using SHA1 and that hash is returned.
**
** The original SQL text is included as part of the hash.
**
** The hash is not just a concatenation of the outputs. Each query
** is delimited and each row and value within the query is delimited,
** with all values being marked with their datatypes.
*/
static void sha1QueryFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
sqlite3 *db = sqlite3_context_db_handle(context);
const char *zSql = (const char*)sqlite3_value_text(argv[0]);
sqlite3_stmt *pStmt = 0;
int rc;
SHA1Context cx;
char zOut[44];
assert( argc==1 );
if( zSql==0 ) return;
hash_init(&cx);
while( zSql[0] ){
rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zSql);
if( rc ){
char *zMsg = sqlite3_mprintf("error SQL statement [%s]: %s",
zSql, sqlite3_errmsg(db));
sqlite3_finalize(pStmt);
sqlite3_result_error(context, zMsg, -1);
sqlite3_free(zMsg);
return;
}
if( !sqlite3_stmt_readonly(pStmt) ){
char *zMsg = sqlite3_mprintf("non-query: [%s]", sqlite3_sql(pStmt));
sqlite3_finalize(pStmt);
sqlite3_result_error(context, zMsg, -1);
sqlite3_free(zMsg);
return;
}
sha1RunStatement(&cx, pStmt);
sqlite3_finalize(pStmt);
}
hash_finish(&cx, zOut);
sqlite3_result_text(context, zOut, 40, SQLITE_TRANSIENT);
}
/* End of ext/misc/sha1.c
******************************************************************************/
/* How much output to display */
#define VOLUME_MIN 0
#define VOLUME_OFF 0
#define VOLUME_ERROR_ONLY 1
#define VOLUME_LOW 2
#define VOLUME_ECHO 3
#define VOLUME_VERBOSE 4
#define VOLUME_MAX 4
/* A string accumulator
*/
typedef struct Str {
char *z; /* Accumulated text */
int n; /* Bytes of z[] used so far */
int nAlloc; /* Bytes allocated for z[] */
} Str;
/* Append text to the Str object
*/
static void strAppend(Str *p, const char *z){
int n = (int)strlen(z);
if( p->n+n >= p->nAlloc ){
p->nAlloc += p->n+n + 100;
p->z = sqlite3_realloc(p->z, p->nAlloc);
if( z==0 ){
printf("Could not allocate %d bytes\n", p->nAlloc);
exit(1);
}
}
memcpy(p->z+p->n, z, n+1);
p->n += n;
}
/* This is an sqlite3_exec() callback that will capture all
** output in a Str.
**
** Columns are separated by ",". Rows are separated by "|".
*/
static int execCallback(void *pStr, int argc, char **argv, char **colv){
int i;
Str *p = (Str*)pStr;
if( p->n ) strAppend(p, "|");
for(i=0; i<argc; i++){
const char *z = (const char*)argv[i];
if( z==0 ) z = "NULL";
if( i>0 ) strAppend(p, ",");
strAppend(p, z);
}
return 0;
}
/*
** Run an SQL statement constructing using sqlite3_vmprintf().
** Return the number of errors.
*/
static int runSql(sqlite3 *db, const char *zFormat, ...){
char *zSql;
char *zErr = 0;
int rc;
int nErr = 0;
va_list ap;
va_start(ap, zFormat);
zSql = sqlite3_vmprintf(zFormat, ap);
va_end(ap);
if( zSql==0 ){
printf("Out of memory\n");
exit(1);
}
rc = sqlite3_exec(db, zSql, 0, 0, &zErr);
if( rc || zErr ){
printf("SQL error in [%s]: code=%d: %s\n", zSql, rc, zErr);
nErr++;
}
sqlite3_free(zSql);
return nErr;
}
/*
** Generate a prepared statement using a formatted string.
*/
static sqlite3_stmt *prepareSql(sqlite3 *db, const char *zFormat, ...){
char *zSql;
int rc;
sqlite3_stmt *pStmt = 0;
va_list ap;
va_start(ap, zFormat);
zSql = sqlite3_vmprintf(zFormat, ap);
va_end(ap);
if( zSql==0 ){
printf("Out of memory\n");
exit(1);
}
rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
if( rc ){
printf("SQL error in [%s]: code=%d: %s\n", zSql, rc, sqlite3_errmsg(db));
sqlite3_finalize(pStmt);
pStmt = 0;
}
sqlite3_free(zSql);
return pStmt;
}
/*
** Construct the standard selftest configuration for the database.
*/
static int buildSelftestTable(sqlite3 *db){
int rc;
sqlite3_stmt *pStmt;
int tno = 110;
char *zSql;
char zHash[50];
rc = runSql(db,
"CREATE TABLE IF NOT EXISTS selftest(\n"
" tno INTEGER PRIMARY KEY, -- test number\n"
" op TEXT, -- what kind of test\n"
" sql TEXT, -- SQL text for the test\n"
" ans TEXT -- expected answer\n"
");"
"INSERT INTO selftest"
" VALUES(100,'memo','Hashes generated using --init',NULL);"
);
if( rc ) return 1;
tno = 110;
zSql = "SELECT type,name,tbl_name,sql FROM sqlite_master ORDER BY name";
sha1Exec(db, zSql, zHash);
rc = runSql(db,
"INSERT INTO selftest(tno,op,sql,ans)"
" VALUES(%d,'sha1',%Q,%Q)", tno, zSql, zHash);
tno += 10;
pStmt = prepareSql(db,
"SELECT lower(name) FROM sqlite_master"
" WHERE type='table' AND sql NOT GLOB 'CREATE VIRTUAL*'"
" AND name<>'selftest'"
" ORDER BY 1");
if( pStmt==0 ) return 1;
while( SQLITE_ROW==sqlite3_step(pStmt) ){
zSql = sqlite3_mprintf("SELECT * FROM \"%w\" NOT INDEXED",
sqlite3_column_text(pStmt, 0));
if( zSql==0 ){
printf("Of of memory\n");
exit(1);
}
sha1Exec(db, zSql, zHash);
rc = runSql(db,
"INSERT INTO selftest(tno,op,sql,ans)"
" VALUES(%d,'sha1',%Q,%Q)", tno, zSql, zHash);
tno += 10;
sqlite3_free(zSql);
if( rc ) break;
}
sqlite3_finalize(pStmt);
if( rc ) return 1;
rc = runSql(db,
"INSERT INTO selftest(tno,op,sql,ans)"
" VALUES(%d,'run','PRAGMA integrity_check','ok');", tno);
if( rc ) return 1;
return rc;
}
/*
** Return true if the named table exists
*/
static int tableExists(sqlite3 *db, const char *zTab){
return sqlite3_table_column_metadata(db, "main", zTab, 0, 0, 0, 0, 0, 0)
== SQLITE_OK;
}
/*
** Default selftest table content, for use when there is no selftest table
*/
static char *azDefaultTest[] = {
0, 0, 0, 0,
"0", "memo", "Missing SELFTEST table - default checks only", "",
"1", "run", "PRAGMA integrity_check", "ok"
};
int main(int argc, char **argv){
int eVolume = VOLUME_LOW; /* How much output to display */
const char **azDb = 0; /* Name of the database file */
int nDb = 0; /* Number of database files to check */
int doInit = 0; /* True if --init is present */
sqlite3 *db = 0; /* Open database connection */
int rc; /* Return code from API calls */
char *zErrMsg = 0; /* An error message return */
char **azTest; /* Content of the selftest table */
int nRow = 0, nCol = 0; /* Rows and columns in azTest[] */
int i; /* Loop counter */
int nErr = 0; /* Number of errors */
int iDb; /* Loop counter for databases */
Str str; /* Result accumulator */
int nTest = 0; /* Number of tests run */
for(i=1; i<argc; i++){
const char *z = argv[i];
if( z[0]=='-' ){
if( z[1]=='-' ) z++;
if( strcmp(z, "-help")==0 ){
printf("%s", zHelp);
return 0;
}else
if( strcmp(z, "-init")==0 ){
doInit = 1;
}else
if( strcmp(z, "-a")==0 ){
if( eVolume>VOLUME_MIN) eVolume--;
}else
if( strcmp(z, "-v")==0 ){
if( eVolume<VOLUME_MAX) eVolume++;
}else
{
printf("unknown option: \"%s\"\nUse --help for more information\n",
argv[i]);
return 1;
}
}else{
nDb++;
azDb = sqlite3_realloc(azDb, nDb*sizeof(azDb[0]));
if( azDb==0 ){
printf("out of memory\n");
exit(1);
}
azDb[nDb-1] = argv[i];
}
}
if( nDb==0 ){
printf("No databases specified. Use --help for more info\n");
return 1;
}
if( eVolume>=VOLUME_LOW ){
printf("SQLite %s\n", sqlite3_sourceid());
}
memset(&str, 0, sizeof(str));
strAppend(&str, "\n");
for(iDb=0; iDb<nDb; iDb++, sqlite3_close(db)){
rc = sqlite3_open_v2(azDb[iDb], &db,
doInit ? SQLITE_OPEN_READWRITE : SQLITE_OPEN_READONLY, 0);
if( rc ){
printf("Cannot open \"%s\": %s\n", azDb[iDb], sqlite3_errmsg(db));
return 1;
}
rc = sqlite3_create_function(db, "sha1", 1, SQLITE_UTF8, 0,
sha1Func, 0, 0);
if( rc==SQLITE_OK ){
rc = sqlite3_create_function(db, "sha1_query", 1, SQLITE_UTF8, 0,
sha1QueryFunc, 0, 0);
}
if( rc ){
printf("Initialization error: %s\n", sqlite3_errmsg(db));
sqlite3_close(db);
return 1;
}
if( doInit && !tableExists(db, "selftest") ){
buildSelftestTable(db);
}
if( !tableExists(db, "selftest") ){
azTest = azDefaultTest;
nCol = 4;
nRow = 2;
}else{
rc = sqlite3_get_table(db,
"SELECT tno,op,sql,ans FROM selftest ORDER BY tno",
&azTest, &nRow, &nCol, &zErrMsg);
if( rc || zErrMsg ){
printf("Error querying selftest: %s\n", zErrMsg);
sqlite3_free_table(azTest);
continue;
}
}
for(i=1; i<=nRow; i++){
int tno = atoi(azTest[i*nCol]);
const char *zOp = azTest[i*nCol+1];
const char *zSql = azTest[i*nCol+2];
const char *zAns = azTest[i*nCol+3];
if( eVolume>=VOLUME_ECHO ){
char *zQuote = sqlite3_mprintf("%q", zSql);
printf("%d: %s %s\n", tno, zOp, zSql);
sqlite3_free(zQuote);
}
if( strcmp(zOp,"memo")==0 ){
if( eVolume>=VOLUME_LOW ){
printf("%s: %s\n", azDb[iDb], zSql);
}
}else
if( strcmp(zOp,"sha1")==0 ){
char zOut[44];
rc = sha1Exec(db, zSql, zOut);
nTest++;
if( eVolume>=VOLUME_VERBOSE ){
printf("Result: %s\n", zOut);
}
if( rc ){
nErr++;
if( eVolume>=VOLUME_ERROR_ONLY ){
printf("%d: error-code-%d: %s\n", tno, rc, sqlite3_errmsg(db));
}
}else if( strcmp(zAns,zOut)!=0 ){
nErr++;
if( eVolume>=VOLUME_ERROR_ONLY ){
printf("%d: Expected: [%s]\n", tno, zAns);
printf("%d: Got: [%s]\n", tno, zOut);
}
}
}else
if( strcmp(zOp,"run")==0 ){
str.n = 0;
str.z[0] = 0;
zErrMsg = 0;
rc = sqlite3_exec(db, zSql, execCallback, &str, &zErrMsg);
nTest++;
if( eVolume>=VOLUME_VERBOSE ){
printf("Result: %s\n", str.z);
}
if( rc || zErrMsg ){
nErr++;
if( eVolume>=VOLUME_ERROR_ONLY ){
printf("%d: error-code-%d: %s\n", tno, rc, zErrMsg);
}
sqlite3_free(zErrMsg);
}else if( strcmp(zAns,str.z)!=0 ){
nErr++;
if( eVolume>=VOLUME_ERROR_ONLY ){
printf("%d: Expected: [%s]\n", tno, zAns);
printf("%d: Got: [%s]\n", tno, str.z);
}
}
}else
{
printf("Unknown operation \"%s\" on selftest line %d\n", zOp, tno);
return 1;
}
}
if( azTest!=azDefaultTest ) sqlite3_free_table(azTest);
}
if( eVolume>=VOLUME_LOW || (nErr>0 && eVolume>=VOLUME_ERROR_ONLY) ){
printf("%d errors out of %d tests on %d databases\n", nErr, nTest, nDb);
}
return nErr;
}
+73
View File
@@ -0,0 +1,73 @@
# 2017 Feb 27
#
# 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.
#
#***********************************************************************
#
# Tests of the last_insert_rowid functionality with fts4.
#
set testdir [file dirname $argv0]
source [file join [file dirname [info script]] tester.tcl]
set testprefix fts4lastrowid
ifcapable !fts3 {
finish_test
return
}
do_execsql_test 1.0 {
CREATE VIRTUAL TABLE t1 USING fts4(str);
}
do_execsql_test 1.1 {
INSERT INTO t1 VALUES('one string');
INSERT INTO t1 VALUES('two string');
INSERT INTO t1 VALUES('three string');
SELECT last_insert_rowid();
} {3}
do_execsql_test 1.2 {
BEGIN;
INSERT INTO t1 VALUES('one string');
INSERT INTO t1 VALUES('two string');
INSERT INTO t1 VALUES('three string');
COMMIT;
SELECT last_insert_rowid();
} {6}
do_execsql_test 1.3 {
INSERT INTO t1(rowid, str) VALUES(-22, 'some more text');
SELECT last_insert_rowid();
} {-22}
do_execsql_test 1.4 {
BEGIN;
INSERT INTO t1(rowid, str) VALUES(45, 'some more text');
INSERT INTO t1(rowid, str) VALUES(46, 'some more text');
INSERT INTO t1(rowid, str) VALUES(222, 'some more text');
SELECT last_insert_rowid();
COMMIT;
SELECT last_insert_rowid();
} {222 222}
do_execsql_test 1.5 {
CREATE TABLE x1(x);
INSERT INTO x1 VALUES('john'), ('paul'), ('george'), ('ringo');
INSERT INTO t1 SELECT x FROM x1;
SELECT last_insert_rowid();
} {226}
do_execsql_test 1.6 {
INSERT INTO t1(rowid, str) SELECT rowid+10, x FROM x1;
SELECT last_insert_rowid();
} {14}
finish_test
+21 -5
View File
@@ -805,6 +805,7 @@ static void showHelp(void){
" --load-db ARGS... Load template databases from files into SOURCE_DB\n"
" -m TEXT Add a description to the database\n"
" --native-vfs Use the native VFS for initially empty database files\n"
" --native-malloc Turn off MEMSYS3/5 and Lookaside\n"
" --oss-fuzz Enable OSS-FUZZ testing\n"
" --prng-seed N Seed value for the PRGN inside of SQLite\n"
" --rebuild Rebuild and vacuum the database file\n"
@@ -851,6 +852,7 @@ int main(int argc, char **argv){
void *pHeap = 0; /* Heap for use by SQLite */
int ossFuzz = 0; /* enable OSS-FUZZ testing */
int ossFuzzThisDb = 0; /* ossFuzz value for this particular database */
int nativeMalloc = 0; /* Turn off MEMSYS3/5 and lookaside if true */
sqlite3_vfs *pDfltVfs; /* The default VFS */
iBegin = timeOfDay();
@@ -911,6 +913,9 @@ int main(int argc, char **argv){
if( i>=argc-1 ) fatalError("missing arguments on %s", argv[i]);
zMsg = argv[++i];
}else
if( strcmp(z,"native-malloc")==0 ){
nativeMalloc = 1;
}else
if( strcmp(z,"native-vfs")==0 ){
nativeFlag = 1;
}else
@@ -972,7 +977,7 @@ int main(int argc, char **argv){
/* Process each source database separately */
for(iSrcDb=0; iSrcDb<nSrcDb; iSrcDb++){
rc = sqlite3_open_v2(azSrcDb[iSrcDb], &db,
SQLITE_OPEN_READONLY, pDfltVfs->zName);
SQLITE_OPEN_READWRITE, pDfltVfs->zName);
if( rc ){
fatalError("cannot open source database %s - %s",
azSrcDb[iSrcDb], sqlite3_errmsg(db));
@@ -1013,7 +1018,7 @@ int main(int argc, char **argv){
ossFuzzThisDb = sqlite3_column_int(pStmt,1);
if( verboseFlag ) printf("Config: oss-fuzz=%d\n", ossFuzzThisDb);
}
if( strcmp(zName, "limit-mem")==0 ){
if( strcmp(zName, "limit-mem")==0 && !nativeMalloc ){
#if !defined(SQLITE_ENABLE_MEMSYS3) && !defined(SQLITE_ENABLE_MEMSYS5)
fatalError("the limit-mem option requires -DSQLITE_ENABLE_MEMSYS5"
" or _MEMSYS3");
@@ -1047,6 +1052,8 @@ int main(int argc, char **argv){
sqlite3_close(db);
return 0;
}
rc = sqlite3_exec(db, "PRAGMA query_only=1;", 0, 0, 0);
if( rc ) fatalError("cannot set database to query-only");
if( zExpDb!=0 || zExpSql!=0 ){
sqlite3_create_function(db, "writefile", 2, SQLITE_UTF8, 0,
writefileFunc, 0, 0);
@@ -1141,14 +1148,19 @@ int main(int argc, char **argv){
}
/* Limit available memory, if requested */
if( nMemThisDb>0 ){
sqlite3_shutdown();
sqlite3_shutdown();
if( nMemThisDb>0 && !nativeMalloc ){
pHeap = realloc(pHeap, nMemThisDb);
if( pHeap==0 ){
fatalError("failed to allocate %d bytes of heap memory", nMem);
}
sqlite3_config(SQLITE_CONFIG_HEAP, pHeap, nMemThisDb, 128);
}
/* Disable lookaside with the --native-malloc option */
if( nativeMalloc ){
sqlite3_config(SQLITE_CONFIG_LOOKASIDE, 0, 0);
}
/* Reset the in-memory virtual filesystem */
formatVfs();
@@ -1205,9 +1217,13 @@ int main(int argc, char **argv){
runSql(db, (char*)pSql->a, runFlags);
}while( timeoutTest );
setAlarm(0);
sqlite3_exec(db, "PRAGMA temp_store_directory=''", 0, 0, 0);
sqlite3_close(db);
}
if( sqlite3_memory_used()>0 ) fatalError("memory leak");
if( sqlite3_memory_used()>0 ){
fatalError("memory leak: %lld bytes outstanding",
sqlite3_memory_used());
}
reformatVfs();
nTest++;
g.zTestName[0] = 0;
+33
View File
@@ -15,6 +15,7 @@
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix insert4
ifcapable !view||!subquery {
finish_test
@@ -566,4 +567,36 @@ do_catchsql_test insert4-9.1 {
INSERT INTO t1(x) VALUES(5 COLLATE xyzzy) UNION SELECT 0;
} {1 {no such collation sequence: xyzzy}}
#-------------------------------------------------------------------------
# Check that running an integrity-check does not disable the xfer
# optimization for tables with CHECK constraints.
#
do_execsql_test 10.1 {
CREATE TABLE t8(
rid INTEGER,
pid INTEGER,
mid INTEGER,
px INTEGER DEFAULT(0) CHECK(px IN(0, 1))
);
CREATE TEMP TABLE x(
rid INTEGER,
pid INTEGER,
mid INTEGER,
px INTEGER DEFAULT(0) CHECK(px IN(0, 1))
);
}
do_test 10.2 {
set sqlite3_xferopt_count 0
execsql { INSERT INTO x SELECT * FROM t8 }
set sqlite3_xferopt_count
} {1}
do_test 10.3 {
execsql { PRAGMA integrity_check }
set sqlite3_xferopt_count 0
execsql { INSERT INTO x SELECT * FROM t8 }
set sqlite3_xferopt_count
} {1}
finish_test
+130
View File
@@ -0,0 +1,130 @@
# 2017-03-22
#
# 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 tests for json_patch(A,B) SQL function.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
ifcapable !json1 {
finish_test
return
}
# This is the example from pages 2 and 3 of RFC-7396
do_execsql_test json104-100 {
SELECT json_patch('{
"a": "b",
"c": {
"d": "e",
"f": "g"
}
}','{
"a":"z",
"c": {
"f": null
}
}');
} {{{"a":"z","c":{"d":"e"}}}}
# This is the example from pages 4 and 5 of RFC-7396
do_execsql_test json104-110 {
SELECT json_patch('{
"title": "Goodbye!",
"author" : {
"givenName" : "John",
"familyName" : "Doe"
},
"tags":[ "example", "sample" ],
"content": "This will be unchanged"
}','{
"title": "Hello!",
"phoneNumber": "+01-123-456-7890",
"author": {
"familyName": null
},
"tags": [ "example" ]
}');
} {{{"title":"Hello!","author":{"givenName":"John"},"tags":["example"],"content":"This will be unchanged","phoneNumber":"+01-123-456-7890"}}}
do_execsql_test json104-200 {
SELECT json_patch('[1,2,3]','{"x":null}');
} {{{}}}
do_execsql_test json104-210 {
SELECT json_patch('[1,2,3]','{"x":null,"y":1,"z":null}');
} {{{"y":1}}}
do_execsql_test json104-220 {
SELECT json_patch('{}','{"a":{"bb":{"ccc":null}}}');
} {{{"a":{"bb":{}}}}}
do_execsql_test json104-221 {
SELECT json_patch('{}','{"a":{"bb":{"ccc":[1,null,3]}}}');
} {{{"a":{"bb":{"ccc":[1,null,3]}}}}}
do_execsql_test json104-222 {
SELECT json_patch('{}','{"a":{"bb":{"ccc":[1,{"dddd":null},3]}}}');
} {{{"a":{"bb":{"ccc":[1,{"dddd":null},3]}}}}}
# Example test cases at the end of the RFC-7396 document
do_execsql_test json104-300 {
SELECT json_patch('{"a":"b"}','{"a":"c"}');
} {{{"a":"c"}}}
do_execsql_test json104-300a {
SELECT coalesce(json_patch(null,'{"a":"c"}'), 'real-null');
} {{real-null}}
do_execsql_test json104-301 {
SELECT json_patch('{"a":"b"}','{"b":"c"}');
} {{{"a":"b","b":"c"}}}
do_execsql_test json104-302 {
SELECT json_patch('{"a":"b"}','{"a":null}');
} {{{}}}
do_execsql_test json104-303 {
SELECT json_patch('{"a":"b","b":"c"}','{"a":null}');
} {{{"b":"c"}}}
do_execsql_test json104-304 {
SELECT json_patch('{"a":["b"]}','{"a":"c"}');
} {{{"a":"c"}}}
do_execsql_test json104-305 {
SELECT json_patch('{"a":"c"}','{"a":["b"]}');
} {{{"a":["b"]}}}
do_execsql_test json104-306 {
SELECT json_patch('{"a":{"b":"c"}}','{"a":{"b":"d","c":null}}');
} {{{"a":{"b":"d"}}}}
do_execsql_test json104-307 {
SELECT json_patch('{"a":[{"b":"c"}]}','{"a":[1]}');
} {{{"a":[1]}}}
do_execsql_test json104-308 {
SELECT json_patch('["a","b"]','["c","d"]');
} {{["c","d"]}}
do_execsql_test json104-309 {
SELECT json_patch('{"a":"b"}','["c"]');
} {{["c"]}}
do_execsql_test json104-310 {
SELECT json_patch('{"a":"foo"}','null');
} {{null}}
do_execsql_test json104-310a {
SELECT coalesce(json_patch('{"a":"foo"}',null), 'real-null');
} {{real-null}}
do_execsql_test json104-311 {
SELECT json_patch('{"a":"foo"}','"bar"');
} {{"bar"}}
do_execsql_test json104-312 {
SELECT json_patch('{"e":null}','{"a":1}');
} {{{"e":null,"a":1}}}
do_execsql_test json104-313 {
SELECT json_patch('[1,2]','{"a":"b","c":null}');
} {{{"a":"b"}}}
do_execsql_test json104-314 {
SELECT json_patch('{}','{"a":{"bb":{"ccc":null}}}');
} {{{"a":{"bb":{}}}}}
finish_test
+30 -28
View File
@@ -39,11 +39,27 @@ ifcapable !memorymanage {
return
}
# The sizes of memory allocations from system malloc() might vary,
# depending on the memory allocator algorithms used. The following
# routine is designed to support answers that fall within a range
# of values while also supplying easy-to-understand "expected" values
# when errors occur.
#
proc value_in_range {target x args} {
set v [lindex $args 0]
if {$v!=""} {
if {$v<$target*$x} {return $v}
if {$v>$target/$x} {return $v}
}
return "number between [expr {int($target*$x)}] and [expr {int($target/$x)}]"
}
set mrange 0.98 ;# plus or minus 2%
test_set_config_pagecache 0 100
sqlite3_soft_heap_limit 0
sqlite3 db test.db
db eval {PRAGMA cache_size=1}
# db eval {PRAGMA cache_size=1}
do_test malloc5-1.1 {
# Simplest possible test. Call sqlite3_release_memory when there is exactly
@@ -71,24 +87,8 @@ do_test malloc5-1.3 {
# in the cache belonging to db2.
#
set ::pgalloc [sqlite3_release_memory]
} {0}
# The sizes of memory allocations from system malloc() might vary,
# depending on the memory allocator algorithms used. The following
# routine is designed to support answers that fall within a range
# of values while also supplying easy-to-understand "expected" values
# when errors occur.
#
proc value_in_range {target x args} {
set v [lindex $args 0]
if {$v!=""} {
if {$v<$target*$x} {return $v}
if {$v>$target/$x} {return $v}
}
return "number between [expr {int($target*$x)}] and [expr {int($target/$x)}]"
}
set mrange 0.98 ;# plus or minus 2%
value_in_range 1288 0.75
} [value_in_range 1288 0.75]
do_test malloc5-1.4 {
# Commit the transaction and open a new one. Read 1 page into the cache.
@@ -117,12 +117,12 @@ do_test malloc5-1.6 {
db2 close
execsql {
BEGIN;
SELECT * FROM abc;
CREATE TABLE def(d, e, f);
SELECT * FROM abc;
}
breakpoint
value_in_range $::pgalloc $::mrange [sqlite3_release_memory 500]
} [value_in_range $::pgalloc $::mrange]
do_test malloc5-1.7 {
# Database should not be locked this time.
sqlite3 db2 test.db
@@ -346,7 +346,7 @@ do_test malloc5-6.2.2 {
# If we now try to reclaim some memory, it should come from the db2 cache.
sqlite3_release_memory 3000
expr [nPage db] + [nPage db2]
} {4}
} {1}
do_test malloc5-6.2.3 {
# Access the db2 cache again, so that all the db2 pages have been used
# more recently than all the db pages. Then try to reclaim 3000 bytes.
@@ -354,7 +354,7 @@ do_test malloc5-6.2.3 {
execsql { SELECT * FROM abc } db2
sqlite3_release_memory 3000
expr [nPage db] + [nPage db2]
} {4}
} {0}
do_test malloc5-6.3.1 {
# Now open a transaction and update 2 pages in the db2 cache. Then
@@ -364,6 +364,8 @@ do_test malloc5-6.3.1 {
# sync() to free up the dirty db2 pages. The only page that cannot be
# freed is page1 of db2. Because there is an open transaction, the
# btree layer holds a reference to page 1 in the db2 cache.
#
# UPDATE: No longer. As release_memory() does not cause a sync()
execsql {
BEGIN;
UPDATE abc SET c = randstr(100,100)
@@ -377,13 +379,13 @@ do_test malloc5-6.3.2 {
# non-dirty pages held by db2.
sqlite3_release_memory [expr 7*1132]
list [nPage db] [nPage db2]
} {1 3}
} {0 3}
do_test malloc5-6.3.3 {
# Try to release another 1000 bytes. This should come fromt the db
# cache, since all three pages held by db2 are either in-use or diry.
sqlite3_release_memory 1000
list [nPage db] [nPage db2]
} {1 3}
} {0 3}
do_test malloc5-6.3.4 {
# Now release 9900 more (about 9 pages worth). This should expunge
# the rest of the db cache. But the db2 cache remains intact, because
@@ -394,20 +396,20 @@ do_test malloc5-6.3.4 {
sqlite3_release_memory 9900
}
list [nPage db] [nPage db2]
} {1 3}
} {0 3}
do_test malloc5-6.3.5 {
# But if we are really insistent, SQLite will consent to call sync()
# if there is no other option. UPDATE: As of 3.6.2, SQLite will not
# call sync() in this scenario. So no further memory can be reclaimed.
sqlite3_release_memory 1000
list [nPage db] [nPage db2]
} {1 3}
} {0 3}
do_test malloc5-6.3.6 {
# The referenced page (page 1 of the db2 cache) will not be freed no
# matter how much memory we ask for:
sqlite3_release_memory 31459
list [nPage db] [nPage db2]
} {1 3}
} {0 3}
db2 close
+48
View File
@@ -0,0 +1,48 @@
# 2017 March 13
#
# 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.
#
#***********************************************************************
# Further OOM tests.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/malloc_common.tcl
set testprefix mallocM
sqlite3_db_config_lookaside db 0 0 0
do_execsql_test 1.0 {
CREATE TABLE t1(x);
}
do_faultsim_test 1 -faults oom* -body {
execsql {
SELECT 'abc' FROM ( SELECT 'xyz' FROM t1 WHERE (SELECT 1) )
}
} -test {
faultsim_test_result {0 {}}
}
do_execsql_test 2.0.1 { SELECT instr(x'', x'') } {1}
do_execsql_test 2.0.2 { SELECT instr(x'12345678', x'') } {1}
do_execsql_test 2.0.3 { SELECT instr(x'', x'1234') } {0}
do_faultsim_test 2.1 -faults oom* -body {
execsql { SELECT instr (x'00', zeroblob(1)) }
} -test {
faultsim_test_result {0 1}
}
do_faultsim_test 2.2 -faults oom* -body {
execsql { SELECT instr (zeroblob(1), x'00') }
} -test {
faultsim_test_result {0 1}
}
finish_test
+87 -17
View File
@@ -4,14 +4,69 @@
*/
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "sqlite3.h"
/* Global debugging settings. OSS-Fuzz will have all debugging turned
** off. But if LLVMFuzzerTestOneInput() is called interactively from
** the ossshell utility program, then these flags might be set.
*/
static unsigned mDebug = 0;
#define FUZZ_SQL_TRACE 0x0001 /* Set an sqlite3_trace() callback */
#define FUZZ_SHOW_MAX_DELAY 0x0002 /* Show maximum progress callback delay */
#define FUZZ_SHOW_ERRORS 0x0004 /* Print error messages from SQLite */
/* The ossshell utility program invokes this interface to see the
** debugging flags. Unused by OSS-Fuzz.
*/
void ossfuzz_set_debug_flags(unsigned x){
mDebug = x;
}
/* Return the current real-world time in milliseconds since the
** Julian epoch (-4714-11-24).
*/
static sqlite3_int64 timeOfDay(void){
static sqlite3_vfs *clockVfs = 0;
sqlite3_int64 t;
if( clockVfs==0 ) clockVfs = sqlite3_vfs_find(0);
if( clockVfs->iVersion>=2 && clockVfs->xCurrentTimeInt64!=0 ){
clockVfs->xCurrentTimeInt64(clockVfs, &t);
}else{
double r;
clockVfs->xCurrentTime(clockVfs, &r);
t = (sqlite3_int64)(r*86400000.0);
}
return t;
}
/* An instance of the following object is passed by pointer as the
** client data to various callbacks.
*/
typedef struct FuzzCtx {
sqlite3 *db; /* The database connection */
sqlite3_int64 iCutoffTime; /* Stop processing at this time. */
sqlite3_int64 iLastCb; /* Time recorded for previous progress callback */
sqlite3_int64 mxInterval; /* Longest interval between two progress calls */
unsigned nCb; /* Number of progress callbacks */
} FuzzCtx;
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
/*
** Progress handler callback
** Progress handler callback.
**
** The argument is the cutoff-time after which all processing should
** stop. So return non-zero if the cut-off time is exceeded.
*/
static int progress_handler(void *pReturn) {
return *(int*)pReturn;
static int progress_handler(void *pClientData) {
FuzzCtx *p = (FuzzCtx*)pClientData;
sqlite3_int64 iNow = timeOfDay();
int rc = iNow>=p->iCutoffTime;
sqlite3_int64 iDiff = iNow - p->iLastCb;
if( iDiff > p->mxInterval ) p->mxInterval = iDiff;
p->nCb++;
return rc;
}
#endif
@@ -31,14 +86,14 @@ static int exec_handler(void *pCnt, int argc, char **argv, char **namev){
** fuzzed input.
*/
int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
int progressArg = 0; /* 1 causes progress handler abort */
int execCnt = 0; /* Abort row callback when count reaches zero */
char *zErrMsg = 0; /* Error message returned by sqlite_exec() */
sqlite3 *db; /* The database connection */
uint8_t uSelector; /* First byte of input data[] */
int rc; /* Return code from various interfaces */
char *zSql; /* Zero-terminated copy of data[] */
FuzzCtx cx; /* Fuzzing context */
memset(&cx, 0, sizeof(cx));
if( size<3 ) return 0; /* Early out if unsufficient data */
/* Extract the selector byte from the beginning of the input. But only
@@ -51,22 +106,26 @@ int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
}
/* Open the database connection. Only use an in-memory database. */
rc = sqlite3_open_v2("fuzz.db", &db,
rc = sqlite3_open_v2("fuzz.db", &cx.db,
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_MEMORY, 0);
if( rc ) return 0;
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
/* Bit 0 of the selector enables progress callbacks. Bit 1 is the
** return code from progress callbacks */
if( uSelector & 1 ){
sqlite3_progress_handler(db, 4, progress_handler, (void*)&progressArg);
}
/* Invoke the progress handler frequently to check to see if we
** are taking too long. The progress handler will return true
** (which will block further processing) if more than 10 seconds have
** elapsed since the start of the test.
*/
cx.iLastCb = timeOfDay();
cx.iCutoffTime = cx.iLastCb + 10000; /* Now + 10 seconds */
sqlite3_progress_handler(cx.db, 10, progress_handler, (void*)&cx);
#endif
uSelector >>= 1;
progressArg = uSelector & 1; uSelector >>= 1;
/* Bit 2 of the selector enables foreign key constraints */
sqlite3_db_config(db, SQLITE_DBCONFIG_ENABLE_FKEY, uSelector&1, &rc);
/* Set a limit on the maximum size of a prepared statement */
sqlite3_limit(cx.db, SQLITE_LIMIT_VDBE_OP, 25000);
/* Bit 1 of the selector enables foreign key constraints */
sqlite3_db_config(cx.db, SQLITE_DBCONFIG_ENABLE_FKEY, uSelector&1, &rc);
uSelector >>= 1;
/* Remaining bits of the selector determine a limit on the number of
@@ -76,11 +135,22 @@ int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
/* Run the SQL. The sqlite_exec() interface expects a zero-terminated
** string, so make a copy. */
zSql = sqlite3_mprintf("%.*s", (int)size, data);
sqlite3_exec(db, zSql, exec_handler, (void*)&execCnt, &zErrMsg);
sqlite3_exec(cx.db, zSql, exec_handler, (void*)&execCnt, &zErrMsg);
/* Show any errors */
if( (mDebug & FUZZ_SHOW_ERRORS)!=0 && zErrMsg ){
printf("Error: %s\n", zErrMsg);
}
/* Cleanup and return */
sqlite3_free(zErrMsg);
sqlite3_free(zSql);
sqlite3_close(db);
sqlite3_exec(cx.db, "PRAGMA temp_store_directory=''", 0, 0, 0);
sqlite3_close(cx.db);
if( mDebug & FUZZ_SHOW_MAX_DELAY ){
printf("Progress callback count....... %d\n", cx.nCb);
printf("Max time between callbacks.... %d ms\n", (int)cx.mxInterval);
}
return 0;
}
+33
View File
@@ -9,6 +9,7 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "sqlite3.h"
/*
@@ -16,6 +17,13 @@
*/
int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size);
/* Must match equivalent #defines in ossfuzz.c */
#define FUZZ_SQL_TRACE 0x0001 /* Set an sqlite3_trace() callback */
#define FUZZ_SHOW_MAX_DELAY 0x0002 /* Show maximum progress callback delay */
#define FUZZ_SHOW_ERRORS 0x0004 /* Show SQL errors */
extern void ossfuzz_set_debug_flags(unsigned);
/*
** Read files named on the command-line and invoke the fuzzer for
@@ -27,9 +35,32 @@ int main(int argc, char **argv){
int nErr = 0;
uint8_t *zBuf = 0;
size_t sz;
unsigned mDebug = 0;
for(i=1; i<argc; i++){
const char *zFilename = argv[i];
if( zFilename[0]=='-' ){
if( zFilename[1]=='-' ) zFilename++;
if( strcmp(zFilename, "-show-errors")==0 ){
mDebug |= FUZZ_SHOW_ERRORS;
ossfuzz_set_debug_flags(mDebug);
}else
if( strcmp(zFilename, "-show-max-delay")==0 ){
mDebug |= FUZZ_SHOW_MAX_DELAY;
ossfuzz_set_debug_flags(mDebug);
}else
if( strcmp(zFilename, "-sql-trace")==0 ){
mDebug |= FUZZ_SQL_TRACE;
ossfuzz_set_debug_flags(mDebug);
}else
{
printf("unknown option \"%s\"\n", argv[i]);
printf("should be one of: --show-errors --show-max-delay"
" --sql-trace\n");
exit(1);
}
continue;
}
in = fopen(zFilename, "rb");
if( in==0 ){
fprintf(stderr, "cannot open \"%s\"\n", zFilename);
@@ -50,8 +81,10 @@ int main(int argc, char **argv){
nErr++;
}else{
printf("%s... ", zFilename);
if( mDebug ) printf("\n");
fflush(stdout);
(void)LLVMFuzzerTestOneInput(zBuf, sz);
if( mDebug ) printf("%s: ", zFilename);
printf("ok\n");
}
fclose(in);
+18 -16
View File
@@ -247,22 +247,24 @@ test_suite "threads" -prefix "" -description {
test_suite "fts3" -prefix "" -description {
All FTS3 tests except fts3rnd.test.
} -files {
fts3aa.test fts3ab.test fts3ac.test fts3ad.test fts3ae.test
fts3af.test fts3ag.test fts3ah.test fts3ai.test fts3aj.test
fts3ak.test fts3al.test fts3am.test fts3an.test fts3ao.test
fts3atoken.test fts3b.test fts3c.test fts3cov.test fts3d.test
fts3defer.test fts3defer2.test fts3e.test fts3expr.test fts3expr2.test
fts3expr3.test
fts3near.test fts3query.test fts3shared.test fts3snippet.test
fts3sort.test
fts3fault.test fts3malloc.test fts3matchinfo.test
fts3aux1.test fts3comp1.test fts3auto.test
fts4aa.test fts4content.test
fts3conf.test fts3prefix.test fts3fault2.test fts3corrupt.test
fts3corrupt2.test fts3first.test fts4langid.test fts4merge.test
fts4check.test fts4unicode.test fts4noti.test
fts3varint.test
fts4growth.test fts4growth2.test
fts3aa.test fts3ab.test fts3ac.test fts3ad.test
fts3ae.test fts3af.test fts3ag.test fts3ah.test
fts3ai.test fts3aj.test fts3ak.test fts3al.test
fts3am.test fts3an.test fts3ao.test fts3atoken.test
fts3auto.test fts3aux1.test fts3aux2.test fts3b.test
fts3comp1.test fts3conf.test fts3corrupt2.test fts3corrupt.test
fts3cov.test fts3c.test fts3defer2.test fts3defer3.test
fts3defer.test fts3drop.test fts3d.test fts3e.test
fts3expr2.test fts3expr3.test fts3expr4.test fts3expr5.test
fts3expr.test fts3fault2.test fts3fault.test fts3first.test
fts3join.test fts3malloc.test fts3matchinfo.test fts3near.test
fts3offsets.test fts3prefix2.test fts3prefix.test fts3query.test
fts3shared.test fts3snippet.test fts3sort.test fts3tok1.test
fts3tok_err.test fts3varint.test fts4aa.test fts4check.test
fts4content.test fts4docid.test fts4growth2.test fts4growth.test
fts4incr.test fts4langid.test fts4lastrowid.test fts4merge2.test
fts4merge4.test fts4merge.test fts4noti.test fts4onepass.test
fts4opt.test fts4unicode.test
}
test_suite "fts5" -prefix "" -description {
+39
View File
@@ -0,0 +1,39 @@
# 2010 June 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.
#
#***********************************************************************
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/lock_common.tcl
source $testdir/malloc_common.tcl
set testprefix pragmafault
db close
sqlite3 db test.db
sqlite3_db_config_lookaside db 0 0 0
do_execsql_test 1.0 {
CREATE TABLE t1(a, b, CHECK(a!=b));
INSERT INTO t1 VALUES(1, 2);
INSERT INTO t1 VALUES(3, 4);
}
faultsim_save_and_close
do_faultsim_test 1 -prep {
faultsim_restore_and_reopen
} -body {
catchsql { PRAGMA integrity_check }
set {} 0
} -test {
faultsim_test_result {0 0}
}
finish_test
+146 -13
View File
@@ -300,7 +300,7 @@ do_test shell1-3.4.2 {
do_test shell1-3.4.3 {
# too many arguments
catchcmd "test.db" ".dump FOO BAD"
} {1 {Usage: .dump ?LIKE-PATTERN?}}
} {1 {Usage: .dump ?--preserve-rowids? ?LIKE-PATTERN?}}
# .echo ON|OFF Turn command echo on or off
do_test shell1-3.5.1 {
@@ -740,21 +740,154 @@ do_test shell1-4.1 {
} {0 {PRAGMA foreign_keys=OFF;
BEGIN TRANSACTION;
CREATE TABLE t1(x);
INSERT INTO "t1" VALUES(NULL);
INSERT INTO "t1" VALUES('');
INSERT INTO "t1" VALUES(1);
INSERT INTO "t1" VALUES(2.25);
INSERT INTO "t1" VALUES('hello');
INSERT INTO "t1" VALUES(X'807F');
INSERT INTO t1 VALUES(NULL);
INSERT INTO t1 VALUES('');
INSERT INTO t1 VALUES(1);
INSERT INTO t1 VALUES(2.25);
INSERT INTO t1 VALUES('hello');
INSERT INTO t1 VALUES(X'807f');
CREATE TABLE t3(x,y);
INSERT INTO "t3" VALUES(1,NULL);
INSERT INTO "t3" VALUES(2,'');
INSERT INTO "t3" VALUES(3,1);
INSERT INTO "t3" VALUES(4,2.25);
INSERT INTO "t3" VALUES(5,'hello');
INSERT INTO "t3" VALUES(6,X'807F');
INSERT INTO t3 VALUES(1,NULL);
INSERT INTO t3 VALUES(2,'');
INSERT INTO t3 VALUES(3,1);
INSERT INTO t3 VALUES(4,2.25);
INSERT INTO t3 VALUES(5,'hello');
INSERT INTO t3 VALUES(6,X'807f');
COMMIT;}}
ifcapable vtab {
# The --preserve-rowids option to .dump
#
do_test shell1-4.1.1 {
catchcmd test.db {.dump --preserve-rowids}
} {0 {PRAGMA foreign_keys=OFF;
BEGIN TRANSACTION;
CREATE TABLE t1(x);
INSERT INTO t1(rowid,x) VALUES(1,NULL);
INSERT INTO t1(rowid,x) VALUES(2,'');
INSERT INTO t1(rowid,x) VALUES(3,1);
INSERT INTO t1(rowid,x) VALUES(4,2.25);
INSERT INTO t1(rowid,x) VALUES(5,'hello');
INSERT INTO t1(rowid,x) VALUES(6,X'807f');
CREATE TABLE t3(x,y);
INSERT INTO t3(rowid,x,y) VALUES(1,1,NULL);
INSERT INTO t3(rowid,x,y) VALUES(2,2,'');
INSERT INTO t3(rowid,x,y) VALUES(3,3,1);
INSERT INTO t3(rowid,x,y) VALUES(4,4,2.25);
INSERT INTO t3(rowid,x,y) VALUES(5,5,'hello');
INSERT INTO t3(rowid,x,y) VALUES(6,6,X'807f');
COMMIT;}}
# If the table contains an INTEGER PRIMARY KEY, do not record a separate
# rowid column in the output.
#
do_test shell1-4.1.2 {
db close
forcedelete test2.db
sqlite3 db test2.db
db eval {
CREATE TABLE t1(x INTEGER PRIMARY KEY, y);
INSERT INTO t1 VALUES(1,null), (2,''), (3,1),
(4,2.25), (5,'hello'), (6,x'807f');
}
catchcmd test2.db {.dump --preserve-rowids}
} {0 {PRAGMA foreign_keys=OFF;
BEGIN TRANSACTION;
CREATE TABLE t1(x INTEGER PRIMARY KEY, y);
INSERT INTO t1 VALUES(1,NULL);
INSERT INTO t1 VALUES(2,'');
INSERT INTO t1 VALUES(3,1);
INSERT INTO t1 VALUES(4,2.25);
INSERT INTO t1 VALUES(5,'hello');
INSERT INTO t1 VALUES(6,X'807f');
COMMIT;}}
# Verify that the table named [table] is correctly quoted and that
# an INTEGER PRIMARY KEY DESC is not an alias for the rowid.
#
do_test shell1-4.1.3 {
db close
forcedelete test2.db
sqlite3 db test2.db
db eval {
CREATE TABLE [table](x INTEGER PRIMARY KEY DESC, y);
INSERT INTO [table] VALUES(1,null), (12,''), (23,1),
(34,2.25), (45,'hello'), (56,x'807f');
}
catchcmd test2.db {.dump --preserve-rowids}
} {0 {PRAGMA foreign_keys=OFF;
BEGIN TRANSACTION;
CREATE TABLE [table](x INTEGER PRIMARY KEY DESC, y);
INSERT INTO "table"(rowid,x,y) VALUES(1,1,NULL);
INSERT INTO "table"(rowid,x,y) VALUES(2,12,'');
INSERT INTO "table"(rowid,x,y) VALUES(3,23,1);
INSERT INTO "table"(rowid,x,y) VALUES(4,34,2.25);
INSERT INTO "table"(rowid,x,y) VALUES(5,45,'hello');
INSERT INTO "table"(rowid,x,y) VALUES(6,56,X'807f');
COMMIT;}}
# Do not record rowids for a WITHOUT ROWID table. Also check correct quoting
# of table names that contain odd characters.
#
do_test shell1-4.1.4 {
db close
forcedelete test2.db
sqlite3 db test2.db
db eval {
CREATE TABLE [ta<>ble](x INTEGER PRIMARY KEY, y) WITHOUT ROWID;
INSERT INTO [ta<>ble] VALUES(1,null), (12,''), (23,1),
(34,2.25), (45,'hello'), (56,x'807f');
}
catchcmd test2.db {.dump --preserve-rowids}
} {0 {PRAGMA foreign_keys=OFF;
BEGIN TRANSACTION;
CREATE TABLE [ta<>ble](x INTEGER PRIMARY KEY, y) WITHOUT ROWID;
INSERT INTO "ta<>ble" VALUES(1,NULL);
INSERT INTO "ta<>ble" VALUES(12,'');
INSERT INTO "ta<>ble" VALUES(23,1);
INSERT INTO "ta<>ble" VALUES(34,2.25);
INSERT INTO "ta<>ble" VALUES(45,'hello');
INSERT INTO "ta<>ble" VALUES(56,X'807f');
COMMIT;}}
# Do not record rowids if the rowid is inaccessible
#
do_test shell1-4.1.5 {
db close
forcedelete test2.db
sqlite3 db test2.db
db eval {
CREATE TABLE t1(_ROWID_,rowid,oid);
INSERT INTO t1 VALUES(1,null,'alpha'), (12,'',99), (23,1,x'b0b1b2');
}
catchcmd test2.db {.dump --preserve-rowids}
} {0 {PRAGMA foreign_keys=OFF;
BEGIN TRANSACTION;
CREATE TABLE t1(_ROWID_,rowid,oid);
INSERT INTO t1 VALUES(1,NULL,'alpha');
INSERT INTO t1 VALUES(12,'',99);
INSERT INTO t1 VALUES(23,1,X'b0b1b2');
COMMIT;}}
} else {
do_test shell1-4.1.6 {
db close
forcedelete test2.db
sqlite3 db test2.db
db eval {
CREATE TABLE t1(x INTEGER PRIMARY KEY, y);
INSERT INTO t1 VALUES(1,null), (2,''), (3,1),
(4,2.25), (5,'hello'), (6,x'807f');
}
catchcmd test2.db {.dump --preserve-rowids}
} {1 {The --preserve-rowids option is not compatible with SQLITE_OMIT_VIRTUALTABLE}}
}
# Test the output of ".mode insert"
#
do_test shell1-4.2.1 {
+20
View File
@@ -73,6 +73,26 @@ foreach {tn schema output} {
CREATE INDEX 'y1_a' ON 'y1'('a' COLLATE nocase); --> x1(a)
}
7 {
CREATE TABLE x1(a PRIMARY KEY COLLATE nocase, b);
CREATE TABLE y1(a REFERENCES x1);
} {
CREATE INDEX 'y1_a' ON 'y1'('a' COLLATE nocase); --> x1(a)
}
8 {
CREATE TABLE x1(a, b COLLATE nocase, c COLLATE rtrim, PRIMARY KEY(c, b, a));
CREATE TABLE y1(d, e, f, FOREIGN KEY(d, e, f) REFERENCES x1);
} {
CREATE INDEX 'y1_d_e_f' ON 'y1'('d' COLLATE rtrim, 'e' COLLATE nocase, 'f'); --> x1(c,b,a)
}
9 {
CREATE TABLE p1(a, b UNIQUE);
CREATE TABLE c1(x INTEGER PRIMARY KEY REFERENCES p1(b));
} {
}
} {
forcedelete test.db
sqlite3 db test.db
+160
View File
@@ -0,0 +1,160 @@
# 2017 March 16
#
# 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.
#
# Specificly, it tests that "PRAGMA synchronous" appears to work.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix sync2
#
# These tests are only applicable when pager pragma are
# enabled. Also, since every test uses an ATTACHed database, they
# are only run when ATTACH is enabled.
#
ifcapable !pager_pragmas||!attach||!dirsync {
finish_test
return
}
if {$::tcl_platform(platform)!="unix"
|| [permutation] == "journaltest"
|| [permutation] == "inmemory_journal"
} {
finish_test
return
}
proc execsql_sync {sql} {
set s $::sqlite_sync_count
set res [execsql $sql]
concat [expr $::sqlite_sync_count-$s] $res
}
proc do_execsql_sync_test {tn sql res} {
uplevel [list do_test $tn [list execsql_sync $sql] [list {*}$res]]
}
#-----------------------------------------------------------------------
# Tests for journal mode.
#
sqlite3 db test.db
do_execsql_test 1.0 {
CREATE TABLE t1(a, b);
INSERT INTO t1 VALUES(1, 2);
}
do_execsql_sync_test 1.1 { INSERT INTO t1 VALUES(3, 4) } 4
# synchronous=normal. So, 1 sync on the directory, 1 on the journal, 1
# on the db file. 3 in total.
do_execsql_test 1.2.1 { PRAGMA main.synchronous = NORMAL }
do_execsql_test 1.2.2 { PRAGMA main.synchronous } 1
do_execsql_sync_test 1.2.3 { INSERT INTO t1 VALUES(5, 6) } 3
# synchronous=off. No syncs.
do_execsql_test 1.3.1 { PRAGMA main.synchronous = OFF }
do_execsql_test 1.3.2 { PRAGMA main.synchronous } 0
do_execsql_sync_test 1.3.3 { INSERT INTO t1 VALUES(7, 8) } 0
# synchronous=full, journal_mode=delete. So, 1 sync on the directory,
# 2 on the journal, 1 on the db file. 4 in total.
do_execsql_test 1.4.1 { PRAGMA main.synchronous = FULL }
do_execsql_test 1.4.2 { PRAGMA main.synchronous } 2
do_execsql_sync_test 1.4.3 { INSERT INTO t1 VALUES(9, 10) } 4
#-----------------------------------------------------------------------
# Tests for wal mode.
#
do_execsql_test 1.5 { PRAGMA journal_mode = wal } {wal}
# sync=full, journal_mode=wal. One sync on the directory, two on the
# wal file.
do_execsql_sync_test 1.6 { INSERT INTO t1 VALUES(11, 12) } 3
# One sync on the wal file.
do_execsql_sync_test 1.7 { INSERT INTO t1 VALUES(13, 14) } 1
# No syncs.
do_execsql_test 1.8.1 { PRAGMA main.synchronous = NORMAL }
do_execsql_test 1.8.2 { PRAGMA main.synchronous } 1
do_execsql_sync_test 1.8.3 { INSERT INTO t1 VALUES(15, 16) } 0
# One sync on wal file, one on the db file.
do_execsql_sync_test 1.9 { PRAGMA wal_checkpoint } {2 0 3 3}
# No syncs.
do_execsql_test 1.10.1 { PRAGMA main.synchronous = OFF }
do_execsql_test 1.10.2 { PRAGMA main.synchronous } 0
do_execsql_sync_test 1.10.3 { INSERT INTO t1 VALUES(17, 18) } 0
#-----------------------------------------------------------------------
# Tests for the compile time settings SQLITE_DEFAULT_SYNCHRONOUS and
# SQLITE_DEFAULT_WAL_SYNCHRONOUS. These tests only run if the former
# is set to "2" and the latter to "1". This is not the default, but
# it is currently the recommended configuration.
#
# https://sqlite.org/compile.html#recommended_compile_time_options
#
if {$SQLITE_DEFAULT_SYNCHRONOUS==2 && $SQLITE_DEFAULT_WAL_SYNCHRONOUS==1} {
db close
sqlite3 db test.db
# Wal mode, sync=normal. The first transaction does one sync on directory,
# one on the wal file. The second does no syncs.
do_execsql_sync_test 1.11.1 { INSERT INTO t1 VALUES(19, 20) } 2
do_execsql_sync_test 1.11.2 { INSERT INTO t1 VALUES(21, 22) } 0
do_execsql_test 1.11.3 { PRAGMA main.synchronous } 1
# One sync on wal file, one on the db file.
do_execsql_sync_test 1.12 { PRAGMA wal_checkpoint } {2 0 2 2}
# First transaction syncs the wal file once, the second not at all.
# one on the wal file. The second does no syncs.
do_execsql_sync_test 1.13.1 { INSERT INTO t1 VALUES(22, 23) } 1
do_execsql_sync_test 1.13.2 { INSERT INTO t1 VALUES(24, 25) } 0
do_execsql_test 1.14 { PRAGMA journal_mode = delete } {delete}
# Delete mode, sync=full. The first transaction does one sync on
# directory, two on the journal file, one on the db. The second does
# the same.
do_execsql_sync_test 1.15.1 { INSERT INTO t1 VALUES(26, 27) } 4
do_execsql_sync_test 1.15.2 { INSERT INTO t1 VALUES(28, 29) } 4
do_execsql_test 1.15.3 { PRAGMA main.synchronous } 2
# Switch back to wal mode.
do_execsql_test 1.16 { PRAGMA journal_mode = wal } {wal}
do_execsql_sync_test 1.17.1 { INSERT INTO t1 VALUES(30, 31) } 2
do_execsql_sync_test 1.17.2 { INSERT INTO t1 VALUES(32, 33) } 0
do_execsql_test 1.17.3 { PRAGMA main.synchronous } 1
# Now set synchronous=off, then switch back to delete mode. Check
# that the db handle is still using synchronous=off.
do_execsql_test 1.18.3 { PRAGMA main.synchronous=off }
do_execsql_test 1.18 { PRAGMA journal_mode = delete } {delete}
do_execsql_sync_test 1.19.1 { INSERT INTO t1 VALUES(34, 35) } 0
do_execsql_sync_test 1.19.2 { INSERT INTO t1 VALUES(36, 37) } 0
do_execsql_test 1.19.3 { PRAGMA main.synchronous } 0
# Close and reopen the db. Back to synchronous=normal.
db close
sqlite3 db test.db
do_execsql_sync_test 1.20.1 { INSERT INTO t1 VALUES(38, 39) } 4
do_execsql_sync_test 1.20.2 { INSERT INTO t1 VALUES(40, 41) } 4
do_execsql_test 1.20.3 { PRAGMA main.synchronous } 2
}
finish_test
+4 -2
View File
@@ -1533,6 +1533,7 @@ proc crashsql {args} {
set tclbody {}
set crashfile ""
set dc ""
set dfltvfs 0
set sql [lindex $args end]
for {set ii 0} {$ii < [llength $args]-1} {incr ii 2} {
@@ -1546,7 +1547,8 @@ proc crashsql {args} {
elseif {$n>1 && [string first $z -file]==0} {set crashfile $z2} \
elseif {$n>1 && [string first $z -tclbody]==0} {set tclbody $z2} \
elseif {$n>1 && [string first $z -blocksize]==0} {set blocksize "-s $z2" } \
elseif {$n>1 && [string first $z -characteristics]==0} {set dc "-c {$z2}" } \
elseif {$n>1 && [string first $z -characteristics]==0} {set dc "-c {$z2}" }\
elseif {$n>1 && [string first $z -dfltvfs]==0} {set dfltvfs $z2 }\
else { error "Unrecognized option: $z" }
}
@@ -1560,7 +1562,7 @@ proc crashsql {args} {
set cfile [string map {\\ \\\\} [file nativename [file join [get_pwd] $crashfile]]]
set f [open crash.tcl w]
puts $f "sqlite3_crash_enable 1"
puts $f "sqlite3_crash_enable 1 $dfltvfs"
puts $f "sqlite3_crashparams $blocksize $dc $crashdelay $cfile"
puts $f "sqlite3_test_control_pending_byte $::sqlite_pending_byte"
+65
View File
@@ -0,0 +1,65 @@
# 2017-03-24
#
# 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.
#
#***********************************************************************
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix triggerG
ifcapable {!trigger} {
finish_test
return
}
# Test cases for ticket
# https://www.sqlite.org/src/tktview/06796225f59c057cd120f
#
# The OP_Once opcode was not working correctly for recursive triggers.
#
do_execsql_test 100 {
PRAGMA recursive_triggers = 1;
CREATE TABLE t1(a);
CREATE INDEX i1 ON t1(a);
INSERT INTO t1(a) VALUES(0),(2),(3),(8),(9);
CREATE TABLE t2(b);
CREATE TABLE t3(c);
CREATE TRIGGER tr AFTER INSERT ON t3 BEGIN
INSERT INTO t3 SELECT new.c+1 WHERE new.c<5;
INSERT INTO t2 SELECT new.c*100+a FROM t1 WHERE a IN (1, 2, 3, 4);
END;
INSERT INTO t3 VALUES(2);
SELECT c FROM t3 ORDER BY c;;
} {2 3 4 5}
do_execsql_test 110 {
SELECT b FROM t2 ORDER BY b;
} {202 203 302 303 402 403 502 503}
do_execsql_test 200 {
DELETE FROM t1;
INSERT INTO t1(a) VALUES(0),(2),(3),(8),(9);
DELETE FROM t2;
DELETE FROM t3;
DROP TRIGGER tr;
CREATE TRIGGER tr AFTER INSERT ON t3 BEGIN
INSERT INTO t3 SELECT new.c+1 WHERE new.c<5;
INSERT INTO t2 SELECT new.c*10000+xx.a*100+yy.a
FROM t1 AS xx, t1 AS yy
WHERE xx.a IN (1,2,3,4)
AND yy.a IN (2,3,4,5);
END;
INSERT INTO t3 VALUES(2);
SELECT b FROM t2 ORDER BY b;
} {20202 20203 20302 20303 30202 30203 30302 30303 40202 40203 40302 40303 50202 50203 50302 50303}
finish_test
+13 -1
View File
@@ -124,7 +124,7 @@ IF NOT EXIST "%FRAMEWORKDIR%\csc.exe" (
GOTO errors
)
SET PATH=%FRAMEWORKDIR%;%PATH%
CALL :fn_PrependToPath FRAMEWORKDIR
:skip_addToPath
@@ -246,6 +246,18 @@ GOTO no_errors
ENDLOCAL && SET %1=%VALUE%
GOTO :EOF
:fn_PrependToPath
IF NOT DEFINED %1 GOTO :EOF
SETLOCAL
SET __ECHO_CMD=ECHO %%%1%%
FOR /F "delims=" %%V IN ('%__ECHO_CMD%') DO (
SET VALUE=%%V
)
SET VALUE=%VALUE:"=%
REM "
ENDLOCAL && SET PATH=%VALUE%;%PATH%
GOTO :EOF
:fn_ResetErrorLevel
VERIFY > NUL
GOTO :EOF
+5 -1
View File
@@ -460,7 +460,7 @@ FOR %%P IN (%PLATFORMS%) DO (
REM
REM NOTE: Reset the PATH here to the absolute bare minimum required.
REM
SET PATH=%TOOLPATH%;%SystemRoot%\System32;%SystemRoot%
CALL :fn_ResetPath
REM
REM NOTE: This is the inner loop. There are normally two iterations, one
@@ -818,6 +818,10 @@ GOTO no_errors
CALL :fn_ResetErrorLevel
GOTO :EOF
:fn_ResetPath
SET PATH=%TOOLPATH%;%SystemRoot%\System32;%SystemRoot%
GOTO :EOF
:fn_AppendVariable
SET __ECHO_CMD=ECHO %%%1%%
IF DEFINED %1 (
+5 -5
View File
@@ -225,8 +225,8 @@ set pragma_def {
NAME: stats
FLAG: NeedSchema Result0 SchemaReq
COLS: table index width height
IF: !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
COLS: tbl idx wdth hght flgs
IF: !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) && defined(SQLITE_DEBUG)
NAME: index_info
TYPE: INDEX_INFO
@@ -331,9 +331,6 @@ set pragma_def {
NAME: shrink_memory
FLAG: NoColumns
NAME: vdbe_cycle_limit
FLAG: NoColumns
NAME: busy_timeout
FLAG: Result0
COLS: timeout
@@ -364,6 +361,9 @@ set pragma_def {
NAME: threads
FLAG: Result0
NAME: optimize
FLAG: Result1 NeedSchema
}
# Open the output file
+1 -1
View File
@@ -535,7 +535,7 @@ static void decodeCell(
j = i;
nCol = 0;
k = nHdr;
while( x+j<end && j<nHdr ){
while( x+j<=end && j<nHdr ){
const char *zTypeName;
int sz = 0;
char zNm[30];