Compare commits

..

112 Commits

Author SHA1 Message Date
drh baf5dec700 Simplifications to blobSeekToRow().
FossilOrigin-Name: 495ea824093ff535734c22c3115384c08f855c02
2017-01-31 19:02:15 +00:00
drh 0caad09585 Remove a C99-style comment. Fixes to the kvtest-speed.sh script.
FossilOrigin-Name: 91eb6b628e278d20eccc647293e5b30765163e12
2017-01-31 16:49:01 +00:00
drh d59bcbdee7 Remove another unnecessary local variable initialization from sqlite3VdbeExec()
FossilOrigin-Name: 2361b03b61311aab9b9ec9de040bbb73be31be0d
2017-01-31 16:43:36 +00:00
drh 78a9e92ecf Remove an unnecessary initialization of the pOp variable in sqlite3VdbeExec().
FossilOrigin-Name: 02f6293f278f7b0a0f4876f5c6a0f4dc42620d79
2017-01-31 16:34:51 +00:00
drh 9dc7ad1d7e Add the "stat" command to kvtest.c. Also add the --variance option to the
"init" command.  Add the tool/kvtest-speed.sh script used for doing 
performance testing on key/value access patterns.

FossilOrigin-Name: b63deed600b1a457a6960ebad5645f4de9c56e5d
2017-01-31 15:29:05 +00:00
drh 1379521f4a Fix a typo in a comment.
FossilOrigin-Name: bd22bf9cbe028e9811ca3afaadafd90312cb0fc9
2017-01-31 15:27:04 +00:00
drh 8e74e7ba4c Further minor enhancement and size reduction in
sqlite3ExprAssignVarNumber().

FossilOrigin-Name: eacfdcf25796ea29b5e63499c3d7397498305ad9
2017-01-31 12:41:48 +00:00
drh 18814dfb7e Performance optimization in sqlite3ExprAssignVarNumber().
FossilOrigin-Name: 5987ca1ff94ed3c1666f783bb15b16158aa7e1db
2017-01-31 03:52:34 +00:00
dan e7eeeb99f7 Fix building with SQLITE_OMIT_FOREIGN_KEY defined.
FossilOrigin-Name: e93d2c49a44af994ff10cc9cc7eafacd5a4f73ab
2017-01-30 11:38:19 +00:00
drh d26cc54183 In the amalgamation, allocate the parser engine object from stack rather than
from heap, for improved performance.  This only happens in the amalgamation,
since otherwise the sqlite3RunParser() routine does not know the object size.

FossilOrigin-Name: 4fe879d4b5da6ae0688a7a99004683a234966597
2017-01-28 20:46:37 +00:00
mistachkin 51b15c3871 Fix a couple comment typos. No changes to code.
FossilOrigin-Name: 2a2e7d86b275c970726f642a37a098950a3b906e
2017-01-28 19:53:51 +00:00
dan f64ece143c Avoid redundant table b-tree cursor seeks in UPDATE statements that use the
two-pass strategy.

FossilOrigin-Name: dc555b1039c6930f6d15355c698ff917a85e8056
2017-01-28 19:45:34 +00:00
drh 6034d47618 Updates to the sqlite3_blob documentation. No changes to code.
FossilOrigin-Name: 426b440a5745f9c431c6a3d9ba542af61a6a83fb
2017-01-28 15:26:14 +00:00
drh 27c8467734 In the speed-check.sh script, automatically invoke "fossil test-diff --tk" on
the cachegrind output against trunk, if not generating a trunk run.

FossilOrigin-Name: aa1ab37100a91ab4bb91d50a1267c26967efcb21
2017-01-28 13:40:55 +00:00
dan 2d2e4f3895 Fix a typo in the docs for sqlite3_update_hook().
FossilOrigin-Name: 7c029655cc3369a1e46741fdd3701d36d420b28b
2017-01-28 06:50:15 +00:00
drh cc04dacb85 Add the sha1.c loadable extension that implements the sha1() and sha1_query()
SQL functions.

FossilOrigin-Name: 24e77c1cef163a9822635570b3211789ff23d5c9
2017-01-27 19:27:38 +00:00
dan 50133dea28 Fix a problem causing the pre-update hook to be invoked by DROP TABLE
statements.

FossilOrigin-Name: fbb6bf1b69cfd581b4ffd778c344e3fbd9c9406f
2017-01-27 17:02:26 +00:00
drh 9ec82ff2ba Alternative ICU fix (compare to check-in [50e60cb4]) that avoids casting
integers to pointers.

FossilOrigin-Name: d9752c8f7c55426fd7d2b877c5cc3784f93b5349
2017-01-27 13:14:12 +00:00
drh 7aee83b935 In the command-line shell, enhance the ".mode" command so that it restores the
default column and row separators for modes "line", "list", "column", and
"tcl".

FossilOrigin-Name: 58f02e6eae8fc9e2577fe435b0282fb46af3960d
2017-01-27 01:52:42 +00:00
drh 6ee610bfc0 Another micro-optimization in accessPayload(). Slightly smaller and faster.
FossilOrigin-Name: c012619b65d70b4ef6cf33532ef57d7f8ba42d74
2017-01-27 01:25:00 +00:00
drh cdf360a0d5 Performance optimization in accessPayload().
FossilOrigin-Name: ebb1fd98d4e448aa6d8f1e5be7ddc5bedb3db95b
2017-01-27 01:13:49 +00:00
drh 42e28f12a3 Simplify the accessPayload() routine so that it always populates the overflow
page cache.  In the one case where populating the page cache can lead to 
problems, simply invalidate the cache as soon as accessPayload() returns.  
This simplification reduces code size and helps accessPayload() to run a 
little faster.  This backs out the eOp==2 mode of accessPayload() added by 
check-in [da59198505].

FossilOrigin-Name: 68e7a8c6765649195ef1ad9407d87d44a307b462
2017-01-27 00:31:59 +00:00
drh 945b094632 Remove an unreachable branch in the error handling logic for
sqlite3BtreePayloadChecked().

FossilOrigin-Name: 293bf3ed7e40745349c83b202b27ed1b48517e1a
2017-01-26 21:30:00 +00:00
drh b7dab70a92 Improvement to the OP_Permutation opcode to prevent it from using CPU cycles
for initialization in prepared statements that do not use that opcode.

FossilOrigin-Name: b4a98f65564a0d9fba2fef95ebd00a39b3e1e572
2017-01-26 18:00:00 +00:00
drh fae58d51ce Remove the obsolete lastRowid cache from the sqlite3VdbeExec() for a size
reduction and performance improvement.

FossilOrigin-Name: b4803184652e5f4f823c1521412bc480baeb3dbf
2017-01-26 17:26:44 +00:00
drh d08406477a Performance optimization in sqlite3VdbeCloseStatement().
FossilOrigin-Name: 1e96e5ec1ee617cb5b5cbdc5a2ee79c8cc35821d
2017-01-26 17:11:18 +00:00
drh 83ec2761fa Performance optimization to sqlite3_blob_read().
FossilOrigin-Name: 7459f4b7ed4007d9ec44c3bf0fcba04f5f8540a9
2017-01-26 16:54:47 +00:00
drh 8bb9fd3b45 Minor simplification and performance optimization for Direct Overflow Read.
FossilOrigin-Name: 3e96d6efa867b765c8acf1454014b1e71b2e4f21
2017-01-26 16:27:32 +00:00
drh d930b5cb06 Make SQLITE_DIRECT_OVERFLOW_READ work for in WAL mode as long as the page
being read is not in the the -wal file.

FossilOrigin-Name: 9879be1899adf5634f551a2077b15ccb1133e4e3
2017-01-26 02:26:02 +00:00
drh 2b15f6e11b Enhancements to the kvtest utility program. Add the --jmode option.
Improved output formatting.

FossilOrigin-Name: 62a4851ccf88837d1c16dae8204f7f264e80e3c9
2017-01-26 01:54:39 +00:00
drh 87f500ce43 Modify the ICU extension to use a static initializer, as VC++ complains about
a dynamic initialization.  Maybe the dynamic structure initialization is a
GCC extension.

FossilOrigin-Name: 50e60cb44fd3687dde5551d02bad60c323beaabc
2017-01-26 00:58:27 +00:00
drh d447dced96 Trim NULL values off the end of records when the SQLITE_ENABLE_TRIM_NULLS
compile-time option is used.  Increase the size of the P5 operand to 16 bits.
Fix a problem with short records in the sessions extension.

FossilOrigin-Name: 4801bd59a01dcc11a3eb9e776e7599b36f162d2a
2017-01-25 20:55:11 +00:00
dan 7271d7a19c Fix another pre-update hook issue, this time in sqlite3preupdate_old().
FossilOrigin-Name: c7651d21bfdfd9b8cf04b26e0264bc58c03d247f
2017-01-25 18:53:27 +00:00
dan d47e1ccb57 Fix a test script problem in exclusive2.test causing it to fail on this
branch.

FossilOrigin-Name: f66614dc78e32d2d369518200b3322cd97990ffe
2017-01-25 18:12:46 +00:00
dan 2a86c1962c Fix a problem with the pre-update hook on this branch.
FossilOrigin-Name: 6fc4fbfa29cfa795edf32e4a1f2d0eceb3007f68
2017-01-25 17:44:13 +00:00
drh 585ce1923c Experimental enhancement to automatically trim NULL values from the end of
records, for a reduced disk footprint.  This change also involves increasing
the P5 operand from 8 to 16 bits.

FossilOrigin-Name: 118ded403b95050b74ae2b03919c43d614094a32
2017-01-25 14:58:27 +00:00
drh 7888d14caa Ensure that sqlite3_blob_reopen() correctly handles short rows.
Fix for ticket [e6e962d6b0f06f46e].

FossilOrigin-Name: 8cd1a4451cce1fe28f462800e2be1dee1735c0d0
2017-01-25 14:38:19 +00:00
drh 666d34c791 Fix SQLITEINT_H macro usage in two extensions.
FossilOrigin-Name: 0803390c152141c9ab4e7a28406b2a5d72a5c2fa
2017-01-25 13:54:27 +00:00
drh 210b0d0eb3 Ensure that sqlite3_blob_reopen() correctly handles short rows.
Proposed fix for ticket [e6e962d6b0f06f46e].  Further testing needed.

FossilOrigin-Name: 57d8dad35c2a9ab635e954dce7f3986ae1ca8ed2
2017-01-25 04:41:34 +00:00
drh d1b2566b07 Document the --mmap option in the --help screen for kvtest. Enhance kvtest so
that numeric arguments can have suffixes like "K" or "M".  Add kvtest to the
unix makefiles.

FossilOrigin-Name: 175bda87288c7ce15b163316159f53a60822ccad
2017-01-23 19:11:38 +00:00
drh bace324082 Add the --mmap option to the kvtest utility program.
FossilOrigin-Name: 4948f7e6d2a1cfce36a7aab2f5b65be07c285ac3
2017-01-23 18:40:15 +00:00
drh 6aabff38e9 Optimization: Try to avoid unnecessary btree searching when repositioning
a cursor to the next row.

FossilOrigin-Name: ee793d30c1dc1f78f49e6230d17750eceedbd8ed
2017-01-23 16:56:18 +00:00
dan 65c4c0b02d Add the missing SQLITE_API symbol to test_delete.c (it is not added
automatically as this file is not part of the amalgamation).

FossilOrigin-Name: 7a4f512ddf9e7e718389c80930d6268ab598459c
2017-01-23 15:58:09 +00:00
dan 1b9fd2651b Fix a problem preventing FTS5 from correctly passing the FTS5_TOKENIZE_PREFIX
flag to custom tokenizer implementations.

FossilOrigin-Name: 03c601344ed56b316bcc5fd02f6648b0009ba61b
2017-01-23 07:06:27 +00:00
drh 38305ab55f Fix an uninitialized variable in the command-line shell.
FossilOrigin-Name: 06b8001ade62bc59e6ae20f761167a81d85a4272
2017-01-22 16:34:35 +00:00
mistachkin 35f30d3398 Fixes to documentation comments in the public header file.
FossilOrigin-Name: 772dcb08f400f20d4dbfb74df39de78da24ee5fd
2017-01-22 02:04:05 +00:00
drh eacb4412b1 Fix an initialized variable in kvtest.
FossilOrigin-Name: ed62c5a6562262709128099f757ae60807a930d7
2017-01-22 00:11:07 +00:00
drh 7f11afaba1 A better implementation of the moveto-neighbor optimization that checks for
nearby rows on adjacent pages.

FossilOrigin-Name: 2c4ecb85a475b9063aa8a3bb517ac181a7ded649
2017-01-21 21:47:54 +00:00
drh 451e76d5b5 B-tree optimization: When seeking on a rowid table that has already been
positioned, check to see if the new row happens to be the next row on the
same leaf page.  That is a reasonably common case, and if it is true it
avoids a full binary search.

FossilOrigin-Name: 8e5cfb2039126da7689c4b1c88760f10e1234eaf
2017-01-21 16:54:19 +00:00
drh 3b2936fada Change sqlite3_blob_reopen() to call sqlite3VdbeExec() directly rather than
going through sqlite3_step().  Performance enhancement.

FossilOrigin-Name: 347df3c1fd7322e7aacaf1e9f8be81830947c482
2017-01-21 16:27:56 +00:00
drh 184d902db1 In the kvtest.c test utility, reuse the buffer into which blobs are read,
rather than reallocating it for each row.  This is a closer match to how
other test programs work, and thus provides a better comparison.

FossilOrigin-Name: 0d1ad13a296b22d6fe36879b56f99bd6af1acd3a
2017-01-21 15:55:41 +00:00
drh 36cae856ee Remove an unnecessary sqlite3_bind_int64() call from sqlite3_blob_open().
Also other minor refactoring of the sqlite3_blob implementation.

FossilOrigin-Name: 9d197a532349f4b1caf66bbed70ca46df86cb86f
2017-01-21 14:11:28 +00:00
drh cd64553015 Minor performance optimization and size reduction to the accessPayload()
routine in btree.c.

FossilOrigin-Name: 264e5c10d7144910b3223b64546567fa20e4bc65
2017-01-20 20:43:14 +00:00
dan dfd0de82f1 Fix a typo in the help message for kvtest.
FossilOrigin-Name: 8971d98f25a4f5fb060db8ed6a4b06f083122a50
2017-01-20 16:47:34 +00:00
dan befcd8ad84 Add option "--stats" to test program kvtest. Specifying --stats causes kvtest
to output information similar to the shell tool option of the same name.

FossilOrigin-Name: 90291327fc127671d9847a4a2ce1ed47a408cfc6
2017-01-20 16:46:20 +00:00
drh 508286701a Get the "--testset rtree" option working on speedtest1. Add the --rtree,
--lookaside, and --clang options to the speed-check.sh script.

FossilOrigin-Name: 87b640c8d07a76b2bc7e896e01965cc09e06f77b
2017-01-20 16:09:12 +00:00
drh 4df65fc20f Minor performance optimizations to sqlite3_blob_open() and
sqlite3_blob_reopen().

FossilOrigin-Name: 52a61967d920047ea0b4409b79793e05c0128964
2017-01-20 00:40:26 +00:00
drh 8674e49214 If compiled with SQLITE_INLINE_MEMCPY, all memcpy() calls are replaced with
in-line code.  With that change, cachegrind shows which memcpy() calls
are taking the most time.  This is a performance-measurement hack only and
is not for production use.

FossilOrigin-Name: 9ed38521617136223a667988aed40e25797faf84
2017-01-19 21:20:11 +00:00
mistachkin 2f31d02049 In the 'vtshim' extension, avoid accessing freed memory when handling errors from xCreate/xConnect.
FossilOrigin-Name: ffd559afd32dcdce9c733ebccdee88fda9b689cf
2017-01-19 18:20:36 +00:00
mistachkin aac853bae8 In the 'windirent' test module, use a macro for the hidden/system attribute checking.
FossilOrigin-Name: a84a08d0716656dc0b26eafb1841c48d83c67ef2
2017-01-18 22:47:42 +00:00
mistachkin d3e73d6c1c Remove superfluous option to Tcl 'lsort' in the vtabH test file.
FossilOrigin-Name: b92cc6e58ae31cbe6600a522beb5485f7add04b2
2017-01-18 22:19:01 +00:00
mistachkin 7059138a08 Make the vtabH-3.1 test more portable and robust.
FossilOrigin-Name: d3c91c1fb345fbcbfc60a897bebf771c795430c9
2017-01-18 22:16:34 +00:00
mistachkin 8a9e83583b Fix handling of initial hidden and/or system files in the opendir() implementation for Windows. No changes to non-test code.
FossilOrigin-Name: 26dd42b462dc621b8b0a2295fc91d3e61ac732b6
2017-01-18 22:16:20 +00:00
dan 25fd2e247b Fix a problem that could cause a spurious SQLITE_NOMEM error when attempting
to resume an RBU operation if the previous client failed right after
completing the incremental checkpoint. Also a "cannot vacuum wal db" error
that could occur when resuming an RBU vacuum if an error (OOM or IO error)
occurs during the incremental checkpoint.

FossilOrigin-Name: 681d96eb822e606da53700867191d4738bda20c8
2017-01-17 10:41:42 +00:00
drh c711f53f30 Disable intrinsic functions for Windows using Clang, due to reports of
linkage errors.  This causes a 0.6% performance reduction.  We will want to
revisit this change in the future.

FossilOrigin-Name: 7fd560c6d2ff470b755ad118287a0a8825b3009e
2017-01-17 00:10:58 +00:00
drh de48a3f98a Back out check-in [0b3174e0b1364c] and replace it with a better fix for \ticket [91e2e8ba6ff2e2] - a fix that does not cause the problem identified by
ticket [7ffd1ca1d2ad4ec]. Add new test cases for both tickets.

FossilOrigin-Name: 9b64af7b5201a8700ae9e384b04714ca18df7449
2017-01-16 18:10:17 +00:00
drh da060052e3 Back out check-in [0b3174e0b1364c] and replace it with a better fix
for ticket [91e2e8ba6ff2e2] - a fix that does not cause the problem
identified by ticket [7ffd1ca1d2ad4ec].

FossilOrigin-Name: 0613665274346917f5482f9210bf0c60a0fed7d9
2017-01-16 16:43:02 +00:00
drh ce31643fd9 Add test cases for tickets [91e2e8ba6ff2e2] and [7ffd1ca1d2ad4ec].
FossilOrigin-Name: 9d0dfe0b088a5917afa06207ca3ac5618e3da82f
2017-01-16 16:01:50 +00:00
dan ef2f5925d8 Fix a problem preventing resumption of RBU operations after recovering from a
process or system failure that occurs during the incremental-checkpoint phase.

FossilOrigin-Name: 97914266cb4ec63b0c9185ab139673139bd2f0ed
2017-01-13 18:24:37 +00:00
drh be7a0cee4e Fix the build for SQLITE_ENABLE_MEMORY_MANAGEMENT.
FossilOrigin-Name: 8c85b8fdd7f0ba65fba83361d361a567b797a184
2017-01-13 12:53:35 +00:00
drh 7b20a15d13 Remove a branch that is probably unreachable, and which adds no value.
FossilOrigin-Name: 9acc72381ccd5e36f3ffdf7e7fbefc5a15701eb4
2017-01-12 19:10:55 +00:00
drh ae051a8970 Fix harmless compiler warnings in the UPDATE code generator.
FossilOrigin-Name: 385db266673abaf7013ffad09b28014c246547ef
2017-01-12 16:21:54 +00:00
drh 70d90a2c37 Remove an unnecessary corruption test from the btree balancer. If corruption
is present, it will be found harmlessly by later tests.

FossilOrigin-Name: bddf39562d08e259c43dd59b82afb62fe0eb2eef
2017-01-12 16:14:33 +00:00
drh b701c9a6c3 Improved detection of cells that extend into the reserved space at the end
of the page while adjusting overflow page pointers during autovacuum.

FossilOrigin-Name: 8097712c9c1f4ea16bc5dd462da248ef98896061
2017-01-12 15:11:03 +00:00
drh 24be549329 Remove invalid test case from cursorhints2.test
FossilOrigin-Name: 163cc1b2f7100827d5803b81dcd97a1417744f66
2017-01-12 11:52:47 +00:00
drh ea8f0a155e Make sure Tcl_AppendResult() always has a NULL-pointer argument at the end.
FossilOrigin-Name: c07aef6f909fe35de110f0b180dbf5aa4c226af3
2017-01-12 11:50:08 +00:00
dan ba47020b63 Changes to allow some multi-row UPDATE statements to avoid the two-pass
approach.

FossilOrigin-Name: 7ae6104a3e0d1d2cacfe2be732f0220a53908132
2017-01-11 21:03:53 +00:00
dan e206ea7f48 Fix a problem causing the pre-update hook to be passed an incorrect rowid
value in some single-pass multi-row updates.

FossilOrigin-Name: 62257eb53c13d4c7ed128d5d89f6f10d4aff945c
2017-01-11 20:10:30 +00:00
dan 2c6fec21dc Fix a problem with single-pass multi-row UPDATE statements that invoke REPLACE
conflict handling.

FossilOrigin-Name: 0a2b8e1b9dc600b5a93622e8eea6218649df5e0f
2017-01-11 19:03:08 +00:00
dan 372f942f17 Fix a problem preventing UPDATE statements that use a range-scan on the PK
index of a WITHOUT ROWID table from using a one-pass strategy.

FossilOrigin-Name: cab86c90945126c24c40cf2dedd053a8c46d00d6
2017-01-11 15:42:14 +00:00
drh 785d8ed0d4 In the STAT4 computations, ensure that the aAvgEq values do not go negative.
FossilOrigin-Name: f58f75b5a06f88ba97bd1a02bee621c64691c6f8
2017-01-11 14:15:29 +00:00
dan f91c1318f4 Changes to allow some multi-row UPDATE statements to avoid the two-pass
approach.

FossilOrigin-Name: 46db23ccd116ce5b9d949f9293be8a2818411b46
2017-01-10 20:04:38 +00:00
dan f112f0b3de Add a test case for ticket [25e335f802dd].
FossilOrigin-Name: e500c15a9f55aed1601f7c14169dd56fd76f1fdd
2017-01-10 17:37:49 +00:00
drh 8e36ddd37e Throw an error if the ON clause of a LEFT JOIN references tables to the right
of the ON clause.  Fix for ticket [25e335f802dd].

FossilOrigin-Name: c92ecff2ec5f178433d21f25c653d0fdd9128d7c
2017-01-10 17:33:43 +00:00
drh 1d21bac8aa Avoid unnecessary calls to the xRoundup() method of the memory allocator when
the soft heap limit is not set.

FossilOrigin-Name: 4209b89eab01814228a178963238e0dffffad2a4
2017-01-10 16:09:46 +00:00
drh d9bcb32ebb Fix a potential assertion fault discovered by OSS-Fuzz.
FossilOrigin-Name: 71c03b59b645884ebd6b9e18713cd2eb8c949870
2017-01-10 15:08:06 +00:00
drh e4a8b8769e Remove a redundant assignment statement.
FossilOrigin-Name: a5fa09657bd6c4ea5fe6712b0f8af2170cbe0381
2017-01-09 19:55:19 +00:00
drh 7441df72be Performance optimization and size reduction in the OP_Variable opcode.
FossilOrigin-Name: 237aa97452e20c312f256a8fd62531e3d447f84b
2017-01-09 19:27:04 +00:00
mistachkin ab61cf7d93 Fix typo in a comment. No changes to code.
FossilOrigin-Name: d38fd22935b1572f4481b39c2f9274329b18ea99
2017-01-09 18:22:54 +00:00
drh e7b554d615 Modify the OP_RowData opcode so that when P3!=0 it is allowed to hold an
ephemeral copy of the content.  This avoids unnecessary memcpy() operations
in the xfer-optimization and VACUUM.

FossilOrigin-Name: 6e106acd74da3baa5c308a76443d2f0a7c904e5e
2017-01-09 15:44:25 +00:00
drh f4e994b23a Add the SQLITE_UINT64_TYPE compile-time option.
FossilOrigin-Name: a5fe03bc419d9c7e6068ed38810e3f183de179b5
2017-01-09 13:43:09 +00:00
drh 68116939eb Improvements to the iIdxNoSeek optimization of sqlite3GenerateRowDelete()
so that it is automatically disabled for BEFORE triggers but works in all
other cases.

FossilOrigin-Name: 3178ec4c27efc4ff84bcd17ddb17ec50a6ac96b3
2017-01-07 14:47:03 +00:00
drh 4cef5b1c81 Critical fix to the previous check-in so that it works when there are
BEFORE triggers that move the cursor before the OP_Delete has a chance to
be applied.

FossilOrigin-Name: db2c0960ffb3b396b20e0441d3edb812254c82bc
2017-01-07 14:26:28 +00:00
drh ad1d9a8707 Avoid an unnecessary btree seek while deleting an index entry due to a conflict
on a REPLACE operation.

FossilOrigin-Name: f0495c5133d0dc04d63521136d6b9ca440792cdf
2017-01-07 03:26:50 +00:00
drh a67b5cb6b3 Avoid duplicate b-tree searches in the duplicate row detector used to
implement DISTINCT.

FossilOrigin-Name: d577dda0a7fbfacda57e8cad2bc4651d2a05d813
2017-01-07 00:56:01 +00:00
dan e1ff3f5e11 Ensure that "PRAGMA case_sensitive_like" and "PRAGMA shrink_memory" set the
number of output columns to 0 (as they are statements that return no data).

FossilOrigin-Name: 6696cd1878be4bd44a24841b04163e52d847711e
2017-01-06 13:49:40 +00:00
dan 1439a1e80f Improve handling of corrupt data in fts5.
FossilOrigin-Name: 609ac1c73f7c2b48a571c178a72383996a9538fe
2017-01-06 11:55:03 +00:00
drh 3d775e7586 Clarify the documentation on sqlite3_column_count().
FossilOrigin-Name: 9ea0baddd893e54ec79399ae83033ae139650535
2017-01-06 01:09:43 +00:00
mistachkin 817be73bfc Remove several non-portable tests for the deprecated temp_store_directory PRAGMA.
FossilOrigin-Name: 28d87789141d816e0bce6d3965ce84c79b803218
2017-01-06 00:02:51 +00:00
dan 2b64313b8d Ensure that sqlite3_column_count() returns 0 for the "set" mode of "get/set"
PRAGMA statements that do not return a value in that case (e.g. page_size,
cache_size, auto_vacuum).

FossilOrigin-Name: 2f57939a5583ae420b525c7e0f0dcda8626fe992
2017-01-05 20:00:08 +00:00
dan 9e1ab1a8a4 Ensure that sqlite3_column_count() returns 0 for the "set" mode of "get/set"
PRAGMA statements that do not return a value in that case (e.g. page_size,
cache_size, auto_vacuum).

FossilOrigin-Name: 5c05d8ec5e895661dae2de30c73dfdeaff93511e
2017-01-05 19:32:48 +00:00
dan ac56ab7e48 Fix handling the case where a sub-query in a FROM clause is itself a UNION
ALL, and one side of that UNION ALL is a query on a view that includes an
ORDER BY. Fix for ticket [190c2507].

FossilOrigin-Name: 590ca83b8e8cdd5d24ed7f10f43e540aa0627f22
2017-01-05 17:23:11 +00:00
drh 5f40cebf43 Fix problems in trigger and foreign key handling when doing REPLACE on a
WITHOUT ROWID table that has no secondary indexes.

FossilOrigin-Name: 571f166ea8721e2322965b6f23e758b78d13baca
2017-01-05 13:50:12 +00:00
drh 34d04d64f0 Ensure that the sqlite3_value_text() interface returns a buffer that is long
enough to hold the complete string plus the zero terminator even when the
input is a zeroblob.  Fix for a problem detected by OSS-Fuzz.

FossilOrigin-Name: 2dc7eeb5b4d2eaf1d843eda56f339fd4cc80d78e
2017-01-05 07:58:29 +00:00
dan f9a12a106b Fix some problems with foreign key processing within REPLACE ops on WITHOUT
ROWID tables with no triggers or auxiliary indexes.

FossilOrigin-Name: c1220b1af62629d7fc2178512786d613cd7ea711
2017-01-05 06:57:42 +00:00
drh 801f55d837 Improved the comment on the block of code the provides the performance
optimization originally added by check-in [925840cfdb].  The original
check-in omitted condition 4, which was the cause of bug [30027b613b].

FossilOrigin-Name: c6506b82aa6583ccde5f673c79526d5f3920b67a
2017-01-04 22:02:56 +00:00
dan 4e1f0efb4d Possible fix for 30027b61. There may still be problems surrounding foreign key
processing.

FossilOrigin-Name: 71ccb1f4c490fdebc7008e884384e7809b849742
2017-01-04 20:13:51 +00:00
drh 87e1e56b5b Adjust filename creation in test_sqllog.c so that it uses leading zeros on
counters, so that files appear in order when sorted lexicographically.

FossilOrigin-Name: 8d670973595bd01ffc9b2ab53b965e6d6d22c573
2017-01-04 14:53:53 +00:00
drh b005f9e620 Performance enhancements in the printf implementation.
FossilOrigin-Name: 82e4001b8caef7b31967f3edcbc1a545c081bdbc
2017-01-04 13:09:05 +00:00
drh 49c5ab243b Factor constant functions out of the inner loop since they are more expensive
than the extra OP_Copy needed to move the result into place.

FossilOrigin-Name: 80ad317f89c46db0d0d252aefdc036a34a61183d
2017-01-04 04:18:00 +00:00
drh ad879ffdb5 Clean up the implementation of constant function factorization.
FossilOrigin-Name: 2ab997e47998d261bd6190bbce5c09f3fbd4cfd3
2017-01-04 04:10:02 +00:00
drh 1e9b53f9bc Attempt to factor out constant functions from the interior of table scans,
since functions can often be expensive to compute.

FossilOrigin-Name: 62e9270a8057d758621da33adb27fad14225f95d
2017-01-04 01:07:24 +00:00
71 changed files with 2808 additions and 661 deletions
+7 -2
View File
@@ -1177,8 +1177,13 @@ LogEst$(TEXE): $(TOP)/tool/logest.c sqlite3.h
wordcount$(TEXE): $(TOP)/test/wordcount.c sqlite3.lo
$(LTLINK) -o $@ $(TOP)/test/wordcount.c sqlite3.lo $(TLIBS)
speedtest1$(TEXE): $(TOP)/test/speedtest1.c sqlite3.lo
$(LTLINK) -o $@ $(TOP)/test/speedtest1.c sqlite3.lo $(TLIBS)
speedtest1$(TEXE): $(TOP)/test/speedtest1.c sqlite3.c
$(LTLINK) $(ST_OPT) -o $@ $(TOP)/test/speedtest1.c sqlite3.c $(TLIBS)
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)
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)
+1 -1
View File
@@ -1601,7 +1601,7 @@ Fts5ExprPhrase *sqlite3Fts5ParseTerm(
rc = fts5ParseStringFromToken(pToken, &z);
if( rc==SQLITE_OK ){
int flags = FTS5_TOKENIZE_QUERY | (bPrefix ? FTS5_TOKENIZE_QUERY : 0);
int flags = FTS5_TOKENIZE_QUERY | (bPrefix ? FTS5_TOKENIZE_PREFIX : 0);
int n;
sqlite3Fts5Dequote(z);
n = (int)strlen(z);
+4 -3
View File
@@ -2039,7 +2039,7 @@ static void fts5SegIterNext(
else if( pLeaf->nn>pLeaf->szLeaf ){
pIter->iPgidxOff = pLeaf->szLeaf + fts5GetVarint32(
&pLeaf->p[pLeaf->szLeaf], iOff
);
);
pIter->iLeafOffset = iOff;
pIter->iEndofDoclist = iOff;
bNewTerm = 1;
@@ -2073,6 +2073,7 @@ static void fts5SegIterNext(
*/
int nSz;
assert( p->rc==SQLITE_OK );
assert( pIter->iLeafOffset<=pIter->pLeaf->nn );
fts5FastGetVarint32(pIter->pLeaf->p, pIter->iLeafOffset, nSz);
pIter->bDel = (nSz & 0x0001);
pIter->nPos = nSz>>1;
@@ -3067,7 +3068,7 @@ static void fts5ChunkIterate(
break;
}else{
pgno++;
pData = fts5DataRead(p, FTS5_SEGMENT_ROWID(pSeg->pSeg->iSegid, pgno));
pData = fts5LeafRead(p, FTS5_SEGMENT_ROWID(pSeg->pSeg->iSegid, pgno));
if( pData==0 ) break;
pChunk = &pData->p[4];
nChunk = MIN(nRem, pData->szLeaf - 4);
@@ -5829,7 +5830,7 @@ static void fts5IndexIntegrityCheckSegment(
** ignore this b-tree entry. Otherwise, load it into memory. */
if( iIdxLeaf<pSeg->pgnoFirst ) continue;
iRow = FTS5_SEGMENT_ROWID(pSeg->iSegid, iIdxLeaf);
pLeaf = fts5DataRead(p, iRow);
pLeaf = fts5LeafRead(p, iRow);
if( pLeaf==0 ) break;
/* Check that the leaf contains at least one term, and that it is equal
+1 -1
View File
@@ -152,7 +152,7 @@ foreach {tn expr res} {
1 {abc} {"abc"}
2 {one} {"one"|"i"|"1"}
3 {3} {"3"|"iii"|"three"}
4 {3*} {"3"|"iii"|"three" *}
4 {3*} {"3" *}
} {
do_execsql_test 4.1.$tn {
SELECT fts5_expr($expr, 'tokenize=tclnum')
+39
View File
@@ -262,5 +262,44 @@ do_execsql_test 8.3 {
brown dog fox jump lazi over quick the
}
#-------------------------------------------------------------------------
# Check that the FTS5_TOKENIZE_PREFIX flag is passed to the tokenizer
# implementation.
#
reset_db
proc tcl_create {args} { return "tcl_tokenize" }
sqlite3_fts5_create_tokenizer db tcl tcl_create
set ::flags [list]
proc tcl_tokenize {tflags text} {
lappend ::flags $tflags
foreach {w iStart iEnd} [fts5_tokenize_split $text] {
sqlite3_fts5_token $w $iStart $iEnd
}
}
do_execsql_test 9.1.1 {
CREATE VIRTUAL TABLE t1 USING fts5(a, tokenize=tcl);
INSERT INTO t1 VALUES('abc');
INSERT INTO t1 VALUES('xyz');
} {}
do_test 9.1.2 { set ::flags } {document document}
set ::flags [list]
do_execsql_test 9.2.1 { SELECT * FROM t1('abc'); } {abc}
do_test 9.2.2 { set ::flags } {query}
set ::flags [list]
do_execsql_test 9.3.1 { SELECT * FROM t1('ab*'); } {abc}
do_test 9.3.2 { set ::flags } {prefixquery}
set ::flags [list]
do_execsql_test 9.4.1 { SELECT * FROM t1('"abc xyz" *'); } {}
do_test 9.4.2 { set ::flags } {prefixquery}
set ::flags [list]
do_execsql_test 9.5.1 { SELECT * FROM t1('"abc xyz*"'); } {}
do_test 9.5.2 { set ::flags } {query}
finish_test
+21 -23
View File
@@ -493,38 +493,36 @@ static void icuLoadCollation(
** Register the ICU extension functions with database db.
*/
int sqlite3IcuInit(sqlite3 *db){
struct IcuScalar {
static const struct IcuScalar {
const char *zName; /* Function name */
int nArg; /* Number of arguments */
int enc; /* Optimal text encoding */
void *pContext; /* sqlite3_user_data() context */
unsigned char nArg; /* Number of arguments */
unsigned short enc; /* Optimal text encoding */
unsigned char iContext; /* sqlite3_user_data() context */
void (*xFunc)(sqlite3_context*,int,sqlite3_value**);
} scalars[] = {
{"regexp", 2, SQLITE_ANY|SQLITE_DETERMINISTIC, 0, icuRegexpFunc},
{"lower", 1, SQLITE_UTF16|SQLITE_DETERMINISTIC, 0, icuCaseFunc16},
{"lower", 2, SQLITE_UTF16|SQLITE_DETERMINISTIC, 0, icuCaseFunc16},
{"upper", 1, SQLITE_UTF16|SQLITE_DETERMINISTIC, (void*)1, icuCaseFunc16},
{"upper", 2, SQLITE_UTF16|SQLITE_DETERMINISTIC, (void*)1, icuCaseFunc16},
{"lower", 1, SQLITE_UTF8|SQLITE_DETERMINISTIC, 0, icuCaseFunc16},
{"lower", 2, SQLITE_UTF8|SQLITE_DETERMINISTIC, 0, icuCaseFunc16},
{"upper", 1, SQLITE_UTF8|SQLITE_DETERMINISTIC, (void*)1, icuCaseFunc16},
{"upper", 2, SQLITE_UTF8|SQLITE_DETERMINISTIC, (void*)1, icuCaseFunc16},
{"like", 2, SQLITE_UTF8|SQLITE_DETERMINISTIC, 0, icuLikeFunc},
{"like", 3, SQLITE_UTF8|SQLITE_DETERMINISTIC, 0, icuLikeFunc},
{"icu_load_collation", 2, SQLITE_UTF8, (void*)db, icuLoadCollation},
{"icu_load_collation", 2, SQLITE_UTF8, 1, icuLoadCollation},
{"regexp", 2, SQLITE_ANY|SQLITE_DETERMINISTIC, 0, icuRegexpFunc},
{"lower", 1, SQLITE_UTF16|SQLITE_DETERMINISTIC, 0, icuCaseFunc16},
{"lower", 2, SQLITE_UTF16|SQLITE_DETERMINISTIC, 0, icuCaseFunc16},
{"upper", 1, SQLITE_UTF16|SQLITE_DETERMINISTIC, 1, icuCaseFunc16},
{"upper", 2, SQLITE_UTF16|SQLITE_DETERMINISTIC, 1, icuCaseFunc16},
{"lower", 1, SQLITE_UTF8|SQLITE_DETERMINISTIC, 0, icuCaseFunc16},
{"lower", 2, SQLITE_UTF8|SQLITE_DETERMINISTIC, 0, icuCaseFunc16},
{"upper", 1, SQLITE_UTF8|SQLITE_DETERMINISTIC, 1, icuCaseFunc16},
{"upper", 2, SQLITE_UTF8|SQLITE_DETERMINISTIC, 1, icuCaseFunc16},
{"like", 2, SQLITE_UTF8|SQLITE_DETERMINISTIC, 0, icuLikeFunc},
{"like", 3, SQLITE_UTF8|SQLITE_DETERMINISTIC, 0, icuLikeFunc},
};
int rc = SQLITE_OK;
int i;
for(i=0; rc==SQLITE_OK && i<(int)(sizeof(scalars)/sizeof(scalars[0])); i++){
struct IcuScalar *p = &scalars[i];
const struct IcuScalar *p = &scalars[i];
rc = sqlite3_create_function(
db, p->zName, p->nArg, p->enc, p->pContext, p->xFunc, 0, 0
db, p->zName, p->nArg, p->enc,
p->iContext ? (void*)db : (void*)0,
p->xFunc, 0, 0
);
}
+1 -1
View File
@@ -22,7 +22,7 @@
** how JSONB might improve on that.)
*/
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_JSON1)
#if !defined(_SQLITEINT_H_)
#if !defined(SQLITEINT_H)
#include "sqlite3ext.h"
#endif
SQLITE_EXTENSION_INIT1
+399
View File
@@ -0,0 +1,399 @@
/*
** 2017-01-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.
**
******************************************************************************
**
** This SQLite extension implements a functions that compute SHA1 hashes.
** Two SQL functions are implemented:
**
** sha1(X)
** sha1_query(Y)
**
** The sha1(X) function computes the SHA1 hash of the input X, or NULL if
** X is NULL.
**
** The sha1_query(Y) function evalutes all queries in the SQL statements of Y
** and returns a hash of their results.
*/
#include "sqlite3ext.h"
SQLITE_EXTENSION_INIT1
#include <assert.h>
#include <string.h>
#include <stdarg.h>
/******************************************************************************
** The Hash Engine
*/
/* 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.
*/
#define a qq[0]
#define b qq[1]
#define c qq[2]
#define d qq[3]
#define e qq[4]
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));
/* 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;
}
/* 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;
}
/* End of the hashing logic
*****************************************************************************/
/*
** 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];
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);
}
/*
** 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 nCol; /* Number of columns in the result set */
int i; /* Loop counter */
int rc;
int n;
const char *z;
SHA1Context cx;
char zOut[44];
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;
}
nCol = sqlite3_column_count(pStmt);
z = sqlite3_sql(pStmt);
n = (int)strlen(z);
hash_step_vformat(&cx,"S%d:",n);
hash_step(&cx,(unsigned char*)z,n);
/* Compute a hash over the result of the query */
while( SQLITE_ROW==sqlite3_step(pStmt) ){
hash_step(&cx,(const unsigned char*)"R",1);
for(i=0; i<nCol; i++){
switch( sqlite3_column_type(pStmt,i) ){
case SQLITE_NULL: {
hash_step(&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';
hash_step(&cx, x, 9);
break;
}
case SQLITE_FLOAT: {
sqlite3_uint64 u;
int j;
unsigned char x[8];
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(&cx,x,9);
break;
}
case SQLITE_TEXT: {
int n = sqlite3_column_bytes(pStmt, i);
const unsigned char *z = sqlite3_column_text(pStmt, i);
hash_step_vformat(&cx,"T%d:",n);
hash_step(&cx, z, n);
break;
}
case SQLITE_BLOB: {
int n = sqlite3_column_bytes(pStmt, i);
const unsigned char *z = sqlite3_column_blob(pStmt, i);
hash_step_vformat(&cx,"B%d:",n);
hash_step(&cx, z, n);
break;
}
}
}
}
sqlite3_finalize(pStmt);
}
hash_finish(&cx, zOut);
sqlite3_result_text(context, zOut, 40, SQLITE_TRANSIENT);
}
#ifdef _WIN32
__declspec(dllexport)
#endif
int sqlite3_sha_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, "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);
}
return rc;
}
+2
View File
@@ -95,6 +95,7 @@ static int vtshimCreate(
if( rc ){
sqlite3_free(pNew);
*ppVtab = 0;
return rc;
}
pNew->pAux = pAux;
pNew->ppPrev = &pAux->pAllVtab;
@@ -133,6 +134,7 @@ static int vtshimConnect(
if( rc ){
sqlite3_free(pNew);
*ppVtab = 0;
return rc;
}
pNew->pAux = pAux;
pNew->ppPrev = &pAux->pAllVtab;
+66
View File
@@ -0,0 +1,66 @@
# 2014 October 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.
#
#***********************************************************************
#
if {![info exists testdir]} {
set testdir [file join [file dirname [info script]] .. .. test]
}
source $testdir/tester.tcl
source $testdir/malloc_common.tcl
set ::testprefix rbufault4
for {set tn 1} {1} {incr tn} {
reset_db
do_execsql_test 1.0 {
CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
CREATE INDEX i1b ON t1(b);
CREATE INDEX i1c ON t1(c);
INSERT INTO t1 VALUES(1, 2, 3);
INSERT INTO t1 VALUES(4, 5, 6);
}
forcedelete test.db2
sqlite3rbu_vacuum rbu test.db test.db2
for {set i 0} {$i < $tn} {incr i} { rbu step }
set rc [rbu close]
if {$rc!="SQLITE_OK"} {
if {$rc!="SQLITE_DONE"} {error $rc}
break
}
faultsim_save
do_faultsim_test $tn -faults oom-t* -prep {
faultsim_restore
} -body {
sqlite3rbu_vacuum rbu test.db test.db2
while 1 {
set rc [rbu step]
if {$rc=="SQLITE_DONE"} break
if {$rc!="SQLITE_OK"} { error $rc }
}
} -test {
catch {rbu close}
faultsim_test_result {0 {}} {1 SQLITE_NOMEM} {1 SQLITE_IOERR_NOMEM}
sqlite3rbu_vacuum rbu test.db test.db2
while {[rbu step]=="SQLITE_OK"} {}
set trc [rbu close]
if {$trc!="SQLITE_DONE"} { error "Got $trc instead of SQLITE_DONE!" }
set rc [db one {PRAGMA integrity_check}]
if {$rc!="ok"} { error "Got $rc instead of ok!" }
}
}
finish_test
+254
View File
@@ -0,0 +1,254 @@
# 2017 January 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 contains tests for resumption of RBU operations in the
# case where the previous RBU process crashed.
#
source [file join [file dirname [info script]] rbu_common.tcl]
set ::testprefix rburesume
forcedelete test.db-shm test.db-oal
do_execsql_test 1.0 {
CREATE TABLE t1(a PRIMARY KEY, b, c);
CREATE INDEX t1a ON t1(a);
CREATE INDEX t1b ON t1(b);
CREATE INDEX t1c ON t1(c);
WITH s(i) AS (
VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<50
)
INSERT INTO t1 SELECT randomblob(50), randomblob(75), randomblob(100) FROM s;
}
db_save_and_close
do_test 1.1 {
list [file exists test.db] \
[file exists test.db-wal] \
[file exists test.db-shm] \
[file exists test.db-oal]
} {1 0 0 0}
# Each iteration of the following loop:
#
# 1. Restores the db to the state it was in following test case 1.0
# 2. Opens an RBU vacuum and steps it $n times.
# 3. Closes the RBU vacuum handled opened in (2).
# 4. Opens a second RBU vacuum handle, resumes and completes the vacuum op.
#
# The loop runs until $n is large enough that step (2) vacuums the entire
# database.
#
for {set n 1} {$n < 5000} {incr n} {
db_restore
forcedelete state.db
sqlite3rbu_vacuum rbu test.db state.db
for {set i 0} {$i<$n} {incr i} {
set rc [rbu step]
if {$rc == "SQLITE_DONE"} break
}
rbu close
if {$rc == "SQLITE_DONE"} break
do_test 1.2.$n.1 {
sqlite3rbu_vacuum rbu test.db state.db
while {[rbu step]=="SQLITE_OK"} {}
rbu close
} {SQLITE_DONE}
do_test 1.2.$n.2 {
sqlite3 db2 test.db
db2 eval {
SELECT count(*) FROM t1;
PRAGMA integrity_check;
}
} {50 ok}
db2 close
}
# Each iteration of this loop:
#
# 1. Restores the db to the state it was in following test case 1.0
# 2. Opens an RBU vacuum and steps it $n times.
# 3. Takes a copy of all database files and the state db.
# 4. Opens a second RBU vacuum handle on the copy, resumes and completes the
# vacuum op.
#
# The loop runs until $n is large enough that step (2) vacuums the entire
# database.
#
for {set n 1} {$n < 5000} {incr n} {
db_restore
forcedelete state.db state.db-shm state.db-oal state.db-wal
sqlite3rbu_vacuum rbu test.db state.db
for {set i 0} {$i<$n} {incr i} {
set rc [rbu step]
if {$rc == "SQLITE_DONE"} break
}
if {$rc == "SQLITE_DONE"} {
rbu close
break
}
foreach f {test.db test.db-oal test.db-wal test.db-shm test.db-vacuum} {
set f2 [string map [list test.db test.db2] $f]
if {[file exists $f]} {
forcecopy $f $f2
} else {
forcedelete $f2
}
}
forcecopy state.db state.db2
rbu close
do_test 1.3.$n.1 {
sqlite3rbu_vacuum rbu test.db2 state.db2
while {[rbu step]=="SQLITE_OK"} {}
rbu close
} {SQLITE_DONE}
do_test 1.3.$n.2 {
sqlite3 db2 test.db2
db2 eval {
SELECT count(*) FROM t1;
PRAGMA integrity_check;
}
} {50 ok}
db2 close
}
# Each iteration of this loop:
#
# 1. Restores the db to the state it was in following test case 1.0
# 2. Opens an RBU vacuum and steps it 10 times. Then closes it.
# 2. Opens an RBU vacuum and steps it $n times.
# 3. Takes a copy of all database files and the state db.
# 4. Opens a second RBU vacuum handle on the copy, resumes and completes the
# vacuum op.
#
# The loop runs until $n is large enough that step (3) vacuums the entire
# database.
#
for {set n 1} {$n < 5000} {incr n} {
db_restore
forcedelete state.db state.db-shm state.db-oal state.db-wal
sqlite3rbu_vacuum rbu test.db state.db
for {set i 0} {$i<10} {incr i} {
rbu step
}
rbu close
sqlite3rbu_vacuum rbu test.db state.db
for {set i 0} {$i<$n} {incr i} {
set rc [rbu step]
if {$rc == "SQLITE_DONE"} break
}
if {$rc == "SQLITE_DONE"} {
rbu close
break
}
foreach f {test.db test.db-oal test.db-wal test.db-shm test.db-vacuum} {
set f2 [string map [list test.db test.db2] $f]
if {[file exists $f]} {
forcecopy $f $f2
} else {
forcedelete $f2
}
}
forcecopy state.db state.db2
rbu close
do_test 1.4.$n.1 {
sqlite3rbu_vacuum rbu test.db2 state.db2
while {[rbu step]=="SQLITE_OK"} {}
rbu close
} {SQLITE_DONE}
do_test 1.4.$n.2 {
sqlite3 db2 test.db2
db2 eval {
SELECT count(*) FROM t1;
PRAGMA integrity_check;
}
} {50 ok}
db2 close
}
forcedelete rbu.db
do_test 2.0 {
sqlite3 db2 rbu.db
db2 eval {
CREATE TABLE data_t1(a, b, c, rbu_control);
WITH s(i) AS (
VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<10
)
INSERT INTO data_t1
SELECT randomblob(50), randomblob(75), randomblob(100), 0 FROM s;
}
db2 close
} {}
# Each iteration of this loop:
#
# 1. Restores the db to the state it was in following test case 1.0
# 2. Opens an RBU handle to apply the RBU update created in test case 2.0.
# 3. Steps the RBU handle $n times.
# 4. Takes a copy of all database files and the state db.
# 5. Opens a second RBU handle on the copy, resumes and completes the
# RBU op. Checks it worked as expected.
#
# The loop runs until $n is large enough that step (3) applies the entire
# update.
#
for {set n 1} {$n < 5000} {incr n} {
db_restore
forcedelete state.db state.db-shm state.db-oal state.db-wal
sqlite3rbu rbu test.db rbu.db state.db
for {set i 0} {$i<$n} {incr i} {
set rc [rbu step]
if {$rc == "SQLITE_DONE"} break
}
if {$rc == "SQLITE_DONE"} {
rbu close
break
}
foreach f {test.db test.db-oal test.db-wal test.db-shm test.db-vacuum} {
set f2 [string map [list test.db test.db2] $f]
if {[file exists $f]} {
forcecopy $f $f2
} else {
forcedelete $f2
}
}
forcecopy state.db state.db2
rbu close
do_test 2.$n.1 {
sqlite3rbu rbu test.db2 rbu.db state.db2
while {[rbu step]=="SQLITE_OK"} {}
rbu close
} {SQLITE_DONE}
do_test 2.$n.2 {
sqlite3 db2 test.db2
db2 eval {
SELECT count(*) FROM t1;
PRAGMA integrity_check;
}
} {60 ok}
db2 close
}
finish_test
+31
View File
@@ -199,6 +199,37 @@ if {$::tcl_platform(platform)=="unix"} {
}
}
#-------------------------------------------------------------------------
# Test the outcome of some other connection running a checkpoint while
# the incremental checkpoint is suspended.
#
reset_db
do_execsql_test 6.0 {
CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
CREATE INDEX i1b ON t1(b);
CREATE INDEX i1c ON t1(c);
INSERT INTO t1 VALUES(1, 2, 3);
INSERT INTO t1 VALUES(4, 5, 6);
}
forcedelete test.db2
do_test 6.1 {
sqlite3rbu_vacuum rbu test.db test.db2
while {[rbu state]!="checkpoint"} { rbu step }
rbu close
} {SQLITE_OK}
do_execsql_test 6.2 {
SELECT 1 FROM sqlite_master LIMIT 1;
PRAGMA wal_checkpoint;
} {1 0 4 4}
do_test 6.3 {
sqlite3rbu_vacuum rbu test.db test.db2
while {[rbu step]!="SQLITE_DONE"} { rbu step }
rbu close
execsql { PRAGMA integrity_check }
} {ok}
finish_test
+31 -8
View File
@@ -2333,7 +2333,7 @@ static RbuState *rbuLoadState(sqlite3rbu *p){
** Open the database handle and attach the RBU database as "rbu". If an
** error occurs, leave an error code and message in the RBU handle.
*/
static void rbuOpenDatabase(sqlite3rbu *p){
static void rbuOpenDatabase(sqlite3rbu *p, int *pbRetry){
assert( p->rc || (p->dbMain==0 && p->dbRbu==0) );
assert( p->rc || rbuIsVacuum(p) || p->zTarget!=0 );
@@ -2408,7 +2408,7 @@ static void rbuOpenDatabase(sqlite3rbu *p){
}else{
RbuState *pState = rbuLoadState(p);
if( pState ){
bOpen = (pState->eStage>RBU_STAGE_MOVE);
bOpen = (pState->eStage>=RBU_STAGE_MOVE);
rbuFreeState(pState);
}
}
@@ -2420,6 +2420,15 @@ static void rbuOpenDatabase(sqlite3rbu *p){
if( !rbuIsVacuum(p) ){
p->dbMain = rbuOpenDbhandle(p, p->zTarget, 1);
}else if( p->pRbuFd->pWalFd ){
if( pbRetry ){
p->pRbuFd->bNolock = 0;
sqlite3_close(p->dbRbu);
sqlite3_close(p->dbMain);
p->dbMain = 0;
p->dbRbu = 0;
*pbRetry = 1;
return;
}
p->rc = SQLITE_ERROR;
p->zErrmsg = sqlite3_mprintf("cannot vacuum wal mode database");
}else{
@@ -2600,16 +2609,18 @@ static void rbuSetupCheckpoint(sqlite3rbu *p, RbuState *pState){
if( rc2!=SQLITE_INTERNAL ) p->rc = rc2;
}
if( p->rc==SQLITE_OK ){
if( p->rc==SQLITE_OK && p->nFrame>0 ){
p->eStage = RBU_STAGE_CKPT;
p->nStep = (pState ? pState->nRow : 0);
p->aBuf = rbuMalloc(p, p->pgsz);
p->iWalCksum = rbuShmChecksum(p);
}
if( p->rc==SQLITE_OK && pState && pState->iWalCksum!=p->iWalCksum ){
p->rc = SQLITE_DONE;
p->eStage = RBU_STAGE_DONE;
if( p->rc==SQLITE_OK ){
if( p->nFrame==0 || (pState && pState->iWalCksum!=p->iWalCksum) ){
p->rc = SQLITE_DONE;
p->eStage = RBU_STAGE_DONE;
}
}
}
@@ -2782,7 +2793,7 @@ static void rbuMoveOalFile(sqlite3rbu *p){
#endif
if( p->rc==SQLITE_OK ){
rbuOpenDatabase(p);
rbuOpenDatabase(p, 0);
rbuSetupCheckpoint(p, 0);
}
}
@@ -3493,6 +3504,7 @@ static sqlite3rbu *openRbuHandle(
/* Open the target, RBU and state databases */
if( p->rc==SQLITE_OK ){
char *pCsr = (char*)&p[1];
int bRetry = 0;
if( zTarget ){
p->zTarget = pCsr;
memcpy(p->zTarget, zTarget, nTarget+1);
@@ -3504,7 +3516,18 @@ static sqlite3rbu *openRbuHandle(
if( zState ){
p->zState = rbuMPrintf(p, "%s", zState);
}
rbuOpenDatabase(p);
/* If the first attempt to open the database file fails and the bRetry
** flag it set, this means that the db was not opened because it seemed
** to be a wal-mode db. But, this may have happened due to an earlier
** RBU vacuum operation leaving an old wal file in the directory.
** If this is the case, it will have been checkpointed and deleted
** when the handle was closed and a second attempt to open the
** database may succeed. */
rbuOpenDatabase(p, &bRetry);
if( bRetry ){
rbuOpenDatabase(p, 0);
}
}
if( p->rc==SQLITE_OK ){
+19
View File
@@ -582,4 +582,23 @@ do_iterator_test 11.2 * {
} {
}
reset_db
do_execsql_test 12.1 {
CREATE TABLE t1(r INTEGER PRIMARY KEY, a, b);
CREATE INDEX i1 ON t1(a);
INSERT INTO t1 VALUES(1, 1, 1);
INSERT INTO t1 VALUES(2, 1, 2);
INSERT INTO t1 VALUES(3, 1, 3);
}
do_iterator_test 12.2 * {
UPDATE t1 SET b='one' WHERE a=1;
} {
{UPDATE t1 0 X.. {i 1 {} {} i 1} {{} {} {} {} t one}}
{UPDATE t1 0 X.. {i 2 {} {} i 2} {{} {} {} {} t one}}
{UPDATE t1 0 X.. {i 3 {} {} i 3} {{} {} {} {} t one}}
}
finish_test
+1 -1
View File
@@ -22,7 +22,7 @@
** directory as this file for additional information.
*/
#ifdef SQLITE_USER_AUTHENTICATION
#ifndef _SQLITEINT_H_
#ifndef SQLITEINT_H
# include "sqliteInt.h"
#endif
+7 -2
View File
@@ -478,6 +478,8 @@ SHELL_OPT += -DSQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
FUZZERSHELL_OPT = -DSQLITE_ENABLE_JSON1
FUZZCHECK_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5
DBFUZZ_OPT =
KV_OPT = -DSQLITE_THREADSAFE=0 -DSQLITE_DIRECT_OVERFLOW_READ
ST_OPT = -DSQLITE_THREADSAFE=0
# This is the default Makefile target. The objects listed here
# are what get build when you type just "make" with no arguments.
@@ -892,8 +894,11 @@ wordcount$(EXE): $(TOP)/test/wordcount.c sqlite3.c
$(TCC) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -o wordcount$(EXE) \
$(TOP)/test/wordcount.c sqlite3.c
speedtest1$(EXE): $(TOP)/test/speedtest1.c sqlite3.o
$(TCC) -I. $(OTAFLAGS) -o speedtest1$(EXE) $(TOP)/test/speedtest1.c sqlite3.o $(THREADLIB)
speedtest1$(EXE): $(TOP)/test/speedtest1.c sqlite3.c
$(TCCX) -I. $(ST_OPT) -o speedtest1$(EXE) $(TOP)/test/speedtest1.c sqlite3.c $(THREADLIB)
kvtest$(EXE): $(TOP)/test/kvtest.c sqlite3.c
$(TCCX) -I. $(KV+OPT) -o kvtest$(EXE) $(TOP)/test/kvtest.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 \
+74 -69
View File
@@ -1,6 +1,6 @@
C Changes\sto\sthe\sprintf\simplementation\sfor\sbetter\sperformance.
D 2017-01-04T00:26:28.506
F Makefile.in 41bd4cad981487345c4a84081074bcdb876e4b2e
C Simplifications\sto\sblobSeekToRow().
D 2017-01-31T19:02:15.083
F Makefile.in 5f415e7867296d678fed2e6779aea10c1318b4bc
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
F Makefile.msc b8ca53350ae545e3562403d5da2a69cec79308da
F README.md 8ecc12493ff9f820cdea6520a9016001cb2e59b7
@@ -102,9 +102,9 @@ F ext/fts5/fts5Int.h b2eda36e0f224365c8e23dc8f559311834f1c13f
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 dc2cee9f56b1818b85df59304b8104a5dfb8ab60
F ext/fts5/fts5_expr.c 33f0e8063ac7360bcd71c0ff0dcbacdc05fffe50
F ext/fts5/fts5_hash.c 880998e596b60f078348d48732ca4ad9a90caad2
F ext/fts5/fts5_index.c fdbe46da11e81c1817cd4cb2de25ffdb4dd83711
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_tcl.c 4a901f00c8553740dba63511603f5527d741c26a
@@ -184,11 +184,11 @@ F ext/fts5/test/fts5rowid.test 16908a99d6efc9ba21081b4f2b86b3fc699839a6
F ext/fts5/test/fts5simple.test 5da9b15ed534eb0be9f279d8a2bb2e24d30e4e38
F ext/fts5/test/fts5simple2.test 00839031878f52391562594fdab0503e424ee071
F ext/fts5/test/fts5simple3.test 25faa8cb8ad470c6f01f670bcc1317c19a89f091
F ext/fts5/test/fts5synonym.test 6475d189c2e20d60795808f83e36bf9318708d48
F ext/fts5/test/fts5synonym.test f964f9a98580dec06c995d4638ecb36eee60ae4a
F ext/fts5/test/fts5synonym2.test aa4c43bd3b691ff80f658cb064f5ab40690e834e
F ext/fts5/test/fts5tok1.test beb894c6f3468f10a574302f69ebe4436b0287c7
F ext/fts5/test/fts5tok2.test dcacb32d4a2a3f0dd3215d4a3987f78ae4be21a2
F ext/fts5/test/fts5tokenizer.test ea4df698b35cc427ebf2ba22829d0e28386d8c89
F ext/fts5/test/fts5tokenizer.test f64ab5fe48fa1317ff6315264bfe26e73cbdefde
F ext/fts5/test/fts5unicode.test fbef8d8a3b4b88470536cc57604a82ca52e51841
F ext/fts5/test/fts5unicode2.test 529ac7e8648c943bc87bfed1e427128a2f3f9e33
F ext/fts5/test/fts5unicode3.test 35c3d02aa7acf7d43d8de3bfe32c15ba96e8928e
@@ -202,7 +202,7 @@ F ext/fts5/tool/loadfts5.tcl 95b03429ee6b138645703c6ca192c3ac96eaf093
F ext/fts5/tool/mkfts5c.tcl d1c2a9ab8e0ec690a52316f33dd9b1d379942f45
F ext/fts5/tool/showfts5.tcl d54da0e067306663e2d5d523965ca487698e722c
F ext/icu/README.txt d9fbbad0c2f647c3fdf715fc9fd64af53aedfc43
F ext/icu/icu.c 03ff6f90f3004a7e5a86205b581b2b7035ebf6e1
F ext/icu/icu.c 84900472a088a3a172c6c079f58a1d3a1952c332
F ext/icu/sqliteicu.h 728867a802baa5a96de7495e9689a8e01715ef37
F ext/misc/amatch.c 211108e201105e4bb0c076527b8cfd34330fc234
F ext/misc/carray.c 40c27641010a4dc67e3690bdb7c9d36ca58b3c2d
@@ -213,7 +213,7 @@ 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 e0797ef1bfa637429ceab9140ecba620809ee02a
F ext/misc/json1.c 552a7d730863419e05dc947265b28bd411680e2e
F ext/misc/memvfs.c e5225bc22e79dde6b28380f3a068ddf600683a33
F ext/misc/nextchar.c 35c8b8baacb96d92abbb34a83a997b797075b342
F ext/misc/percentile.c 92699c8cd7d517ff610e6037e56506f8904dae2e
@@ -222,12 +222,13 @@ F ext/misc/remember.c 8440f8d0b452c5cdefb62b57135ccd1267aa729d
F ext/misc/rot13.c 1ac6f95f99b575907b9b09c81a349114cf9be45a
F ext/misc/scrub.c 1c5bfb8b0cd18b602fcb55755e84abf0023ac2fb
F ext/misc/series.c e11e534ada797d5b816d7e7a93c022306563ca35
F ext/misc/sha1.c b2e4eb8e26f09701ec15548395baf698f00e5895
F ext/misc/showauth.c 732578f0fe4ce42d577e1c86dc89dd14a006ab52
F ext/misc/spellfix.c a4723b6aff748a417b5091b68a46443265c40f0d
F ext/misc/totype.c 4a167594e791abeed95e0a8db028822b5e8fe512
F ext/misc/vfslog.c fe40fab5c077a40477f7e5eba994309ecac6cc95
F ext/misc/vfsstat.c bf10ef0bc51e1ad6756629e1edb142f7a8db1178
F ext/misc/vtshim.c babb0dc2bf116029e3e7c9a618b8a1377045303e
F ext/misc/vtshim.c 1976e6dd68dd0d64508c91a6dfab8e75f8aaf6cd
F ext/misc/wholenumber.c 784b12543d60702ebdd47da936e278aa03076212
F ext/rbu/rbu.c b2c0b5e6ae1a89affc0edfc127ebfa5f637a0ce4
F ext/rbu/rbu1.test 43836fac8c7179a358eaf38a8a1ef3d6e6285842
@@ -252,12 +253,14 @@ F ext/rbu/rbudor.test 99b05cc0df613e962c2c8085cfb05686a09cf315
F ext/rbu/rbufault.test cc0be8d5d392d98b0c2d6a51be377ea989250a89
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/rburesume.test 8acb77f4a422ff55acfcfc9cc15a5cb210b1de83
F ext/rbu/rbusave.test 0f43b6686084f426ddd040b878426452fd2c2f48
F ext/rbu/rbuvacuum.test 4a977447c15c2581ab668781d9ef4294382530e0
F ext/rbu/rbuvacuum2.test 2569205b74ff40fbf3bda2fce33a58eb40eebdcc
F ext/rbu/sqlite3rbu.c e074c38798b90591f7f0cf0032d62f152ce5a95e
F ext/rbu/rbuvacuum2.test 2074ab14fe66e1c7e7210c62562650dcd215bbaa
F ext/rbu/sqlite3rbu.c bb0de6cdbdb14a7d55a097238a434b7e99caf318
F ext/rbu/sqlite3rbu.h 6fb6294c34a9ca93b5894a33bca530c6f08decba
F ext/rbu/test_rbu.c 5aa22616afac6f71ebd3d9bc9bf1006cfabcca88
F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761
@@ -285,7 +288,7 @@ F ext/rtree/sqlite3rtree.h 9c5777af3d2921c7b4ae4954e8e5697502289d28
F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de
F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024
F ext/session/changeset.c 4ccbaa4531944c24584bf6a61ba3a39c62b6267a
F ext/session/session1.test e5125b216d1e8c91e0984b361b0b68529e7c5dfb
F ext/session/session1.test 482e9b861169d0b7e283e1563a28c0fa32779fa5
F ext/session/session2.test 284de45abae4cc1082bc52012ee81521d5ac58e0
F ext/session/session3.test a7a9ce59b8d1e49e2cc23d81421ac485be0eea01
F ext/session/session4.test 457b02bdc349eb01151e54de014df77abd3c08c8
@@ -308,11 +311,11 @@ F ext/session/sqlite3session.h 9345166bd8f80562145586cf817f707de5ecada2
F ext/session/test_session.c eb0bd6c1ea791c1d66ee4ef94c16500dad936386
F ext/userauth/sqlite3userauth.h 19cb6f0e31316d0ee4afdfb7a85ef9da3333a220
F ext/userauth/user-auth.txt e6641021a9210364665fe625d067617d03f27b04
F ext/userauth/userauth.c 5fa3bdb492f481bbc1709fc83c91ebd13460c69e
F ext/userauth/userauth.c 3410be31283abba70255d71fd24734e017a4497f
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60
F main.mk 2cf5f0362c5687fd8e912c3a327b49a2e8ba0f9b
F main.mk afc52937b4e5fe08678e8d5a4fe4487d44e3bc61
F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
@@ -325,14 +328,14 @@ F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
F src/alter.c 3b23977620ce9662ac54443f65b87ba996e36121
F src/analyze.c 3c4a63ff7a55faefecf6eb1589932fdbc06b2415
F src/analyze.c 317dbaf31c16050582b09bf4f323b4e0f1813251
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 d2c100618784bd89c089fcef03ff6e789768ecae
F src/btree.h 2349a588abcd7e0c04f984e15c5c777b61637583
F src/btree.c 6a63fa34e6fe86e87090e41963c0f2fcf9d3e16d
F src/btree.h e6d352808956ec163a17f832193a3e198b3fb0ac
F src/btreeInt.h 10c4b77c2fb399580babbcc7cf652ac10dba796e
F src/build.c 9e799f1edd910dfa8a0bc29bd390d35d310596af
F src/callback.c 2e76147783386374bf01b227f752c81ec872d730
@@ -340,8 +343,8 @@ F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
F src/ctime.c 9f2296a4e5d26ebf0e0d95a0af4628f1ea694e7a
F src/date.c dc3f1391d9297f8c748132813aaffcb117090d6e
F src/dbstat.c 19ee7a4e89979d4df8e44cfac7a8f905ec89b77d
F src/delete.c c8bc10d145c9666a34ae906250326fdaa8d58fa5
F src/expr.c 449cbb8b9857ff8eb685b72555086818a178858c
F src/delete.c 0d9d5549d42e79ce4d82ff1db1e6c81e36d2f67c
F src/expr.c d7ef6fdb70bc18259d7d36b22aa0bc4845c5c5b9
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
F src/fkey.c 2e9aabe1aee76273aff8a84ee92c464e095400ae
F src/func.c c67273e1ec08abbdcc14c189892a3ff6eeece86b
@@ -350,11 +353,11 @@ 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 91ba5d0143e66479081536ebbaff1850ec9f57d9
F src/insert.c 8183e1778ec42d26732bec8c98aeffa8af13038f
F src/legacy.c 75d3023be8f0d2b99d60f905090341a03358c58e
F src/loadext.c 5d6642d141c07d366e43d359e94ec9de47add41d
F src/loadext.c a68d8d1d14cf7488bb29dc5311cb1ce9a4404258
F src/main.c e207b81542d13b9f13d61e78ca441f9781f055b0
F src/malloc.c f3fad34cd570022abca558c573f1761fb09a8212
F src/malloc.c fc1b9f445290f2145da48fc08730c26e6082b640
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c 6919bcf12f221868ea066eec27e579fed95ce98b
F src/mem2.c f1940d9e91948dd6a908fbb9ce3835c36b5d83c3
@@ -375,29 +378,29 @@ F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586
F src/os_unix.c 30e2c43e4955db990e5b5a81e901f8aa74cc8820
F src/os_win.c cf90abd4e50d9f56d2c20ce8e005aff55d7bd8e9
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
F src/pager.c 9dc72d23eebbdf992bd69f2ab954d0d3a27c7340
F src/pager.h d1e944291030351f362a0a7da9b5c3e34e603e39
F src/parse.y 29153738a7322054359320eb00b5a4cd44389f20
F src/pager.c ff1232b3088a39806035ecfac4fffeb22717d80b
F src/pager.h f2a99646c5533ffe11afa43e9e0bea74054e4efa
F src/parse.y 591704fce84f814d9a3642774c1f011d38f4149c
F src/pcache.c 51070ec9b8251bbf9c6ea3d35fd96a458752929e
F src/pcache.h 2cedcd8407eb23017d92790b112186886e179490
F src/pcache1.c e3967219b2a92b9edcb9324a4ba75009090d3953
F src/pragma.c 5a23557e490e7ac5afef097efc4b59dce5b482c2
F src/pragma.h f9b221b2c8949ea941dbee49934299e4ed5af41c
F src/pragma.c 0e7a7c6f1c6fd8ff50c0fff65b8bb80174bc49c5
F src/pragma.h 61aa5389118594bebb28120a6720401aee34ce1a
F src/prepare.c b1140c3d0cf59bc85ace00ce363153041b424b7a
F src/printf.c ff10a9b9902cd2afe5f655f3013c6307d969b1fd
F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
F src/resolve.c bb070cf5f23611c44ab7e4788803684e385fc3fb
F src/resolve.c f9bc0de45a30a450da47b3766de00be89bf9be79
F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac
F src/select.c dfb6cadc3dcfba1b1bdbfba62ebba2b4b673413e
F src/shell.c 6095531aa900decdaa765e0f3993fba7153c92c1
F src/sqlite.h.in e8e2d108d82647f0a812fdb74accf91c1ec08ddc
F src/select.c 3856db523b942062bca8722ba03b61c324ff94d6
F src/shell.c a84e453c213f3e0d6935a582024da4e242f85a19
F src/sqlite.h.in 8fd2b1a4e4aac023d4533313442528b81105fab3
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h 8648034aa702469afb553231677306cc6492a1ae
F src/sqliteInt.h f3450b70cfd99b434304225cf3b95de9cb4a9536
F src/sqliteInt.h 6f29b23415ce207c2fda61054bf244b74f96359c
F src/sqliteLimit.h c0373387c287c8d0932510b5547ecde31b5da247
F src/status.c a9e66593dfb28a9e746cba7153f84d49c1ddc4b1
F src/table.c 5226df15ab9179b9ed558d89575ea0ce37b03fc9
F src/tclsqlite.c 205c66b9b81d97978a155caa3ef5be9c4de2b174
F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34
F src/tclsqlite.c 418f5e5e0840425a7e5b33f3600dccd378a57549
F src/test1.c 8a98191a1da8e100f77cdb5cc716df67d405028d
F src/test2.c 3efb99ab7f1fc8d154933e02ae1378bac9637da5
F src/test3.c d03f5b5da9a2410b7a91c64b0d3306ed28ab6fee
@@ -414,7 +417,7 @@ F src/test_bestindex.c d23f80d334c59662af69191854c76b8d3d0c8c96
F src/test_blob.c 6a4c7920d1d9c6cc0f7aa50c89c4f80016aeda83
F src/test_btree.c 8b2dc8b8848cf3a4db93f11578f075e82252a274
F src/test_config.c 83179ea845479b5be9a651d014649e3f2722a1fe
F src/test_delete.c 8499d4d323f2ec8e28301deb3d6ddd8eef8b8139
F src/test_delete.c af7eab5702f853fb1c62a5f7665e2234cf1ae17b
F src/test_demovfs.c a0c3bdd45ed044115c2c9f7779e56eafff18741e
F src/test_devsym.c 4e58dec2602d8e139ca08659f62a62450587cb58
F src/test_fs.c e16cbe68d3b107e00a907c20a9a02629870eb69b
@@ -437,31 +440,31 @@ F src/test_quota.h 2a8ad1952d1d2ca9af0ce0465e56e6c023b5e15d
F src/test_rtree.c 671f3fae50ff116ef2e32a3bf1fe21b5615b4b7b
F src/test_schema.c f575932cb6274d12147a77e13ea4b49d52408513
F src/test_server.c a2615049954cbb9cfb4a62e18e2f0616e4dc38fe
F src/test_sqllog.c 0d138a8180a312bf996b37fa66da5c5799d4d57b
F src/test_sqllog.c 11e6ce7575f489155c604ac4b439f2ac1d3d5aef
F src/test_superlock.c 4839644b9201da822f181c5bc406c0b2385f672e
F src/test_syscall.c 1073306ba2e9bfc886771871a13d3de281ed3939
F src/test_tclvar.c df9fe1213c2634687a9ca0b0bec0d2119d359ae3
F src/test_thread.c 911d15fb14e19c0c542bdc8aabf981c2f10a4858
F src/test_vfs.c f0186261a24de2671d080bcd8050732f0cb64f6e
F src/test_vfstrace.c bab9594adc976cbe696ff3970728830b4c5ed698
F src/test_windirent.c 600398db0198ca1c77ca183831bf456746b6f5c4
F src/test_windirent.h 7edc57e2faa727026dbd5d010dd0e2e665d5aa01
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 5c2f516876fc27fbd7753913f032f49eb89e83b5
F src/tokenize.c 25ccc63ae2c4163933221f3181c9982b47cd08d2
F src/treeview.c 4e44ade3bfe59d82005039f72e09333ce2b4162c
F src/trigger.c c9f0810043b265724fdb1bdd466894f984dfc182
F src/update.c 1da7c462110bffed442a42884cb0d528c1db46d8
F src/update.c 456d4a4656f8a03c2abc88a51b19172197400e58
F src/utf.c 699001c79f28e48e9bcdf8a463da029ea660540c
F src/util.c a88b0466fddf445ce752226d4698ca3faada620a
F src/vacuum.c 33c174b28886b2faf26e503b5a49a1c01a9b1c16
F src/vdbe.c 88bd6c32b333580d2661ac3afe33369757fb1522
F src/vdbe.h 50ee139f9c68fff91be1d717ed3a6abbd496919c
F src/vdbe.c d3765f4d8f667b8d10232b2a1d0498497f3ac09f
F src/vdbe.h 59998ffd71d7caa8886bc78dafaf8caeccd4c13c
F src/vdbeInt.h 281cb70332dc8b593b8c7afe776f3a2ba7d4255e
F src/vdbeapi.c d6ebaa465f070eb1af8ba4e7b34583ece87bdd24
F src/vdbeaux.c 12919c5aa354296d6b9ba808bca3e9dda836858c
F src/vdbeblob.c f4f98ea672b242f807c08c92c7faaa79e5091b65
F src/vdbemem.c d3fd85b7b7ef3eb75de29c6d7e1d10d3ca78b4fd
F src/vdbeapi.c 7a65f10684982daecfce50f557f2632b7f20b198
F src/vdbeaux.c 6847b02aa2db536ed15d90f1fdc2923afef93c5b
F src/vdbeblob.c 359891617358deefc85bef7bcf787fa6b77facb9
F src/vdbemem.c 3b5a9a5b375458d3e12a50ae1aaa41eeec2175fd
F src/vdbesort.c eda25cb2d1727efca6f7862fea32b8aa33c0face
F src/vdbetrace.c 41963d5376f0349842b5fc4aaaaacd7d9cdc0834
F src/vtab.c c4bbe0f870f52036553f8098aee0703997f0577a
@@ -469,12 +472,13 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
F src/wal.c 40c543f0a2195d1b0dc88ef12142bea690009344
F src/wal.h 06b2a0b599cc0f53ea97f497cf8c6b758c999f71
F src/walker.c 91a6df7435827e41cff6bb7df50ea00934ee78b0
F src/where.c 6bbf9284f4f15a6fa48663d033870cc0d7f5ee66
F src/where.c bc71775e23d23334e8f449aa31012d692dc09cb2
F src/whereInt.h 2bcc3d176e6091cb8f50a30b65c006e88a73614d
F src/wherecode.c e04ac8f24c3ac8621df6c3be3ac8c7d4fa893745
F src/whereexpr.c 87ecdf24beba4498e4380b31c4131febb0a6ceaa
F src/wherecode.c 99a8ced164c75edf41b3a865a75381c9adb38b28
F src/whereexpr.c 35ad025389a632a3987a35617c878be3b3d70dc6
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd
F test/affinity3.test 6a101af2fc945ce2912f6fe54dd646018551710d
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
F test/aggnested.test b35b4cd69fc913f90d39a575e171e1116c3a4bb7
F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87
@@ -626,7 +630,7 @@ F test/cse.test 277350a26264495e86b1785f34d2d0c8600e021c
F test/csv01.test e0ba3caaa57e4c667a0b45977689fb8082f14348
F test/ctime.test ff6c38e822459d6ca743c34901caf57740b08b54
F test/cursorhint.test 7bc346788390475e77a345da2b92270d04d35856
F test/cursorhint2.test fa41f0d997e67db921d08c31e73111b32811201a
F test/cursorhint2.test 8457e93d97f665f23f97cdbc8477d16e3480331b
F test/date.test a6a5a48b90907bca9fbcc79a30be5a715c1ab2fc
F test/dbfuzz.c 8cc2bdb818b4483a052f9f80f96be74cbd9a6e1d
F test/dbstatus.test 73149851b3aff14fc6db478e58f9083a66422cf5
@@ -676,7 +680,7 @@ F test/eqp.test 3fe051af50921284189d1970eb653f9fcf5117d2
F test/errmsg.test f31592a594b44ee121371d25ddd5d63497bb3401
F test/eval.test a64c9105d6ff163df7cf09d6ac29cdad5922078c
F test/exclusive.test 9a57bd66e39144b888ca75c309914fcdefb4e3f9
F test/exclusive2.test 32798111aae78a5deec980eee383213f189df308
F test/exclusive2.test 984090e8e9d1b331d2e8111daf6e5d61dda0bef7
F test/exec.test e949714dc127eaa5ecc7d723efec1ec27118fdd7
F test/exists.test 79a75323c78f02bbe9c251ea502a092f9ef63dac
F test/expr.test 66a2c9ac34f74f036faa4092f5402c7d3162fc93
@@ -692,7 +696,7 @@ F test/fkey4.test 86446017011273aad8f9a99c1a65019e7bd9ca9d
F test/fkey5.test 5a373303f201ac03c22ba1ef17a733d3f56e611a
F test/fkey6.test d078a1e323a740062bed38df32b8a736fd320dc0
F test/fkey7.test 72e915890ee4a005daaf3002cb208e8fe973ac13
F test/fkey8.test 7bd1dd0174a0e29a90c62c517b9e2a410a0b345d
F test/fkey8.test e5372e32cdb4481f121ec3550703eeb7b4e0762c
F test/fkey_malloc.test 594a7ea1fbab553c036c70813cd8bd9407d63749
F test/fordelete.test eb93a2f34137bb87bdab88fcab06c0bd92719aff
F test/format4.test 1f0cac8ff3895e9359ed87e41aaabee982a812eb
@@ -829,7 +833,7 @@ F test/gcfault.test dd28c228a38976d6336a3fc42d7e5f1ad060cb8c
F test/genesis.tcl 1e2e2e8e5cc4058549a154ff1892fe5c9de19f98
F test/hexlit.test 4a6a5f46e3c65c4bf1fa06f5dd5a9507a5627751
F test/hidden.test 23c1393a79e846d68fd902d72c85d5e5dcf98711
F test/hook.test 3a01b876691f9151d3e44562354f7d663ff90fce
F test/hook.test dbc0b87756e1e20e7497b56889c9e9cd2f8cc2b5
F test/icu.test 73956798bace8982909c00476b216714a6d0559a
F test/ieee754.test 806fc0ce7f305f57e3331eaceeddcfec9339e607
F test/imposter1.test c3f1db2d3db2c24611a6596a3fc0ffc14f1466c8
@@ -880,7 +884,7 @@ F test/ioerr4.test f130fe9e71008577b342b8874d52984bd04ede2c
F test/ioerr5.test 2edfa4fb0f896f733071303b42224df8bedd9da4
F test/ioerr6.test a395a6ab144b26a9e3e21059a1ab6a7149cca65b
F test/join.test f9d4a28dec81c6e9dc21b73518e024d73b5ebf57
F test/join2.test f2171c265e57ee298a27e57e7051d22962f9f324
F test/join2.test a48f723c5692e2cbb23a9297ac2720cb77d51a70
F test/join3.test 6f0c774ff1ba0489e6c88a3e77b9d3528fb4fda0
F test/join4.test 1a352e4e267114444c29266ce79e941af5885916
F test/join5.test bc98ea4b4e5003f5b1453701ebb8cd7d1c01a550
@@ -895,7 +899,7 @@ F test/json101.test c0897616f32d95431f37fd291cb78742181980ac
F test/json102.test bf3fe7a706d30936a76a0f7a0375e1e8e73aff5a
F test/json103.test c5f6b85e69de05f6b3195f9f9d5ce9cd179099a0
F test/keyword1.test 37ef6bba5d2ed5b07ecdd6810571de2956599dff
F test/kvtest.c 2c66ddefcd03c2caa337f6dd79e6c82368af83df
F test/kvtest.c 7a3c38ee56b9cc45dc5a5edc50fd9bc9425659a9
F test/lastinsert.test 42e948fd6442f07d60acbd15d33fb86473e0ef63
F test/laststmtchanges.test ae613f53819206b3222771828d024154d51db200
F test/like.test 0603f4fa0dad50987f70032c05800cbfa8985302
@@ -1010,6 +1014,7 @@ F test/permutations.test cd0b7bc04bf5e50d3a993d24c834d591f7d4f5fe
F test/pragma.test 1e94755164a3a3264cd39836de4bebcb7809e5f8
F test/pragma2.test e5d5c176360c321344249354c0c16aec46214c9f
F test/pragma3.test 14c12bc5352b1e100e0b6b44f371053a81ccf8ed
F test/pragma4.test 6e85b6eab8e61ffc9c7db59d842276674e8e3264
F test/printf.test b3ff34e73d59124140eaf89f7672e21bc2ca5fcc
F test/printf2.test 0b61566dd1c0f0b802f59dffa228c5dc5aa6b054
F test/progress.test ebab27f670bd0d4eb9d20d49cef96e68141d92fb
@@ -1073,7 +1078,7 @@ F test/select8.test 8c8f5ae43894c891efc5755ed905467d1d67ad5d
F test/select9.test aebc2bb0c3bc44606125033cbcaac2c8d1f33a95
F test/selectA.test 101e722370ac6e84978c2958b8931c78b10a1709
F test/selectB.test 954e4e49cf1f896d61794e440669e03a27ceea25
F test/selectC.test 871fb55d884d3de5943c4057ebd22c2459e71977
F test/selectC.test e25243f8ca503e06f252eb0218976d07cfeceac3
F test/selectD.test b0f02a04ef7737decb24e08be2c39b9664b43394
F test/selectE.test a8730ca330fcf40ace158f134f4fe0eb00c7edbf
F test/selectF.test 21c94e6438f76537b72532fa9fd4710cdd455fc3
@@ -1127,7 +1132,7 @@ F test/speed3.test 694affeb9100526007436334cf7d08f3d74b85ef
F test/speed4.test abc0ad3399dcf9703abed2fff8705e4f8e416715
F test/speed4p.explain 6b5f104ebeb34a038b2f714150f51d01143e59aa
F test/speed4p.test 0e51908951677de5a969b723e03a27a1c45db38b
F test/speedtest1.c 4e8ea6165046f02e1cfe0f4700256e91c981ec10
F test/speedtest1.c 02fe15bb784c5276a083ffe9969cc51e0bce7644
F test/spellfix.test f9c1f431e2c096c8775fec032952320c0e4700db
F test/spellfix2.test dfc8f519a3fc204cb2dfa8b4f29821ae90f6f8c3
F test/spellfix3.test 0f9efaaa502a0e0a09848028518a6fb096c8ad33
@@ -1159,7 +1164,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 4ce5afd5e192db4cae178e1a983b060e0f08c5d6
F test/tester.tcl 2a49c1aff731f380ea640106377e19611a1443ae
F test/thread001.test 9f22fd3525a307ff42a326b6bc7b0465be1745a5
F test/thread002.test e630504f8a06c00bf8bbe68528774dd96aeb2e58
F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7
@@ -1336,6 +1341,7 @@ F test/triggerB.test 56780c031b454abac2340dbb3b71ac5c56c3d7fe
F test/triggerC.test 302d8995f5ffe63bbc15053abb3ef7a39cf5a092
F test/triggerD.test 8e7f3921a92a5797d472732108109e44575fa650
F test/triggerE.test 15fa63f1097db1f83dd62d121616006978063d1f
F test/triggerF.test 55b1eb13433997faac3a4948c1d8252f6c8c636b
F test/tt3_checkpoint.c 9e75cf7c1c364f52e1c47fd0f14c4340a9db0fe1
F test/tt3_index.c 39eec10a35f57672225be4d182862152896dee4a
F test/tt3_lookaside1.c 0377e202c3c2a50d688cb65ba203afeda6fafeb9
@@ -1349,6 +1355,7 @@ F test/unique2.test 3674e9f2a3f1fbbfd4772ac74b7a97090d0f77d2
F test/unixexcl.test d936ba2b06794018e136418addd59a2354eeae97
F test/unordered.test ca7adce0419e4ca0c50f039885e76ed2c531eda8
F test/update.test 6c68446b8a0a33d522a7c72b320934596a2d7d32
F test/update2.test 81772e5c9b93d1006d66d65e9a1327281bdec4e8
F test/uri.test 3481026f00ade6dfe8adb7acb6e1e47b04369568
F test/uri2.test 9d3ba7a53ee167572d53a298ee4a5d38ec4a8fb7
F test/userauth01.test e740a2697a7b40d7c5003a7d7edaee16acd349a9
@@ -1377,7 +1384,7 @@ F test/vtabC.test 4528f459a13136f982e75614d120aef165f17292
F test/vtabD.test 05b3f1d77117271671089e48719524b676842e96
F test/vtabE.test d5024aa42754962f6bb0afd261681686488e7afe
F test/vtabF.test 1918844c7c902f6a16c8dacf1ec8f84886d6e78b
F test/vtabH.test 97f61b0253260831af6232163f7852e2653baed6
F test/vtabH.test a2912cd3ea3386aecc3cb74ebfdfcc4e6d4b7dd3
F test/vtabI.test 751b07636700dbdea328e4265b6077ccd6811a3f
F test/vtab_alter.test 9e374885248f69e251bdaacf480b04a197f125e5
F test/vtab_err.test 0d4d8eb4def1d053ac7c5050df3024fd47a3fbd8
@@ -1468,8 +1475,9 @@ F tool/fuzzershell.c dbf6c26eef936ec78cb0707570de3a4308b2507e
F tool/genfkey.README cf68fddd4643bbe3ff8e31b8b6d8b0a1b85e20f4
F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5
F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce
F tool/kvtest-speed.sh 4761a9c4b3530907562314d7757995787f7aef8f
F tool/lemon.c 5ccba178a8e8a4b21e1c9232944d23973da38ad7
F tool/lempar.c 320d630b44da693407684c64d9fa91a163419dac
F tool/lempar.c db1bdb4821f2d8fbd76e577cf3ab18642c8d08d1
F tool/libvers.c caafc3b689638a1d88d44bc5f526c2278760d9b9
F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862
F tool/logest.c 11346aa019e2e77a00902aa7d0cabd27bd2e8cca
@@ -1479,7 +1487,7 @@ F tool/mkmsvcmin.tcl 2f12f7fa8858bbe61cf81820a2da96c79ed1ca8d
F tool/mkopcodec.tcl d1b6362bd3aa80d5520d4d6f3765badf01f6c43c
F tool/mkopcodeh.tcl a01d2c1d8a6205b03fc635adf3735b4c523befd3
F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e
F tool/mkpragmatab.tcl a30ee93515135466fc49ae881f75da07ebcafd19
F tool/mkpragmatab.tcl ebb4bfcd2f8010e0a3934b6118db4b5f2f5edf5c
F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97
F tool/mksqlite3c-noext.tcl fef88397668ae83166735c41af99d79f56afaabb
F tool/mksqlite3c.tcl 06b2e6a0f21cc0a5d70fbbd136b3e0a96470645e
@@ -1501,7 +1509,7 @@ F tool/showstat4.c b14159aa062f661b394ba37b6b7b94bfb8012ab9
F tool/showwal.c ec79959834f7b21f1e0a2aa52bb7c056d2203977
F tool/soak1.tcl 8d407956e1a45b485a8e072470a3e629a27037fe
F tool/spaceanal.tcl ab7d9bf68062907282a64b3e12ccbfad47193c5a
F tool/speed-check.sh e6ca0695b047af64201ebe0ef452e423f55d78b1
F tool/speed-check.sh 9630ba0468b609c52f48309243d4eb6e9c34deda
F tool/speedtest.tcl 06c76698485ccf597b9e7dbb1ac70706eb873355
F tool/speedtest16.c ecb6542862151c3e6509bbc00509b234562ae81e
F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
@@ -1541,10 +1549,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P d3ac32a6e7f1823450feb3d1089802542090d164
R 1c116e0d91d0fafdc790fe63a7695a8d
T *branch * printf-optimization
T *sym-printf-optimization *
T -sym-trunk *
P 91eb6b628e278d20eccc647293e5b30765163e12
R 793d15c782afd1bb1c67c16147a858a7
U drh
Z 6815c125f61af9819176bed00aaf68bc
Z 0d3326b5592bbe49f8801dfaea3a7026
+1 -1
View File
@@ -1 +1 @@
acdb8f6f10953ed4290aadc9e026edd57d1dd21a
495ea824093ff535734c22c3115384c08f855c02
+1 -1
View File
@@ -1615,7 +1615,7 @@ static void initAvgEq(Index *pIdx){
}
}
if( nDist100>nSum100 ){
if( nDist100>nSum100 && sumEq<nRow ){
avgEq = ((i64)100 * (nRow - sumEq))/(nDist100 - nSum100);
}
if( avgEq==0 ) avgEq = 1;
+120 -82
View File
@@ -3356,12 +3356,14 @@ static int modifyPagePointer(MemPage *pPage, Pgno iFrom, Pgno iTo, u8 eType){
if( eType==PTRMAP_OVERFLOW1 ){
CellInfo info;
pPage->xParseCell(pPage, pCell, &info);
if( info.nLocal<info.nPayload
&& pCell+info.nSize-1<=pPage->aData+pPage->maskPage
&& iFrom==get4byte(pCell+info.nSize-4)
){
put4byte(pCell+info.nSize-4, iTo);
break;
if( info.nLocal<info.nPayload ){
if( pCell+info.nSize > pPage->aData+pPage->pBt->usableSize ){
return SQLITE_CORRUPT_BKPT;
}
if( iFrom==get4byte(pCell+info.nSize-4) ){
put4byte(pCell+info.nSize-4, iTo);
break;
}
}
}else{
if( get4byte(pCell)==iFrom ){
@@ -4422,7 +4424,6 @@ static int copyPayload(
**
** 0: The operation is a read. Populate the overflow cache.
** 1: The operation is a write. Populate the overflow cache.
** 2: The operation is a read. Do not populate the overflow cache.
**
** A total of "amt" bytes are read or written beginning at "offset".
** Data is read to or from the buffer pBuf.
@@ -4430,13 +4431,13 @@ static int copyPayload(
** The content being read or written might appear on the main page
** or be scattered out on multiple overflow pages.
**
** If the current cursor entry uses one or more overflow pages and the
** eOp argument is not 2, this function may allocate space for and lazily
** populates the overflow page-list cache array (BtCursor.aOverflow).
** If the current cursor entry uses one or more overflow pages
** this function may allocate space for and lazily populate
** the overflow page-list cache array (BtCursor.aOverflow).
** Subsequent calls use this cache to make seeking to the supplied offset
** more efficient.
**
** Once an overflow page-list cache has been allocated, it may be
** Once an overflow page-list cache has been allocated, it must be
** invalidated if some other cursor writes to the same table, or if
** the cursor is moved to a different row. Additionally, in auto-vacuum
** mode, the following events may invalidate an overflow page-list cache.
@@ -4458,21 +4459,17 @@ static int accessPayload(
MemPage *pPage = pCur->apPage[pCur->iPage]; /* Btree page of current entry */
BtShared *pBt = pCur->pBt; /* Btree this cursor belongs to */
#ifdef SQLITE_DIRECT_OVERFLOW_READ
unsigned char * const pBufStart = pBuf;
int bEnd; /* True if reading to end of data */
unsigned char * const pBufStart = pBuf; /* Start of original out buffer */
#endif
assert( pPage );
assert( eOp==0 || eOp==1 );
assert( pCur->eState==CURSOR_VALID );
assert( pCur->aiIdx[pCur->iPage]<pPage->nCell );
assert( cursorHoldsMutex(pCur) );
assert( eOp!=2 || offset==0 ); /* Always start from beginning for eOp==2 */
getCellInfo(pCur);
aPayload = pCur->info.pPayload;
#ifdef SQLITE_DIRECT_OVERFLOW_READ
bEnd = offset+amt==pCur->info.nPayload;
#endif
assert( offset+amt <= pCur->info.nPayload );
assert( aPayload > pPage->aData );
@@ -4491,7 +4488,7 @@ static int accessPayload(
if( a+offset>pCur->info.nLocal ){
a = pCur->info.nLocal - offset;
}
rc = copyPayload(&aPayload[offset], pBuf, a, (eOp & 0x01), pPage->pDbPage);
rc = copyPayload(&aPayload[offset], pBuf, a, eOp, pPage->pDbPage);
offset = 0;
pBuf += a;
amt -= a;
@@ -4507,53 +4504,46 @@ static int accessPayload(
nextPage = get4byte(&aPayload[pCur->info.nLocal]);
/* If the BtCursor.aOverflow[] has not been allocated, allocate it now.
** Except, do not allocate aOverflow[] for eOp==2.
**
** The aOverflow[] array is sized at one entry for each overflow page
** in the overflow chain. The page number of the first overflow page is
** stored in aOverflow[0], etc. A value of 0 in the aOverflow[] array
** means "not yet known" (the cache is lazily populated).
*/
if( eOp!=2 && (pCur->curFlags & BTCF_ValidOvfl)==0 ){
if( (pCur->curFlags & BTCF_ValidOvfl)==0 ){
int nOvfl = (pCur->info.nPayload-pCur->info.nLocal+ovflSize-1)/ovflSize;
if( nOvfl>pCur->nOvflAlloc ){
Pgno *aNew = (Pgno*)sqlite3Realloc(
pCur->aOverflow, nOvfl*2*sizeof(Pgno)
);
if( aNew==0 ){
rc = SQLITE_NOMEM_BKPT;
return SQLITE_NOMEM_BKPT;
}else{
pCur->nOvflAlloc = nOvfl*2;
pCur->aOverflow = aNew;
}
}
if( rc==SQLITE_OK ){
memset(pCur->aOverflow, 0, nOvfl*sizeof(Pgno));
pCur->curFlags |= BTCF_ValidOvfl;
memset(pCur->aOverflow, 0, nOvfl*sizeof(Pgno));
pCur->curFlags |= BTCF_ValidOvfl;
}else{
/* If the overflow page-list cache has been allocated and the
** entry for the first required overflow page is valid, skip
** directly to it.
*/
if( pCur->aOverflow[offset/ovflSize] ){
iIdx = (offset/ovflSize);
nextPage = pCur->aOverflow[iIdx];
offset = (offset%ovflSize);
}
}
/* If the overflow page-list cache has been allocated and the
** entry for the first required overflow page is valid, skip
** directly to it.
*/
if( (pCur->curFlags & BTCF_ValidOvfl)!=0
&& pCur->aOverflow[offset/ovflSize]
){
iIdx = (offset/ovflSize);
nextPage = pCur->aOverflow[iIdx];
offset = (offset%ovflSize);
}
for( ; rc==SQLITE_OK && amt>0 && nextPage; iIdx++){
assert( rc==SQLITE_OK && amt>0 );
while( nextPage ){
/* If required, populate the overflow page-list cache. */
if( (pCur->curFlags & BTCF_ValidOvfl)!=0 ){
assert( pCur->aOverflow[iIdx]==0
|| pCur->aOverflow[iIdx]==nextPage
|| CORRUPT_DB );
pCur->aOverflow[iIdx] = nextPage;
}
assert( pCur->aOverflow[iIdx]==0
|| pCur->aOverflow[iIdx]==nextPage
|| CORRUPT_DB );
pCur->aOverflow[iIdx] = nextPage;
if( offset>=ovflSize ){
/* The only reason to read this page is to obtain the page
@@ -4561,11 +4551,7 @@ static int accessPayload(
** data is not required. So first try to lookup the overflow
** page-list cache, if any, then fall back to the getOverflowPage()
** function.
**
** Note that the aOverflow[] array must be allocated because eOp!=2
** here. If eOp==2, then offset==0 and this branch is never taken.
*/
assert( eOp!=2 );
assert( pCur->curFlags & BTCF_ValidOvfl );
assert( pCur->pBtree->db==pBt->db );
if( pCur->aOverflow[iIdx+1] ){
@@ -4579,7 +4565,7 @@ static int accessPayload(
** range of data that is being read (eOp==0) or written (eOp!=0).
*/
#ifdef SQLITE_DIRECT_OVERFLOW_READ
sqlite3_file *fd;
sqlite3_file *fd; /* File from which to do direct overflow read */
#endif
int a = amt;
if( a + offset > ovflSize ){
@@ -4591,27 +4577,25 @@ static int accessPayload(
**
** 1) this is a read operation, and
** 2) data is required from the start of this overflow page, and
** 3) the database is file-backed, and
** 4) there is no open write-transaction, and
** 5) the database is not a WAL database,
** 6) all data from the page is being read.
** 7) at least 4 bytes have already been read into the output buffer
** 3) there is no open write-transaction, and
** 4) the database is file-backed, and
** 5) the page is not in the WAL file
** 6) at least 4 bytes have already been read into the output buffer
**
** then data can be read directly from the database file into the
** output buffer, bypassing the page-cache altogether. This speeds
** up loading large records that span many overflow pages.
*/
if( (eOp&0x01)==0 /* (1) */
if( eOp==0 /* (1) */
&& offset==0 /* (2) */
&& (bEnd || a==ovflSize) /* (6) */
&& pBt->inTransaction==TRANS_READ /* (4) */
&& (fd = sqlite3PagerFile(pBt->pPager))->pMethods /* (3) */
&& 0==sqlite3PagerUseWal(pBt->pPager) /* (5) */
&& &pBuf[-4]>=pBufStart /* (7) */
&& pBt->inTransaction==TRANS_READ /* (3) */
&& (fd = sqlite3PagerFile(pBt->pPager))->pMethods /* (4) */
&& 0==sqlite3PagerUseWal(pBt->pPager, nextPage) /* (5) */
&& &pBuf[-4]>=pBufStart /* (6) */
){
u8 aSave[4];
u8 *aWrite = &pBuf[-4];
assert( aWrite>=pBufStart ); /* hence (7) */
assert( aWrite>=pBufStart ); /* due to (6) */
memcpy(aSave, aWrite, 4);
rc = sqlite3OsRead(fd, aWrite, a+4, (i64)pBt->pageSize*(nextPage-1));
nextPage = get4byte(aWrite);
@@ -4622,24 +4606,27 @@ static int accessPayload(
{
DbPage *pDbPage;
rc = sqlite3PagerGet(pBt->pPager, nextPage, &pDbPage,
((eOp&0x01)==0 ? PAGER_GET_READONLY : 0)
(eOp==0 ? PAGER_GET_READONLY : 0)
);
if( rc==SQLITE_OK ){
aPayload = sqlite3PagerGetData(pDbPage);
nextPage = get4byte(aPayload);
rc = copyPayload(&aPayload[offset+4], pBuf, a, (eOp&0x01), pDbPage);
rc = copyPayload(&aPayload[offset+4], pBuf, a, eOp, pDbPage);
sqlite3PagerUnref(pDbPage);
offset = 0;
}
}
amt -= a;
if( amt==0 ) return rc;
pBuf += a;
}
if( rc ) break;
iIdx++;
}
}
if( rc==SQLITE_OK && amt>0 ){
return SQLITE_CORRUPT_BKPT;
return SQLITE_CORRUPT_BKPT; /* Overflow chain ends prematurely */
}
return rc;
}
@@ -4668,21 +4655,34 @@ int sqlite3BtreePayload(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){
assert( pCur->aiIdx[pCur->iPage]<pCur->apPage[pCur->iPage]->nCell );
return accessPayload(pCur, offset, amt, (unsigned char*)pBuf, 0);
}
/*
** This variant of sqlite3BtreePayload() works even if the cursor has not
** in the CURSOR_VALID state. It is only used by the sqlite3_blob_read()
** interface.
*/
#ifndef SQLITE_OMIT_INCRBLOB
int sqlite3BtreePayloadChecked(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){
static SQLITE_NOINLINE int accessPayloadChecked(
BtCursor *pCur,
u32 offset,
u32 amt,
void *pBuf
){
int rc;
if ( pCur->eState==CURSOR_INVALID ){
return SQLITE_ABORT;
}
assert( cursorOwnsBtShared(pCur) );
rc = restoreCursorPosition(pCur);
if( rc==SQLITE_OK ){
assert( pCur->eState==CURSOR_VALID );
assert( pCur->iPage>=0 && pCur->apPage[pCur->iPage] );
assert( pCur->aiIdx[pCur->iPage]<pCur->apPage[pCur->iPage]->nCell );
rc = accessPayload(pCur, offset, amt, pBuf, 0);
rc = btreeRestoreCursorPosition(pCur);
return rc ? rc : accessPayload(pCur, offset, amt, pBuf, 0);
}
int sqlite3BtreePayloadChecked(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){
if( pCur->eState==CURSOR_VALID ){
assert( cursorOwnsBtShared(pCur) );
return accessPayload(pCur, offset, amt, pBuf, 0);
}else{
return accessPayloadChecked(pCur, offset, amt, pBuf);
}
return rc;
}
#endif /* SQLITE_OMIT_INCRBLOB */
@@ -5088,9 +5088,26 @@ int sqlite3BtreeMovetoUnpacked(
*pRes = 0;
return SQLITE_OK;
}
if( (pCur->curFlags & BTCF_AtLast)!=0 && pCur->info.nKey<intKey ){
*pRes = -1;
return SQLITE_OK;
if( pCur->info.nKey<intKey ){
if( (pCur->curFlags & BTCF_AtLast)!=0 ){
*pRes = -1;
return SQLITE_OK;
}
/* If the requested key is one more than the previous key, then
** try to get there using sqlite3BtreeNext() rather than a full
** binary search. This is an optimization only. The correct answer
** is still obtained without this ase, only a little more slowely */
if( pCur->info.nKey+1==intKey && !pCur->skipNext ){
*pRes = 0;
rc = sqlite3BtreeNext(pCur, pRes);
if( rc ) return rc;
if( *pRes==0 ){
getCellInfo(pCur);
if( pCur->info.nKey==intKey ){
return SQLITE_OK;
}
}
}
}
}
@@ -5226,7 +5243,8 @@ int sqlite3BtreeMovetoUnpacked(
goto moveto_finish;
}
pCur->aiIdx[pCur->iPage] = (u16)idx;
rc = accessPayload(pCur, 0, nCell, (unsigned char*)pCellKey, 2);
rc = accessPayload(pCur, 0, nCell, (unsigned char*)pCellKey, 0);
pCur->curFlags &= ~BTCF_ValidOvfl;
if( rc ){
sqlite3_free(pCellKey);
goto moveto_finish;
@@ -7269,7 +7287,6 @@ static int balance_nonroot(
for(i=0; i<nOld; i++){
MemPage *p = apOld[i];
szNew[i] = usableSpace - p->nFree;
if( szNew[i]<0 ){ rc = SQLITE_CORRUPT_BKPT; goto balance_cleanup; }
for(j=0; j<p->nOverflow; j++){
szNew[i] += 2 + p->xCellSize(p, p->apOvfl[j]);
}
@@ -7948,7 +7965,7 @@ static int balance(BtCursor *pCur){
int sqlite3BtreeInsert(
BtCursor *pCur, /* Insert data into the table of this cursor */
const BtreePayload *pX, /* Content of the row to be inserted */
int appendBias, /* True if this is likely an append */
int flags, /* True if this is likely an append */
int seekResult /* Result of prior MovetoUnpacked() call */
){
int rc;
@@ -7961,6 +7978,8 @@ int sqlite3BtreeInsert(
unsigned char *oldCell;
unsigned char *newCell = 0;
assert( (flags & (BTREE_SAVEPOSITION|BTREE_APPEND))==flags );
if( pCur->eState==CURSOR_FAULT ){
assert( pCur->skipNext!=SQLITE_OK );
return pCur->skipNext;
@@ -8001,6 +8020,11 @@ int sqlite3BtreeInsert(
** cursors open on the row being replaced */
invalidateIncrblobCursors(p, 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. */
assert( (flags & BTREE_SAVEPOSITION)==0 ||
((pCur->curFlags&BTCF_ValidNKey)!=0 && pX->nKey==pCur->info.nKey) );
/* If the cursor is currently on the last row and we are appending a
** new row onto the end, set the "loc" to avoid an unnecessary
** btreeMoveto() call */
@@ -8010,10 +8034,10 @@ int sqlite3BtreeInsert(
&& pCur->info.nKey==pX->nKey-1 ){
loc = -1;
}else if( loc==0 ){
rc = sqlite3BtreeMovetoUnpacked(pCur, 0, pX->nKey, appendBias, &loc);
rc = sqlite3BtreeMovetoUnpacked(pCur, 0, pX->nKey, flags!=0, &loc);
if( rc ) return rc;
}
}else if( loc==0 ){
}else if( loc==0 && (flags & BTREE_SAVEPOSITION)==0 ){
if( pX->nMem ){
UnpackedRecord r;
r.pKeyInfo = pCur->pKeyInfo;
@@ -8024,9 +8048,9 @@ int sqlite3BtreeInsert(
r.r1 = 0;
r.r2 = 0;
r.eqSeen = 0;
rc = sqlite3BtreeMovetoUnpacked(pCur, &r, 0, appendBias, &loc);
rc = sqlite3BtreeMovetoUnpacked(pCur, &r, 0, flags!=0, &loc);
}else{
rc = btreeMoveto(pCur, pX->pKey, pX->nKey, appendBias, &loc);
rc = btreeMoveto(pCur, pX->pKey, pX->nKey, flags!=0, &loc);
}
if( rc ) return rc;
}
@@ -8114,6 +8138,20 @@ int sqlite3BtreeInsert(
** from trying to save the current position of the cursor. */
pCur->apPage[pCur->iPage]->nOverflow = 0;
pCur->eState = CURSOR_INVALID;
if( (flags & BTREE_SAVEPOSITION) && rc==SQLITE_OK ){
rc = moveToRoot(pCur);
if( pCur->pKeyInfo ){
assert( pCur->pKey==0 );
pCur->pKey = sqlite3Malloc( pX->nKey );
if( pCur->pKey==0 ){
rc = SQLITE_NOMEM;
}else{
memcpy(pCur->pKey, pX->pKey, pX->nKey);
}
}
pCur->eState = CURSOR_REQUIRESEEK;
pCur->nKey = pX->nKey;
}
}
assert( pCur->apPage[pCur->iPage]->nOverflow==0 );
+3 -2
View File
@@ -249,9 +249,10 @@ int sqlite3BtreeCursorHasMoved(BtCursor*);
int sqlite3BtreeCursorRestore(BtCursor*, int*);
int sqlite3BtreeDelete(BtCursor*, u8 flags);
/* Allowed flags for the 2nd argument to sqlite3BtreeDelete() */
/* Allowed flags for sqlite3BtreeDelete() and sqlite3BtreeInsert() */
#define BTREE_SAVEPOSITION 0x02 /* Leave cursor pointing at NEXT or PREV */
#define BTREE_AUXDELETE 0x04 /* not the primary delete operation */
#define BTREE_APPEND 0x08 /* Insert is likely an append */
/* An instance of the BtreePayload object describes the content of a single
** entry in either an index or table btree.
@@ -282,7 +283,7 @@ struct BtreePayload {
};
int sqlite3BtreeInsert(BtCursor*, const BtreePayload *pPayload,
int bias, int seekResult);
int flags, int seekResult);
int sqlite3BtreeFirst(BtCursor*, int *pRes);
int sqlite3BtreeLast(BtCursor*, int *pRes);
int sqlite3BtreeNext(BtCursor*, int *pRes);
+24 -15
View File
@@ -519,12 +519,8 @@ void sqlite3DeleteFrom(
#endif
{
int count = (pParse->nested==0); /* True to count changes */
int iIdxNoSeek = -1;
if( bComplex==0 && aiCurOnePass[1]!=iDataCur ){
iIdxNoSeek = aiCurOnePass[1];
}
sqlite3GenerateRowDelete(pParse, pTab, pTrigger, iDataCur, iIdxCur,
iKey, nKey, count, OE_Default, eOnePass, iIdxNoSeek);
iKey, nKey, count, OE_Default, eOnePass, aiCurOnePass[1]);
}
/* End of the loop over all rowids/primary-keys. */
@@ -604,15 +600,17 @@ delete_from_cleanup:
**
** If eMode is ONEPASS_MULTI, then this call is being made as part
** of a ONEPASS delete that affects multiple rows. In this case, if
** iIdxNoSeek is a valid cursor number (>=0), then its position should
** be preserved following the delete operation. Or, if iIdxNoSeek is not
** a valid cursor number, the position of iDataCur should be preserved
** instead.
** iIdxNoSeek is a valid cursor number (>=0) and is not the same as
** iDataCur, then its position should be preserved following the delete
** operation. Or, if iIdxNoSeek is not a valid cursor number, the
** position of iDataCur should be preserved instead.
**
** iIdxNoSeek:
** If iIdxNoSeek is a valid cursor number (>=0), then it identifies an
** index cursor (from within array of cursors starting at iIdxCur) that
** already points to the index entry to be deleted.
** If iIdxNoSeek is a valid cursor number (>=0) not equal to iDataCur,
** then it identifies an index cursor (from within array of cursors
** starting at iIdxCur) that already points to the index entry to be deleted.
** Except, this optimization is disabled if there are BEFORE triggers since
** the trigger body might have moved the cursor.
*/
void sqlite3GenerateRowDelete(
Parse *pParse, /* Parsing context */
@@ -683,13 +681,18 @@ void sqlite3GenerateRowDelete(
/* If any BEFORE triggers were coded, then seek the cursor to the
** row to be deleted again. It may be that the BEFORE triggers moved
** the cursor or of already deleted the row that the cursor was
** the cursor or already deleted the row that the cursor was
** pointing to.
**
** Also disable the iIdxNoSeek optimization since the BEFORE trigger
** may have moved that cursor.
*/
if( addrStart<sqlite3VdbeCurrentAddr(v) ){
sqlite3VdbeAddOp4Int(v, opSeek, iDataCur, iLabel, iPk, nPk);
VdbeCoverageIf(v, opSeek==OP_NotExists);
VdbeCoverageIf(v, opSeek==OP_NotFound);
testcase( iIdxNoSeek>=0 );
iIdxNoSeek = -1;
}
/* Do FK processing. This call checks that any FK constraints that
@@ -712,11 +715,13 @@ void sqlite3GenerateRowDelete(
u8 p5 = 0;
sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur,0,iIdxNoSeek);
sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, (count?OPFLAG_NCHANGE:0));
sqlite3VdbeAppendP4(v, (char*)pTab, P4_TABLE);
if( pParse->nested==0 ){
sqlite3VdbeAppendP4(v, (char*)pTab, P4_TABLE);
}
if( eMode!=ONEPASS_OFF ){
sqlite3VdbeChangeP5(v, OPFLAG_AUXDELETE);
}
if( iIdxNoSeek>=0 ){
if( iIdxNoSeek>=0 && iIdxNoSeek!=iDataCur ){
sqlite3VdbeAddOp1(v, OP_Delete, iIdxNoSeek);
}
if( eMode==ONEPASS_MULTI ) p5 |= OPFLAG_SAVEPOSITION;
@@ -870,6 +875,10 @@ int sqlite3GenerateIndexKey(
}
if( regOut ){
sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol, regOut);
if( pIdx->pTable->pSelect ){
const char *zAff = sqlite3IndexAffinityStr(pParse->db, pIdx);
sqlite3VdbeChangeP4(v, -1, zAff, P4_TRANSIENT);
}
}
sqlite3ReleaseTempRange(pParse, regBase, nCol);
return regBase;
+36 -20
View File
@@ -967,8 +967,13 @@ void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr, u32 n){
/* Wildcard of the form "?nnn". Convert "nnn" to an integer and
** use it as the variable number */
i64 i;
int bOk = 0==sqlite3Atoi64(&z[1], &i, n-1, SQLITE_UTF8);
x = (ynVar)i;
int bOk;
if( n==2 ){ /*OPTIMIZATION-IF-TRUE*/
i = z[1]-'0'; /* The common case of ?N for a single digit N */
bOk = 1;
}else{
bOk = 0==sqlite3Atoi64(&z[1], &i, n-1, SQLITE_UTF8);
}
testcase( i==0 );
testcase( i==1 );
testcase( i==db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]-1 );
@@ -978,6 +983,7 @@ void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr, u32 n){
db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]);
return;
}
x = (ynVar)i;
if( x>pParse->nVar ){
pParse->nVar = (int)x;
doAdd = 1;
@@ -3612,6 +3618,11 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
u8 enc = ENC(db); /* The text encoding used by this database */
CollSeq *pColl = 0; /* A collating sequence */
if( ConstFactorOk(pParse) && sqlite3ExprIsConstantNotJoin(pExpr) ){
/* SQL functions can be expensive. So try to move constant functions
** out of the inner loop, even if that means an extra OP_Copy. */
return sqlite3ExprCodeAtInit(pParse, pExpr, -1);
}
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
if( ExprHasProperty(pExpr, EP_TokenOnly) ){
pFarg = 0;
@@ -3992,24 +4003,40 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
/*
** Factor out the code of the given expression to initialization time.
**
** If regDest>=0 then the result is always stored in that register and the
** result is not reusable. If regDest<0 then this routine is free to
** store the value whereever it wants. The register where the expression
** is stored is returned. When regDest<0, two identical expressions will
** code to the same register.
*/
void sqlite3ExprCodeAtInit(
int sqlite3ExprCodeAtInit(
Parse *pParse, /* Parsing context */
Expr *pExpr, /* The expression to code when the VDBE initializes */
int regDest, /* Store the value in this register */
u8 reusable /* True if this expression is reusable */
int regDest /* Store the value in this register */
){
ExprList *p;
assert( ConstFactorOk(pParse) );
p = pParse->pConstExpr;
if( regDest<0 && p ){
struct ExprList_item *pItem;
int i;
for(pItem=p->a, i=p->nExpr; i>0; pItem++, i--){
if( pItem->reusable && sqlite3ExprCompare(pItem->pExpr,pExpr,-1)==0 ){
return pItem->u.iConstExprReg;
}
}
}
pExpr = sqlite3ExprDup(pParse->db, pExpr, 0);
p = sqlite3ExprListAppend(pParse, p, pExpr);
if( p ){
struct ExprList_item *pItem = &p->a[p->nExpr-1];
pItem->reusable = regDest<0;
if( regDest<0 ) regDest = ++pParse->nMem;
pItem->u.iConstExprReg = regDest;
pItem->reusable = reusable;
}
pParse->pConstExpr = p;
return regDest;
}
/*
@@ -4032,19 +4059,8 @@ int sqlite3ExprCodeTemp(Parse *pParse, Expr *pExpr, int *pReg){
&& pExpr->op!=TK_REGISTER
&& sqlite3ExprIsConstantNotJoin(pExpr)
){
ExprList *p = pParse->pConstExpr;
int i;
*pReg = 0;
if( p ){
struct ExprList_item *pItem;
for(pItem=p->a, i=p->nExpr; i>0; pItem++, i--){
if( pItem->reusable && sqlite3ExprCompare(pItem->pExpr,pExpr,-1)==0 ){
return pItem->u.iConstExprReg;
}
}
}
r2 = ++pParse->nMem;
sqlite3ExprCodeAtInit(pParse, pExpr, r2, 1);
r2 = sqlite3ExprCodeAtInit(pParse, pExpr, -1);
}else{
int r1 = sqlite3GetTempReg(pParse);
r2 = sqlite3ExprCodeTarget(pParse, pExpr, r1);
@@ -4098,7 +4114,7 @@ void sqlite3ExprCodeCopy(Parse *pParse, Expr *pExpr, int target){
*/
void sqlite3ExprCodeFactorable(Parse *pParse, Expr *pExpr, int target){
if( pParse->okConstFactor && sqlite3ExprIsConstant(pExpr) ){
sqlite3ExprCodeAtInit(pParse, pExpr, target, 0);
sqlite3ExprCodeAtInit(pParse, pExpr, target);
}else{
sqlite3ExprCode(pParse, pExpr, target);
}
@@ -4170,7 +4186,7 @@ int sqlite3ExprCodeExprList(
sqlite3VdbeAddOp2(v, copyOp, j+srcReg-1, target+i);
}
}else if( (flags & SQLITE_ECEL_FACTOR)!=0 && sqlite3ExprIsConstant(pExpr) ){
sqlite3ExprCodeAtInit(pParse, pExpr, target+i, 0);
sqlite3ExprCodeAtInit(pParse, pExpr, target+i);
}else{
int inReg = sqlite3ExprCodeTarget(pParse, pExpr, target+i);
if( inReg!=target+i ){
+46 -7
View File
@@ -1549,12 +1549,25 @@ void sqlite3GenerateConstraintChecks(
onError = OE_Abort;
}
if( ix==0 && pPk==pIdx && onError==OE_Replace && pPk->pNext==0 ){
/* Collision detection may be omitted if all of the following are true:
** (1) The conflict resolution algorithm is REPLACE
** (2) The table is a WITHOUT ROWID table
** (3) There are no secondary indexes on the table
** (4) No delete triggers need to be fired if there is a conflict
** (5) No FK constraint counters need to be updated if a conflict occurs.
*/
if( (ix==0 && pIdx->pNext==0) /* Condition 3 */
&& pPk==pIdx /* Condition 2 */
&& onError==OE_Replace /* Condition 1 */
&& ( 0==(db->flags&SQLITE_RecTriggers) || /* Condition 4 */
0==sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0))
&& ( 0==(db->flags&SQLITE_ForeignKeys) || /* Condition 5 */
(0==pTab->pFKey && 0==sqlite3FkReferences(pTab)))
){
sqlite3VdbeResolveLabel(v, addrUniqueOk);
continue;
}
/* Check to see if the new index entry will be unique */
sqlite3VdbeAddOp4Int(v, OP_NoConflict, iThisCur, addrUniqueOk,
regIdx, pIdx->nKeyCol); VdbeCoverage(v);
@@ -1638,7 +1651,7 @@ void sqlite3GenerateConstraintChecks(
}
sqlite3GenerateRowDelete(pParse, pTab, pTrigger, iDataCur, iIdxCur,
regR, nPkField, 0, OE_Replace,
(pIdx==pPk ? ONEPASS_SINGLE : ONEPASS_OFF), -1);
(pIdx==pPk ? ONEPASS_SINGLE : ONEPASS_OFF), iThisCur);
seenReplace = 1;
break;
}
@@ -1655,6 +1668,25 @@ void sqlite3GenerateConstraintChecks(
VdbeModuleComment((v, "END: GenCnstCks(%d)", seenReplace));
}
#ifdef SQLITE_ENABLE_NULL_TRIM
/*
** Change the P5 operand on the last opcode (which should be an OP_MakeRecord)
** to be the number of columns in table pTab that must not be NULL-trimmed.
**
** Or if no columns of pTab may be NULL-trimmed, leave P5 at zero.
*/
void sqlite3SetMakeRecordP5(Vdbe *v, Table *pTab){
u16 i;
/* Records with omitted columns are only allowed for schema format
** version 2 and later (SQLite version 3.1.4, 2005-02-20). */
if( pTab->pSchema->file_format<2 ) return;
for(i=pTab->nCol; i>1 && pTab->aCol[i-1].pDflt==0; i--){}
sqlite3VdbeChangeP5(v, i);
}
#endif
/*
** This routine generates code to finish the INSERT or UPDATE operation
** that was started by a prior call to sqlite3GenerateConstraintChecks.
@@ -1671,7 +1703,7 @@ void sqlite3CompleteInsertion(
int iIdxCur, /* First index cursor */
int regNewData, /* Range of content */
int *aRegIdx, /* Register used by each index. 0 for unused indices */
int isUpdate, /* True for UPDATE, False for INSERT */
int update_flags, /* True for UPDATE, False for INSERT */
int appendBias, /* True if this is likely to be an append */
int useSeekResult /* True to set the USESEEKRESULT flag on OP_[Idx]Insert */
){
@@ -1683,6 +1715,11 @@ void sqlite3CompleteInsertion(
int i; /* Loop counter */
u8 bAffinityDone = 0; /* True if OP_Affinity has been run already */
assert( update_flags==0
|| update_flags==OPFLAG_ISUPDATE
|| update_flags==(OPFLAG_ISUPDATE|OPFLAG_SAVEPOSITION)
);
v = sqlite3GetVdbe(pParse);
assert( v!=0 );
assert( pTab->pSelect==0 ); /* This table is not a VIEW */
@@ -1701,6 +1738,7 @@ void sqlite3CompleteInsertion(
if( IsPrimaryKeyIndex(pIdx) && !HasRowid(pTab) ){
assert( pParse->nested==0 );
pik_flags |= OPFLAG_NCHANGE;
pik_flags |= (update_flags & OPFLAG_SAVEPOSITION);
}
sqlite3VdbeChangeP5(v, pik_flags);
}
@@ -1708,6 +1746,7 @@ void sqlite3CompleteInsertion(
regData = regNewData + 1;
regRec = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp3(v, OP_MakeRecord, regData, pTab->nCol, regRec);
sqlite3SetMakeRecordP5(v, pTab);
if( !bAffinityDone ){
sqlite3TableAffinity(v, pTab, 0);
sqlite3ExprCacheAffinityChange(pParse, regData, pTab->nCol);
@@ -1716,7 +1755,7 @@ void sqlite3CompleteInsertion(
pik_flags = 0;
}else{
pik_flags = OPFLAG_NCHANGE;
pik_flags |= (isUpdate?OPFLAG_ISUPDATE:OPFLAG_LASTROWID);
pik_flags |= (update_flags?update_flags:OPFLAG_LASTROWID);
}
if( appendBias ){
pik_flags |= OPFLAG_APPEND;
@@ -2125,7 +2164,7 @@ static int xferOptimization(
addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid);
assert( (pDest->tabFlags & TF_Autoincrement)==0 );
}
sqlite3VdbeAddOp2(v, OP_RowData, iSrc, regData);
sqlite3VdbeAddOp3(v, OP_RowData, iSrc, regData, 1);
if( db->flags & SQLITE_Vacuum ){
sqlite3VdbeAddOp3(v, OP_Last, iDest, 0, -1);
insFlags = OPFLAG_NCHANGE|OPFLAG_LASTROWID|
@@ -2157,7 +2196,7 @@ static int xferOptimization(
sqlite3VdbeChangeP5(v, OPFLAG_BULKCSR);
VdbeComment((v, "%s", pDestIdx->zName));
addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0); VdbeCoverage(v);
sqlite3VdbeAddOp2(v, OP_RowData, iSrc, regData);
sqlite3VdbeAddOp3(v, OP_RowData, iSrc, regData, 1);
if( db->flags & SQLITE_Vacuum ){
/* This INSERT command is part of a VACUUM operation, which guarantees
** that the destination table is empty. If all indexed columns use
-1
View File
@@ -18,7 +18,6 @@
#endif
#include "sqlite3ext.h"
#include "sqliteInt.h"
#include <string.h>
#ifndef SQLITE_OMIT_LOAD_EXTENSION
/*
+5 -6
View File
@@ -217,14 +217,14 @@ static void sqlite3MallocAlarm(int nByte){
** Do a memory allocation with statistics and alarms. Assume the
** lock is already held.
*/
static int mallocWithAlarm(int n, void **pp){
int nFull;
static void mallocWithAlarm(int n, void **pp){
void *p;
int nFull = 0;
assert( sqlite3_mutex_held(mem0.mutex) );
nFull = sqlite3GlobalConfig.m.xRoundup(n);
sqlite3StatusHighwater(SQLITE_STATUS_MALLOC_SIZE, n);
if( mem0.alarmThreshold>0 ){
sqlite3_int64 nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED);
nFull = sqlite3GlobalConfig.m.xRoundup(n);
if( nUsed >= mem0.alarmThreshold - nFull ){
mem0.nearlyFull = 1;
sqlite3MallocAlarm(nFull);
@@ -232,11 +232,11 @@ static int mallocWithAlarm(int n, void **pp){
mem0.nearlyFull = 0;
}
}
p = sqlite3GlobalConfig.m.xMalloc(nFull);
p = sqlite3GlobalConfig.m.xMalloc(n);
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
if( p==0 && mem0.alarmThreshold>0 ){
sqlite3MallocAlarm(nFull);
p = sqlite3GlobalConfig.m.xMalloc(nFull);
p = sqlite3GlobalConfig.m.xMalloc(n);
}
#endif
if( p ){
@@ -245,7 +245,6 @@ static int mallocWithAlarm(int n, void **pp){
sqlite3StatusUp(SQLITE_STATUS_MALLOC_COUNT, 1);
}
*pp = p;
return nFull;
}
/*
+12 -6
View File
@@ -814,14 +814,20 @@ static const unsigned char aJournalMagic[] = {
#define isOpen(pFd) ((pFd)->pMethods!=0)
/*
** Return true if this pager uses a write-ahead log instead of the usual
** rollback journal. Otherwise false.
** Return true if this pager uses a write-ahead log to read page pgno.
** Return false if the pager reads pgno directly from the database.
*/
#ifndef SQLITE_OMIT_WAL
int sqlite3PagerUseWal(Pager *pPager){
return (pPager->pWal!=0);
#if !defined(SQLITE_OMIT_WAL) && defined(SQLITE_DIRECT_OVERFLOW_READ)
int sqlite3PagerUseWal(Pager *pPager, Pgno pgno){
u32 iRead = 0;
int rc;
if( pPager->pWal==0 ) return 0;
rc = sqlite3WalFindFrame(pPager->pWal, pgno, &iRead);
return rc || iRead;
}
# define pagerUseWal(x) sqlite3PagerUseWal(x)
#endif
#ifndef SQLITE_OMIT_WAL
# define pagerUseWal(x) ((x)->pWal!=0)
#else
# define pagerUseWal(x) 0
# define pagerRollbackWal(x) 0
+4 -2
View File
@@ -178,14 +178,16 @@ int sqlite3PagerSharedLock(Pager *pPager);
int sqlite3PagerWalCallback(Pager *pPager);
int sqlite3PagerOpenWal(Pager *pPager, int *pisOpen);
int sqlite3PagerCloseWal(Pager *pPager, sqlite3*);
int sqlite3PagerUseWal(Pager *pPager);
# ifdef SQLITE_DIRECT_OVERFLOW_READ
int sqlite3PagerUseWal(Pager *pPager, Pgno);
# endif
# ifdef SQLITE_ENABLE_SNAPSHOT
int sqlite3PagerSnapshotGet(Pager *pPager, sqlite3_snapshot **ppSnapshot);
int sqlite3PagerSnapshotOpen(Pager *pPager, sqlite3_snapshot *pSnapshot);
int sqlite3PagerSnapshotRecover(Pager *pPager);
# endif
#else
# define sqlite3PagerUseWal(x) 0
# define sqlite3PagerUseWal(x,y) 0
#endif
#ifdef SQLITE_ENABLE_ZIPVFS
+13
View File
@@ -65,6 +65,19 @@
*/
#define YYPARSEFREENEVERNULL 1
/*
** In the amalgamation, the parse.c file generated by lemon and the
** tokenize.c file are concatenated. In that case, sqlite3RunParser()
** has access to the the size of the yyParser object and so the parser
** engine can be allocated from stack. In that case, only the
** sqlite3ParserInit() and sqlite3ParserFinalize() routines are invoked
** and the sqlite3ParserAlloc() and sqlite3ParserFree() routines can be
** omitted.
*/
#ifdef SQLITE_AMALGAMATION
# define sqlite3Parser_ENGINEALWAYSONSTACK 1
#endif
/*
** Alternative datatype for the argument to the malloc() routine passed
** into sqlite3ParserAlloc(). The default is size_t.
+12 -1
View File
@@ -408,7 +408,9 @@ void sqlite3Pragma(
}
/* Register the result column names for pragmas that return results */
if( (pPragma->mPragFlg & PragFlg_NoColumns)==0 ){
if( (pPragma->mPragFlg & PragFlg_NoColumns)==0
&& ((pPragma->mPragFlg & PragFlg_NoColumns1)==0 || zRight==0)
){
setPragmaResultColumnNames(v, pPragma);
}
@@ -1953,6 +1955,15 @@ void sqlite3Pragma(
} /* End of the PRAGMA switch */
/* The following block is a no-op unless SQLITE_DEBUG is defined. Its only
** purpose is to execute assert() statements to verify that if the
** PragFlg_NoColumns1 flag is set and the caller specified an argument
** to the PRAGMA, the implementation has not added any OP_ResultRow
** instructions to the VM. */
if( (pPragma->mPragFlg & PragFlg_NoColumns1) && zRight ){
sqlite3VdbeVerifyNoResultRow(v);
}
pragma_out:
sqlite3DbFree(db, zLeft);
sqlite3DbFree(db, zRight);
+47 -46
View File
@@ -52,11 +52,12 @@
/* Property flags associated with various pragma. */
#define PragFlg_NeedSchema 0x01 /* Force schema load before running */
#define PragFlg_NoColumns 0x02 /* OP_ResultRow called with zero columns */
#define PragFlg_ReadOnly 0x04 /* Read-only HEADER_VALUE */
#define PragFlg_Result0 0x08 /* Acts as query when no argument */
#define PragFlg_Result1 0x10 /* Acts as query when has one argument */
#define PragFlg_SchemaOpt 0x20 /* Schema restricts name search if present */
#define PragFlg_SchemaReq 0x40 /* Schema required - "main" is default */
#define PragFlg_NoColumns1 0x04 /* zero columns if RHS argument is present */
#define PragFlg_ReadOnly 0x08 /* Read-only HEADER_VALUE */
#define PragFlg_Result0 0x10 /* Acts as query when no argument */
#define PragFlg_Result1 0x20 /* Acts as query when has one argument */
#define PragFlg_SchemaOpt 0x40 /* Schema restricts name search if present */
#define PragFlg_SchemaReq 0x80 /* Schema required - "main" is default */
/* Names of columns for pragmas that return multi-column result
** or that return single-column results where the name of the
@@ -133,14 +134,14 @@ static const PragmaName aPragmaName[] = {
#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
{/* zName: */ "application_id",
/* ePragTyp: */ PragTyp_HEADER_VALUE,
/* ePragFlg: */ PragFlg_Result0,
/* ePragFlg: */ PragFlg_NoColumns1|PragFlg_Result0,
/* ColNames: */ 0, 0,
/* iArg: */ BTREE_APPLICATION_ID },
#endif
#if !defined(SQLITE_OMIT_AUTOVACUUM)
{/* zName: */ "auto_vacuum",
/* ePragTyp: */ PragTyp_AUTO_VACUUM,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1,
/* ColNames: */ 0, 0,
/* iArg: */ 0 },
#endif
@@ -148,7 +149,7 @@ static const PragmaName aPragmaName[] = {
#if !defined(SQLITE_OMIT_AUTOMATIC_INDEX)
{/* zName: */ "automatic_index",
/* ePragTyp: */ PragTyp_FLAG,
/* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns,
/* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
/* ColNames: */ 0, 0,
/* iArg: */ SQLITE_AutoIndex },
#endif
@@ -161,31 +162,31 @@ static const PragmaName aPragmaName[] = {
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
{/* zName: */ "cache_size",
/* ePragTyp: */ PragTyp_CACHE_SIZE,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1,
/* ColNames: */ 0, 0,
/* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
{/* zName: */ "cache_spill",
/* ePragTyp: */ PragTyp_CACHE_SPILL,
/* ePragFlg: */ PragFlg_Result0|PragFlg_SchemaReq,
/* ePragFlg: */ PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1,
/* ColNames: */ 0, 0,
/* iArg: */ 0 },
#endif
{/* zName: */ "case_sensitive_like",
/* ePragTyp: */ PragTyp_CASE_SENSITIVE_LIKE,
/* ePragFlg: */ 0,
/* ePragFlg: */ PragFlg_NoColumns,
/* ColNames: */ 0, 0,
/* iArg: */ 0 },
{/* zName: */ "cell_size_check",
/* ePragTyp: */ PragTyp_FLAG,
/* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns,
/* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
/* ColNames: */ 0, 0,
/* iArg: */ SQLITE_CellSizeCk },
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
{/* zName: */ "checkpoint_fullfsync",
/* ePragTyp: */ PragTyp_FLAG,
/* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns,
/* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
/* ColNames: */ 0, 0,
/* iArg: */ SQLITE_CkptFullFSync },
#endif
@@ -206,21 +207,21 @@ static const PragmaName aPragmaName[] = {
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
{/* zName: */ "count_changes",
/* ePragTyp: */ PragTyp_FLAG,
/* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns,
/* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
/* ColNames: */ 0, 0,
/* iArg: */ SQLITE_CountRows },
#endif
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && SQLITE_OS_WIN
{/* zName: */ "data_store_directory",
/* ePragTyp: */ PragTyp_DATA_STORE_DIRECTORY,
/* ePragFlg: */ 0,
/* ePragFlg: */ PragFlg_NoColumns1,
/* ColNames: */ 0, 0,
/* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
{/* zName: */ "data_version",
/* ePragTyp: */ PragTyp_HEADER_VALUE,
/* ePragFlg: */ PragFlg_Result0|PragFlg_ReadOnly,
/* ePragFlg: */ PragFlg_ReadOnly|PragFlg_Result0,
/* ColNames: */ 0, 0,
/* iArg: */ BTREE_DATA_VERSION },
#endif
@@ -234,7 +235,7 @@ static const PragmaName aPragmaName[] = {
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED)
{/* zName: */ "default_cache_size",
/* ePragTyp: */ PragTyp_DEFAULT_CACHE_SIZE,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1,
/* ColNames: */ 0, 1,
/* iArg: */ 0 },
#endif
@@ -242,7 +243,7 @@ static const PragmaName aPragmaName[] = {
#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
{/* zName: */ "defer_foreign_keys",
/* ePragTyp: */ PragTyp_FLAG,
/* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns,
/* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
/* ColNames: */ 0, 0,
/* iArg: */ SQLITE_DeferFKs },
#endif
@@ -250,14 +251,14 @@ static const PragmaName aPragmaName[] = {
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
{/* zName: */ "empty_result_callbacks",
/* ePragTyp: */ PragTyp_FLAG,
/* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns,
/* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
/* ColNames: */ 0, 0,
/* iArg: */ SQLITE_NullCallback },
#endif
#if !defined(SQLITE_OMIT_UTF16)
{/* zName: */ "encoding",
/* ePragTyp: */ PragTyp_ENCODING,
/* ePragFlg: */ PragFlg_Result0,
/* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
/* ColNames: */ 0, 0,
/* iArg: */ 0 },
#endif
@@ -279,7 +280,7 @@ static const PragmaName aPragmaName[] = {
#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
{/* zName: */ "foreign_keys",
/* ePragTyp: */ PragTyp_FLAG,
/* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns,
/* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
/* ColNames: */ 0, 0,
/* iArg: */ SQLITE_ForeignKeys },
#endif
@@ -287,19 +288,19 @@ static const PragmaName aPragmaName[] = {
#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
{/* zName: */ "freelist_count",
/* ePragTyp: */ PragTyp_HEADER_VALUE,
/* ePragFlg: */ PragFlg_Result0|PragFlg_ReadOnly,
/* ePragFlg: */ PragFlg_ReadOnly|PragFlg_Result0,
/* ColNames: */ 0, 0,
/* iArg: */ BTREE_FREE_PAGE_COUNT },
#endif
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
{/* zName: */ "full_column_names",
/* ePragTyp: */ PragTyp_FLAG,
/* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns,
/* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
/* ColNames: */ 0, 0,
/* iArg: */ SQLITE_FullColNames },
{/* zName: */ "fullfsync",
/* ePragTyp: */ PragTyp_FLAG,
/* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns,
/* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
/* ColNames: */ 0, 0,
/* iArg: */ SQLITE_FullFSync },
#endif
@@ -319,7 +320,7 @@ static const PragmaName aPragmaName[] = {
#if !defined(SQLITE_OMIT_CHECK)
{/* zName: */ "ignore_check_constraints",
/* ePragTyp: */ PragTyp_FLAG,
/* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns,
/* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
/* ColNames: */ 0, 0,
/* iArg: */ SQLITE_IgnoreChecks },
#endif
@@ -377,14 +378,14 @@ static const PragmaName aPragmaName[] = {
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
{/* zName: */ "legacy_file_format",
/* ePragTyp: */ PragTyp_FLAG,
/* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns,
/* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
/* ColNames: */ 0, 0,
/* iArg: */ SQLITE_LegacyFileFmt },
#endif
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && SQLITE_ENABLE_LOCKING_STYLE
{/* zName: */ "lock_proxy_file",
/* ePragTyp: */ PragTyp_LOCK_PROXY_FILE,
/* ePragFlg: */ 0,
/* ePragFlg: */ PragFlg_NoColumns1,
/* ColNames: */ 0, 0,
/* iArg: */ 0 },
#endif
@@ -418,7 +419,7 @@ static const PragmaName aPragmaName[] = {
/* iArg: */ 0 },
{/* zName: */ "page_size",
/* ePragTyp: */ PragTyp_PAGE_SIZE,
/* ePragFlg: */ PragFlg_Result0|PragFlg_SchemaReq,
/* ePragFlg: */ PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1,
/* ColNames: */ 0, 0,
/* iArg: */ 0 },
#endif
@@ -432,7 +433,7 @@ static const PragmaName aPragmaName[] = {
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
{/* zName: */ "query_only",
/* ePragTyp: */ PragTyp_FLAG,
/* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns,
/* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
/* ColNames: */ 0, 0,
/* iArg: */ SQLITE_QueryOnly },
#endif
@@ -446,12 +447,12 @@ static const PragmaName aPragmaName[] = {
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
{/* zName: */ "read_uncommitted",
/* ePragTyp: */ PragTyp_FLAG,
/* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns,
/* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
/* ColNames: */ 0, 0,
/* iArg: */ SQLITE_ReadUncommitted },
{/* zName: */ "recursive_triggers",
/* ePragTyp: */ PragTyp_FLAG,
/* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns,
/* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
/* ColNames: */ 0, 0,
/* iArg: */ SQLITE_RecTriggers },
#endif
@@ -465,14 +466,14 @@ static const PragmaName aPragmaName[] = {
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
{/* zName: */ "reverse_unordered_selects",
/* ePragTyp: */ PragTyp_FLAG,
/* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns,
/* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
/* ColNames: */ 0, 0,
/* iArg: */ SQLITE_ReverseOrder },
#endif
#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
{/* zName: */ "schema_version",
/* ePragTyp: */ PragTyp_HEADER_VALUE,
/* ePragFlg: */ PragFlg_Result0,
/* ePragFlg: */ PragFlg_NoColumns1|PragFlg_Result0,
/* ColNames: */ 0, 0,
/* iArg: */ BTREE_SCHEMA_VERSION },
#endif
@@ -486,13 +487,13 @@ static const PragmaName aPragmaName[] = {
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
{/* zName: */ "short_column_names",
/* ePragTyp: */ PragTyp_FLAG,
/* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns,
/* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
/* ColNames: */ 0, 0,
/* iArg: */ SQLITE_ShortColNames },
#endif
{/* zName: */ "shrink_memory",
/* ePragTyp: */ PragTyp_SHRINK_MEMORY,
/* ePragFlg: */ 0,
/* ePragFlg: */ PragFlg_NoColumns,
/* ColNames: */ 0, 0,
/* iArg: */ 0 },
{/* zName: */ "soft_heap_limit",
@@ -504,7 +505,7 @@ static const PragmaName aPragmaName[] = {
#if defined(SQLITE_DEBUG)
{/* zName: */ "sql_trace",
/* ePragTyp: */ PragTyp_FLAG,
/* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns,
/* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
/* ColNames: */ 0, 0,
/* iArg: */ SQLITE_SqlTrace },
#endif
@@ -519,7 +520,7 @@ static const PragmaName aPragmaName[] = {
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
{/* zName: */ "synchronous",
/* ePragTyp: */ PragTyp_SYNCHRONOUS,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1,
/* ColNames: */ 0, 0,
/* iArg: */ 0 },
#endif
@@ -533,12 +534,12 @@ static const PragmaName aPragmaName[] = {
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
{/* zName: */ "temp_store",
/* ePragTyp: */ PragTyp_TEMP_STORE,
/* ePragFlg: */ PragFlg_Result0,
/* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
/* ColNames: */ 0, 0,
/* iArg: */ 0 },
{/* zName: */ "temp_store_directory",
/* ePragTyp: */ PragTyp_TEMP_STORE_DIRECTORY,
/* ePragFlg: */ 0,
/* ePragFlg: */ PragFlg_NoColumns1,
/* ColNames: */ 0, 0,
/* iArg: */ 0 },
#endif
@@ -550,7 +551,7 @@ static const PragmaName aPragmaName[] = {
#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
{/* zName: */ "user_version",
/* ePragTyp: */ PragTyp_HEADER_VALUE,
/* ePragFlg: */ PragFlg_Result0,
/* ePragFlg: */ PragFlg_NoColumns1|PragFlg_Result0,
/* ColNames: */ 0, 0,
/* iArg: */ BTREE_USER_VERSION },
#endif
@@ -558,27 +559,27 @@ static const PragmaName aPragmaName[] = {
#if defined(SQLITE_DEBUG)
{/* zName: */ "vdbe_addoptrace",
/* ePragTyp: */ PragTyp_FLAG,
/* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns,
/* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
/* ColNames: */ 0, 0,
/* iArg: */ SQLITE_VdbeAddopTrace },
{/* zName: */ "vdbe_debug",
/* ePragTyp: */ PragTyp_FLAG,
/* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns,
/* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
/* ColNames: */ 0, 0,
/* iArg: */ SQLITE_SqlTrace|SQLITE_VdbeListing|SQLITE_VdbeTrace },
{/* zName: */ "vdbe_eqp",
/* ePragTyp: */ PragTyp_FLAG,
/* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns,
/* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
/* ColNames: */ 0, 0,
/* iArg: */ SQLITE_VdbeEQP },
{/* zName: */ "vdbe_listing",
/* ePragTyp: */ PragTyp_FLAG,
/* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns,
/* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
/* ColNames: */ 0, 0,
/* iArg: */ SQLITE_VdbeListing },
{/* zName: */ "vdbe_trace",
/* ePragTyp: */ PragTyp_FLAG,
/* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns,
/* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
/* ColNames: */ 0, 0,
/* iArg: */ SQLITE_VdbeTrace },
#endif
@@ -598,7 +599,7 @@ static const PragmaName aPragmaName[] = {
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
{/* zName: */ "writable_schema",
/* ePragTyp: */ PragTyp_FLAG,
/* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns,
/* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
/* ColNames: */ 0, 0,
/* iArg: */ SQLITE_WriteSchema|SQLITE_RecoveryMode },
#endif
-2
View File
@@ -15,8 +15,6 @@
** table and column.
*/
#include "sqliteInt.h"
#include <stdlib.h>
#include <string.h>
/*
** Walk the expression tree pExpr and increase the aggregate function
+4 -3
View File
@@ -657,6 +657,7 @@ static void codeDistinct(
sqlite3VdbeAddOp4Int(v, OP_Found, iTab, addrRepeat, iMem, N); VdbeCoverage(v);
sqlite3VdbeAddOp3(v, OP_MakeRecord, iMem, N, r1);
sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iTab, r1, iMem, N);
sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
sqlite3ReleaseTempReg(pParse, r1);
}
@@ -742,8 +743,7 @@ static void selectInnerLoop(
}else{
ecelFlags = 0;
}
assert( eDest!=SRT_Table || pSort==0 );
if( pSort && hasDistinct==0 && eDest!=SRT_EphemTab ){
if( pSort && hasDistinct==0 && eDest!=SRT_EphemTab && eDest!=SRT_Table ){
/* For each expression in pEList that is a copy of an expression in
** the ORDER BY clause (pSort->pOrderBy), set the associated
** iOrderByCol value to one more than the index of the ORDER BY
@@ -1285,6 +1285,7 @@ static void generateSortTail(
VdbeComment((v, "%s", aOutEx[i].zName ? aOutEx[i].zName : aOutEx[i].zSpan));
}
switch( eDest ){
case SRT_Table:
case SRT_EphemTab: {
sqlite3VdbeAddOp2(v, OP_NewRowid, iParm, regRowid);
sqlite3VdbeAddOp3(v, OP_Insert, iParm, regRow, regRowid);
@@ -5651,7 +5652,7 @@ int sqlite3Select(
** of output.
*/
resetAccumulator(pParse, &sAggInfo);
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pMinMax,0,flag,0);
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pMinMax, 0,flag,0);
if( pWInfo==0 ){
sqlite3ExprListDelete(db, pDel);
goto select_end;
+6 -1
View File
@@ -4288,15 +4288,20 @@ static int do_meta_command(char *zLine, ShellState *p){
int c2 = zMode[0];
if( c2=='l' && n2>2 && strncmp(azArg[1],"lines",n2)==0 ){
p->mode = MODE_Line;
sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
}else if( c2=='c' && strncmp(azArg[1],"columns",n2)==0 ){
p->mode = MODE_Column;
sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
}else if( c2=='l' && n2>2 && strncmp(azArg[1],"list",n2)==0 ){
p->mode = MODE_List;
sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Column);
sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
}else if( c2=='h' && strncmp(azArg[1],"html",n2)==0 ){
p->mode = MODE_Html;
}else if( c2=='t' && strncmp(azArg[1],"tcl",n2)==0 ){
p->mode = MODE_Tcl;
sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Space);
sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
}else if( c2=='c' && strncmp(azArg[1],"csv",n2)==0 ){
p->mode = MODE_Csv;
sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma);
@@ -5297,7 +5302,7 @@ static int do_meta_command(char *zLine, ShellState *p){
if( c=='v' && strncmp(azArg[0], "vfsinfo", n)==0 ){
const char *zDbName = nArg==2 ? azArg[1] : "main";
sqlite3_vfs *pVfs;
sqlite3_vfs *pVfs = 0;
if( p->db ){
sqlite3_file_control(p->db, zDbName, SQLITE_FCNTL_VFS_POINTER, &pVfs);
if( pVfs ){
+28 -7
View File
@@ -259,7 +259,11 @@ typedef struct sqlite3 sqlite3;
*/
#ifdef SQLITE_INT64_TYPE
typedef SQLITE_INT64_TYPE sqlite_int64;
typedef unsigned SQLITE_INT64_TYPE sqlite_uint64;
# ifdef SQLITE_UINT64_TYPE
typedef SQLITE_UINT64_TYPE sqlite_uint64;
# else
typedef unsigned SQLITE_INT64_TYPE sqlite_uint64;
# endif
#elif defined(_MSC_VER) || defined(__BORLANDC__)
typedef __int64 sqlite_int64;
typedef unsigned __int64 sqlite_uint64;
@@ -572,7 +576,7 @@ int sqlite3_exec(
** file that were written at the application level might have changed
** and that adjacent bytes, even bytes within the same sector are
** guaranteed to be unchanged. The SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN
** flag indicate that a file cannot be deleted when open. The
** flag indicates that a file cannot be deleted when open. The
** SQLITE_IOCAP_IMMUTABLE flag indicates that the file is on
** read-only media and cannot be changed even by processes with
** elevated privileges.
@@ -722,6 +726,9 @@ struct sqlite3_file {
** <li> [SQLITE_IOCAP_ATOMIC64K]
** <li> [SQLITE_IOCAP_SAFE_APPEND]
** <li> [SQLITE_IOCAP_SEQUENTIAL]
** <li> [SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN]
** <li> [SQLITE_IOCAP_POWERSAFE_OVERWRITE]
** <li> [SQLITE_IOCAP_IMMUTABLE]
** </ul>
**
** The SQLITE_IOCAP_ATOMIC property means that all writes of
@@ -3896,8 +3903,12 @@ int sqlite3_clear_bindings(sqlite3_stmt*);
** METHOD: sqlite3_stmt
**
** ^Return the number of columns in the result set returned by the
** [prepared statement]. ^This routine returns 0 if pStmt is an SQL
** statement that does not return data (for example an [UPDATE]).
** [prepared statement]. ^If this routine returns 0, that means the
** [prepared statement] returns no data (for example an [UPDATE]).
** ^However, just because this routine returns a positive number does not
** mean that one or more rows of data will be returned. ^A SELECT statement
** will always have a positive sqlite3_column_count() but depending on the
** WHERE clause constraints and the table content, it might return no rows.
**
** See also: [sqlite3_data_count()]
*/
@@ -5406,7 +5417,7 @@ void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*);
** ^The update hook is not invoked when [WITHOUT ROWID] tables are modified.
**
** ^In the current implementation, the update hook
** is not invoked when duplication rows are deleted because of an
** is not invoked when conflicting rows are deleted because of an
** [ON CONFLICT | ON CONFLICT REPLACE] clause. ^Nor is the update hook
** invoked when rows are deleted using the [truncate optimization].
** The exceptions defined in this paragraph might change in a future
@@ -6188,6 +6199,12 @@ typedef struct sqlite3_blob sqlite3_blob;
** [database connection] error code and message accessible via
** [sqlite3_errcode()] and [sqlite3_errmsg()] and related functions.
**
** A BLOB referenced by sqlite3_blob_open() may be read using the
** [sqlite3_blob_read()] interface and modified by using
** [sqlite3_blob_write()]. The [BLOB handle] can be moved to a
** different row of the same table using the [sqlite3_blob_reopen()]
** interface. However, the column, table, or database of a [BLOB handle]
** cannot be changed after the [BLOB handle] is opened.
**
** ^(If the row that a BLOB handle points to is modified by an
** [UPDATE], [DELETE], or by [ON CONFLICT] side-effects
@@ -6211,6 +6228,10 @@ typedef struct sqlite3_blob sqlite3_blob;
**
** To avoid a resource leak, every open [BLOB handle] should eventually
** be released by a call to [sqlite3_blob_close()].
**
** See also: [sqlite3_blob_close()],
** [sqlite3_blob_reopen()], [sqlite3_blob_read()],
** [sqlite3_blob_bytes()], [sqlite3_blob_write()].
*/
int sqlite3_blob_open(
sqlite3*,
@@ -6226,11 +6247,11 @@ int sqlite3_blob_open(
** CAPI3REF: Move a BLOB Handle to a New Row
** METHOD: sqlite3_blob
**
** ^This function is used to move an existing blob handle so that it points
** ^This function is used to move an existing [BLOB handle] so that it points
** to a different row of the same database table. ^The new row is identified
** by the rowid value passed as the second argument. Only the row can be
** changed. ^The database, table and column on which the blob handle is open
** remain the same. Moving an existing blob handle to a new row can be
** remain the same. Moving an existing [BLOB handle] to a new row is
** faster than closing the existing handle and opening a new one.
**
** ^(The new row must meet the same criteria as for [sqlite3_blob_open()] -
+27 -7
View File
@@ -111,7 +111,7 @@
#endif
/* What version of CLANG is being used. 0 means CLANG is not being used */
#ifdef __clang__
#if defined(__clang__) && !defined(_WIN32)
# define CLANG_VERSION \
(__clang_major__*1000000+__clang_minor__*1000+__clang_patchlevel__)
#else
@@ -511,6 +511,18 @@
#include <assert.h>
#include <stddef.h>
/*
** Use a macro to replace memcpy() if compiled with SQLITE_INLINE_MEMCPY.
** This allows better measurements of where memcpy() is used when running
** cachegrind. But this macro version of memcpy() is very slow so it
** should not be used in production. This is a performance measurement
** hack only.
*/
#ifdef SQLITE_INLINE_MEMCPY
# define memcpy(D,S,N) {char*xxd=(char*)(D);const char*xxs=(const char*)(S);\
int xxn=(N);while(xxn-->0)*(xxd++)=*(xxs++);}
#endif
/*
** If compiling for a processor that lacks floating point support,
** substitute integer for floating-point
@@ -2580,7 +2592,7 @@ struct SrcList {
#define WHERE_SORTBYGROUP 0x0200 /* Support sqlite3WhereIsSorted() */
#define WHERE_SEEK_TABLE 0x0400 /* Do not defer seeks on main table */
#define WHERE_ORDERBY_LIMIT 0x0800 /* ORDERBY+LIMIT on the inner loop */
/* 0x1000 not currently used */
#define WHERE_SEEK_UNIQ_TABLE 0x1000 /* Do not defer seeks if unique */
/* 0x2000 not currently used */
#define WHERE_USE_LIMIT 0x4000 /* Use the LIMIT in cost estimates */
/* 0x8000 not currently used */
@@ -3041,7 +3053,7 @@ struct AuthContext {
#define OPFLAG_NCHANGE 0x01 /* OP_Insert: Set to update db->nChange */
/* Also used in P2 (not P5) of OP_Delete */
#define OPFLAG_EPHEM 0x01 /* OP_Column: Ephemeral output is ok */
#define OPFLAG_LASTROWID 0x02 /* Set to update db->lastRowid */
#define OPFLAG_LASTROWID 0x20 /* Set to update db->lastRowid */
#define OPFLAG_ISUPDATE 0x04 /* This OP_Insert is an sql UPDATE */
#define OPFLAG_APPEND 0x08 /* This is likely to be an append */
#define OPFLAG_USESEEKRESULT 0x10 /* Try to avoid a seek in BtreeInsert() */
@@ -3055,7 +3067,7 @@ struct AuthContext {
#define OPFLAG_FORDELETE 0x08 /* OP_Open should use BTREE_FORDELETE */
#define OPFLAG_P2ISREG 0x10 /* P2 to OP_Open** is a register number */
#define OPFLAG_PERMUTE 0x01 /* OP_Compare: use the permutation */
#define OPFLAG_SAVEPOSITION 0x02 /* OP_Delete: keep cursor position */
#define OPFLAG_SAVEPOSITION 0x02 /* OP_Delete/Insert: save cursor pos */
#define OPFLAG_AUXDELETE 0x04 /* OP_Delete: index in a DELETE op */
/*
@@ -3716,7 +3728,7 @@ void sqlite3ExprCacheAffinityChange(Parse*, int, int);
void sqlite3ExprCode(Parse*, Expr*, int);
void sqlite3ExprCodeCopy(Parse*, Expr*, int);
void sqlite3ExprCodeFactorable(Parse*, Expr*, int);
void sqlite3ExprCodeAtInit(Parse*, Expr*, int, u8);
int sqlite3ExprCodeAtInit(Parse*, Expr*, int);
int sqlite3ExprCodeTemp(Parse*, Expr*, int*);
int sqlite3ExprCodeTarget(Parse*, Expr*, int);
void sqlite3ExprCodeAndCache(Parse*, Expr*, int);
@@ -3778,6 +3790,11 @@ int sqlite3GenerateIndexKey(Parse*, Index*, int, int, int, int*,Index*,int);
void sqlite3ResolvePartIdxLabel(Parse*,int);
void sqlite3GenerateConstraintChecks(Parse*,Table*,int*,int,int,int,int,
u8,u8,int,int*,int*);
#ifdef SQLITE_ENABLE_NULL_TRIM
void sqlite3SetMakeRecordP5(Vdbe*,Table*);
#else
# define sqlite3SetMakeRecordP5(A,B)
#endif
void sqlite3CompleteInsertion(Parse*,Table*,int,int,int,int*,int,int,int);
int sqlite3OpenTableAndIndices(Parse*, Table*, int, u8, int, u8*, int*, int*);
void sqlite3BeginWriteOperation(Parse*, int, int);
@@ -4056,8 +4073,10 @@ char sqlite3IndexColumnAffinity(sqlite3*, Index*, int);
/*
** The interface to the LEMON-generated parser
*/
void *sqlite3ParserAlloc(void*(*)(u64));
void sqlite3ParserFree(void*, void(*)(void*));
#ifndef SQLITE_AMALGAMATION
void *sqlite3ParserAlloc(void*(*)(u64));
void sqlite3ParserFree(void*, void(*)(void*));
#endif
void sqlite3Parser(void*, int, Token, Parse*);
#ifdef YYTRACKMAXSTACKDEPTH
int sqlite3ParserStackPeak(void*);
@@ -4167,6 +4186,7 @@ const char *sqlite3JournalModename(int);
#define sqlite3FkDropTable(a,b,c)
#define sqlite3FkOldmask(a,b) 0
#define sqlite3FkRequired(a,b,c,d) 0
#define sqlite3FkReferences(a) 0
#endif
#ifndef SQLITE_OMIT_FOREIGN_KEY
void sqlite3FkDelete(sqlite3 *, Table*);
-2
View File
@@ -17,8 +17,6 @@
** if they are not used.
*/
#include "sqliteInt.h"
#include <stdlib.h>
#include <string.h>
#ifndef SQLITE_OMIT_GET_TABLE
+4 -4
View File
@@ -2307,7 +2307,7 @@ static int SQLITE_TCLAPI DbObjCmd(
}
in = fopen(zFile, "rb");
if( in==0 ){
Tcl_AppendResult(interp, "Error: cannot open file: ", zFile, NULL);
Tcl_AppendResult(interp, "Error: cannot open file: ", zFile, (char*)0);
sqlite3_finalize(pStmt);
return TCL_ERROR;
}
@@ -2536,7 +2536,7 @@ static int SQLITE_TCLAPI DbObjCmd(
int n = strlen30(z);
if( n>2 && strncmp(z, "-argcount",n)==0 ){
if( i==(objc-2) ){
Tcl_AppendResult(interp, "option requires an argument: ", z, 0);
Tcl_AppendResult(interp, "option requires an argument: ", z,(char*)0);
return TCL_ERROR;
}
if( Tcl_GetIntFromObj(interp, objv[i+1], &nArg) ) return TCL_ERROR;
@@ -2551,7 +2551,7 @@ static int SQLITE_TCLAPI DbObjCmd(
flags |= SQLITE_DETERMINISTIC;
}else{
Tcl_AppendResult(interp, "bad option \"", z,
"\": must be -argcount or -deterministic", 0
"\": must be -argcount or -deterministic", (char*)0
);
return TCL_ERROR;
}
@@ -3208,7 +3208,7 @@ static int SQLITE_TCLAPI DbObjCmd(
pObj = Tcl_NewStringObj((char*)sqlite3_value_text(pValue), -1);
Tcl_SetObjResult(interp, pObj);
}else{
Tcl_AppendResult(interp, sqlite3_errmsg(pDb->db), 0);
Tcl_AppendResult(interp, sqlite3_errmsg(pDb->db), (char*)0);
return TCL_ERROR;
}
}
+1 -1
View File
@@ -80,7 +80,7 @@ static int sqlite3DeleteUnlinkIfExists(const char *zFile, int *pbExists){
** Delete the database file identified by the string argument passed to this
** function. The string must contain a filename, not an SQLite URI.
*/
int sqlite3_delete_database(
SQLITE_API int sqlite3_delete_database(
const char *zFile /* File to delete */
){
char *zBuf; /* Buffer to sprintf() filenames to */
+3 -3
View File
@@ -313,7 +313,7 @@ static void sqllogCopydb(struct SLConn *p, const char *zSearch, int bLog){
/* Generate a file-name to use for the copy of this database */
iDb = sqllogglobal.iNextDb++;
zInit = sqlite3_mprintf("%s_%d.db", sqllogglobal.zPrefix, iDb);
zInit = sqlite3_mprintf("%s_%02d.db", sqllogglobal.zPrefix, iDb);
/* Create the backup */
assert( sqllogglobal.bRec==0 );
@@ -376,7 +376,7 @@ static void sqllogOpenlog(struct SLConn *p){
char *zVar = getenv(ENVIRONMENT_VARIABLE1_NAME);
if( zVar==0 || strlen(zVar)+10>=(sizeof(sqllogglobal.zPrefix)) ) return;
sqlite3_snprintf(sizeof(sqllogglobal.zPrefix), sqllogglobal.zPrefix,
"%s/sqllog_%d", zVar, getProcessId());
"%s/sqllog_%05d", zVar, getProcessId());
sqlite3_snprintf(sizeof(sqllogglobal.zIdx), sqllogglobal.zIdx,
"%s.idx", sqllogglobal.zPrefix);
if( getenv(ENVIRONMENT_VARIABLE2_NAME) ){
@@ -387,7 +387,7 @@ static void sqllogOpenlog(struct SLConn *p){
}
/* Open the log file */
zLog = sqlite3_mprintf("%s_%d.sql", sqllogglobal.zPrefix, p->iLog);
zLog = sqlite3_mprintf("%s_%05d.sql", sqllogglobal.zPrefix, p->iLog);
p->fd = fopen(zLog, "w");
sqlite3_free(zLog);
if( p->fd==0 ){
+15 -8
View File
@@ -63,6 +63,7 @@ LPDIR opendir(
dirname = windirent_getenv("SystemDrive");
}
memset(&data, 0, sizeof(struct _finddata_t));
_snprintf(data.name, namesize, "%s\\*", dirname);
dirp->d_handle = _findfirst(data.name, &data);
@@ -71,12 +72,18 @@ LPDIR opendir(
return NULL;
}
/* TODO: Remove this block to allow hidden and system files. */
if( data.attrib&_A_HIDDEN || data.attrib&_A_SYSTEM ){
/* TODO: Remove this block to allow hidden and/or system files. */
if( is_filtered(data) ){
next:
memset(&data, 0, sizeof(struct _finddata_t));
if( _findnext(dirp->d_handle, &data)==-1 ){
closedir(dirp);
return NULL;
}
/* TODO: Remove this block to allow hidden and/or system files. */
if( is_filtered(data) ) goto next;
}
dirp->d_first.d_attributes = data.attrib;
@@ -105,11 +112,11 @@ LPDIRENT readdir(
next:
memset(&data, 0, sizeof(struct _finddata_t));
if( _findnext(dirp->d_handle, &data)==-1 ) return NULL;
/* TODO: Remove this block to allow hidden and system files. */
if( data.attrib&_A_HIDDEN ) goto next;
if( data.attrib&_A_SYSTEM ) goto next;
/* TODO: Remove this block to allow hidden and/or system files. */
if( is_filtered(data) ) goto next;
dirp->d_next.d_ino++;
dirp->d_next.d_attributes = data.attrib;
@@ -146,14 +153,14 @@ INT readdir_r(
next:
memset(&data, 0, sizeof(struct _finddata_t));
if( _findnext(dirp->d_handle, &data)==-1 ){
*result = NULL;
return ENOENT;
}
/* TODO: Remove this block to allow hidden and system files. */
if( data.attrib&_A_HIDDEN ) goto next;
if( data.attrib&_A_SYSTEM ) goto next;
/* TODO: Remove this block to allow hidden and/or system files. */
if( is_filtered(data) ) goto next;
entry->d_ino = (ino_t)-1; /* not available */
entry->d_attributes = data.attrib;
+11
View File
@@ -92,6 +92,17 @@ struct DIR {
DIRENT d_next; /* DIRENT constructed based on "_findnext". */
};
/*
** Provide a macro, for use by the implementation, to determine if a
** particular directory entry should be skipped over when searching for
** the next directory entry that should be returned by the readdir() or
** readdir_r() functions.
*/
#ifndef is_filtered
# define is_filtered(a) ((((a).attrib)&_A_HIDDEN) || (((a).attrib)&_A_SYSTEM))
#endif
/*
** Provide the function prototype for the POSIX compatiable getenv()
** function. This function is not thread-safe.
+12
View File
@@ -481,6 +481,9 @@ int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){
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 */
#endif
assert( zSql!=0 );
mxSqlLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH];
@@ -492,11 +495,16 @@ int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){
i = 0;
assert( pzErrMsg!=0 );
/* sqlite3ParserTrace(stdout, "parser: "); */
#ifdef sqlite3Parser_ENGINEALWAYSONSTACK
pEngine = zSpace;
sqlite3ParserInit(pEngine);
#else
pEngine = sqlite3ParserAlloc(sqlite3Malloc);
if( pEngine==0 ){
sqlite3OomFault(db);
return SQLITE_NOMEM_BKPT;
}
#endif
assert( pParse->pNewTable==0 );
assert( pParse->pNewTrigger==0 );
assert( pParse->nVar==0 );
@@ -548,7 +556,11 @@ int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){
);
sqlite3_mutex_leave(sqlite3MallocMutex());
#endif /* YYDEBUG */
#ifdef sqlite3Parser_ENGINEALWAYSONSTACK
sqlite3ParserFinalize(pEngine);
#else
sqlite3ParserFree(pEngine, sqlite3_free);
#endif
if( db->mallocFailed ){
pParse->rc = SQLITE_NOMEM_BKPT;
}
+113 -69
View File
@@ -71,12 +71,12 @@ void sqlite3ColumnDefault(Vdbe *v, Table *pTab, int i, int iReg){
if( pValue ){
sqlite3VdbeAppendP4(v, pValue, P4_MEM);
}
#ifndef SQLITE_OMIT_FLOATING_POINT
if( pTab->aCol[i].affinity==SQLITE_AFF_REAL ){
sqlite3VdbeAddOp1(v, OP_RealAffinity, iReg);
}
#endif
}
#ifndef SQLITE_OMIT_FLOATING_POINT
if( pTab->aCol[i].affinity==SQLITE_AFF_REAL ){
sqlite3VdbeAddOp1(v, OP_RealAffinity, iReg);
}
#endif
}
/*
@@ -105,7 +105,7 @@ void sqlite3Update(
int iDataCur; /* Cursor for the canonical data btree */
int iIdxCur; /* Cursor for the first index */
sqlite3 *db; /* The database structure */
int *aRegIdx = 0; /* One register assigned to each index to be updated */
int *aRegIdx = 0; /* First register in array assigned to each index */
int *aXRef = 0; /* aXRef[i] is the index in pChanges->a[] of the
** an expression for the i-th column of the table.
** aXRef[i]==-1 if the i-th column is not changed. */
@@ -117,10 +117,11 @@ void sqlite3Update(
AuthContext sContext; /* The authorization context */
NameContext sNC; /* The name-context to resolve expressions in */
int iDb; /* Database containing the table being updated */
int okOnePass; /* True for one-pass algorithm without the FIFO */
int eOnePass; /* ONEPASS_XXX value from where.c */
int hasFK; /* True if foreign key processing is required */
int labelBreak; /* Jump here to break out of UPDATE loop */
int labelContinue; /* Jump here to continue next step of UPDATE loop */
int flags; /* Flags for sqlite3WhereBegin() */
#ifndef SQLITE_OMIT_TRIGGER
int isView; /* True when updating a view (INSTEAD OF trigger) */
@@ -131,6 +132,10 @@ void sqlite3Update(
int iEph = 0; /* Ephemeral table holding all primary key values */
int nKey = 0; /* Number of elements in regKey for WITHOUT ROWID */
int aiCurOnePass[2]; /* The write cursors opened by WHERE_ONEPASS */
int addrOpen = 0; /* Address of OP_OpenEphemeral */
int iPk = 0; /* First of nPk cells holding PRIMARY KEY value */
i16 nPk = 0; /* Number of components of the PRIMARY KEY */
int bReplace = 0; /* True if REPLACE conflict resolution might happen */
/* Register Allocations */
int regRowCount = 0; /* A count of rows changed */
@@ -290,6 +295,11 @@ void sqlite3Update(
if( iIdxCol<0 || aXRef[iIdxCol]>=0 ){
reg = ++pParse->nMem;
pParse->nMem += pIdx->nColumn;
if( (onError==OE_Replace)
|| (onError==OE_Default && pIdx->onError==OE_Replace)
){
bReplace = 1;
}
break;
}
}
@@ -297,6 +307,11 @@ void sqlite3Update(
if( reg==0 ) aToOpen[j+1] = 0;
aRegIdx[j] = reg;
}
if( bReplace ){
/* If REPLACE conflict resolution might be invoked, open cursors on all
** indexes in case they are needed to delete records. */
memset(aToOpen, 1, nIdx+1);
}
/* Begin generating code. */
v = sqlite3GetVdbe(pParse);
@@ -349,51 +364,79 @@ void sqlite3Update(
}
#endif
/* Begin the database scan
*/
/* Initialize the count of updated rows */
if( (db->flags & SQLITE_CountRows) && !pParse->pTriggerTab ){
regRowCount = ++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_Integer, 0, regRowCount);
}
if( HasRowid(pTab) ){
sqlite3VdbeAddOp3(v, OP_Null, 0, regRowSet, regOldRowid);
pWInfo = sqlite3WhereBegin(
pParse, pTabList, pWhere, 0, 0,
WHERE_ONEPASS_DESIRED | WHERE_SEEK_TABLE, iIdxCur
);
if( pWInfo==0 ) goto update_cleanup;
okOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass);
/* Remember the rowid of every item to be updated.
*/
sqlite3VdbeAddOp2(v, OP_Rowid, iDataCur, regOldRowid);
if( !okOnePass ){
sqlite3VdbeAddOp2(v, OP_RowSetAdd, regRowSet, regOldRowid);
}
/* End the database scan loop.
*/
sqlite3WhereEnd(pWInfo);
}else{
int iPk; /* First of nPk memory cells holding PRIMARY KEY value */
i16 nPk; /* Number of components of the PRIMARY KEY */
int addrOpen; /* Address of the OpenEphemeral instruction */
assert( pPk!=0 );
nPk = pPk->nKeyCol;
iPk = pParse->nMem+1;
pParse->nMem += nPk;
regKey = ++pParse->nMem;
iEph = pParse->nTab++;
sqlite3VdbeAddOp2(v, OP_Null, 0, iPk);
addrOpen = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iEph, nPk);
sqlite3VdbeSetP4KeyInfo(pParse, pPk);
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0,
WHERE_ONEPASS_DESIRED, iIdxCur);
if( pWInfo==0 ) goto update_cleanup;
okOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass);
}
/* Begin the database scan.
**
** Do not consider a single-pass strategy for a multi-row update if
** there are any triggers or foreign keys to process, or rows may
** be deleted as a result of REPLACE conflict handling. Any of these
** things might disturb a cursor being used to scan through the table
** or index, causing a single-pass approach to malfunction. */
flags = WHERE_ONEPASS_DESIRED|WHERE_SEEK_UNIQ_TABLE;
if( !pParse->nested && !pTrigger && !hasFK && !chngKey && !bReplace ){
flags |= WHERE_ONEPASS_MULTIROW;
}
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0, flags, iIdxCur);
if( pWInfo==0 ) goto update_cleanup;
/* A one-pass strategy that might update more than one row may not
** be used if any column of the index used for the scan is being
** updated. Otherwise, if there is an index on "b", statements like
** the following could create an infinite loop:
**
** UPDATE t1 SET b=b+1 WHERE b>?
**
** Fall back to ONEPASS_OFF if where.c has selected a ONEPASS_MULTI
** strategy that uses an index for which one or more columns are being
** updated. */
eOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass);
if( eOnePass==ONEPASS_MULTI ){
int iCur = aiCurOnePass[1];
if( iCur>=0 && iCur!=iDataCur && aToOpen[iCur-iBaseCur] ){
eOnePass = ONEPASS_OFF;
}
assert( iCur!=iDataCur || !HasRowid(pTab) );
}
if( HasRowid(pTab) ){
/* Read the rowid of the current row of the WHERE scan. In ONEPASS_OFF
** mode, write the rowid into the FIFO. In either of the one-pass modes,
** leave it in register regOldRowid. */
sqlite3VdbeAddOp2(v, OP_Rowid, iDataCur, regOldRowid);
if( eOnePass==ONEPASS_OFF ){
sqlite3VdbeAddOp2(v, OP_RowSetAdd, regRowSet, regOldRowid);
}
}else{
/* Read the PK of the current row into an array of registers. In
** ONEPASS_OFF mode, serialize the array into a record and store it in
** the ephemeral table. Or, in ONEPASS_SINGLE or MULTI mode, change
** the OP_OpenEphemeral instruction to a Noop (the ephemeral table
** is not required) and leave the PK fields in the array of registers. */
for(i=0; i<nPk; i++){
assert( pPk->aiColumn[i]>=0 );
sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, pPk->aiColumn[i],
iPk+i);
sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur,pPk->aiColumn[i],iPk+i);
}
if( okOnePass ){
if( eOnePass ){
sqlite3VdbeChangeToNoop(v, addrOpen);
nKey = nPk;
regKey = iPk;
@@ -402,50 +445,42 @@ void sqlite3Update(
sqlite3IndexAffinityStr(db, pPk), nPk);
sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iEph, regKey, iPk, nPk);
}
sqlite3WhereEnd(pWInfo);
}
/* Initialize the count of updated rows
*/
if( (db->flags & SQLITE_CountRows) && !pParse->pTriggerTab ){
regRowCount = ++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_Integer, 0, regRowCount);
if( eOnePass!=ONEPASS_MULTI ){
sqlite3WhereEnd(pWInfo);
}
labelBreak = sqlite3VdbeMakeLabel(v);
if( !isView ){
/*
** Open every index that needs updating. Note that if any
** index could potentially invoke a REPLACE conflict resolution
** action, then we need to open all indices because we might need
** to be deleting some records.
*/
if( onError==OE_Replace ){
memset(aToOpen, 1, nIdx+1);
}else{
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
if( pIdx->onError==OE_Replace ){
memset(aToOpen, 1, nIdx+1);
break;
}
}
}
if( okOnePass ){
int addrOnce = 0;
/* Open every index that needs updating. */
if( eOnePass!=ONEPASS_OFF ){
if( aiCurOnePass[0]>=0 ) aToOpen[aiCurOnePass[0]-iBaseCur] = 0;
if( aiCurOnePass[1]>=0 ) aToOpen[aiCurOnePass[1]-iBaseCur] = 0;
}
if( eOnePass==ONEPASS_MULTI && (nIdx-(aiCurOnePass[1]>=0))>0 ){
addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
}
sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, 0, iBaseCur, aToOpen,
0, 0);
if( addrOnce ) sqlite3VdbeJumpHere(v, addrOnce);
}
/* Top of the update loop */
if( okOnePass ){
if( aToOpen[iDataCur-iBaseCur] && !isView ){
if( eOnePass!=ONEPASS_OFF ){
if( !isView && aiCurOnePass[0]!=iDataCur && aiCurOnePass[1]!=iDataCur ){
assert( pPk );
sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelBreak, regKey, nKey);
VdbeCoverageNeverTaken(v);
}
labelContinue = labelBreak;
if( eOnePass==ONEPASS_SINGLE ){
labelContinue = labelBreak;
}else{
labelContinue = sqlite3VdbeMakeLabel(v);
}
sqlite3VdbeAddOp2(v, OP_IsNull, pPk ? regKey : regOldRowid, labelBreak);
VdbeCoverageIf(v, pPk==0);
VdbeCoverageIf(v, pPk!=0);
@@ -570,7 +605,6 @@ void sqlite3Update(
if( !isView ){
int addr1 = 0; /* Address of jump instruction */
int bReplace = 0; /* True if REPLACE conflict resolution might happen */
/* Do constraint checks. */
assert( regOldRowid>0 );
@@ -606,14 +640,18 @@ void sqlite3Update(
assert( regNew==regNewRowid+1 );
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
sqlite3VdbeAddOp3(v, OP_Delete, iDataCur,
OPFLAG_ISUPDATE | ((hasFK || chngKey || pPk!=0) ? 0 : OPFLAG_ISNOOP),
OPFLAG_ISUPDATE | ((hasFK || chngKey) ? 0 : OPFLAG_ISNOOP),
regNewRowid
);
if( eOnePass==ONEPASS_MULTI ){
assert( hasFK==0 && chngKey==0 );
sqlite3VdbeChangeP5(v, OPFLAG_SAVEPOSITION);
}
if( !pParse->nested ){
sqlite3VdbeAppendP4(v, pTab, P4_TABLE);
}
#else
if( hasFK || chngKey || pPk!=0 ){
if( hasFK || chngKey ){
sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, 0);
}
#endif
@@ -626,8 +664,11 @@ void sqlite3Update(
}
/* Insert the new index entries and the new record. */
sqlite3CompleteInsertion(pParse, pTab, iDataCur, iIdxCur,
regNewRowid, aRegIdx, 1, 0, 0);
sqlite3CompleteInsertion(
pParse, pTab, iDataCur, iIdxCur, regNewRowid, aRegIdx,
OPFLAG_ISUPDATE | (eOnePass==ONEPASS_MULTI ? OPFLAG_SAVEPOSITION : 0),
0, 0
);
/* Do any ON CASCADE, SET NULL or SET DEFAULT operations required to
** handle rows (possibly in other tables) that refer via a foreign key
@@ -649,8 +690,11 @@ void sqlite3Update(
/* Repeat the above with the next record to be updated, until
** all record selected by the WHERE clause have been updated.
*/
if( okOnePass ){
if( eOnePass==ONEPASS_SINGLE ){
/* Nothing to do at end-of-loop for a single-pass */
}else if( eOnePass==ONEPASS_MULTI ){
sqlite3VdbeResolveLabel(v, labelContinue);
sqlite3WhereEnd(pWInfo);
}else if( pPk ){
sqlite3VdbeResolveLabel(v, labelContinue);
sqlite3VdbeAddOp2(v, OP_Next, iEph, addrTop); VdbeCoverage(v);
+53 -31
View File
@@ -562,7 +562,7 @@ int sqlite3VdbeExec(
Vdbe *p /* The VDBE */
){
Op *aOp = p->aOp; /* Copy of p->aOp */
Op *pOp = aOp; /* Current operation */
Op *pOp; /* Current operation */
#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE)
Op *pOrigOp; /* Value of pOp at the top of the loop */
#endif
@@ -583,8 +583,6 @@ int sqlite3VdbeExec(
Mem *pIn2 = 0; /* 2nd input operand */
Mem *pIn3 = 0; /* 3rd input operand */
Mem *pOut = 0; /* Output operand */
int *aPermute = 0; /* Permutation of columns for OP_Compare */
i64 lastRowid = db->lastRowid; /* Saved value of the last insert ROWID */
#ifdef VDBE_PROFILE
u64 start; /* CPU clock count at start of opcode */
#endif
@@ -599,7 +597,6 @@ int sqlite3VdbeExec(
}
assert( p->rc==SQLITE_OK || (p->rc&0xff)==SQLITE_BUSY );
assert( p->bIsReader || p->readOnly!=0 );
p->rc = SQLITE_OK;
p->iCurrentTime = 0;
assert( p->explain==0 );
p->pResultSet = 0;
@@ -960,7 +957,6 @@ case OP_Halt: {
p->nFrame--;
sqlite3VdbeSetChanges(db, p->nChange);
pcx = sqlite3VdbeFrameRestore(pFrame);
lastRowid = db->lastRowid;
if( pOp->p2==OE_Ignore ){
/* Instruction pcx is the OP_Program that invoked the sub-program
** currently being halted. If the p2 instruction of this OP_Halt
@@ -1195,7 +1191,7 @@ case OP_Variable: { /* out2 */
if( sqlite3VdbeMemTooBig(pVar) ){
goto too_big;
}
pOut = out2Prerelease(p, pOp);
pOut = &aMem[pOp->p2];
sqlite3VdbeMemShallowCopy(pOut, pVar, MEM_Static);
UPDATE_MAX_BLOBSIZE(pOut);
break;
@@ -1682,9 +1678,7 @@ case OP_Function: {
#endif
MemSetTypeFlag(pCtx->pOut, MEM_Null);
pCtx->fErrorOrAux = 0;
db->lastRowid = lastRowid;
(*pCtx->pFunc->xSFunc)(pCtx, pCtx->argc, pCtx->argv);/* IMP: R-24505-23230 */
lastRowid = db->lastRowid; /* Remember rowid changes made by xSFunc */
/* If the function returned an error, throw an exception */
if( pCtx->fErrorOrAux ){
@@ -2140,8 +2134,8 @@ case OP_ElseNotEq: { /* same as TK_ESCAPE, jump */
/* Opcode: Permutation * * * P4 *
**
** Set the permutation used by the OP_Compare operator to be the array
** of integers in P4.
** Set the permutation used by the OP_Compare operator in the next
** instruction. The permutation is stored in the P4 operand.
**
** The permutation is only valid until the next OP_Compare that has
** the OPFLAG_PERMUTE bit set in P5. Typically the OP_Permutation should
@@ -2153,7 +2147,8 @@ case OP_ElseNotEq: { /* same as TK_ESCAPE, jump */
case OP_Permutation: {
assert( pOp->p4type==P4_INTARRAY );
assert( pOp->p4.ai );
aPermute = pOp->p4.ai + 1;
assert( pOp[1].opcode==OP_Compare );
assert( pOp[1].p5 & OPFLAG_PERMUTE );
break;
}
@@ -2186,8 +2181,17 @@ case OP_Compare: {
int idx;
CollSeq *pColl; /* Collating sequence to use on this term */
int bRev; /* True for DESCENDING sort order */
int *aPermute; /* The permutation */
if( (pOp->p5 & OPFLAG_PERMUTE)==0 ) aPermute = 0;
if( (pOp->p5 & OPFLAG_PERMUTE)==0 ){
aPermute = 0;
}else{
assert( pOp>aOp );
assert( pOp[-1].opcode==OP_Permutation );
assert( pOp[-1].p4type==P4_INTARRAY );
aPermute = pOp[-1].p4.ai + 1;
assert( aPermute!=0 );
}
n = pOp->p3;
pKeyInfo = pOp->p4.pKeyInfo;
assert( n>0 );
@@ -2220,7 +2224,6 @@ case OP_Compare: {
break;
}
}
aPermute = 0;
break;
}
@@ -2777,6 +2780,20 @@ case OP_MakeRecord: {
}while( zAffinity[0] );
}
#ifdef SQLITE_ENABLE_NULL_TRIM
/* NULLs can be safely trimmed from the end of the record, as long as
** as the schema format is 2 or more and none of the omitted columns
** have a non-NULL default value. Also, the record must be left with
** at least one field. If P5>0 then it will be one more than the
** index of the right-most column with a non-NULL default value */
if( pOp->p5 ){
while( (pLast->flags & MEM_Null)!=0 && nField>pOp->p5 ){
pLast--;
nField--;
}
}
#endif
/* Loop through the elements that will make up the record to figure
** out how much space is required for the new record.
*/
@@ -4389,7 +4406,7 @@ case OP_InsertInt: {
assert( HasRowid(pTab) );
op = ((pOp->p5 & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_INSERT);
}else{
pTab = 0; /* Not needed. Silence a comiler warning. */
pTab = 0; /* Not needed. Silence a compiler warning. */
zDb = 0; /* Not needed. Silence a compiler warning. */
}
@@ -4404,7 +4421,7 @@ case OP_InsertInt: {
#endif
if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++;
if( pOp->p5 & OPFLAG_LASTROWID ) db->lastRowid = lastRowid = x.nKey;
if( pOp->p5 & OPFLAG_LASTROWID ) db->lastRowid = x.nKey;
if( pData->flags & MEM_Null ){
x.pData = 0;
x.nData = 0;
@@ -4421,7 +4438,7 @@ case OP_InsertInt: {
}
x.pKey = 0;
rc = sqlite3BtreeInsert(pC->uc.pCursor, &x,
(pOp->p5 & OPFLAG_APPEND)!=0, seekResult
(pOp->p5 & (OPFLAG_APPEND|OPFLAG_SAVEPOSITION)), seekResult
);
pC->deferredMoveto = 0;
pC->cacheStatus = CACHE_STALE;
@@ -4632,7 +4649,7 @@ case OP_SorterData: {
break;
}
/* Opcode: RowData P1 P2 * * *
/* Opcode: RowData P1 P2 P3 * *
** Synopsis: r[P2]=data
**
** Write into register P2 the complete row content for the row at
@@ -4646,14 +4663,26 @@ case OP_SorterData: {
**
** If the P1 cursor must be pointing to a valid row (not a NULL row)
** of a real table, not a pseudo-table.
**
** If P3!=0 then this opcode is allowed to make an ephermeral pointer
** into the database page. That means that the content of the output
** register will be invalidated as soon as the cursor moves - including
** moves caused by other cursors that "save" the the current cursors
** position in order that they can write to the same table. If P3==0
** then a copy of the data is made into memory. P3!=0 is faster, but
** P3==0 is safer.
**
** If P3!=0 then the content of the P2 register is unsuitable for use
** in OP_Result and any OP_Result will invalidate the P2 register content.
** The P2 register content is invalidated by opcodes like OP_Function or
** by any use of another cursor pointing to the same table.
*/
case OP_RowData: {
VdbeCursor *pC;
BtCursor *pCrsr;
u32 n;
pOut = &aMem[pOp->p2];
memAboutToChange(p, pOut);
pOut = out2Prerelease(p, pOp);
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
pC = p->apCsr[pOp->p1];
@@ -4684,14 +4713,9 @@ case OP_RowData: {
goto too_big;
}
testcase( n==0 );
if( sqlite3VdbeMemClearAndResize(pOut, MAX(n,32)) ){
goto no_mem;
}
pOut->n = n;
MemSetTypeFlag(pOut, MEM_Blob);
rc = sqlite3BtreePayload(pCrsr, 0, n, pOut->z);
rc = sqlite3VdbeMemFromBtree(pCrsr, 0, n, pOut);
if( rc ) goto abort_due_to_error;
pOut->enc = SQLITE_UTF8; /* In case the blob is ever cast to text */
if( !pOp->p3 ) Deephemeralize(pOut);
UPDATE_MAX_BLOBSIZE(pOut);
REGISTER_TRACE(pOp->p2, pOut);
break;
@@ -5079,7 +5103,7 @@ case OP_IdxInsert: { /* in2 */
x.aMem = aMem + pOp->p3;
x.nMem = (u16)pOp->p4.i;
rc = sqlite3BtreeInsert(pC->uc.pCursor, &x,
(pOp->p5 & OPFLAG_APPEND)!=0,
(pOp->p5 & (OPFLAG_APPEND|OPFLAG_SAVEPOSITION)),
((pOp->p5 & OPFLAG_USESEEKRESULT) ? pC->seekResult : 0)
);
assert( pC->deferredMoveto==0 );
@@ -5201,7 +5225,6 @@ case OP_IdxRowid: { /* out2 */
}else{
pOut = out2Prerelease(p, pOp);
pOut->u.i = rowid;
pOut->flags = MEM_Int;
}
}else{
assert( pOp->opcode==OP_IdxRowid );
@@ -5843,7 +5866,7 @@ case OP_Program: { /* jump */
p->nFrame++;
pFrame->pParent = p->pFrame;
pFrame->lastRowid = lastRowid;
pFrame->lastRowid = db->lastRowid;
pFrame->nChange = p->nChange;
pFrame->nDbChange = p->db->nChange;
assert( pFrame->pAuxData==0 );
@@ -6784,7 +6807,7 @@ case OP_VUpdate: {
sqlite3VtabImportErrmsg(p, pVtab);
if( rc==SQLITE_OK && pOp->p1 ){
assert( nArg>1 && apArg[0] && (apArg[0]->flags&MEM_Null) );
db->lastRowid = lastRowid = rowid;
db->lastRowid = rowid;
}
if( (rc&0xff)==SQLITE_CONSTRAINT && pOp->p4.pVtab->bConstraint ){
if( pOp->p5==OE_Ignore ){
@@ -7020,7 +7043,6 @@ abort_due_to_error:
** release the mutexes on btrees that were acquired at the
** top. */
vdbe_return:
db->lastRowid = lastRowid;
testcase( nVmStep>0 );
p->aCounter[SQLITE_STMTSTATUS_VM_STEP] += (int)nVmStep;
sqlite3VdbeLeave(p);
+4 -3
View File
@@ -41,8 +41,7 @@ typedef struct SubProgram SubProgram;
struct VdbeOp {
u8 opcode; /* What operation to perform */
signed char p4type; /* One of the P4_xxx constants for p4 */
u8 notUsed1;
u8 p5; /* Fifth parameter is an unsigned character */
u16 p5; /* Fifth parameter is an unsigned 16-bit integer */
int p1; /* First operand */
int p2; /* Second parameter (often the jump destination) */
int p3; /* The third parameter */
@@ -183,8 +182,10 @@ int sqlite3VdbeAddOp4Int(Vdbe*,int,int,int,int,int);
void sqlite3VdbeEndCoroutine(Vdbe*,int);
#if defined(SQLITE_DEBUG) && !defined(SQLITE_TEST_REALLOC_STRESS)
void sqlite3VdbeVerifyNoMallocRequired(Vdbe *p, int N);
void sqlite3VdbeVerifyNoResultRow(Vdbe *p);
#else
# define sqlite3VdbeVerifyNoMallocRequired(A,B)
# define sqlite3VdbeVerifyNoResultRow(A)
#endif
VdbeOp *sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp, int iLineno);
void sqlite3VdbeAddParseSchemaOp(Vdbe*,int,char*);
@@ -192,7 +193,7 @@ void sqlite3VdbeChangeOpcode(Vdbe*, u32 addr, u8);
void sqlite3VdbeChangeP1(Vdbe*, u32 addr, int P1);
void sqlite3VdbeChangeP2(Vdbe*, u32 addr, int P2);
void sqlite3VdbeChangeP3(Vdbe*, u32 addr, int P3);
void sqlite3VdbeChangeP5(Vdbe*, u8 P5);
void sqlite3VdbeChangeP5(Vdbe*, u16 P5);
void sqlite3VdbeJumpHere(Vdbe*, int addr);
int sqlite3VdbeChangeToNoop(Vdbe*, int addr);
int sqlite3VdbeDeletePriorOpcode(Vdbe*, u8 op);
+12 -16
View File
@@ -1660,6 +1660,7 @@ static UnpackedRecord *vdbeUnpackRecord(
*/
int sqlite3_preupdate_old(sqlite3 *db, int iIdx, sqlite3_value **ppValue){
PreUpdate *p = db->pPreUpdate;
Mem *pMem;
int rc = SQLITE_OK;
/* Test that this call is being made from within an SQLITE_DELETE or
@@ -1693,17 +1694,14 @@ int sqlite3_preupdate_old(sqlite3 *db, int iIdx, sqlite3_value **ppValue){
p->aRecord = aRec;
}
if( iIdx>=p->pUnpacked->nField ){
pMem = *ppValue = &p->pUnpacked->aMem[iIdx];
if( iIdx==p->pTab->iPKey ){
sqlite3VdbeMemSetInt64(pMem, p->iKey1);
}else if( iIdx>=p->pUnpacked->nField ){
*ppValue = (sqlite3_value *)columnNullValue();
}else{
Mem *pMem = *ppValue = &p->pUnpacked->aMem[iIdx];
*ppValue = &p->pUnpacked->aMem[iIdx];
if( iIdx==p->pTab->iPKey ){
sqlite3VdbeMemSetInt64(pMem, p->iKey1);
}else if( p->pTab->aCol[iIdx].affinity==SQLITE_AFF_REAL ){
if( pMem->flags & MEM_Int ){
sqlite3VdbeMemRealify(pMem);
}
}else if( p->pTab->aCol[iIdx].affinity==SQLITE_AFF_REAL ){
if( pMem->flags & MEM_Int ){
sqlite3VdbeMemRealify(pMem);
}
}
@@ -1776,13 +1774,11 @@ int sqlite3_preupdate_new(sqlite3 *db, int iIdx, sqlite3_value **ppValue){
}
p->pNewUnpacked = pUnpack;
}
if( iIdx>=pUnpack->nField ){
pMem = &pUnpack->aMem[iIdx];
if( iIdx==p->pTab->iPKey ){
sqlite3VdbeMemSetInt64(pMem, p->iKey2);
}else if( iIdx>=pUnpack->nField ){
pMem = (sqlite3_value *)columnNullValue();
}else{
pMem = &pUnpack->aMem[iIdx];
if( iIdx==p->pTab->iPKey ){
sqlite3VdbeMemSetInt64(pMem, p->iKey2);
}
}
}else{
/* For an UPDATE, memory cell (p->iNewReg+1+iIdx) contains the required
+59 -44
View File
@@ -648,6 +648,22 @@ void sqlite3VdbeVerifyNoMallocRequired(Vdbe *p, int N){
}
#endif
/*
** Verify that the VM passed as the only argument does not contain
** an OP_ResultRow opcode. Fail an assert() if it does. This is used
** by code in pragma.c to ensure that the implementation of certain
** pragmas comports with the flags specified in the mkpragmatab.tcl
** script.
*/
#if defined(SQLITE_DEBUG) && !defined(SQLITE_TEST_REALLOC_STRESS)
void sqlite3VdbeVerifyNoResultRow(Vdbe *p){
int i;
for(i=0; i<p->nOp; i++){
assert( p->aOp[i].opcode!=OP_ResultRow );
}
}
#endif
/*
** This function returns a pointer to the array of opcodes associated with
** the Vdbe passed as the first argument. It is the callers responsibility
@@ -767,7 +783,7 @@ void sqlite3VdbeChangeP2(Vdbe *p, u32 addr, int val){
void sqlite3VdbeChangeP3(Vdbe *p, u32 addr, int val){
sqlite3VdbeGetOp(p,addr)->p3 = val;
}
void sqlite3VdbeChangeP5(Vdbe *p, u8 p5){
void sqlite3VdbeChangeP5(Vdbe *p, u16 p5){
assert( p->nOp>0 || p->db->mallocFailed );
if( p->nOp>0 ) p->aOp[p->nOp-1].p5 = p5;
}
@@ -2481,60 +2497,59 @@ static void checkActiveVdbeCnt(sqlite3 *db){
** If an IO error occurs, an SQLITE_IOERR_XXX error code is returned.
** Otherwise SQLITE_OK.
*/
int sqlite3VdbeCloseStatement(Vdbe *p, int eOp){
static SQLITE_NOINLINE int vdbeCloseStatement(Vdbe *p, int eOp){
sqlite3 *const db = p->db;
int rc = SQLITE_OK;
int i;
const int iSavepoint = p->iStatement-1;
/* If p->iStatement is greater than zero, then this Vdbe opened a
** statement transaction that should be closed here. The only exception
** is that an IO error may have occurred, causing an emergency rollback.
** In this case (db->nStatement==0), and there is nothing to do.
*/
if( db->nStatement && p->iStatement ){
int i;
const int iSavepoint = p->iStatement-1;
assert( eOp==SAVEPOINT_ROLLBACK || eOp==SAVEPOINT_RELEASE);
assert( db->nStatement>0 );
assert( p->iStatement==(db->nStatement+db->nSavepoint) );
assert( eOp==SAVEPOINT_ROLLBACK || eOp==SAVEPOINT_RELEASE);
assert( db->nStatement>0 );
assert( p->iStatement==(db->nStatement+db->nSavepoint) );
for(i=0; i<db->nDb; i++){
int rc2 = SQLITE_OK;
Btree *pBt = db->aDb[i].pBt;
if( pBt ){
if( eOp==SAVEPOINT_ROLLBACK ){
rc2 = sqlite3BtreeSavepoint(pBt, SAVEPOINT_ROLLBACK, iSavepoint);
}
if( rc2==SQLITE_OK ){
rc2 = sqlite3BtreeSavepoint(pBt, SAVEPOINT_RELEASE, iSavepoint);
}
if( rc==SQLITE_OK ){
rc = rc2;
}
}
}
db->nStatement--;
p->iStatement = 0;
if( rc==SQLITE_OK ){
for(i=0; i<db->nDb; i++){
int rc2 = SQLITE_OK;
Btree *pBt = db->aDb[i].pBt;
if( pBt ){
if( eOp==SAVEPOINT_ROLLBACK ){
rc = sqlite3VtabSavepoint(db, SAVEPOINT_ROLLBACK, iSavepoint);
rc2 = sqlite3BtreeSavepoint(pBt, SAVEPOINT_ROLLBACK, iSavepoint);
}
if( rc2==SQLITE_OK ){
rc2 = sqlite3BtreeSavepoint(pBt, SAVEPOINT_RELEASE, iSavepoint);
}
if( rc==SQLITE_OK ){
rc = sqlite3VtabSavepoint(db, SAVEPOINT_RELEASE, iSavepoint);
rc = rc2;
}
}
}
db->nStatement--;
p->iStatement = 0;
/* If the statement transaction is being rolled back, also restore the
** database handles deferred constraint counter to the value it had when
** the statement transaction was opened. */
if( rc==SQLITE_OK ){
if( eOp==SAVEPOINT_ROLLBACK ){
db->nDeferredCons = p->nStmtDefCons;
db->nDeferredImmCons = p->nStmtDefImmCons;
rc = sqlite3VtabSavepoint(db, SAVEPOINT_ROLLBACK, iSavepoint);
}
if( rc==SQLITE_OK ){
rc = sqlite3VtabSavepoint(db, SAVEPOINT_RELEASE, iSavepoint);
}
}
/* If the statement transaction is being rolled back, also restore the
** database handles deferred constraint counter to the value it had when
** the statement transaction was opened. */
if( eOp==SAVEPOINT_ROLLBACK ){
db->nDeferredCons = p->nStmtDefCons;
db->nDeferredImmCons = p->nStmtDefImmCons;
}
return rc;
}
int sqlite3VdbeCloseStatement(Vdbe *p, int eOp){
if( p->db->nStatement && p->iStatement ){
return vdbeCloseStatement(p, eOp);
}
return SQLITE_OK;
}
/*
** This function is called when a transaction opened by the database
@@ -4569,10 +4584,10 @@ void sqlite3VtabImportErrmsg(Vdbe *p, sqlite3_vtab *pVtab){
** This function is used to free UnpackedRecord structures allocated by
** the vdbeUnpackRecord() function found in vdbeapi.c.
*/
static void vdbeFreeUnpacked(sqlite3 *db, UnpackedRecord *p){
static void vdbeFreeUnpacked(sqlite3 *db, int nField, UnpackedRecord *p){
if( p ){
int i;
for(i=0; i<p->nField; i++){
for(i=0; i<nField; i++){
Mem *pMem = &p->aMem[i];
if( pMem->zMalloc ) sqlite3VdbeMemRelease(pMem);
}
@@ -4631,8 +4646,8 @@ void sqlite3VdbePreUpdateHook(
db->xPreUpdateCallback(db->pPreUpdateArg, db, op, zDb, zTbl, iKey1, iKey2);
db->pPreUpdate = 0;
sqlite3DbFree(db, preupdate.aRecord);
vdbeFreeUnpacked(db, preupdate.pUnpacked);
vdbeFreeUnpacked(db, preupdate.pNewUnpacked);
vdbeFreeUnpacked(db, preupdate.keyinfo.nField+1, preupdate.pUnpacked);
vdbeFreeUnpacked(db, preupdate.keyinfo.nField+1, preupdate.pNewUnpacked);
if( preupdate.aNew ){
int i;
for(i=0; i<pCsr->nField; i++){
+32 -27
View File
@@ -23,10 +23,9 @@
*/
typedef struct Incrblob Incrblob;
struct Incrblob {
int flags; /* Copy of "flags" passed to sqlite3_blob_open() */
int nByte; /* Size of open blob, in bytes */
int iOffset; /* Byte offset of blob in cursor data */
int iCol; /* Table column this handle is open on */
u16 iCol; /* Table column this handle is open on */
BtCursor *pCsr; /* Cursor pointing at blob row */
sqlite3_stmt *pStmt; /* Statement holding cursor open */
sqlite3 *db; /* The associated database */
@@ -57,17 +56,27 @@ static int blobSeekToRow(Incrblob *p, sqlite3_int64 iRow, char **pzErr){
char *zErr = 0; /* Error message */
Vdbe *v = (Vdbe *)p->pStmt;
/* Set the value of the SQL statements only variable to integer iRow.
** This is done directly instead of using sqlite3_bind_int64() to avoid
** triggering asserts related to mutexes.
/* Set the value of register r[1] in the SQL statement to integer iRow.
** This is done directly as a performance optimization
*/
assert( v->aVar[0].flags&MEM_Int );
v->aVar[0].u.i = iRow;
v->aMem[1].flags = MEM_Int;
v->aMem[1].u.i = iRow;
rc = sqlite3_step(p->pStmt);
/* If the statement has been run before (and is paused at the OP_ResultRow)
** then back it up to the point where it does the OP_SeekRowid. This could
** have been down with an extra OP_Goto, but simply setting the program
** counter is faster. */
if( v->pc>3 ){
v->pc = 3;
rc = sqlite3VdbeExec(v);
}else{
rc = sqlite3_step(p->pStmt);
}
if( rc==SQLITE_ROW ){
VdbeCursor *pC = v->apCsr[0];
u32 type = pC->aType[p->iCol];
u32 type = pC->nHdrParsed>p->iCol ? pC->aType[p->iCol] : 0;
testcase( pC->nHdrParsed==p->iCol );
testcase( pC->nHdrParsed==p->iCol+1 );
if( type<12 ){
zErr = sqlite3MPrintf(p->db, "cannot open value of type %s",
type==0?"null": type==7?"real": "integer"
@@ -112,7 +121,7 @@ int sqlite3_blob_open(
const char *zTable, /* The table containing the blob */
const char *zColumn, /* The column containing the blob */
sqlite_int64 iRow, /* The row containing the glob */
int flags, /* True -> read/write access, false -> read-only */
int wrFlag, /* True -> read/write access, false -> read-only */
sqlite3_blob **ppBlob /* Handle for accessing the blob returned here */
){
int nAttempt = 0;
@@ -134,7 +143,7 @@ int sqlite3_blob_open(
return SQLITE_MISUSE_BKPT;
}
#endif
flags = !!flags; /* flags = (flags ? 1 : 0); */
wrFlag = !!wrFlag; /* wrFlag = (wrFlag ? 1 : 0); */
sqlite3_mutex_enter(db->mutex);
@@ -194,9 +203,8 @@ int sqlite3_blob_open(
/* If the value is being opened for writing, check that the
** column is not indexed, and that it is not part of a foreign key.
** It is against the rules to open a column to which either of these
** descriptions applies for writing. */
if( flags ){
*/
if( wrFlag ){
const char *zFault = 0;
Index *pIdx;
#ifndef SQLITE_OMIT_FOREIGN_KEY
@@ -257,18 +265,17 @@ int sqlite3_blob_open(
static const VdbeOpList openBlob[] = {
{OP_TableLock, 0, 0, 0}, /* 0: Acquire a read or write lock */
{OP_OpenRead, 0, 0, 0}, /* 1: Open a cursor */
{OP_Variable, 1, 1, 0}, /* 2: Move ?1 into reg[1] */
{OP_NotExists, 0, 7, 1}, /* 3: Seek the cursor */
{OP_Column, 0, 0, 1}, /* 4 */
{OP_ResultRow, 1, 0, 0}, /* 5 */
{OP_Goto, 0, 2, 0}, /* 6 */
{OP_Halt, 0, 0, 0}, /* 7 */
/* blobSeekToRow() will initialize r[1] to the desired rowid */
{OP_NotExists, 0, 5, 1}, /* 2: Seek the cursor to rowid=r[1] */
{OP_Column, 0, 0, 1}, /* 3 */
{OP_ResultRow, 1, 0, 0}, /* 4 */
{OP_Halt, 0, 0, 0}, /* 5 */
};
Vdbe *v = (Vdbe *)pBlob->pStmt;
int iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
VdbeOp *aOp;
sqlite3VdbeAddOp4Int(v, OP_Transaction, iDb, flags,
sqlite3VdbeAddOp4Int(v, OP_Transaction, iDb, wrFlag,
pTab->pSchema->schema_cookie,
pTab->pSchema->iGeneration);
sqlite3VdbeChangeP5(v, 1);
@@ -285,7 +292,7 @@ int sqlite3_blob_open(
#else
aOp[0].p1 = iDb;
aOp[0].p2 = pTab->tnum;
aOp[0].p3 = flags;
aOp[0].p3 = wrFlag;
sqlite3VdbeChangeP4(v, 1, pTab->zName, P4_TRANSIENT);
}
if( db->mallocFailed==0 ){
@@ -293,7 +300,7 @@ int sqlite3_blob_open(
/* Remove either the OP_OpenWrite or OpenRead. Set the P2
** parameter of the other to pTab->tnum. */
if( flags ) aOp[1].opcode = OP_OpenWrite;
if( wrFlag ) aOp[1].opcode = OP_OpenWrite;
aOp[1].p2 = pTab->tnum;
aOp[1].p3 = iDb;
@@ -306,23 +313,21 @@ int sqlite3_blob_open(
*/
aOp[1].p4type = P4_INT32;
aOp[1].p4.i = pTab->nCol+1;
aOp[4].p2 = pTab->nCol;
aOp[3].p2 = pTab->nCol;
pParse->nVar = 1;
pParse->nVar = 0;
pParse->nMem = 1;
pParse->nTab = 1;
sqlite3VdbeMakeReady(v, pParse);
}
}
pBlob->flags = flags;
pBlob->iCol = iCol;
pBlob->db = db;
sqlite3BtreeLeaveAll(db);
if( db->mallocFailed ){
goto blob_open_out;
}
sqlite3_bind_int64(pBlob->pStmt, 1, iRow);
rc = blobSeekToRow(pBlob, iRow, &zErr);
} while( (++nAttempt)<SQLITE_MAX_SCHEMA_RETRY && rc==SQLITE_SCHEMA );
+1
View File
@@ -1010,6 +1010,7 @@ static SQLITE_NOINLINE const void *valueToText(sqlite3_value* pVal, u8 enc){
assert( (pVal->flags & MEM_RowSet)==0 );
assert( (pVal->flags & (MEM_Null))==0 );
if( pVal->flags & (MEM_Blob|MEM_Str) ){
if( ExpandBlob(pVal) ) return 0;
pVal->flags |= MEM_Str;
if( pVal->enc != (enc & ~SQLITE_UTF16_ALIGNED) ){
sqlite3VdbeChangeEncoding(pVal, enc & ~SQLITE_UTF16_ALIGNED);
+2 -1
View File
@@ -4949,7 +4949,8 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
pOp->p2 = x;
pOp->p1 = pLevel->iIdxCur;
}
assert( (pLoop->wsFlags & WHERE_IDX_ONLY)==0 || x>=0 );
assert( (pLoop->wsFlags & WHERE_IDX_ONLY)==0 || x>=0
|| pWInfo->eOnePass );
}else if( pOp->opcode==OP_Rowid ){
pOp->p1 = pLevel->iIdxCur;
pOp->opcode = OP_IdxRowid;
+4 -1
View File
@@ -1591,7 +1591,10 @@ Bitmask sqlite3WhereCodeOneLoopStart(
if( omitTable ){
/* pIdx is a covering index. No need to access the main table. */
}else if( HasRowid(pIdx->pTable) ){
if( (pWInfo->wctrlFlags & WHERE_SEEK_TABLE)!=0 ){
if( (pWInfo->wctrlFlags & WHERE_SEEK_TABLE) || (
(pWInfo->wctrlFlags & WHERE_SEEK_UNIQ_TABLE)
&& (pWInfo->eOnePass==ONEPASS_SINGLE)
)){
iRowidReg = ++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, iRowidReg);
sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg);
+9 -5
View File
@@ -913,6 +913,7 @@ static void exprAnalyze(
Parse *pParse = pWInfo->pParse; /* Parsing context */
sqlite3 *db = pParse->db; /* Database connection */
unsigned char eOp2; /* op2 value for LIKE/REGEXP/GLOB */
int nLeft; /* Number of elements on left side vector */
if( db->mallocFailed ){
return;
@@ -942,6 +943,10 @@ static void exprAnalyze(
prereqAll |= x;
extraRight = x-1; /* ON clause terms may not be used with an index
** on left table of a LEFT JOIN. Ticket #3015 */
if( (prereqAll>>1)>=x ){
sqlite3ErrorMsg(pParse, "ON clause references tables to its right");
return;
}
}
pTerm->prereqAll = prereqAll;
pTerm->leftCursor = -1;
@@ -1184,13 +1189,12 @@ static void exprAnalyze(
** is not a sub-select. */
if( pWC->op==TK_AND
&& (pExpr->op==TK_EQ || pExpr->op==TK_IS)
&& sqlite3ExprIsVector(pExpr->pLeft)
&& (nLeft = sqlite3ExprVectorSize(pExpr->pLeft))>1
&& sqlite3ExprVectorSize(pExpr->pRight)==nLeft
&& ( (pExpr->pLeft->flags & EP_xIsSelect)==0
|| (pExpr->pRight->flags & EP_xIsSelect)==0
)){
int nLeft = sqlite3ExprVectorSize(pExpr->pLeft);
|| (pExpr->pRight->flags & EP_xIsSelect)==0)
){
int i;
assert( nLeft==sqlite3ExprVectorSize(pExpr->pRight) );
for(i=0; i<nLeft; i++){
int idxNew;
Expr *pNew;
+91
View File
@@ -0,0 +1,91 @@
# 2017-01-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.
#
#***********************************************************************
#
# Test cases for bugs:
#
# https://www.sqlite.org/src/info/91e2e8ba6ff2e2
# https://www.sqlite.org/src/info/7ffd1ca1d2ad4ecf
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
# Ticket https://www.sqlite.org/src/info/91e2e8ba6ff2e2 (2011-09-19)
# Automatic index causes undesired type conversions
#
do_execsql_test affinity3-100 {
CREATE TABLE customer (id INT PRIMARY KEY);
CREATE TABLE apr (id INT PRIMARY KEY, apr REAL);
CREATE VIEW v1 AS
SELECT c.id, i.apr
FROM customer c
LEFT JOIN apr i ON i.id=c.id;
CREATE VIEW v2 AS
SELECT c.id, v1.apr
FROM customer c
LEFT JOIN v1 ON v1.id=c.id;
INSERT INTO customer (id) VALUES (1);
INSERT INTO apr (id, apr) VALUES (1, 12);
INSERT INTO customer (id) VALUES (2);
INSERT INTO apr (id, apr) VALUES (2, 12.01);
}
do_execsql_test affinity3-110 {
PRAGMA automatic_index=ON;
SELECT id, (apr / 100), typeof(apr) apr_type FROM v1;
} {1 0.12 real 2 0.1201 real}
do_execsql_test affinity3-120 {
SELECT id, (apr / 100), typeof(apr) apr_type FROM v2;
} {1 0.12 real 2 0.1201 real}
do_execsql_test affinity3-130 {
PRAGMA automatic_index=OFF;
SELECT id, (apr / 100), typeof(apr) apr_type FROM v1;
} {1 0.12 real 2 0.1201 real}
do_execsql_test affinity3-140 {
SELECT id, (apr / 100), typeof(apr) apr_type FROM v2;
} {1 0.12 real 2 0.1201 real}
# Ticket https://www.sqlite.org/src/info/7ffd1ca1d2ad4ecf (2017-01-16)
# Incorrect affinity when using automatic indexes
#
do_execsql_test affinity3-200 {
CREATE TABLE map_integer (id INT, name);
INSERT INTO map_integer VALUES(1,'a');
CREATE TABLE map_text (id TEXT, name);
INSERT INTO map_text VALUES('4','e');
CREATE TABLE data (id TEXT, name);
INSERT INTO data VALUES(1,'abc');
INSERT INTO data VALUES('4','xyz');
CREATE VIEW idmap as
SELECT * FROM map_integer
UNION SELECT * FROM map_text;
CREATE TABLE mzed AS SELECT * FROM idmap;
}
do_execsql_test affinity3-210 {
PRAGMA automatic_index=ON;
SELECT * FROM data JOIN idmap USING(id);
} {1 abc a 4 xyz e}
do_execsql_test affinity3-220 {
SELECT * FROM data JOIN mzed USING(id);
} {1 abc a 4 xyz e}
do_execsql_test affinity3-250 {
PRAGMA automatic_index=OFF;
SELECT * FROM data JOIN idmap USING(id);
} {1 abc a 4 xyz e}
do_execsql_test affinity3-260 {
SELECT * FROM data JOIN mzed USING(id);
} {1 abc a 4 xyz e}
finish_test
+6 -4
View File
@@ -91,10 +91,12 @@ do_extract_hints_test 1.6 {
t2 {EQ(r[2],c0)} t3 {EQ(r[6],c1)}
}
do_extract_hints_test 1.7 {
SELECT * FROM t1 LEFT JOIN t2 ON (a=c AND d=e) LEFT JOIN t3 ON (d=f);
} {
t2 {EQ(r[2],c0)} t3 {AND(EQ(r[6],c0),EQ(r[7],c1))}
if 0 {
do_extract_hints_test 1.7 {
SELECT * FROM t1 LEFT JOIN t2 ON (a=c AND d=e) LEFT JOIN t3 ON (d=f);
} {
t2 {EQ(r[2],c0)} t3 {AND(EQ(r[6],c0),EQ(r[7],c1))}
}
}
#-------------------------------------------------------------------------
+8 -8
View File
@@ -121,13 +121,13 @@ do_test exclusive2-1.1 {
execsql {
BEGIN;
CREATE TABLE t1(a, b);
INSERT INTO t1(a) VALUES(randstr(10, 400));
INSERT INTO t1(a) VALUES(randstr(10, 400));
INSERT INTO t1(a) SELECT randstr(10, 400) FROM t1;
INSERT INTO t1(a) SELECT randstr(10, 400) FROM t1;
INSERT INTO t1(a) SELECT randstr(10, 400) FROM t1;
INSERT INTO t1(a) SELECT randstr(10, 400) FROM t1;
INSERT INTO t1(a) SELECT randstr(10, 400) FROM t1;
INSERT INTO t1(a, b) VALUES(randstr(10, 400), 0);
INSERT INTO t1(a, b) VALUES(randstr(10, 400), 0);
INSERT INTO t1(a, b) SELECT randstr(10, 400), 0 FROM t1;
INSERT INTO t1(a, b) SELECT randstr(10, 400), 0 FROM t1;
INSERT INTO t1(a, b) SELECT randstr(10, 400), 0 FROM t1;
INSERT INTO t1(a, b) SELECT randstr(10, 400), 0 FROM t1;
INSERT INTO t1(a, b) SELECT randstr(10, 400), 0 FROM t1;
COMMIT;
SELECT count(*) FROM t1;
}
@@ -154,7 +154,7 @@ do_test exclusive2-1.4 {
} $::sig
do_test exclusive2-1.5 {
execsql {
UPDATE t1 SET b=a, a=NULL;
UPDATE t1 SET b=a, a=0;
} db2
expr {[t1sig db2] eq $::sig}
} 0
+62
View File
@@ -101,5 +101,67 @@ foreach {tn use_stmt sql schema} {
} $use_stmt
}
#-------------------------------------------------------------------------
# The following tests check that foreign key constaint counters are
# correctly updated for any implicit DELETE operations that occur
# when a REPLACE command is executed against a WITHOUT ROWID table
# that has no triggers or auxiliary indexes.
#
reset_db
do_execsql_test 2.1.0 {
PRAGMA foreign_keys = on;
CREATE TABLE p1(a PRIMARY KEY, b) WITHOUT ROWID;
CREATE TABLE c1(x REFERENCES p1 DEFERRABLE INITIALLY DEFERRED);
INSERT INTO p1 VALUES(1, 'one');
INSERT INTO p1 VALUES(2, 'two');
INSERT INTO c1 VALUES(1);
INSERT INTO c1 VALUES(2);
}
do_catchsql_test 2.1.2 {
BEGIN;
DELETE FROM p1 WHERE a=1;
INSERT OR REPLACE INTO p1 VALUES(2, 'two');
COMMIT;
} {1 {FOREIGN KEY constraint failed}}
reset_db
do_execsql_test 2.2.0 {
PRAGMA foreign_keys = on;
CREATE TABLE p2(a PRIMARY KEY, b);
CREATE TABLE c2(
x PRIMARY KEY,
y REFERENCES p2 DEFERRABLE INITIALLY DEFERRED
) WITHOUT ROWID;
}
do_catchsql_test 2.2.1 {
BEGIN;
INSERT INTO c2 VALUES(13, 13);
INSERT OR REPLACE INTO c2 VALUES(13, 13);
DELETE FROM c2;
COMMIT;
} {0 {}}
reset_db
do_execsql_test 2.3.0 {
PRAGMA foreign_keys = on;
CREATE TABLE p3(a PRIMARY KEY, b) WITHOUT ROWID;
CREATE TABLE c3(x REFERENCES p3);
INSERT INTO p3 VALUES(1, 'one');
INSERT INTO p3 VALUES(2, 'two');
INSERT INTO c3 VALUES(1);
INSERT INTO c3 VALUES(2);
CREATE TRIGGER p3d AFTER DELETE ON p3 WHEN old.a=1 BEGIN
INSERT OR REPLACE INTO p3 VALUES(2, 'three');
END;
}
do_catchsql_test 2.3.1 {
DELETE FROM p3 WHERE a=1
} {1 {FOREIGN KEY constraint failed}}
finish_test
+56 -3
View File
@@ -849,9 +849,62 @@ do_preupdate_test 7.6.4 {
}
# No preupdate callbacks for modifying sqlite_master.
do_preupdate_test 8.1 {
CREATE TABLE x1(x, y);
} {
do_preupdate_test 8.1 { CREATE TABLE x1(x, y); } { }
do_preupdate_test 8.2 { ALTER TABLE x1 ADD COLUMN z } { }
do_preupdate_test 8.3 { ALTER TABLE x1 RENAME TO y1 } { }
do_preupdate_test 8.4 { CREATE INDEX y1x ON y1(x) } { }
do_preupdate_test 8.5 { CREATE VIEW v1 AS SELECT * FROM y1 } { }
do_preupdate_test 8.6 { DROP TABLE y1 } { }
#-------------------------------------------------------------------------
reset_db
db preupdate hook preupdate_hook
do_execsql_test 9.0 {
CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
CREATE TABLE t2(a, b INTEGER PRIMARY KEY);
}
do_preupdate_test 9.1 {
INSERT INTO t1 VALUES(456, NULL, NULL);
} {
INSERT main t1 456 456 0 456 {} {}
}
do_execsql_test 9.2 {
ALTER TABLE t1 ADD COLUMN d;
}
do_preupdate_test 9.3 {
INSERT INTO t1(a, b, c) VALUES(457, NULL, NULL);
} {
INSERT main t1 457 457 0 457 {} {} {}
}
do_preupdate_test 9.4 {
DELETE FROM t1 WHERE a=456
} {
DELETE main t1 456 456 0 456 {} {} {}
}
do_preupdate_test 9.5 {
INSERT INTO t2 DEFAULT VALUES;
} {
INSERT main t2 1 1 0 {} 1
}
do_preupdate_test 9.6 {
INSERT INTO t1 DEFAULT VALUES;
} {
INSERT main t1 458 458 0 458 {} {} {}
}
do_execsql_test 10.0 {
CREATE TABLE t3(a, b INTEGER PRIMARY KEY);
}
do_preupdate_test 10.1 {
INSERT INTO t3 DEFAULT VALUES
} {
INSERT main t3 1 1 0 {} 1
}
do_execsql_test 10.2 { SELECT * FROM t3 } {{} 1}
do_preupdate_test 10.3 {
DELETE FROM t3 WHERE b=1
} {DELETE main t3 1 1 0 {} 1}
finish_test
+21 -1
View File
@@ -12,10 +12,10 @@
#
# This file implements tests for joins, including outer joins.
#
# $Id: join2.test,v 1.2 2005/01/21 03:12:16 danielk1977 Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix join2
do_test join2-1.1 {
execsql {
@@ -72,4 +72,24 @@ ifcapable subquery {
} {1 11 111 1111 2 22 {} {} 3 33 {} {}}
}
#-------------------------------------------------------------------------
# Check that ticket [25e335f802ddc] has been resolved. It should be an
# error for the ON clause of a LEFT JOIN to refer to a table to its right.
#
do_execsql_test 2.0 {
CREATE TABLE aa(a);
CREATE TABLE bb(b);
CREATE TABLE cc(c);
INSERT INTO aa VALUES('one');
INSERT INTO bb VALUES('one');
INSERT INTO cc VALUES('one');
}
do_catchsql_test 2.1 {
SELECT * FROM aa LEFT JOIN cc ON (a=b) JOIN bb ON (b=c);
} {1 {ON clause references tables to its right}}
do_catchsql_test 2.2 {
SELECT * FROM aa JOIN cc ON (a=b) JOIN bb ON (b=c);
} {0 {one one one}}
finish_test
+327 -30
View File
@@ -61,32 +61,41 @@
** ./kvtest run x1 --count 10000 --max-id 1000000
*/
static const char zHelp[] =
"Usage: kvhelp COMMAND ARGS...\n"
"Usage: kvtest COMMAND ARGS...\n"
"\n"
" kvhelp init DBFILE --count N --size M --pagesize X\n"
" kvtest init DBFILE --count N --size M --pagesize X\n"
"\n"
" Generate a new test database file named DBFILE containing N\n"
" BLOBs each of size M bytes. The page size of the new database\n"
" file will be X\n"
" file will be X. Additional options:\n"
"\n"
" kvhelp export DBFILE DIRECTORY\n"
" --variance V Randomly vary M by plus or minus V\n"
"\n"
" kvtest export DBFILE DIRECTORY\n"
"\n"
" Export all the blobs in the kv table of DBFILE into separate\n"
" files in DIRECTORY.\n"
"\n"
" kvhelp run DBFILE [options]\n"
" kvtest stat DBFILE\n"
"\n"
" Display summary information about DBFILE\n"
"\n"
" kvtest run DBFILE [options]\n"
"\n"
" Run a performance test. DBFILE can be either the name of a\n"
" database or a directory containing sample files. Options:\n"
"\n"
" --asc Read blobs in ascending order\n"
" --blob-api Use the BLOB API\n"
" --cache-size N Database cache size\n"
" --count N Read N blobs\n"
" --desc Read blobs in descending order\n"
" --max-id N Maximum blob key to use\n"
" --random Read blobs in a random order\n"
" --start N Start reading with this blob key\n"
" --asc Read blobs in ascending order\n"
" --blob-api Use the BLOB API\n"
" --cache-size N Database cache size\n"
" --count N Read N blobs\n"
" --desc Read blobs in descending order\n"
" --max-id N Maximum blob key to use\n"
" --mmap N Mmap as much as N bytes of DBFILE\n"
" --jmode MODE Set MODE journal mode prior to starting\n"
" --random Read blobs in a random order\n"
" --start N Start reading with this blob key\n"
" --stats Output operating stats before exiting\n"
;
/* Reference resources used */
@@ -131,6 +140,64 @@ static void fatalError(const char *zFormat, ...){
exit(1);
}
/*
** Return the value of a hexadecimal digit. Return -1 if the input
** is not a hex digit.
*/
static int hexDigitValue(char c){
if( c>='0' && c<='9' ) return c - '0';
if( c>='a' && c<='f' ) return c - 'a' + 10;
if( c>='A' && c<='F' ) return c - 'A' + 10;
return -1;
}
/*
** Interpret zArg as an integer value, possibly with suffixes.
*/
static int integerValue(const char *zArg){
int v = 0;
static const struct { char *zSuffix; int iMult; } aMult[] = {
{ "KiB", 1024 },
{ "MiB", 1024*1024 },
{ "GiB", 1024*1024*1024 },
{ "KB", 1000 },
{ "MB", 1000000 },
{ "GB", 1000000000 },
{ "K", 1000 },
{ "M", 1000000 },
{ "G", 1000000000 },
};
int i;
int isNeg = 0;
if( zArg[0]=='-' ){
isNeg = 1;
zArg++;
}else if( zArg[0]=='+' ){
zArg++;
}
if( zArg[0]=='0' && zArg[1]=='x' ){
int x;
zArg += 2;
while( (x = hexDigitValue(zArg[0]))>=0 ){
v = (v<<4) + x;
zArg++;
}
}else{
while( zArg[0]>='0' && zArg[0]<='9' ){
v = v*10 + zArg[0] - '0';
zArg++;
}
}
for(i=0; i<sizeof(aMult)/sizeof(aMult[0]); i++){
if( sqlite3_stricmp(aMult[i].zSuffix, zArg)==0 ){
v *= aMult[i].iMult;
break;
}
}
return isNeg? -v : v;
}
/*
** Check the filesystem object zPath. Determine what it is:
**
@@ -190,6 +257,7 @@ static int initMain(int argc, char **argv){
int i, rc;
int nCount = 1000;
int sz = 10000;
int iVariance = 0;
int pgsz = 4096;
sqlite3 *db;
char *zSql;
@@ -204,19 +272,24 @@ static int initMain(int argc, char **argv){
if( z[1]=='-' ) z++;
if( strcmp(z, "-count")==0 ){
if( i==argc-1 ) fatalError("missing argument on \"%s\"", argv[i]);
nCount = atoi(argv[++i]);
nCount = integerValue(argv[++i]);
if( nCount<1 ) fatalError("the --count must be positive");
continue;
}
if( strcmp(z, "-size")==0 ){
if( i==argc-1 ) fatalError("missing argument on \"%s\"", argv[i]);
sz = atoi(argv[++i]);
sz = integerValue(argv[++i]);
if( sz<1 ) fatalError("the --size must be positive");
continue;
}
if( strcmp(z, "-variance")==0 ){
if( i==argc-1 ) fatalError("missing argument on \"%s\"", argv[i]);
iVariance = integerValue(argv[++i]);
continue;
}
if( strcmp(z, "-pagesize")==0 ){
if( i==argc-1 ) fatalError("missing argument on \"%s\"", argv[i]);
pgsz = atoi(argv[++i]);
pgsz = integerValue(argv[++i]);
if( pgsz<512 || pgsz>65536 || ((pgsz-1)&pgsz)!=0 ){
fatalError("the --pagesize must be power of 2 between 512 and 65536");
}
@@ -235,9 +308,9 @@ static int initMain(int argc, char **argv){
"BEGIN;\n"
"CREATE TABLE kv(k INTEGER PRIMARY KEY, v BLOB);\n"
"WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<%d)"
" INSERT INTO kv(k,v) SELECT x, randomblob(%d) FROM c;\n"
" INSERT INTO kv(k,v) SELECT x, randomblob(%d+(random()%%(%d))) FROM c;\n"
"COMMIT;\n",
pgsz, nCount, sz
pgsz, nCount, sz, iVariance
);
rc = sqlite3_exec(db, zSql, 0, 0, &zErrMsg);
if( rc ) fatalError("database create failed: %s", zErrMsg);
@@ -246,6 +319,65 @@ static int initMain(int argc, char **argv){
return 0;
}
/*
** Analyze an existing database file. Report its content.
*/
static int statMain(int argc, char **argv){
char *zDb;
int i, rc;
sqlite3 *db;
char *zSql;
sqlite3_stmt *pStmt;
assert( strcmp(argv[1],"stat")==0 );
assert( argc>=3 );
zDb = argv[2];
for(i=3; i<argc; i++){
char *z = argv[i];
if( z[0]!='-' ) fatalError("unknown argument: \"%s\"", z);
if( z[1]=='-' ) z++;
fatalError("unknown option: \"%s\"", argv[i]);
}
rc = sqlite3_open(zDb, &db);
if( rc ){
fatalError("cannot open database \"%s\": %s", zDb, sqlite3_errmsg(db));
}
zSql = sqlite3_mprintf(
"SELECT count(*), min(length(v)), max(length(v)), avg(length(v))"
" FROM kv"
);
rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
if( rc ) fatalError("cannot prepare SQL [%s]: %s", zSql, sqlite3_errmsg(db));
sqlite3_free(zSql);
if( sqlite3_step(pStmt)==SQLITE_ROW ){
printf("Number of entries: %8d\n", sqlite3_column_int(pStmt, 0));
printf("Average value size: %8d\n", sqlite3_column_int(pStmt, 3));
printf("Minimum value size: %8d\n", sqlite3_column_int(pStmt, 1));
printf("Maximum value size: %8d\n", sqlite3_column_int(pStmt, 2));
}else{
printf("No rows\n");
}
sqlite3_finalize(pStmt);
zSql = sqlite3_mprintf("PRAGMA page_size");
rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
if( rc ) fatalError("cannot prepare SQL [%s]: %s", zSql, sqlite3_errmsg(db));
sqlite3_free(zSql);
if( sqlite3_step(pStmt)==SQLITE_ROW ){
printf("Page-size: %8d\n", sqlite3_column_int(pStmt, 0));
}
sqlite3_finalize(pStmt);
zSql = sqlite3_mprintf("PRAGMA page_count");
rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
if( rc ) fatalError("cannot prepare SQL [%s]: %s", zSql, sqlite3_errmsg(db));
sqlite3_free(zSql);
if( sqlite3_step(pStmt)==SQLITE_ROW ){
printf("Page-count: %8d\n", sqlite3_column_int(pStmt, 0));
}
sqlite3_finalize(pStmt);
sqlite3_close(db);
return 0;
}
/*
** Implementation of the "writefile(X,Y)" SQL function. The argument Y
** is written into file X. The number of bytes written is returned. Or
@@ -369,11 +501,125 @@ static sqlite3_int64 timeOfDay(void){
return t;
}
#ifdef __linux__
/*
** Attempt to display I/O stats on Linux using /proc/PID/io
*/
static void displayLinuxIoStats(FILE *out){
FILE *in;
char z[200];
sqlite3_snprintf(sizeof(z), z, "/proc/%d/io", getpid());
in = fopen(z, "rb");
if( in==0 ) return;
while( fgets(z, sizeof(z), in)!=0 ){
static const struct {
const char *zPattern;
const char *zDesc;
} aTrans[] = {
{ "rchar: ", "Bytes received by read():" },
{ "wchar: ", "Bytes sent to write():" },
{ "syscr: ", "Read() system calls:" },
{ "syscw: ", "Write() system calls:" },
{ "read_bytes: ", "Bytes read from storage:" },
{ "write_bytes: ", "Bytes written to storage:" },
{ "cancelled_write_bytes: ", "Cancelled write bytes:" },
};
int i;
for(i=0; i<sizeof(aTrans)/sizeof(aTrans[0]); i++){
int n = (int)strlen(aTrans[i].zPattern);
if( strncmp(aTrans[i].zPattern, z, n)==0 ){
fprintf(out, "%-36s %s", aTrans[i].zDesc, &z[n]);
break;
}
}
}
fclose(in);
}
#endif
/*
** Display memory stats.
*/
static int display_stats(
sqlite3 *db, /* Database to query */
int bReset /* True to reset SQLite stats */
){
int iCur;
int iHiwtr;
FILE *out = stdout;
fprintf(out, "\n");
iHiwtr = iCur = -1;
sqlite3_status(SQLITE_STATUS_MEMORY_USED, &iCur, &iHiwtr, bReset);
fprintf(out,
"Memory Used: %d (max %d) bytes\n",
iCur, iHiwtr);
iHiwtr = iCur = -1;
sqlite3_status(SQLITE_STATUS_MALLOC_COUNT, &iCur, &iHiwtr, bReset);
fprintf(out, "Number of Outstanding Allocations: %d (max %d)\n",
iCur, iHiwtr);
iHiwtr = iCur = -1;
sqlite3_status(SQLITE_STATUS_PAGECACHE_USED, &iCur, &iHiwtr, bReset);
fprintf(out,
"Number of Pcache Pages Used: %d (max %d) pages\n",
iCur, iHiwtr);
iHiwtr = iCur = -1;
sqlite3_status(SQLITE_STATUS_PAGECACHE_OVERFLOW, &iCur, &iHiwtr, bReset);
fprintf(out,
"Number of Pcache Overflow Bytes: %d (max %d) bytes\n",
iCur, iHiwtr);
iHiwtr = iCur = -1;
sqlite3_status(SQLITE_STATUS_SCRATCH_USED, &iCur, &iHiwtr, bReset);
fprintf(out,
"Number of Scratch Allocations Used: %d (max %d)\n",
iCur, iHiwtr);
iHiwtr = iCur = -1;
sqlite3_status(SQLITE_STATUS_SCRATCH_OVERFLOW, &iCur, &iHiwtr, bReset);
fprintf(out,
"Number of Scratch Overflow Bytes: %d (max %d) bytes\n",
iCur, iHiwtr);
iHiwtr = iCur = -1;
sqlite3_status(SQLITE_STATUS_MALLOC_SIZE, &iCur, &iHiwtr, bReset);
fprintf(out, "Largest Allocation: %d bytes\n",
iHiwtr);
iHiwtr = iCur = -1;
sqlite3_status(SQLITE_STATUS_PAGECACHE_SIZE, &iCur, &iHiwtr, bReset);
fprintf(out, "Largest Pcache Allocation: %d bytes\n",
iHiwtr);
iHiwtr = iCur = -1;
sqlite3_status(SQLITE_STATUS_SCRATCH_SIZE, &iCur, &iHiwtr, bReset);
fprintf(out, "Largest Scratch Allocation: %d bytes\n",
iHiwtr);
iHiwtr = iCur = -1;
sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_USED, &iCur, &iHiwtr, bReset);
fprintf(out, "Pager Heap Usage: %d bytes\n",
iCur);
iHiwtr = iCur = -1;
sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_HIT, &iCur, &iHiwtr, 1);
fprintf(out, "Page cache hits: %d\n", iCur);
iHiwtr = iCur = -1;
sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_MISS, &iCur, &iHiwtr, 1);
fprintf(out, "Page cache misses: %d\n", iCur);
iHiwtr = iCur = -1;
sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_WRITE, &iCur, &iHiwtr, 1);
fprintf(out, "Page cache writes: %d\n", iCur);
iHiwtr = iCur = -1;
#ifdef __linux__
displayLinuxIoStats(out);
#endif
return 0;
}
/* Blob access order */
#define ORDER_ASC 1
#define ORDER_DESC 2
#define ORDER_RANDOM 3
/*
** Run a performance test
*/
@@ -385,19 +631,23 @@ static int runMain(int argc, char **argv){
int nCount = 1000; /* Number of blob fetch operations */
int nExtra = 0; /* Extra cycles */
int iKey = 1; /* Next blob key */
int iMax = 1000; /* Largest allowed key */
int iMax = 0; /* Largest allowed key */
int iPagesize = 0; /* Database page size */
int iCache = 1000; /* Database cache size in kibibytes */
int bBlobApi = 0; /* Use the incremental blob I/O API */
int bStats = 0; /* Print stats before exiting */
int eOrder = ORDER_ASC; /* Access order */
sqlite3 *db = 0; /* Database connection */
sqlite3_stmt *pStmt = 0; /* Prepared statement for SQL access */
sqlite3_blob *pBlob = 0; /* Handle for incremental Blob I/O */
sqlite3_int64 tmStart; /* Start time */
sqlite3_int64 tmElapsed; /* Elapsed time */
int mmapSize = 0; /* --mmap N argument */
int nData = 0; /* Bytes of data */
sqlite3_int64 nTotal = 0; /* Total data read */
unsigned char *pData; /* Content of the blob */
unsigned char *pData = 0; /* Content of the blob */
int nAlloc = 0; /* Space allocated for pData[] */
const char *zJMode = 0; /* Journal mode */
assert( strcmp(argv[1],"run")==0 );
@@ -412,25 +662,35 @@ static int runMain(int argc, char **argv){
if( z[1]=='-' ) z++;
if( strcmp(z, "-count")==0 ){
if( i==argc-1 ) fatalError("missing argument on \"%s\"", argv[i]);
nCount = atoi(argv[++i]);
nCount = integerValue(argv[++i]);
if( nCount<1 ) fatalError("the --count must be positive");
continue;
}
if( strcmp(z, "-mmap")==0 ){
if( i==argc-1 ) fatalError("missing argument on \"%s\"", argv[i]);
mmapSize = integerValue(argv[++i]);
if( nCount<0 ) fatalError("the --mmap must be non-negative");
continue;
}
if( strcmp(z, "-max-id")==0 ){
if( i==argc-1 ) fatalError("missing argument on \"%s\"", argv[i]);
iMax = atoi(argv[++i]);
if( iMax<1 ) fatalError("the --max-id must be positive");
iMax = integerValue(argv[++i]);
continue;
}
if( strcmp(z, "-start")==0 ){
if( i==argc-1 ) fatalError("missing argument on \"%s\"", argv[i]);
iKey = atoi(argv[++i]);
iKey = integerValue(argv[++i]);
if( iKey<1 ) fatalError("the --start must be positive");
continue;
}
if( strcmp(z, "-cache-size")==0 ){
if( i==argc-1 ) fatalError("missing argument on \"%s\"", argv[i]);
iCache = atoi(argv[++i]);
iCache = integerValue(argv[++i]);
continue;
}
if( strcmp(z, "-jmode")==0 ){
if( i==argc-1 ) fatalError("missing argument on \"%s\"", argv[i]);
zJMode = argv[++i];
continue;
}
if( strcmp(z, "-random")==0 ){
@@ -449,6 +709,10 @@ static int runMain(int argc, char **argv){
bBlobApi = 1;
continue;
}
if( strcmp(z, "-stats")==0 ){
bStats = 1;
continue;
}
fatalError("unknown option: \"%s\"", argv[i]);
}
tmStart = timeOfDay();
@@ -458,6 +722,8 @@ static int runMain(int argc, char **argv){
if( rc ){
fatalError("cannot open database \"%s\": %s", zDb, sqlite3_errmsg(db));
}
zSql = sqlite3_mprintf("PRAGMA mmap_size=%d", mmapSize);
sqlite3_exec(db, zSql, 0, 0, 0);
zSql = sqlite3_mprintf("PRAGMA cache_size=%d", iCache);
sqlite3_exec(db, zSql, 0, 0, 0);
sqlite3_free(zSql);
@@ -475,8 +741,29 @@ static int runMain(int argc, char **argv){
}
sqlite3_finalize(pStmt);
pStmt = 0;
if( zJMode ){
zSql = sqlite3_mprintf("PRAGMA journal_mode=%Q", zJMode);
sqlite3_exec(db, zSql, 0, 0, 0);
sqlite3_free(zSql);
}
sqlite3_prepare_v2(db, "PRAGMA journal_mode", -1, &pStmt, 0);
if( sqlite3_step(pStmt)==SQLITE_ROW ){
zJMode = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 0));
}else{
zJMode = "???";
}
sqlite3_finalize(pStmt);
if( iMax<=0 ){
sqlite3_prepare_v2(db, "SELECT max(k) FROM kv", -1, &pStmt, 0);
if( sqlite3_step(pStmt)==SQLITE_ROW ){
iMax = sqlite3_column_int(pStmt, 0);
}
sqlite3_finalize(pStmt);
}
pStmt = 0;
sqlite3_exec(db, "BEGIN", 0, 0, 0);
}
if( iMax<=0 ) iMax = 1000;
for(i=0; i<nCount; i++){
if( eType==PATH_DIR ){
/* CASE 1: Reading blobs out of separate files */
@@ -499,14 +786,16 @@ static int runMain(int argc, char **argv){
}
if( rc==SQLITE_OK ){
nData = sqlite3_blob_bytes(pBlob);
pData = sqlite3_malloc( nData+1 );
if( nAlloc<nData+1 ){
nAlloc = nData+100;
pData = sqlite3_realloc(pData, nAlloc);
}
if( pData==0 ) fatalError("cannot allocate %d bytes", nData+1);
rc = sqlite3_blob_read(pBlob, pData, nData, 0);
if( rc!=SQLITE_OK ){
fatalError("could not read the blob at %d: %s", iKey,
sqlite3_errmsg(db));
}
sqlite3_free(pData);
}
}else{
/* CASE 3: Reading from database using SQL */
@@ -540,8 +829,12 @@ static int runMain(int argc, char **argv){
nTotal += nData;
if( nData==0 ){ nCount++; nExtra++; }
}
if( nAlloc ) sqlite3_free(pData);
if( pStmt ) sqlite3_finalize(pStmt);
if( pBlob ) sqlite3_blob_close(pBlob);
if( bStats ){
display_stats(db, 0);
}
if( db ) sqlite3_close(db);
tmElapsed = timeOfDay() - tmStart;
if( nExtra ){
@@ -551,14 +844,15 @@ static int runMain(int argc, char **argv){
printf("SQLite version: %s\n", sqlite3_libversion());
}
printf("--count %d --max-id %d", nCount-nExtra, iMax);
if( eType==PATH_DB ){
printf(" --cache-size %d", iCache);
}
switch( eOrder ){
case ORDER_RANDOM: printf(" --random\n"); break;
case ORDER_DESC: printf(" --desc\n"); break;
default: printf(" --asc\n"); break;
}
if( eType==PATH_DB ){
printf("--cache-size %d --jmode %s\n", iCache, zJMode);
printf("--mmap %d%s\n", mmapSize, bBlobApi ? " --blob-api" : "");
}
if( iPagesize ) printf("Database page size: %d\n", iPagesize);
printf("Total elapsed time: %.3f\n", tmElapsed/1000.0);
printf("Microseconds per BLOB read: %.3f\n", tmElapsed*1000.0/nCount);
@@ -578,6 +872,9 @@ int main(int argc, char **argv){
if( strcmp(argv[1],"run")==0 ){
return runMain(argc, argv);
}
if( strcmp(argv[1],"stat")==0 ){
return statMain(argc, argv);
}
showHelp();
return 0;
}
+84
View File
@@ -0,0 +1,84 @@
# 2017 Jan 4
#
# 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.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix pragma4
proc do_pragma_ncol_test {tn sql nCol} {
set ::stmt 0
set ::stmt [sqlite3_prepare_v2 db $sql -1 dummy]
uplevel [list do_test $tn { sqlite3_column_count $::stmt } $nCol]
sqlite3_finalize $::stmt
}
# If there is no RHS argument, the following PRAGMA statements operate as
# queries, returning a single row containing a single column.
#
# Or, if there is RHS argument, they return zero rows of zero columns.
#
foreach {tn sql} {
1 "PRAGMA application_id = 10"
2 "PRAGMA automatic_index = 1"
3 "PRAGMA auto_vacuum = 1"
4 "PRAGMA cache_size = -100"
5 "PRAGMA cache_spill = 1"
6 "PRAGMA cell_size_check = 1"
7 "PRAGMA checkpoint_fullfsync = 1"
8 "PRAGMA count_changes = 1"
9 "PRAGMA default_cache_size = 100"
10 "PRAGMA defer_foreign_keys = 1"
11 "PRAGMA empty_result_callbacks = 1"
12 "PRAGMA encoding = 'utf-8'"
13 "PRAGMA foreign_keys = 1"
14 "PRAGMA full_column_names = 1"
15 "PRAGMA fullfsync = 1"
16 "PRAGMA ignore_check_constraints = 1"
17 "PRAGMA legacy_file_format = 1"
18 "PRAGMA page_size = 511"
19 "PRAGMA page_size = 512"
20 "PRAGMA query_only = false"
21 "PRAGMA read_uncommitted = true"
22 "PRAGMA recursive_triggers = false"
23 "PRAGMA reverse_unordered_selects = false"
24 "PRAGMA schema_version = 211"
25 "PRAGMA short_column_names = 1"
26 "PRAGMA synchronous = full"
29 "PRAGMA temp_store = memory"
30 "PRAGMA user_version = 405"
31 "PRAGMA writable_schema = 1"
} {
reset_db
# Without RHS:
do_pragma_ncol_test 1.$tn.1 [lindex [split $sql =] 0] 1
# With RHS:
do_pragma_ncol_test 1.$tn.2 $sql 0
}
# These pragmas should never return any values.
#
foreach {tn sql} {
1 "PRAGMA shrink_memory"
2 "PRAGMA shrink_memory = 10"
3 "PRAGMA case_sensitive_like = 0"
4 "PRAGMA case_sensitive_like = 1"
5 "PRAGMA case_sensitive_like"
} {
do_pragma_ncol_test 1.$tn.1 $sql 0
}
finish_test
+34
View File
@@ -14,6 +14,7 @@
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix selectC
# Ticket #
do_test selectC-1.1 {
@@ -233,4 +234,37 @@ do_execsql_test selectC-4.3 {
select a, udf() from (select distinct a, b from t_distinct_bug)
} {1 1 1 2 1 3}
#-------------------------------------------------------------------------
# Test that the problem in ticket #190c2507 has been fixed.
#
do_execsql_test 5.0 {
CREATE TABLE x1(a);
CREATE TABLE x2(b);
CREATE TABLE x3(c);
CREATE VIEW vvv AS SELECT b FROM x2 ORDER BY 1;
INSERT INTO x1 VALUES('a'), ('b');
INSERT INTO x2 VALUES(22), (23), (25), (24), (21);
INSERT INTO x3 VALUES(302), (303), (301);
}
do_execsql_test 5.1 {
CREATE TABLE x4 AS SELECT b FROM vvv UNION ALL SELECT c from x3;
SELECT * FROM x4;
} {21 22 23 24 25 302 303 301}
do_execsql_test 5.2 {
SELECT * FROM x1, x4
} {
a 21 a 22 a 23 a 24 a 25 a 302 a 303 a 301
b 21 b 22 b 23 b 24 b 25 b 302 b 303 b 301
}
do_execsql_test 5.3 {
SELECT * FROM x1, (SELECT b FROM vvv UNION ALL SELECT c from x3);
} {
a 21 a 22 a 23 a 24 a 25 a 302 a 303 a 301
b 21 b 22 b 23 b 24 b 25 b 302 b 303 b 301
}
finish_test
+10 -18
View File
@@ -61,9 +61,6 @@ static const char zHelp[] =
#if SQLITE_VERSION_NUMBER<3005000
# define sqlite3_int64 sqlite_int64
#endif
#ifdef SQLITE_ENABLE_RBU
# include "sqlite3rbu.h"
#endif
/* All global state is held in this structure */
static struct Global {
@@ -1181,10 +1178,10 @@ void testset_rtree(int p1, int p2){
unsigned mxCoord;
unsigned x0, x1, y0, y1, z0, z1;
unsigned iStep;
int *aCheck = sqlite3_malloc( sizeof(int)*g.szTest*100 );
int *aCheck = sqlite3_malloc( sizeof(int)*g.szTest*500 );
mxCoord = 15000;
n = g.szTest*100;
n = g.szTest*500;
speedtest1_begin_test(100, "%d INSERTs into an r-tree", n);
speedtest1_exec("BEGIN");
speedtest1_exec("CREATE VIRTUAL TABLE rt1 USING rtree(id,x0,x1,y0,y1,z0,z1)");
@@ -1207,11 +1204,11 @@ void testset_rtree(int p1, int p2){
speedtest1_end_test();
speedtest1_begin_test(101, "Copy from rtree to a regular table");
speedtest1_exec(" TABLE t1(id INTEGER PRIMARY KEY,x0,x1,y0,y1,z0,z1)");
speedtest1_exec("CREATE TABLE t1(id INTEGER PRIMARY KEY,x0,x1,y0,y1,z0,z1)");
speedtest1_exec("INSERT INTO t1 SELECT * FROM rt1");
speedtest1_end_test();
n = g.szTest*20;
n = g.szTest*100;
speedtest1_begin_test(110, "%d one-dimensional intersect slice queries", n);
speedtest1_prepare("SELECT count(*) FROM rt1 WHERE x0>=?1 AND x1<=?2");
iStep = mxCoord/n;
@@ -1224,7 +1221,7 @@ void testset_rtree(int p1, int p2){
speedtest1_end_test();
if( g.bVerify ){
n = g.szTest*20;
n = g.szTest*100;
speedtest1_begin_test(111, "Verify result from 1-D intersect slice queries");
speedtest1_prepare("SELECT count(*) FROM t1 WHERE x0>=?1 AND x1<=?2");
iStep = mxCoord/n;
@@ -1240,7 +1237,7 @@ void testset_rtree(int p1, int p2){
speedtest1_end_test();
}
n = g.szTest*20;
n = g.szTest*100;
speedtest1_begin_test(120, "%d one-dimensional overlap slice queries", n);
speedtest1_prepare("SELECT count(*) FROM rt1 WHERE y1>=?1 AND y0<=?2");
iStep = mxCoord/n;
@@ -1253,7 +1250,7 @@ void testset_rtree(int p1, int p2){
speedtest1_end_test();
if( g.bVerify ){
n = g.szTest*20;
n = g.szTest*100;
speedtest1_begin_test(121, "Verify result from 1-D overlap slice queries");
speedtest1_prepare("SELECT count(*) FROM t1 WHERE y1>=?1 AND y0<=?2");
iStep = mxCoord/n;
@@ -1270,7 +1267,7 @@ void testset_rtree(int p1, int p2){
}
n = g.szTest*20;
n = g.szTest*100;
speedtest1_begin_test(125, "%d custom geometry callback queries", n);
sqlite3_rtree_geometry_callback(g.db, "xslice", xsliceGeometryCallback, 0);
speedtest1_prepare("SELECT count(*) FROM rt1 WHERE id MATCH xslice(?1,?2)");
@@ -1286,7 +1283,7 @@ void testset_rtree(int p1, int p2){
}
speedtest1_end_test();
n = g.szTest*80;
n = g.szTest*400;
speedtest1_begin_test(130, "%d three-dimensional intersect box queries", n);
speedtest1_prepare("SELECT count(*) FROM rt1 WHERE x1>=?1 AND x0<=?2"
" AND y1>=?1 AND y0<=?2 AND z1>=?1 AND z0<=?2");
@@ -1299,7 +1296,7 @@ void testset_rtree(int p1, int p2){
}
speedtest1_end_test();
n = g.szTest*100;
n = g.szTest*500;
speedtest1_begin_test(140, "%d rowid queries", n);
speedtest1_prepare("SELECT * FROM rt1 WHERE id=?1");
for(i=1; i<=n; i++){
@@ -1458,11 +1455,6 @@ int main(int argc, char **argv){
noSync = 1;
}else if( strcmp(z,"notnull")==0 ){
g.zNN = "NOT NULL";
#ifdef SQLITE_ENABLE_RBU
}else if( strcmp(z,"rbu")==0 ){
sqlite3ota_create_vfs("rbu", 0);
sqlite3_vfs_register(sqlite3_vfs_find("rbu"), 1);
#endif
}else if( strcmp(z,"pagesize")==0 ){
if( i>=argc-1 ) fatal_error("missing argument on %s\n", argv[i]);
pageSize = integerValue(argv[++i]);
+1 -1
View File
@@ -461,7 +461,7 @@ if {[info exists cmdlinearg]==0} {
}
{^-+backtrace=.+$} {
foreach {dummy cmdlinearg(backtrace)} [split $a =] break
sqlite3_memdebug_backtrace $value
sqlite3_memdebug_backtrace $cmdlinearg(backtrace)
}
{^-+binarylog=.+$} {
foreach {dummy cmdlinearg(binarylog)} [split $a =] break
+72
View File
@@ -0,0 +1,72 @@
# 2017 January 4
#
# 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 triggerF
ifcapable {!trigger} {
finish_test
return
}
foreach {tn sql log} {
1 { } { }
2 {
CREATE TRIGGER trd AFTER DELETE ON t1 BEGIN
INSERT INTO log VALUES(old.a || old.b || (SELECT count(*) FROM t1));
END;
} {1one2 2two1 3three1}
3 {
CREATE TRIGGER trd BEFORE DELETE ON t1 BEGIN
INSERT INTO log VALUES(old.a || old.b || (SELECT count(*) FROM t1));
END;
} {1one3 2two2 3three2}
4 {
CREATE TRIGGER tr1 AFTER DELETE ON t1 BEGIN
INSERT INTO log VALUES(old.a || old.b || (SELECT count(*) FROM t1));
END;
CREATE TRIGGER tr2 BEFORE DELETE ON t1 BEGIN
INSERT INTO log VALUES(old.a || old.b || (SELECT count(*) FROM t1));
END;
} {1one3 1one2 2two2 2two1 3three2 3three1}
} {
reset_db
do_execsql_test 1.$tn.0 {
PRAGMA recursive_triggers = on;
CREATE TABLE t1(a INT PRIMARY KEY, b) WITHOUT ROWID;
CREATE TABLE log(t);
}
execsql $sql
do_execsql_test 1.$tn.1 {
INSERT INTO t1 VALUES(1, 'one');
INSERT INTO t1 VALUES(2, 'two');
INSERT INTO t1 VALUES(3, 'three');
DELETE FROM t1 WHERE a=1;
INSERT OR REPLACE INTO t1 VALUES(2, 'three');
UPDATE OR REPLACE t1 SET a=3 WHERE a=2;
}
do_execsql_test 1.$tn.2 {
SELECT * FROM log ORDER BY rowid;
} $log
}
finish_test
+205
View File
@@ -0,0 +1,205 @@
# 2017 January 9
#
# 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 update2
db func repeat [list string repeat]
#-------------------------------------------------------------------------
# 1.1.* A one-pass UPDATE that does balance() operations on the IPK index
# that it is scanning.
#
# 1.2.* Same again, but with a WITHOUT ROWID table.
#
set nrow [expr 10]
do_execsql_test 1.1.0 {
CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
CREATE TABLE t2(a INTEGER PRIMARY KEY, b);
WITH s(i) AS ( SELECT 0 UNION ALL SELECT i+1 FROM s WHERE i<$nrow )
INSERT INTO t1(b) SELECT char((i % 26) + 65) FROM s;
INSERT INTO t2 SELECT * FROM t1;
}
do_execsql_test 1.1.1 {
UPDATE t1 SET b = repeat(b, 100)
}
do_execsql_test 1.1.2 {
SELECT * FROM t1;
} [db eval { SELECT a, repeat(b, 100) FROM t2 }]
do_execsql_test 1.2.0 {
DROP TABLE t1;
CREATE TABLE t1(a INT PRIMARY KEY, b) WITHOUT ROWID;
WITH s(i) AS ( SELECT 0 UNION ALL SELECT i+1 FROM s WHERE i<$nrow )
INSERT INTO t1(a, b) SELECT i+1, char((i % 26) + 65) FROM s;
}
#explain_i { UPDATE t1 SET b = repeat(b, 100) }
do_execsql_test 1.2.1 {
UPDATE t1 SET b = repeat(b, 100)
}
do_execsql_test 1.2.2 {
SELECT * FROM t1;
} [db eval { SELECT a, repeat(b, 100) FROM t2 }]
#-------------------------------------------------------------------------
# A one-pass UPDATE that does balance() operations on the IPK index
# that it is scanning.
#
do_execsql_test 2.1 {
CREATE TABLE t3(a PRIMARY KEY, b, c);
CREATE INDEX t3i ON t3(b);
} {}
do_execsql_test 2.2 { UPDATE t3 SET c=1 WHERE b=? } {}
do_execsql_test 2.3 { UPDATE t3 SET c=1 WHERE rowid=? } {}
#-------------------------------------------------------------------------
#
do_execsql_test 3.0 {
CREATE TABLE t4(a PRIMARY KEY, b, c) WITHOUT ROWID;
CREATE INDEX t4c ON t4(c);
INSERT INTO t4 VALUES(1, 2, 3);
INSERT INTO t4 VALUES(2, 3, 4);
}
do_execsql_test 3.1 {
UPDATE t4 SET c=c+2 WHERE c>2;
SELECT a, c FROM t4 ORDER BY a;
} {1 5 2 6}
#-------------------------------------------------------------------------
#
foreach {tn sql} {
1 {
CREATE TABLE b1(a INTEGER PRIMARY KEY, b, c);
CREATE TABLE c1(a INTEGER PRIMARY KEY, b, c, d)
}
2 {
CREATE TABLE b1(a INT PRIMARY KEY, b, c) WITHOUT ROWID;
CREATE TABLE c1(a INT PRIMARY KEY, b, c, d) WITHOUT ROWID;
}
} {
execsql { DROP TABLE IF EXISTS b1; DROP TABLE IF EXISTS c1; }
execsql $sql
do_execsql_test 4.$tn.0 {
CREATE UNIQUE INDEX b1c ON b1(c);
INSERT INTO b1 VALUES(1, 'a', 1);
INSERT INTO b1 VALUES(2, 'b', 15);
INSERT INTO b1 VALUES(3, 'c', 3);
INSERT INTO b1 VALUES(4, 'd', 4);
INSERT INTO b1 VALUES(5, 'e', 5);
INSERT INTO b1 VALUES(6, 'f', 6);
INSERT INTO b1 VALUES(7, 'g', 7);
}
do_execsql_test 4.$tn.1 {
UPDATE OR REPLACE b1 SET c=c+10 WHERE a BETWEEN 4 AND 7;
SELECT * FROM b1 ORDER BY a;
} {
1 a 1
3 c 3
4 d 14
5 e 15
6 f 16
7 g 17
}
do_execsql_test 4.$tn.2 {
CREATE INDEX c1d ON c1(d, b);
CREATE UNIQUE INDEX c1c ON c1(c, b);
INSERT INTO c1 VALUES(1, 'a', 1, 1);
INSERT INTO c1 VALUES(2, 'a', 15, 2);
INSERT INTO c1 VALUES(3, 'a', 3, 3);
INSERT INTO c1 VALUES(4, 'a', 4, 4);
INSERT INTO c1 VALUES(5, 'a', 5, 5);
INSERT INTO c1 VALUES(6, 'a', 6, 6);
INSERT INTO c1 VALUES(7, 'a', 7, 7);
}
do_execsql_test 4.$tn.3 {
UPDATE OR REPLACE c1 SET c=c+10 WHERE d BETWEEN 4 AND 7;
SELECT * FROM c1 ORDER BY a;
} {
1 a 1 1
3 a 3 3
4 a 14 4
5 a 15 5
6 a 16 6
7 a 17 7
}
do_execsql_test 4.$tn.4 { PRAGMA integrity_check } ok
do_execsql_test 4.$tn.5 {
DROP INDEX c1d;
DROP INDEX c1c;
DELETE FROM c1;
INSERT INTO c1 VALUES(1, 'a', 1, 1);
INSERT INTO c1 VALUES(2, 'a', 15, 2);
INSERT INTO c1 VALUES(3, 'a', 3, 3);
INSERT INTO c1 VALUES(4, 'a', 4, 4);
INSERT INTO c1 VALUES(5, 'a', 5, 5);
INSERT INTO c1 VALUES(6, 'a', 6, 6);
INSERT INTO c1 VALUES(7, 'a', 7, 7);
CREATE INDEX c1d ON c1(d);
CREATE UNIQUE INDEX c1c ON c1(c);
}
do_execsql_test 4.$tn.6 {
UPDATE OR REPLACE c1 SET c=c+10 WHERE d BETWEEN 4 AND 7;
SELECT * FROM c1 ORDER BY a;
} {
1 a 1 1
3 a 3 3
4 a 14 4
5 a 15 5
6 a 16 6
7 a 17 7
}
}
#-------------------------------------------------------------------------
#
do_execsql_test 5.0 {
CREATE TABLE x1(a INTEGER PRIMARY KEY, b, c);
CREATE INDEX x1c ON x1(b, c);
INSERT INTO x1 VALUES(1, 'a', 1);
INSERT INTO x1 VALUES(2, 'a', 2);
INSERT INTO x1 VALUES(3, 'a', 3);
}
do_execsql_test 5.1.1 {
UPDATE x1 SET c=c+1 WHERE b='a';
}
do_execsql_test 5.1.2 {
SELECT * FROM x1;
} {1 a 2 2 a 3 3 a 4}
do_test 5.2 {
catch { array unset A }
db eval { EXPLAIN UPDATE x1 SET c=c+1 WHERE b='a' } { incr A($opcode) }
set A(NotExists)
} {1}
finish_test
+31 -16
View File
@@ -121,29 +121,43 @@ if {$tcl_platform(platform)!="windows" || \
SELECT name FROM fsdir WHERE dir = '.' AND name = '.'
} {test.db .}
proc sort_files { names {nocase false} } {
if {$nocase && $::tcl_platform(platform) eq "windows"} {
return [lsort -nocase $names]
} else {
return [lsort $names]
}
}
proc list_root_files {} {
if {$::tcl_platform(platform) eq "windows"} {
set res [list]
foreach name [glob -directory $::env(fstreeDrive)/ -- *] {
set res [list]; set dir $::env(fstreeDrive)/; set names [list]
eval lappend names [glob -nocomplain -directory $dir -- *]
foreach name $names {
if {[string index [file tail $name] 0] eq "."} continue
if {[file attributes $name -hidden]} continue
if {[file attributes $name -system]} continue
lappend res $name
}
return $res
return [sort_files $res true]
} else {
return [string map {/ {}} [glob /*]]
return [sort_files [string map {/ {}} [glob -nocomplain -- /*]]]
}
}
proc list_files { pattern } {
if {$::tcl_platform(platform) eq "windows"} {
set res [list]
foreach name [glob -nocomplain $pattern] {
set res [list]; set names [list]
eval lappend names [glob -nocomplain -- $pattern]
foreach name $names {
if {[string index [file tail $name] 0] eq "."} continue
if {[file attributes $name -hidden]} continue
if {[file attributes $name -system]} continue
lappend res $name
}
return $res
return [sort_files $res]
} else {
return [glob -nocomplain $pattern]
return [sort_files [glob -nocomplain -- $pattern]]
}
}
@@ -153,18 +167,19 @@ if {$tcl_platform(platform)!="windows" || \
#
set res [list]
set root_files [list_root_files]
set num_root_files [llength $root_files]
set lim_root_files [expr {$num_root_files > 5 ? 5 : $num_root_files}]
foreach p [lrange $root_files 0 [expr {$lim_root_files - 1}]] {
foreach p $root_files {
if {$::tcl_platform(platform) eq "windows"} {
if {[regexp {\$} $p]} {incr lim_root_files -1} else {lappend res $p}
if {![regexp {\$} $p]} {lappend res $p}
} else {
lappend res "/$p"
}
}
do_execsql_test 3.1 [subst {
SELECT path FROM fstree WHERE path NOT GLOB '*\$*' LIMIT $lim_root_files;
}] $res
set num_root_files [llength $root_files]
do_test 3.1 {
sort_files [execsql {
SELECT path FROM fstree WHERE path NOT GLOB '*\$*' LIMIT $num_root_files;
}] true
} [sort_files $res true]
# Read all entries in the current directory.
#
@@ -182,7 +197,7 @@ if {$tcl_platform(platform)!="windows" || \
set res [contents $pwd]
do_execsql_test 3.2 {
SELECT path FROM fstree WHERE path GLOB $pwd ORDER BY 1
} [lsort $res]
} [sort_files $res]
# Add some sub-directories and files to the current directory.
#
+35
View File
@@ -0,0 +1,35 @@
#!/bin/bash
#
# A script for running speed tests using kvtest.
#
# The test database must be set up first. Recommended
# command-line:
#
# ./kvtest init kvtest.db --count 100K --size 12K --variance 5K
if test "$1" = ""
then
echo "Usage: $0 OUTPUTFILE [OPTIONS]"
exit
fi
NAME=$1
shift
OPTS="-DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_DIRECT_OVERFLOW_READ -DUSE_PREAD"
KVARGS="--count 100K --stats"
gcc -g -Os -I. $OPTS $* kvtest.c sqlite3.c -o kvtest
# First run using SQL
rm cachegrind.out.[1-9][0-9]*
valgrind --tool=cachegrind ./kvtest run kvtest.db $KVARGS 2>&1 | tee summary-kvtest-$NAME.txt
mv cachegrind.out.[1-9][0-9]* cachegrind.out.sql-$NAME
cg_anno.tcl cachegrind.out.sql-$NAME >cout-kvtest-sql-$NAME.txt
# Second run using the sqlite3_blob object
valgrind --tool=cachegrind ./kvtest run kvtest.db $KVARGS --blob-api 2>&1 | tee -a summary-kvtest-$NAME.txt
mv cachegrind.out.[1-9][0-9]* cachegrind.out.$NAME
cg_anno.tcl cachegrind.out.$NAME >cout-kvtest-$NAME.txt
# Diff the sqlite3_blob API analysis for non-trunk runs.
if test "$NAME" != "trunk"; then
fossil test-diff --tk cout-kvtest-trunk.txt cout-kvtest-$NAME.txt &
fi
+44 -27
View File
@@ -316,6 +316,31 @@ static int yyGrowStack(yyParser *p){
# define YYMALLOCARGTYPE size_t
#endif
/* Initialize a new parser that has already been allocated.
*/
void ParseInit(void *yypParser){
yyParser *pParser = (yyParser*)yypParser;
#ifdef YYTRACKMAXSTACKDEPTH
pParser->yyhwm = 0;
#endif
#if YYSTACKDEPTH<=0
pParser->yytos = NULL;
pParser->yystack = NULL;
pParser->yystksz = 0;
if( yyGrowStack(pParser) ){
pParser->yystack = &pParser->yystk0;
pParser->yystksz = 1;
}
#endif
#ifndef YYNOERRORRECOVERY
pParser->yyerrcnt = -1;
#endif
pParser->yytos = pParser->yystack;
pParser->yystack[0].stateno = 0;
pParser->yystack[0].major = 0;
}
#ifndef Parse_ENGINEALWAYSONSTACK
/*
** This function allocates a new parser.
** The only argument is a pointer to a function which works like
@@ -331,28 +356,11 @@ static int yyGrowStack(yyParser *p){
void *ParseAlloc(void *(*mallocProc)(YYMALLOCARGTYPE)){
yyParser *pParser;
pParser = (yyParser*)(*mallocProc)( (YYMALLOCARGTYPE)sizeof(yyParser) );
if( pParser ){
#ifdef YYTRACKMAXSTACKDEPTH
pParser->yyhwm = 0;
#endif
#if YYSTACKDEPTH<=0
pParser->yytos = NULL;
pParser->yystack = NULL;
pParser->yystksz = 0;
if( yyGrowStack(pParser) ){
pParser->yystack = &pParser->yystk0;
pParser->yystksz = 1;
}
#endif
#ifndef YYNOERRORRECOVERY
pParser->yyerrcnt = -1;
#endif
pParser->yytos = pParser->yystack;
pParser->yystack[0].stateno = 0;
pParser->yystack[0].major = 0;
}
if( pParser ) ParseInit(pParser);
return pParser;
}
#endif /* Parse_ENGINEALWAYSONSTACK */
/* The following function deletes the "minor type" or semantic value
** associated with a symbol. The symbol can be either a terminal
@@ -406,6 +414,18 @@ static void yy_pop_parser_stack(yyParser *pParser){
yy_destructor(pParser, yytos->major, &yytos->minor);
}
/*
** Clear all secondary memory allocations from the parser
*/
void ParseFinalize(void *p){
yyParser *pParser = (yyParser*)p;
while( pParser->yytos>pParser->yystack ) yy_pop_parser_stack(pParser);
#if YYSTACKDEPTH<=0
if( pParser->yystack!=&pParser->yystk0 ) free(pParser->yystack);
#endif
}
#ifndef Parse_ENGINEALWAYSONSTACK
/*
** Deallocate and destroy a parser. Destructors are called for
** all stack elements before shutting the parser down.
@@ -418,16 +438,13 @@ void ParseFree(
void *p, /* The parser to be deleted */
void (*freeProc)(void*) /* Function used to reclaim memory */
){
yyParser *pParser = (yyParser*)p;
#ifndef YYPARSEFREENEVERNULL
if( pParser==0 ) return;
if( p==0 ) return;
#endif
while( pParser->yytos>pParser->yystack ) yy_pop_parser_stack(pParser);
#if YYSTACKDEPTH<=0
if( pParser->yystack!=&pParser->yystk0 ) free(pParser->yystack);
#endif
(*freeProc)((void*)pParser);
ParseFinalize(p);
(*freeProc)(p);
}
#endif /* Parse_ENGINEALWAYSONSTACK */
/*
** Return the peak depth of the stack for a parser.
+20 -14
View File
@@ -18,6 +18,7 @@ set flagMeaning(Result1) {Acts as query when has one argument}
set flagMeaning(SchemaReq) {Schema required - "main" is default}
set flagMeaning(SchemaOpt) {Schema restricts name search if present}
set flagMeaning(NoColumns) {OP_ResultRow called with zero columns}
set flagMeaning(NoColumns1) {zero columns if RHS argument is present}
set pragma_def {
NAME: full_column_names
@@ -56,7 +57,7 @@ set pragma_def {
IF: !defined(SQLITE_OMIT_FLAG_PRAGMAS)
NAME: cache_spill
FLAG: Result0 SchemaReq
FLAG: Result0 SchemaReq NoColumns1
IF: !defined(SQLITE_OMIT_FLAG_PRAGMAS)
NAME: reverse_unordered_selects
@@ -149,12 +150,12 @@ set pragma_def {
ARG: SQLITE_CellSizeCk
NAME: default_cache_size
FLAG: NeedSchema Result0 SchemaReq
FLAG: NeedSchema Result0 SchemaReq NoColumns1
COLS: cache_size
IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED)
NAME: page_size
FLAG: Result0 SchemaReq
FLAG: Result0 SchemaReq NoColumns1
IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS)
NAME: secure_delete
@@ -183,14 +184,14 @@ set pragma_def {
IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS)
NAME: cache_size
FLAG: NeedSchema Result0 SchemaReq
FLAG: NeedSchema Result0 SchemaReq NoColumns1
IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS)
NAME: mmap_size
IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS)
NAME: auto_vacuum
FLAG: NeedSchema Result0 SchemaReq
FLAG: NeedSchema Result0 SchemaReq NoColumns1
IF: !defined(SQLITE_OMIT_AUTOVACUUM)
NAME: incremental_vacuum
@@ -198,20 +199,23 @@ set pragma_def {
IF: !defined(SQLITE_OMIT_AUTOVACUUM)
NAME: temp_store
FLAG: Result0
FLAG: Result0 NoColumns1
IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS)
NAME: temp_store_directory
FLAG: NoColumns1
IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS)
NAME: data_store_directory
FLAG: NoColumns1
IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS) && SQLITE_OS_WIN
NAME: lock_proxy_file
FLAG: NoColumns1
IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS) && SQLITE_ENABLE_LOCKING_STYLE
NAME: synchronous
FLAG: NeedSchema Result0 SchemaReq
FLAG: NeedSchema Result0 SchemaReq NoColumns1
IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS)
NAME: table_info
@@ -267,6 +271,7 @@ set pragma_def {
IF: defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_PARSER_TRACE)
NAME: case_sensitive_like
FLAG: NoColumns
NAME: integrity_check
FLAG: NeedSchema
@@ -278,34 +283,37 @@ set pragma_def {
IF: !defined(SQLITE_OMIT_INTEGRITY_CHECK)
NAME: encoding
FLAG: Result0
FLAG: Result0 NoColumns1
IF: !defined(SQLITE_OMIT_UTF16)
NAME: schema_version
TYPE: HEADER_VALUE
ARG: BTREE_SCHEMA_VERSION
FLAG: NoColumns1 Result0
IF: !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
NAME: user_version
TYPE: HEADER_VALUE
ARG: BTREE_USER_VERSION
FLAG: NoColumns1 Result0
IF: !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
NAME: data_version
TYPE: HEADER_VALUE
ARG: BTREE_DATA_VERSION
FLAG: ReadOnly
FLAG: ReadOnly Result0
IF: !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
NAME: freelist_count
TYPE: HEADER_VALUE
ARG: BTREE_FREE_PAGE_COUNT
FLAG: ReadOnly
FLAG: ReadOnly Result0
IF: !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
NAME: application_id
TYPE: HEADER_VALUE
ARG: BTREE_APPLICATION_ID
FLAG: NoColumns1 Result0
IF: !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
NAME: compile_options
@@ -321,6 +329,7 @@ set pragma_def {
IF: !defined(SQLITE_OMIT_WAL)
NAME: shrink_memory
FLAG: NoColumns
NAME: busy_timeout
FLAG: Result0
@@ -408,10 +417,7 @@ foreach line [split $pragma_def \n] {
} elseif {$id=="TYPE"} {
set type $val
if {$type=="FLAG"} {
lappend flags Result0 NoColumns
}
if {$type=="HEADER_VALUE"} {
lappend flags Result0
lappend flags Result0 NoColumns1
}
} elseif {$id=="ARG"} {
set arg $val
+19 -3
View File
@@ -23,6 +23,7 @@ NAME=$1
shift
#CC_OPTS="-DSQLITE_ENABLE_RTREE -DSQLITE_ENABLE_MEMSYS5"
CC_OPTS="-DSQLITE_ENABLE_MEMSYS5"
CC=gcc
SPEEDTEST_OPTS="--shrink-memory --reprepare --stats --heap 10000000 64"
SIZE=5
LEAN_OPTS="-DSQLITE_THREADSAFE=0"
@@ -80,11 +81,19 @@ while test "$1" != ""; do
--lean)
CC_OPTS="$CC_OPTS $LEAN_OPTS"
;;
--clang)
CC=clang
;;
--heap)
CC_OPTS="$CC_OPTS -DSQLITE_ENABLE_MEMSYS5"
shift;
SPEEDTEST_OPTS="$SPEEDTEST_OPTS --heap $1 64"
;;
--lookaside)
shift;
SPEEDTEST_OPTS="$SPEEDTEST_OPTS --lookaside $1 $2"
shift;
;;
--repeat)
CC_OPTS="$CC_OPTS -DSQLITE_ENABLE_RCACHE"
shift;
@@ -94,6 +103,10 @@ while test "$1" != ""; do
shift;
SPEEDTEST_OPTS="$SPEEDTEST_OPTS --mmap $1"
;;
--rtree)
SPEEDTEST_OPTS="$SPEEDTEST_OPTS --testset rtree"
CC_OPTS="$CC_OPTS -DSQLITE_ENABLE_RTREE"
;;
*)
CC_OPTS="$CC_OPTS $1"
;;
@@ -105,15 +118,15 @@ echo "NAME = $NAME" | tee summary-$NAME.txt
echo "SPEEDTEST_OPTS = $SPEEDTEST_OPTS" | tee -a summary-$NAME.txt
echo "CC_OPTS = $CC_OPTS" | tee -a summary-$NAME.txt
rm -f cachegrind.out.* speedtest1 speedtest1.db sqlite3.o
gcc -g -Os -Wall -I. $CC_OPTS -c sqlite3.c
$CC -g -Os -Wall -I. $CC_OPTS -c sqlite3.c
size sqlite3.o | tee -a summary-$NAME.txt
if test $doExplain -eq 1; then
gcc -g -Os -Wall -I. $CC_OPTS \
$CC -g -Os -Wall -I. $CC_OPTS \
-DSQLITE_ENABLE_EXPLAIN_COMMENTS \
./shell.c ./sqlite3.c -o sqlite3 -ldl -lpthread
fi
SRC=./speedtest1.c
gcc -g -Os -Wall -I. $CC_OPTS $SRC ./sqlite3.o -o speedtest1 -ldl -lpthread
$CC -g -Os -Wall -I. $CC_OPTS $SRC ./sqlite3.o -o speedtest1 -ldl -lpthread
ls -l speedtest1 | tee -a summary-$NAME.txt
if test $doCachegrind -eq 1; then
valgrind --tool=cachegrind ./speedtest1 speedtest1.db \
@@ -129,3 +142,6 @@ fi
if test $doExplain -eq 1; then
./speedtest1 --explain $SPEEDTEST_OPTS | ./sqlite3 >explain-$NAME.txt
fi
if test "$NAME" != "trunk"; then
fossil test-diff --tk cout-trunk.txt cout-$NAME.txt
fi