Compare commits

...

72 Commits

Author SHA1 Message Date
drh cf025a8c18 Fix the assert()s in the byte-code engine that prove that cursors
are unidirectional.

FossilOrigin-Name: 4b0b4e14039469b656662312a5f80f086ede293e9ad04c7bc99a202b683a1e55
2018-06-07 18:01:21 +00:00
drh f1949b6634 Remove the NextIfOpen and PrevIfOpen opcodes which are no longer needed
when the IN-early-out optimization is working.

FossilOrigin-Name: 439c8162272795b422a0e01b01b832fbc12b39914c9632a674162af8bdecff98
2018-06-07 17:32:59 +00:00
drh 056f5396fe Test cases.
FossilOrigin-Name: 085e863713a3f2d420c0076b275a6ac445a59d4d93f9eb0e8503b4e3f5589249
2018-06-07 16:07:00 +00:00
drh 64c1f77a8e Merge the ".stat/.eqp" CLI fix from trunk.
FossilOrigin-Name: a91cad3381bb843d6f58975251bf99f0fa1a1398fae53d97a98a6c8ee65e718e
2018-06-07 15:28:40 +00:00
drh 3c49eaf4be Avoid using a prepared statement for ".stats on" after it has been closed
by the ".eqp full" logic.  Fix for ticket [7be932dfa60a8a6b3b26bcf76].

FossilOrigin-Name: bb87c054b1b76959e46258ac66b24027f468b390a4148ac67f208a1fbeda4060
2018-06-07 15:23:43 +00:00
drh f7b0a5f3c3 Add the WHERE_IN_EARLYOUT flag and use it to clarify the logic of this
optimization.

FossilOrigin-Name: 522f1eacc20f11002cad58232a7c2610f369568653510e54f46088f579f778dc
2018-06-07 14:59:22 +00:00
drh bd573c459b Merge recent trunk enhancements.
FossilOrigin-Name: e9d7bf4f7b9d6f8dabc4c95d43ebf12f2149bed1c5e750048b1b684128073c38
2018-06-07 14:32:16 +00:00
drh df12595c09 Change a comma into a logically equivalent but semantically clearer semicolon.
FossilOrigin-Name: 71f97f0f82b3abfb07feb78d64a182fc50ff396e85d6f5aac479dbf58ba4d00a
2018-06-06 23:31:26 +00:00
drh 6eb3480bd7 More space and performance enhancements to sqlite3VdbeRecordCompare().
FossilOrigin-Name: 83a60ff056a63f18479030e9dfb10926fbb0d906d51f2cf88233098e15c75534
2018-06-06 20:55:10 +00:00
drh d882108a01 Small performance optimization in sqlite3VdbeRecordCompareWithSkip() for
the common case where the comparison is equal.

FossilOrigin-Name: 1e616e256a4fb1b64271706fdfa77dc5790eba0a2f0e619544e169bc61d7c805
2018-06-06 20:29:19 +00:00
drh 4011c44322 Rearrange the order of some checks in the integrity_check pragma for a very
slight performance gain.

FossilOrigin-Name: 4b853f020570bf4af1b14e03f35764c7d7a03a40af58efc783e06f2b883cef78
2018-06-06 19:48:19 +00:00
drh 685a50ad74 Fix the sqlite3BeginTrans() calls within the snapshot extension.
FossilOrigin-Name: 1fef7ad25b6a8e59163ac57f5cf0412bfc5b0e9446fd782f5f0a7d7ee11741fc
2018-06-06 18:50:50 +00:00
drh 397776a823 Another minor optimization to OP_Transaction.
FossilOrigin-Name: d80077aee3904e5d93164b342cae14d813de8e84e567462412751e06c7487d41
2018-06-06 17:45:51 +00:00
drh bb2d9b1bf1 Change sqlite3BtreeBeginTrans() to return the BTREE_SCHEMA_COOKIE, for a
small speed improvement when starting new transactions.

FossilOrigin-Name: a10662aa915ae2b5a78b3e10920350d32255b2d6b1a8aac0aba1ad173b07ed2b
2018-06-06 16:28:40 +00:00
drh 0cfd46a1ad Fix the ".archive" command in the CLI (and the corresponding -A command-line
option) so that it silently ignores filenames that contain "../" in their
names.  This prevents the "Zip Slip" attack.

FossilOrigin-Name: 27291f2d7fd4dadf2ee9b9a7d1373158cadfbaf83c3654b00d7030dc921770c6
2018-06-06 01:18:01 +00:00
drh bb777d517d Update the version number to 3.25.0 for the next development cycle.
FossilOrigin-Name: 7598236c356cdb548c6188d69dfef99f7a08b89e512a3addfe1433ccd85e7b68
2018-06-05 23:51:52 +00:00
drh 48baed4f77 Avoid unnecessary loads of columns in an aggregate query that are not
within an aggregate function and that are not part of the GROUP BY clause.

FossilOrigin-Name: e15e100660d290249ef235e7a8927b88296e56ec0f80ec626eecbd542adc7633
2018-06-05 23:21:11 +00:00
drh 8c2b6d784b Add the OP_IfNoHope and OP_SeekHit opcodes used to reduce the number of
unnecessary sqlite3BtreeMovetoUnpacked() calls when checking for an early
exit on IN-operator loops.  Futher optimizations are likely possible here.

FossilOrigin-Name: 6bf251af4347165a470d39457d61ab6d2a06c206db8f30bd8be5dbb388ae8a5b
2018-06-05 20:45:20 +00:00
dan 280c894b74 Calculate non-aggregate expressions in the SELECT list of an aggregate query
that does not use min() or max() once per group, instead of once per row
visited.

FossilOrigin-Name: dce2dfbe1590deb3ef5661230ae2d232bd492441195defbf698ac56f9629211c
2018-06-05 20:04:28 +00:00
drh 86d0ea7558 Use an OP_NotFound opcode to cancel futile IN operators early. The current
implementation is suboptimal because it always runs teh OP_NotFound.  This
still needs to be enhanced to only do the OP_NotFound if no results have been
seen on the current loop.

FossilOrigin-Name: 87a9fc504f9a78caf7a7949cc7ada0a19d61bfab51bb49a00a1607194c116212
2018-06-05 15:16:25 +00:00
drh 995bbbf993 Merge trunk changes.
FossilOrigin-Name: 047295c588e9fdf2ffa4e69e166f177fd193309531dc6a9ac755fb7a763adb72
2018-06-05 13:54:06 +00:00
drh 8e9deb61af Update and correct the documentation on the OP_OpenRead, OP_OpenWrite,
and OP_ReopenIdx opcodes.  No code changes other than the addition of
an assert().

FossilOrigin-Name: 8a0b730d0ea640d5cf75febe39b2162411a12eb5275765a85882158b5a085681
2018-06-05 13:43:02 +00:00
drh 00583291bd Version 3.24.0
FossilOrigin-Name: c7ee0833225bfd8c5ec2f9bf62b97c4e04d03bd9566366d5221ac8fb199a87ca
2018-06-04 19:24:41 +00:00
drh 6b27f5fab7 Merge recent changes from trunk.
FossilOrigin-Name: f8df2a8e28acdd9573a9ffc18027553f35f769a989f5dfbf81f31b0656ee6065
2018-06-04 13:27:39 +00:00
drh eb7df46e32 Avoid using a misaligned pointer.
FossilOrigin-Name: 1ecb3aa13de5c8dc611b814ff34010de0bd90aae73d88aa37a59c4627be4cc2d
2018-06-02 19:14:58 +00:00
drh 1fb7a60ca0 Fix the usage of posix_fallocate() so that it correctly responds to
EINVAL returns.

FossilOrigin-Name: ce2c3e7a875ede4366c48660ae8239d2b74e5f690ad5059844a45f1164f41e61
2018-06-02 19:01:54 +00:00
dan 69a4b383a2 Update a test case in malloc5.test to take into account that malloc()
sometimes returns slightly more space than requested.

FossilOrigin-Name: 3d5eae1c26353cdee89f31f1293b05c0edb494c775ba0912d9b4fda9ab0ef304
2018-06-02 17:00:57 +00:00
drh 5ba5f5b5d2 Work around a sanitizer warning about a pointer being only 4-byte aligned
instead of 8-byte aligned.

FossilOrigin-Name: 1b807b51cdf455b4f54216b73fd22bbc90f94e24222401e045f88cfd27f487e3
2018-06-02 16:32:04 +00:00
drh 789df14b11 Proposed fix for the use of posix_fallocate() so that it handles EINVAL
returns correctly.

FossilOrigin-Name: ab3a5539db82814cafb832cdaebd1e14566139306453ef9cdba6b244a994fe0b
2018-06-02 14:37:39 +00:00
drh e893e2e4ee Fix the CSV extension so that it works with single-column CSV files.
FossilOrigin-Name: e336cf00486bdc0ec04ecded2b7c874d73a87e6aba3544e3678bedfb9a4af3b6
2018-06-02 12:05:18 +00:00
drh 4344dbd3ab Ensure that sqlite3AuthRead() is only call for TK_COLUMN and TK_TRIGGER
expression nodes.  This fixes a harmless assert() identified by OSSFuzz.
Move the assert() into a position where it is tested even if the authorizer
is disabled.

FossilOrigin-Name: d0c3beef7cdc680c0768ddd18f766a4ca7be822c1eb1776b2f73b7433d9962dc
2018-06-02 11:31:15 +00:00
dan 0f86c9d8fa Fix a bug in the SQLITE_ENABLE_SORTER_REFERENCES code causing an out-of-bounds
array reference.

FossilOrigin-Name: 8cadaf587dc96370f9c8a1dccc366b93021e8cfe4526da9368a088828fd14faf
2018-06-01 13:30:45 +00:00
drh 416a801600 More documentation typo fixes. No code changes.
FossilOrigin-Name: 66c24513c2f6de98bd888c3e4c07bbb39fabf30ea9dd01eb255460054055347d
2018-05-31 19:14:52 +00:00
drh 8cdafc384e Fix a harmless typo in a comment used to generate documentation.
FossilOrigin-Name: 5a2a88cb01ef4b299f9a5b2963f392a3bae90e8a7f84b190e67f86090f891e23
2018-05-31 19:00:20 +00:00
drh fc232d6f65 Add the Makefile.fallback makefile to the amalgamation tarball.
FossilOrigin-Name: ce3d04563337c9556d66e55acfb454789b0baa49a1be8fcc349251ce88236d62
2018-05-30 14:17:09 +00:00
drh 5d3112872d Do not use the codec on the resetdb.test script.
FossilOrigin-Name: fe55cea0c80ab29120574c5c4a8473b83fc80f79d7e11bc7c326bfdb32aa3902
2018-05-30 07:36:55 +00:00
drh 8e02a180b9 Fix a typo in an error message in the CLI.
FossilOrigin-Name: 808839808141493c1e5122f40b2cdff725be0cd1212e03d609345dbff7af03e4
2018-05-30 07:24:41 +00:00
drh 6a8b94e266 Fix the parser so that it builds with -DSQLITE_OMIT_CTE.
FossilOrigin-Name: 86ee267ee86f5264774a9f215b1158aeaa2d605e77c205731b5ee3945d7de4c2
2018-05-30 01:14:20 +00:00
drh 3e62ddbf13 Fix a harmless compiler warning.
FossilOrigin-Name: 8d02c7a6a09f7520ad180b0d943db475894cd39b0ccdb2ad2c44009d5f25c8a6
2018-05-30 00:59:09 +00:00
drh a0368d9396 Demonstration code on a possible technique for optimizing the use of IN
operator on columns to the right of multicolumn indexes.  If the OP_Noop
generated where were really a new opcode that checked to see if there existed
any entries in the index with a matching prefix, it might prevent unnecessary
iterations of the IN operator.

FossilOrigin-Name: 92f0fe155d5546fc7f4a443d0630613dabe149061966308e5420fad652278f16
2018-05-30 00:54:23 +00:00
dan ea93e2804d Increase the number of database handles opened by test script oserror.test to
provoke an "out of file-descriptors" error to 20000 (from 2000).

FossilOrigin-Name: 3b00f73456c65dfc1827fdada9afb49245f9addfa684d5ae35e69a07f39164bf
2018-05-29 19:12:58 +00:00
dan 867e6de4d7 Fix autoinc.test and resetdb.test so that they work with all permutations.
FossilOrigin-Name: 89f56d6b0a6847b042a1556cdf79c598c9bfdbdd5f9529d508ca7b4d26a6ed38
2018-05-29 16:37:12 +00:00
drh 59ee43a78e Add a comment to justify a goto statement. No code changes.
FossilOrigin-Name: f141d806476aabe592a15d83b72c9409d2cd6bd7f9cced1ea2513c134191430a
2018-05-29 15:18:31 +00:00
dan 1d40cdbd4b More minor changes to test scripts.
FossilOrigin-Name: ce9b756f09df4feb485bbf9695f8c6774906eb1b2fb45a340b74ffd21c9adfd8
2018-05-29 14:29:28 +00:00
dan d3e17ffbb7 Fix some test script issues caused by recent EXPLAIN QUERY PLAN enhancements.
FossilOrigin-Name: f808e22831c33bfe3d0dd44e209f64d527c23ca7c72be7c694736535afee1317
2018-05-29 14:06:55 +00:00
dan 66e82b47d9 Do not run test file "resetdb.test" as part of permutation "inmemory_journal".
FossilOrigin-Name: 4921e5bae4c12c3413cc0b2e58766cf2ac117ad95f92fcd1c2457db6cfabb054
2018-05-29 13:25:14 +00:00
dan fecfb3189b Do not require a statement journal in cases where REPLACE conflict handling is
used to insert a single row, so long as the REPLACE operation cannot fire any
triggers or foreign key actions.

FossilOrigin-Name: 469a62ca33081854e54f3af6d93ab5a350484b149c8c8c4ee8be0ae5418382d9
2018-05-28 18:29:46 +00:00
drh 50baf3d525 When compiling with SQLITE_DEBUG, add run-time checks to ensure that no statement aborts unless either there have been no writes or else there is a statement journal.
FossilOrigin-Name: ce99c7724460b9cf4ccaf7f6bc1a522b5c34d5ad0683d465f7926b10f31f7d05
2018-05-28 18:25:19 +00:00
drh 341141c339 Fix the build so that it works with -DSQLITE_TEST_REALLOC_STRESS
FossilOrigin-Name: 90ba2b2e5ce2619e68879eb325b43639159f27eb462b9fb6795534c91200a3d2
2018-05-28 17:43:28 +00:00
drh 4031bafafb When compiling with SQLITE_DEBUG, add run-time checks to ensure that no
statement aborts unless either there have been no writes or else there is
a statement journal.

FossilOrigin-Name: 5a4542dbcf17a9f7fed600897555c271e1651fd50eb41d0b126725b486e1d14c
2018-05-28 17:31:20 +00:00
drh 9201184711 Store application-defined function names as lower-case to avoid the need
for case conversions before calling xFindFunction on virtual tables.
Avoid using lookaside to store the destructors for application defined
functions, as lookaside should be reserved for transient allocations.

FossilOrigin-Name: 777189ce88799f93f393fd14fd716111c85bcdcb23690fd561f78ea2bd2ce5da
2018-05-26 16:00:26 +00:00
drh 7fc86b96ba Add a single sentence of documentation about the virtual table
scan flags.  No changes to code.

FossilOrigin-Name: 27b4fa5dd0defc6ddaf5d8cde6a1e1162b70d99bfdc69c1d2290621a6d23ed91
2018-05-26 13:55:04 +00:00
drh 338e311acb When doing a one-pass UPDATE or DELETE on virtual tables, close the cursor
prior to running VUpdate.  This allows one-pass to work on virtual tables
that do not allow concurrent reads and writes.  Enhance rtree to take
advantage of this new capability.

FossilOrigin-Name: b816023ce07d01024d5769e16db924374a49bf909edd12dc1344a0a1ef693db5
2018-05-24 23:51:57 +00:00
drh 30fc7f8009 New test case for reading and writing the same rtree concurrently.
FossilOrigin-Name: 3ba08e53d54165f5541756ad13a4c2f0b18516cb612a256e056ed1ff76c1fa83
2018-05-24 22:42:27 +00:00
drh c8c9cdd9dd Do not allow RTree writes when a read cursor is active on the same virtual
table, as the writes might rebalance and disrupt the read cursors.  Return
the new SQLITE_LOCKED_VTAB error code if this happens.

FossilOrigin-Name: d4ce66610851c825cb712f985216b63e015c753fdd5521f929c67ad18bfd7664
2018-05-24 22:31:01 +00:00
drh b9cd2c4536 In the OOM testing logic, add the sqlite3FirstFault() routine as a place to
set a breakpoint the first time any simulated OOM fault occurs for a single
test case.

FossilOrigin-Name: b4d80bd287ca7f3a6d182ba2435273266035b94fdf6a44047a64a4eff931c571
2018-05-24 17:38:00 +00:00
drh bbd574bc37 Fix a typo in a comment used to generate VDBE opcode documentation. No
code changes.

FossilOrigin-Name: 36cdfbf2ce1811691c790fde3eaeed0238c03b4dc97dc3a20d1e0397520145d1
2018-05-24 17:25:35 +00:00
drh cf8784cd8f Addition cases for rtree preformance testing in speedtest1.c. Add the
--nodiff option to the speed-check.sh script.

FossilOrigin-Name: 95f2d62cf3cf8dbe0f12b652b47fe1f8e0f52bc269e269955fafdf802afc47c1
2018-05-24 16:18:35 +00:00
drh 7458a9f3f7 Updates to the sqlite3_vtab_nochange() documentation. No changes to code.
FossilOrigin-Name: 5bd99abc10b8153aadff5f815ae15fbe375f34f043c65def4be03014d2efdb50
2018-05-24 13:59:45 +00:00
drh 4c57e326ef Remove a branch that is no longer used due to the fix to the
sqlite_sequence schema problem, ticket
[d8dc2b3a58cd5dc2918a1d4acbba4676a23ada4c]

FossilOrigin-Name: 066742692a9e8735b814c6a145545f97a7fb10b29cead78e68e25324e79aabaa
2018-05-23 17:53:07 +00:00
drh 186ebd41cf Verify that the sqlite_sequence table exists and is in approximately the
correct format prior to using it to process an autoincrement table.
Fix for ticket [d8dc2b3a58cd5dc2918a1d4a].

FossilOrigin-Name: e199e859ace4f8381c6380175206e7a276e3f2228fadbbca9341bca8d2fc445d
2018-05-23 16:50:21 +00:00
drh e8cf689df3 Add support for auxiliary columns to the rtree extension.
FossilOrigin-Name: c6071ac99cfa4b6272ac4d739fc61a85acb544f6c1c2ae67b31e92aadcc995bd
2018-05-18 17:58:33 +00:00
drh 16d261b3ef Merge enhancements from trunk, especially the CLI fixes.
FossilOrigin-Name: a350040a3bb962823f92908fb31cade52baf13eab90ef608ca3a8349e4c28c9d
2018-05-18 17:17:36 +00:00
drh 9e80403bfc In the CLI, detect and report errors on sqlite3_close(). Clear global
variables prior to exit to so that valgrind can better detect resource
leaks.

FossilOrigin-Name: e3b2e0a078b82ac6cd3c3312e8ac0983c1375e1052f1e324476d2f8d1b227c30
2018-05-18 17:11:50 +00:00
drh a02fd67b99 Avoid unnecessary sqlite3_finalize() operations.
FossilOrigin-Name: 16f71032a3a2919cb226b25b5256a370adb5c55fa506d4774b7f83dc8868e793
2018-05-18 16:53:07 +00:00
drh 136c9903bf Fix a prepare-statement leak.
FossilOrigin-Name: 95fd296ffc8130526a1453cbdca6ce47f22fc5b5c474aa31d66b627d0c7393a1
2018-05-18 16:46:09 +00:00
drh 252f39619a Improved error messages. Limit the number of auxiliary columns to 100.
FossilOrigin-Name: 059d20abd57727e6d312f15b640359ef778786f577d9b50b17b57195db2d0aef
2018-05-18 15:21:43 +00:00
drh bc30e2023b Improvements to integer/float comparisons on architectures that lack a
"long double" type.

FossilOrigin-Name: 5139ea62a8a6c6dc6558c337de39bcbadd26f6515742263387be03c862c78cf0
2018-05-18 14:24:23 +00:00
drh 26fb126622 Fix an issue with rtreecheck() and auxiliary data columns.
FossilOrigin-Name: 46715136078a51ca7dd08b83214d6ad0e85728af8a26cd342077b8dd4ada1d60
2018-05-16 19:56:20 +00:00
drh 7578456c25 Do not allow auxiliary columns in the rtree to interfere with query planning.
Begin adding test cases.

FossilOrigin-Name: 9abe023e1afa7dc1a7eba7fbb3128401de129873d86b7c71c221decca26a821c
2018-05-16 19:07:07 +00:00
drh 1e76c22b4a Fix the OOM issue mentioned in the previous check-in.
FossilOrigin-Name: c489d8e44eac4cd355096ab66bb40f13ef662f31e080c9f1f2ee379fe55b207a
2018-05-16 18:18:24 +00:00
drh e297196524 Initial implementation of the ability to have auxiliary columns in an rtree
virtual table that store arbitrary content.  It mostly works, but there are
some minor issues in OOM corner cases.

FossilOrigin-Name: 0c87fec970221f954e0a92f3ef0437b382255479fac5b403ee37b1bb5ab29719
2018-05-16 17:57:30 +00:00
69 changed files with 1458 additions and 465 deletions
+1 -1
View File
@@ -1 +1 @@
3.24.0
3.25.0
+1 -1
View File
@@ -14,7 +14,7 @@ sqlite3_CFLAGS = $(AM_CFLAGS) -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_D
include_HEADERS = sqlite3.h sqlite3ext.h
EXTRA_DIST = sqlite3.1 tea Makefile.msc sqlite3.rc README.txt Replace.cs
EXTRA_DIST = sqlite3.1 tea Makefile.msc sqlite3.rc README.txt Replace.cs Makefile.fallback
pkgconfigdir = ${libdir}/pkgconfig
pkgconfig_DATA = sqlite3.pc
+19
View File
@@ -0,0 +1,19 @@
#!/usr/bin/make
#
# If the configure script does not work, then this Makefile is available
# as a backup. Manually configure the variables below.
#
# Note: This makefile works out-of-the-box on MacOS 10.2 (Jaguar)
#
CC = gcc
CFLAGS = -O0 -I.
LIBS = -lz
COPTS += -D_BSD_SOURCE
COPTS += -DSQLITE_ENABLE_LOCKING_STYLE=0
COPTS += -DSQLITE_THREADSAFE=0
COPTS += -DSQLITE_OMIT_LOAD_EXTENSION
COPTS += -DSQLITE_WITHOUT_ZONEMALLOC
COPTS += -DSQLITE_ENABLE_RTREE
sqlite3: shell.c sqlite3.c
$(CC) $(CFLAGS) $(COPTS) -o sqlite3 shell.c sqlite3.c $(LIBS)
Vendored
+9 -9
View File
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.69 for sqlite 3.24.0.
# Generated by GNU Autoconf 2.69 for sqlite 3.25.0.
#
#
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
@@ -726,8 +726,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='sqlite'
PACKAGE_TARNAME='sqlite'
PACKAGE_VERSION='3.24.0'
PACKAGE_STRING='sqlite 3.24.0'
PACKAGE_VERSION='3.25.0'
PACKAGE_STRING='sqlite 3.25.0'
PACKAGE_BUGREPORT=''
PACKAGE_URL=''
@@ -1465,7 +1465,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
\`configure' configures sqlite 3.24.0 to adapt to many kinds of systems.
\`configure' configures sqlite 3.25.0 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1530,7 +1530,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
short | recursive ) echo "Configuration of sqlite 3.24.0:";;
short | recursive ) echo "Configuration of sqlite 3.25.0:";;
esac
cat <<\_ACEOF
@@ -1655,7 +1655,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
sqlite configure 3.24.0
sqlite configure 3.25.0
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2074,7 +2074,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
It was created by sqlite $as_me 3.24.0, which was
It was created by sqlite $as_me 3.25.0, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -12242,7 +12242,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
This file was extended by sqlite $as_me 3.24.0, which was
This file was extended by sqlite $as_me 3.25.0, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -12308,7 +12308,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
sqlite config.status 3.24.0
sqlite config.status 3.25.0
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
-1
View File
@@ -286,7 +286,6 @@ do_setup_rec_test $tn.14 {
INSERT INTO t9 VALUES(?, ?, ?);
} {
CREATE INDEX t10_idx_00000062 ON t10(b);
-- TRIGGER t9t
SEARCH TABLE t10 USING INDEX t10_idx_00000062 (b=?)
}
+3 -1
View File
@@ -1152,7 +1152,9 @@ int idxFindIndexes(
}
}
pStmt->zEQP = idxAppendText(&rc, pStmt->zEQP, "%s\n", zDetail);
if( zDetail[0]!='-' ){
pStmt->zEQP = idxAppendText(&rc, pStmt->zEQP, "%s\n", zDetail);
}
}
for(pEntry=hIdx.pFirst; pEntry; pEntry=pEntry->pNext){
+4 -5
View File
@@ -205,7 +205,8 @@ static int csv_append(CsvReader *p, char c){
** + Store the character that terminates the field in p->cTerm. Store
** EOF on end-of-file.
**
** Return "" at EOF. Return 0 on an OOM error.
** Return 0 at EOF or on OOM. On EOF, the p->cTerm character will have
** been set to EOF.
*/
static char *csv_read_one_field(CsvReader *p){
int c;
@@ -213,7 +214,7 @@ static char *csv_read_one_field(CsvReader *p){
c = csv_getc(p);
if( c==EOF ){
p->cTerm = EOF;
return "";
return 0;
}
if( c=='"' ){
int pc, ppc;
@@ -544,8 +545,7 @@ static int csvtabConnect(
pNew->nCol = nCol;
}else{
do{
const char *z = csv_read_one_field(&sRdr);
if( z==0 ) goto csvtab_connect_oom;
csv_read_one_field(&sRdr);
pNew->nCol++;
}while( sRdr.cTerm==',' );
}
@@ -663,7 +663,6 @@ static int csvtabNext(sqlite3_vtab_cursor *cur){
do{
z = csv_read_one_field(&pCur->rdr);
if( z==0 ){
csv_xfer_error(pTab, &pCur->rdr);
break;
}
if( i<pTab->nCol ){
+244 -88
View File
@@ -24,14 +24,15 @@
**
** CREATE TABLE %_node(nodeno INTEGER PRIMARY KEY, data BLOB)
** CREATE TABLE %_parent(nodeno INTEGER PRIMARY KEY, parentnode INTEGER)
** CREATE TABLE %_rowid(rowid INTEGER PRIMARY KEY, nodeno INTEGER)
** CREATE TABLE %_rowid(rowid INTEGER PRIMARY KEY, nodeno INTEGER, ...)
**
** The data for each node of the r-tree structure is stored in the %_node
** table. For each node that is not the root node of the r-tree, there is
** an entry in the %_parent table associating the node with its parent.
** And for each row of data in the table, there is an entry in the %_rowid
** table that maps from the entries rowid to the id of the node that it
** is stored on.
** is stored on. If the r-tree contains auxiliary columns, those are stored
** on the end of the %_rowid table.
**
** The root node of an r-tree always exists, even if the r-tree table is
** empty. The nodeno of the root node is always 1. All other nodes in the
@@ -94,6 +95,9 @@ typedef struct RtreeSearchPoint RtreeSearchPoint;
/* The rtree may have between 1 and RTREE_MAX_DIMENSIONS dimensions. */
#define RTREE_MAX_DIMENSIONS 5
/* Maximum number of auxiliary columns */
#define RTREE_MAX_AUX_COLUMN 100
/* Size of hash table Rtree.aHash. This hash table is not expected to
** ever contain very many entries, so a fixed number of buckets is
** used.
@@ -122,12 +126,15 @@ struct Rtree {
u8 eCoordType; /* RTREE_COORD_REAL32 or RTREE_COORD_INT32 */
u8 nBytesPerCell; /* Bytes consumed per cell */
u8 inWrTrans; /* True if inside write transaction */
u8 nAux; /* # of auxiliary columns in %_rowid */
int iDepth; /* Current depth of the r-tree structure */
char *zDb; /* Name of database containing r-tree table */
char *zName; /* Name of r-tree table */
u32 nBusy; /* Current number of users of this structure */
i64 nRowEst; /* Estimated number of rows in this table */
u32 nCursor; /* Number of open cursors */
u32 nNodeRef; /* Number RtreeNodes with positive nRef */
char *zReadAuxSql; /* SQL for statement to read aux data */
/* List of nodes removed during a CondenseTree operation. List is
** linked together via the pointer normally used for hash chains -
@@ -154,6 +161,9 @@ struct Rtree {
sqlite3_stmt *pWriteParent;
sqlite3_stmt *pDeleteParent;
/* Statement for writing to the "aux:" fields, if there are any */
sqlite3_stmt *pWriteAux;
RtreeNode *aHash[HASHSIZE]; /* Hash table of in-memory nodes. */
};
@@ -230,6 +240,7 @@ struct RtreeCursor {
sqlite3_vtab_cursor base; /* Base class. Must be first */
u8 atEOF; /* True if at end of search */
u8 bPoint; /* True if sPoint is valid */
u8 bAuxValid; /* True if pReadAux is valid */
int iStrategy; /* Copy of idxNum search parameter */
int nConstraint; /* Number of entries in aConstraint */
RtreeConstraint *aConstraint; /* Search constraints. */
@@ -237,6 +248,7 @@ struct RtreeCursor {
int nPoint; /* Number of slots used in aPoint[] */
int mxLevel; /* iLevel value for root of the tree */
RtreeSearchPoint *aPoint; /* Priority queue for search points */
sqlite3_stmt *pReadAux; /* Statement to read aux-data */
RtreeSearchPoint sPoint; /* Cached next search point */
RtreeNode *aNode[RTREE_CACHE_SZ]; /* Rtree node cache */
u32 anQueue[RTREE_MAX_DEPTH+1]; /* Number of queued entries by iLevel */
@@ -523,6 +535,7 @@ static int writeInt64(u8 *p, i64 i){
*/
static void nodeReference(RtreeNode *p){
if( p ){
assert( p->nRef>0 );
p->nRef++;
}
}
@@ -590,6 +603,7 @@ static RtreeNode *nodeNew(Rtree *pRtree, RtreeNode *pParent){
memset(pNode, 0, sizeof(RtreeNode) + pRtree->iNodeSize);
pNode->zData = (u8 *)&pNode[1];
pNode->nRef = 1;
pRtree->nNodeRef++;
pNode->pParent = pParent;
pNode->isDirty = 1;
nodeReference(pParent);
@@ -623,10 +637,10 @@ static int nodeAcquire(
/* Check if the requested node is already in the hash table. If so,
** increase its reference count and return it.
*/
if( (pNode = nodeHashLookup(pRtree, iNode)) ){
if( (pNode = nodeHashLookup(pRtree, iNode))!=0 ){
assert( !pParent || !pNode->pParent || pNode->pParent==pParent );
if( pParent && !pNode->pParent ){
nodeReference(pParent);
pParent->nRef++;
pNode->pParent = pParent;
}
pNode->nRef++;
@@ -665,6 +679,7 @@ static int nodeAcquire(
pNode->pParent = pParent;
pNode->zData = (u8 *)&pNode[1];
pNode->nRef = 1;
pRtree->nNodeRef++;
pNode->iNode = iNode;
pNode->isDirty = 0;
pNode->pNext = 0;
@@ -705,7 +720,10 @@ static int nodeAcquire(
}
*ppNode = pNode;
}else{
sqlite3_free(pNode);
if( pNode ){
pRtree->nNodeRef--;
sqlite3_free(pNode);
}
*ppNode = 0;
}
@@ -802,8 +820,10 @@ static int nodeRelease(Rtree *pRtree, RtreeNode *pNode){
int rc = SQLITE_OK;
if( pNode ){
assert( pNode->nRef>0 );
assert( pRtree->nNodeRef>0 );
pNode->nRef--;
if( pNode->nRef==0 ){
pRtree->nNodeRef--;
if( pNode->iNode==1 ){
pRtree->iDepth = -1;
}
@@ -920,8 +940,9 @@ static void rtreeRelease(Rtree *pRtree){
pRtree->nBusy--;
if( pRtree->nBusy==0 ){
pRtree->inWrTrans = 0;
pRtree->nCursor = 0;
assert( pRtree->nCursor==0 );
nodeBlobReset(pRtree);
assert( pRtree->nNodeRef==0 );
sqlite3_finalize(pRtree->pWriteNode);
sqlite3_finalize(pRtree->pDeleteNode);
sqlite3_finalize(pRtree->pReadRowid);
@@ -930,6 +951,8 @@ static void rtreeRelease(Rtree *pRtree){
sqlite3_finalize(pRtree->pReadParent);
sqlite3_finalize(pRtree->pWriteParent);
sqlite3_finalize(pRtree->pDeleteParent);
sqlite3_finalize(pRtree->pWriteAux);
sqlite3_free(pRtree->zReadAuxSql);
sqlite3_free(pRtree);
}
}
@@ -1018,6 +1041,7 @@ static int rtreeClose(sqlite3_vtab_cursor *cur){
RtreeCursor *pCsr = (RtreeCursor *)cur;
assert( pRtree->nCursor>0 );
freeCursorConstraints(pCsr);
sqlite3_finalize(pCsr->pReadAux);
sqlite3_free(pCsr->aPoint);
for(ii=0; ii<RTREE_CACHE_SZ; ii++) nodeRelease(pRtree, pCsr->aNode[ii]);
sqlite3_free(pCsr);
@@ -1389,7 +1413,7 @@ static RtreeSearchPoint *rtreeSearchPointNew(
if( ii<RTREE_CACHE_SZ ){
assert( pCur->aNode[ii]==0 );
pCur->aNode[ii] = pCur->aNode[0];
}else{
}else{
nodeRelease(RTREE_OF_CURSOR(pCur), pCur->aNode[0]);
}
pCur->aNode[0] = 0;
@@ -1560,6 +1584,10 @@ static int rtreeNext(sqlite3_vtab_cursor *pVtabCursor){
/* Move to the next entry that matches the configured constraints. */
RTREE_QUEUE_TRACE(pCsr, "POP-Nx:");
if( pCsr->bAuxValid ){
pCsr->bAuxValid = 0;
sqlite3_reset(pCsr->pReadAux);
}
rtreeSearchPointPop(pCsr);
rc = rtreeStepToLeaf(pCsr);
return rc;
@@ -1594,7 +1622,7 @@ static int rtreeColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){
if( p==0 ) return SQLITE_OK;
if( i==0 ){
sqlite3_result_int64(ctx, nodeGetRowid(pRtree, pNode, p->iCell));
}else{
}else if( i<=pRtree->nDim2 ){
nodeGetCoord(pRtree, pNode, p->iCell, i-1, &c);
#ifndef SQLITE_RTREE_INT_ONLY
if( pRtree->eCoordType==RTREE_COORD_REAL32 ){
@@ -1605,7 +1633,27 @@ static int rtreeColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){
assert( pRtree->eCoordType==RTREE_COORD_INT32 );
sqlite3_result_int(ctx, c.i);
}
}
}else{
if( !pCsr->bAuxValid ){
if( pCsr->pReadAux==0 ){
rc = sqlite3_prepare_v3(pRtree->db, pRtree->zReadAuxSql, -1, 0,
&pCsr->pReadAux, 0);
if( rc ) return rc;
}
sqlite3_bind_int64(pCsr->pReadAux, 1,
nodeGetRowid(pRtree, pNode, p->iCell));
rc = sqlite3_step(pCsr->pReadAux);
if( rc==SQLITE_ROW ){
pCsr->bAuxValid = 1;
}else{
sqlite3_reset(pCsr->pReadAux);
if( rc==SQLITE_DONE ) rc = SQLITE_OK;
return rc;
}
}
sqlite3_result_value(ctx,
sqlite3_column_value(pCsr->pReadAux, i - pRtree->nDim2 + 1));
}
return SQLITE_OK;
}
@@ -1683,14 +1731,17 @@ static int rtreeFilter(
int ii;
int rc = SQLITE_OK;
int iCell = 0;
sqlite3_stmt *pStmt;
rtreeReference(pRtree);
/* Reset the cursor to the same state as rtreeOpen() leaves it in. */
freeCursorConstraints(pCsr);
sqlite3_free(pCsr->aPoint);
pStmt = pCsr->pReadAux;
memset(pCsr, 0, sizeof(RtreeCursor));
pCsr->base.pVtab = (sqlite3_vtab*)pRtree;
pCsr->pReadAux = pStmt;
pCsr->iStrategy = idxNum;
if( idxNum==1 ){
@@ -1853,10 +1904,14 @@ static int rtreeBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
*/
pIdxInfo->estimatedCost = 30.0;
pIdxInfo->estimatedRows = 1;
pIdxInfo->idxFlags = SQLITE_INDEX_SCAN_UNIQUE;
return SQLITE_OK;
}
if( p->usable && (p->iColumn>0 || p->op==SQLITE_INDEX_CONSTRAINT_MATCH) ){
if( p->usable
&& ((p->iColumn>0 && p->iColumn<=pRtree->nDim2)
|| p->op==SQLITE_INDEX_CONSTRAINT_MATCH)
){
u8 op;
switch( p->op ){
case SQLITE_INDEX_CONSTRAINT_EQ: op = RTREE_EQ; break;
@@ -2429,7 +2484,7 @@ static int SplitNode(
}else{
pLeft = pNode;
pRight = nodeNew(pRtree, pLeft->pParent);
nodeReference(pLeft);
pLeft->nRef++;
}
if( !pLeft || !pRight ){
@@ -2919,6 +2974,7 @@ static int rtreeDeleteRowid(Rtree *pRtree, sqlite3_int64 iDelete){
rc = reinsertNodeContent(pRtree, pLeaf);
}
pRtree->pDeleted = pLeaf->pNext;
pRtree->nNodeRef--;
sqlite3_free(pLeaf);
}
@@ -3015,7 +3071,7 @@ static int rtreeConstraintError(Rtree *pRtree, int iCol){
static int rtreeUpdate(
sqlite3_vtab *pVtab,
int nData,
sqlite3_value **azData,
sqlite3_value **aData,
sqlite_int64 *pRowid
){
Rtree *pRtree = (Rtree *)pVtab;
@@ -3023,6 +3079,12 @@ static int rtreeUpdate(
RtreeCell cell; /* New cell to insert if nData>1 */
int bHaveRowid = 0; /* Set to 1 after new rowid is determined */
if( pRtree->nNodeRef ){
/* Unable to write to the btree while another cursor is reading from it,
** since the write might do a rebalance which would disrupt the read
** cursor. */
return SQLITE_LOCKED_VTAB;
}
rtreeReference(pRtree);
assert(nData>=1);
@@ -3041,8 +3103,10 @@ static int rtreeUpdate(
*/
if( nData>1 ){
int ii;
int nn = nData - 4;
/* Populate the cell.aCoord[] array. The first coordinate is azData[3].
if( nn > pRtree->nDim2 ) nn = pRtree->nDim2;
/* Populate the cell.aCoord[] array. The first coordinate is aData[3].
**
** NB: nData can only be less than nDim*2+3 if the rtree is mis-declared
** with "column" that are interpreted as table constraints.
@@ -3050,13 +3114,12 @@ static int rtreeUpdate(
** This problem was discovered after years of use, so we silently ignore
** these kinds of misdeclared tables to avoid breaking any legacy.
*/
assert( nData<=(pRtree->nDim2 + 3) );
#ifndef SQLITE_RTREE_INT_ONLY
if( pRtree->eCoordType==RTREE_COORD_REAL32 ){
for(ii=0; ii<nData-4; ii+=2){
cell.aCoord[ii].f = rtreeValueDown(azData[ii+3]);
cell.aCoord[ii+1].f = rtreeValueUp(azData[ii+4]);
for(ii=0; ii<nn; ii+=2){
cell.aCoord[ii].f = rtreeValueDown(aData[ii+3]);
cell.aCoord[ii+1].f = rtreeValueUp(aData[ii+4]);
if( cell.aCoord[ii].f>cell.aCoord[ii+1].f ){
rc = rtreeConstraintError(pRtree, ii+1);
goto constraint;
@@ -3065,9 +3128,9 @@ static int rtreeUpdate(
}else
#endif
{
for(ii=0; ii<nData-4; ii+=2){
cell.aCoord[ii].i = sqlite3_value_int(azData[ii+3]);
cell.aCoord[ii+1].i = sqlite3_value_int(azData[ii+4]);
for(ii=0; ii<nn; ii+=2){
cell.aCoord[ii].i = sqlite3_value_int(aData[ii+3]);
cell.aCoord[ii+1].i = sqlite3_value_int(aData[ii+4]);
if( cell.aCoord[ii].i>cell.aCoord[ii+1].i ){
rc = rtreeConstraintError(pRtree, ii+1);
goto constraint;
@@ -3077,10 +3140,10 @@ static int rtreeUpdate(
/* If a rowid value was supplied, check if it is already present in
** the table. If so, the constraint has failed. */
if( sqlite3_value_type(azData[2])!=SQLITE_NULL ){
cell.iRowid = sqlite3_value_int64(azData[2]);
if( sqlite3_value_type(azData[0])==SQLITE_NULL
|| sqlite3_value_int64(azData[0])!=cell.iRowid
if( sqlite3_value_type(aData[2])!=SQLITE_NULL ){
cell.iRowid = sqlite3_value_int64(aData[2]);
if( sqlite3_value_type(aData[0])==SQLITE_NULL
|| sqlite3_value_int64(aData[0])!=cell.iRowid
){
int steprc;
sqlite3_bind_int64(pRtree->pReadRowid, 1, cell.iRowid);
@@ -3099,16 +3162,16 @@ static int rtreeUpdate(
}
}
/* If azData[0] is not an SQL NULL value, it is the rowid of a
/* If aData[0] is not an SQL NULL value, it is the rowid of a
** record to delete from the r-tree table. The following block does
** just that.
*/
if( sqlite3_value_type(azData[0])!=SQLITE_NULL ){
rc = rtreeDeleteRowid(pRtree, sqlite3_value_int64(azData[0]));
if( sqlite3_value_type(aData[0])!=SQLITE_NULL ){
rc = rtreeDeleteRowid(pRtree, sqlite3_value_int64(aData[0]));
}
/* If the azData[] array contains more than one element, elements
** (azData[2]..azData[argc-1]) contain a new record to insert into
/* If the aData[] array contains more than one element, elements
** (aData[2]..aData[argc-1]) contain a new record to insert into
** the r-tree structure.
*/
if( rc==SQLITE_OK && nData>1 ){
@@ -3133,6 +3196,16 @@ static int rtreeUpdate(
rc = rc2;
}
}
if( pRtree->nAux ){
sqlite3_stmt *pUp = pRtree->pWriteAux;
int jj;
sqlite3_bind_int64(pUp, 1, *pRowid);
for(jj=0; jj<pRtree->nAux; jj++){
sqlite3_bind_value(pUp, jj+2, aData[pRtree->nDim2+3+jj]);
}
sqlite3_step(pUp);
rc = sqlite3_reset(pUp);
}
}
constraint:
@@ -3289,18 +3362,18 @@ static int rtreeSqlInit(
#define N_STATEMENT 8
static const char *azSql[N_STATEMENT] = {
/* Write the xxx_node table */
"INSERT OR REPLACE INTO '%q'.'%q_node' VALUES(:1, :2)",
"DELETE FROM '%q'.'%q_node' WHERE nodeno = :1",
"INSERT OR REPLACE INTO '%q'.'%q_node' VALUES(?1, ?2)",
"DELETE FROM '%q'.'%q_node' WHERE nodeno = ?1",
/* Read and write the xxx_rowid table */
"SELECT nodeno FROM '%q'.'%q_rowid' WHERE rowid = :1",
"INSERT OR REPLACE INTO '%q'.'%q_rowid' VALUES(:1, :2)",
"DELETE FROM '%q'.'%q_rowid' WHERE rowid = :1",
"SELECT nodeno FROM '%q'.'%q_rowid' WHERE rowid = ?1",
"INSERT OR REPLACE INTO '%q'.'%q_rowid' VALUES(?1, ?2)",
"DELETE FROM '%q'.'%q_rowid' WHERE rowid = ?1",
/* Read and write the xxx_parent table */
"SELECT parentnode FROM '%q'.'%q_parent' WHERE nodeno = :1",
"INSERT OR REPLACE INTO '%q'.'%q_parent' VALUES(:1, :2)",
"DELETE FROM '%q'.'%q_parent' WHERE nodeno = :1"
"SELECT parentnode FROM '%q'.'%q_parent' WHERE nodeno = ?1",
"INSERT OR REPLACE INTO '%q'.'%q_parent' VALUES(?1, ?2)",
"DELETE FROM '%q'.'%q_parent' WHERE nodeno = ?1"
};
sqlite3_stmt **appStmt[N_STATEMENT];
int i;
@@ -3308,14 +3381,25 @@ static int rtreeSqlInit(
pRtree->db = db;
if( isCreate ){
char *zCreate = sqlite3_mprintf(
"CREATE TABLE \"%w\".\"%w_node\"(nodeno INTEGER PRIMARY KEY, data BLOB);"
"CREATE TABLE \"%w\".\"%w_rowid\"(rowid INTEGER PRIMARY KEY, nodeno INTEGER);"
"CREATE TABLE \"%w\".\"%w_parent\"(nodeno INTEGER PRIMARY KEY,"
" parentnode INTEGER);"
"INSERT INTO '%q'.'%q_node' VALUES(1, zeroblob(%d))",
zDb, zPrefix, zDb, zPrefix, zDb, zPrefix, zDb, zPrefix, pRtree->iNodeSize
);
char *zCreate;
sqlite3_str *p = sqlite3_str_new(db);
int ii;
sqlite3_str_appendf(p,
"CREATE TABLE \"%w\".\"%w_rowid\"(rowid INTEGER PRIMARY KEY,nodeno",
zDb, zPrefix);
for(ii=0; ii<pRtree->nAux; ii++){
sqlite3_str_appendf(p,",a%d",ii);
}
sqlite3_str_appendf(p,
");CREATE TABLE \"%w\".\"%w_node\"(nodeno INTEGER PRIMARY KEY,data);",
zDb, zPrefix);
sqlite3_str_appendf(p,
"CREATE TABLE \"%w\".\"%w_parent\"(nodeno INTEGER PRIMARY KEY,parentnode);",
zDb, zPrefix);
sqlite3_str_appendf(p,
"INSERT INTO \"%w\".\"%w_node\"VALUES(1,zeroblob(%d))",
zDb, zPrefix, pRtree->iNodeSize);
zCreate = sqlite3_str_finish(p);
if( !zCreate ){
return SQLITE_NOMEM;
}
@@ -3337,7 +3421,17 @@ static int rtreeSqlInit(
rc = rtreeQueryStat1(db, pRtree);
for(i=0; i<N_STATEMENT && rc==SQLITE_OK; i++){
char *zSql = sqlite3_mprintf(azSql[i], zDb, zPrefix);
char *zSql;
const char *zFormat;
if( i!=3 || pRtree->nAux==0 ){
zFormat = azSql[i];
}else {
/* An UPSERT is very slightly slower than REPLACE, but it is needed
** if there are auxiliary columns */
zFormat = "INSERT INTO\"%w\".\"%w_rowid\"(rowid,nodeno)VALUES(?1,?2)"
"ON CONFLICT(rowid)DO UPDATE SET nodeno=excluded.nodeno";
}
zSql = sqlite3_mprintf(zFormat, zDb, zPrefix);
if( zSql ){
rc = sqlite3_prepare_v3(db, zSql, -1, SQLITE_PREPARE_PERSISTENT,
appStmt[i], 0);
@@ -3346,6 +3440,32 @@ static int rtreeSqlInit(
}
sqlite3_free(zSql);
}
if( pRtree->nAux ){
pRtree->zReadAuxSql = sqlite3_mprintf(
"SELECT * FROM \"%w\".\"%w_rowid\" WHERE rowid=?1",
zDb, zPrefix);
if( pRtree->zReadAuxSql==0 ){
rc = SQLITE_NOMEM;
}else{
sqlite3_str *p = sqlite3_str_new(db);
int ii;
char *zSql;
sqlite3_str_appendf(p, "UPDATE \"%w\".\"%w_rowid\"SET ", zDb, zPrefix);
for(ii=0; ii<pRtree->nAux; ii++){
if( ii ) sqlite3_str_append(p, ",", 1);
sqlite3_str_appendf(p,"a%d=?%d",ii,ii+2);
}
sqlite3_str_appendf(p, " WHERE rowid=?1");
zSql = sqlite3_str_finish(p);
if( zSql==0 ){
rc = SQLITE_NOMEM;
}else{
rc = sqlite3_prepare_v3(db, zSql, -1, SQLITE_PREPARE_PERSISTENT,
&pRtree->pWriteAux, 0);
sqlite3_free(zSql);
}
}
}
return rc;
}
@@ -3448,17 +3568,22 @@ static int rtreeInit(
int nDb; /* Length of string argv[1] */
int nName; /* Length of string argv[2] */
int eCoordType = (pAux ? RTREE_COORD_INT32 : RTREE_COORD_REAL32);
sqlite3_str *pSql;
char *zSql;
int ii = 4;
int iErr;
const char *aErrMsg[] = {
0, /* 0 */
"Wrong number of columns for an rtree table", /* 1 */
"Too few columns for an rtree table", /* 2 */
"Too many columns for an rtree table" /* 3 */
"Too many columns for an rtree table", /* 3 */
"Auxiliary rtree columns must be last" /* 4 */
};
int iErr = (argc<6) ? 2 : argc>(RTREE_MAX_DIMENSIONS*2+4) ? 3 : argc%2;
if( aErrMsg[iErr] ){
*pzErr = sqlite3_mprintf("%s", aErrMsg[iErr]);
assert( RTREE_MAX_AUX_COLUMN<256 ); /* Aux columns counted by a u8 */
if( argc>RTREE_MAX_AUX_COLUMN+3 ){
*pzErr = sqlite3_mprintf("%s", aErrMsg[3]);
return SQLITE_ERROR;
}
@@ -3476,53 +3601,73 @@ static int rtreeInit(
pRtree->base.pModule = &rtreeModule;
pRtree->zDb = (char *)&pRtree[1];
pRtree->zName = &pRtree->zDb[nDb+1];
pRtree->nDim = (u8)((argc-4)/2);
pRtree->nDim2 = pRtree->nDim*2;
pRtree->nBytesPerCell = 8 + pRtree->nDim2*4;
pRtree->eCoordType = (u8)eCoordType;
memcpy(pRtree->zDb, argv[1], nDb);
memcpy(pRtree->zName, argv[2], nName);
/* Figure out the node size to use. */
rc = getNodeSize(db, pRtree, isCreate, pzErr);
/* Create/Connect to the underlying relational database schema. If
** that is successful, call sqlite3_declare_vtab() to configure
** the r-tree table schema.
*/
if( rc==SQLITE_OK ){
if( (rc = rtreeSqlInit(pRtree, db, argv[1], argv[2], isCreate)) ){
*pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
pSql = sqlite3_str_new(db);
sqlite3_str_appendf(pSql, "CREATE TABLE x(%s", argv[3]);
for(ii=4; ii<argc; ii++){
if( argv[ii][0]=='+' ){
pRtree->nAux++;
sqlite3_str_appendf(pSql, ",%s", argv[ii]+1);
}else if( pRtree->nAux>0 ){
break;
}else{
sqlite3_str *pSql = sqlite3_str_new(db);
char *zSql;
int ii;
if( pSql==0 ){
zSql = 0;
}else{
sqlite3_str_appendf(pSql, "CREATE TABLE x(%s", argv[3]);
for(ii=4; ii<argc; ii++){
sqlite3_str_appendf(pSql, ", %s", argv[ii]);
}
sqlite3_str_appendf(pSql, ");");
zSql = sqlite3_str_finish(pSql);
}
if( !zSql ){
rc = SQLITE_NOMEM;
}else if( SQLITE_OK!=(rc = sqlite3_declare_vtab(db, zSql)) ){
*pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
}
sqlite3_free(zSql);
pRtree->nDim2++;
sqlite3_str_appendf(pSql, ",%s", argv[ii]);
}
}
if( rc==SQLITE_OK ){
*ppVtab = (sqlite3_vtab *)pRtree;
}else{
assert( *ppVtab==0 );
assert( pRtree->nBusy==1 );
rtreeRelease(pRtree);
sqlite3_str_appendf(pSql, ");");
zSql = sqlite3_str_finish(pSql);
if( !zSql ){
rc = SQLITE_NOMEM;
}else if( ii<argc ){
*pzErr = sqlite3_mprintf("%s", aErrMsg[4]);
rc = SQLITE_ERROR;
}else if( SQLITE_OK!=(rc = sqlite3_declare_vtab(db, zSql)) ){
*pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
}
sqlite3_free(zSql);
if( rc ) goto rtreeInit_fail;
pRtree->nDim = pRtree->nDim2/2;
if( pRtree->nDim<1 ){
iErr = 2;
}else if( pRtree->nDim2>RTREE_MAX_DIMENSIONS*2 ){
iErr = 3;
}else if( pRtree->nDim2 % 2 ){
iErr = 1;
}else{
iErr = 0;
}
if( iErr ){
*pzErr = sqlite3_mprintf("%s", aErrMsg[iErr]);
goto rtreeInit_fail;
}
pRtree->nBytesPerCell = 8 + pRtree->nDim2*4;
/* Figure out the node size to use. */
rc = getNodeSize(db, pRtree, isCreate, pzErr);
if( rc ) goto rtreeInit_fail;
rc = rtreeSqlInit(pRtree, db, argv[1], argv[2], isCreate);
if( rc ){
*pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
goto rtreeInit_fail;
}
*ppVtab = (sqlite3_vtab *)pRtree;
return SQLITE_OK;
rtreeInit_fail:
if( rc==SQLITE_OK ) rc = SQLITE_ERROR;
assert( *ppVtab==0 );
assert( pRtree->nBusy==1 );
rtreeRelease(pRtree);
return rc;
}
@@ -3751,7 +3896,7 @@ static u8 *rtreeCheckGetNode(RtreeCheck *pCheck, i64 iNode, int *pnNode){
** two tables are:
**
** CREATE TABLE %_parent(nodeno INTEGER PRIMARY KEY, parentnode INTEGER)
** CREATE TABLE %_rowid(rowid INTEGER PRIMARY KEY, nodeno INTEGER)
** CREATE TABLE %_rowid(rowid INTEGER PRIMARY KEY, nodeno INTEGER, ...)
**
** In both cases, this function checks that there exists an entry with
** IPK value iKey and the second column set to iVal.
@@ -3766,8 +3911,8 @@ static void rtreeCheckMapping(
int rc;
sqlite3_stmt *pStmt;
const char *azSql[2] = {
"SELECT parentnode FROM %Q.'%q_parent' WHERE nodeno=?",
"SELECT nodeno FROM %Q.'%q_rowid' WHERE rowid=?"
"SELECT parentnode FROM %Q.'%q_parent' WHERE nodeno=?1",
"SELECT nodeno FROM %Q.'%q_rowid' WHERE rowid=?1"
};
assert( bLeaf==0 || bLeaf==1 );
@@ -3951,6 +4096,7 @@ static int rtreeCheckTable(
RtreeCheck check; /* Common context for various routines */
sqlite3_stmt *pStmt = 0; /* Used to find column count of rtree table */
int bEnd = 0; /* True if transaction should be closed */
int nAux = 0; /* Number of extra columns. */
/* Initialize the context object */
memset(&check, 0, sizeof(check));
@@ -3966,11 +4112,21 @@ static int rtreeCheckTable(
bEnd = 1;
}
/* Find the number of auxiliary columns */
if( check.rc==SQLITE_OK ){
pStmt = rtreeCheckPrepare(&check, "SELECT * FROM %Q.'%q_rowid'", zDb, zTab);
if( pStmt ){
nAux = sqlite3_column_count(pStmt) - 2;
sqlite3_finalize(pStmt);
}
check.rc = SQLITE_OK;
}
/* Find number of dimensions in the rtree table. */
pStmt = rtreeCheckPrepare(&check, "SELECT * FROM %Q.%Q", zDb, zTab);
if( pStmt ){
int rc;
check.nDim = (sqlite3_column_count(pStmt) - 1) / 2;
check.nDim = (sqlite3_column_count(pStmt) - 1 - nAux) / 2;
if( check.nDim<1 ){
rtreeCheckAppendMsg(&check, "Schema corrupt or not an rtree");
}else if( SQLITE_ROW==sqlite3_step(pStmt) ){
+43 -5
View File
@@ -476,11 +476,11 @@ foreach {tn sql_template testdata} {
}
3 "UPDATE %CONF% t1 SET idx = 2 WHERE idx = 4" {
ROLLBACK 1 1 {1 1 2 3 4 2 2 3 4 5 3 3 4 5 6}
ABORT 1 1 {1 1 2 3 4 2 2 3 4 5 3 3 4 5 6 4 4 5 6 7}
IGNORE 1 0 {1 1 2 3 4 2 2 3 4 5 3 3 4 5 6 4 4 5 6 7}
FAIL 1 1 {1 1 2 3 4 2 2 3 4 5 3 3 4 5 6 4 4 5 6 7}
REPLACE 1 0 {1 1 2 3 4 2 4 5 6 7 3 3 4 5 6}
ROLLBACK 0 1 {1 1 2 3 4 2 2 3 4 5 3 3 4 5 6}
ABORT 0 1 {1 1 2 3 4 2 2 3 4 5 3 3 4 5 6 4 4 5 6 7}
IGNORE 0 0 {1 1 2 3 4 2 2 3 4 5 3 3 4 5 6 4 4 5 6 7}
FAIL 0 1 {1 1 2 3 4 2 2 3 4 5 3 3 4 5 6 4 4 5 6 7}
REPLACE 0 0 {1 1 2 3 4 2 4 5 6 7 3 3 4 5 6}
}
3 "UPDATE %CONF% t1 SET idx = ((idx+1)%5)+1 WHERE idx > 2" {
@@ -609,5 +609,43 @@ do_execsql_test 15.2 {
COMMIT;
}
# Test cases for the new auxiliary columns feature
#
do_catchsql_test 16.100 {
CREATE VIRTUAL TABLE t16 USING rtree(id,x0,x1,y0,+aux1,x1);
} {1 {Auxiliary rtree columns must be last}}
do_test 16.110 {
set sql {
CREATE VIRTUAL TABLE t16 USING rtree(
id, x00, x01, x10, x11, x20, x21, x30, x31, x40, x41
}
for {set i 12} {$i<=100} {incr i} {
append sql ", +a$i"
}
append sql ");"
execsql $sql
} {}
do_test 16.120 {
set sql {
CREATE VIRTUAL TABLE t16b USING rtree(
id, x00, x01, x10, x11, x20, x21, x30, x31, x40, x41
}
for {set i 12} {$i<=101} {incr i} {
append sql ", +a$i"
}
append sql ");"
catchsql $sql
} {1 {Too many columns for an rtree table}}
do_execsql_test 16.130 {
DROP TABLE IF EXISTS rt1;
CREATE VIRTUAL TABLE rt1 USING rtree(id, x1, x2, +aux);
INSERT INTO rt1 VALUES(1, 1, 2, 'aux1');
INSERT INTO rt1 VALUES(2, 2, 3, 'aux2');
INSERT INTO rt1 VALUES(3, 3, 4, 'aux3');
INSERT INTO rt1 VALUES(4, 4, 5, 'aux4');
SELECT * FROM rt1 WHERE id IN (1, 2, 3, 4);
} {1 1.0 2.0 aux1 2 2.0 3.0 aux2 3 3.0 4.0 aux3 4 4.0 5.0 aux4}
expand_all_sql db
finish_test
+1 -1
View File
@@ -81,7 +81,7 @@ do_faultsim_test rtree3-2 -faults oom* -prep {
do_malloc_test rtree3-3.prep {
faultsim_delete_and_reopen
execsql {
CREATE VIRTUAL TABLE rt USING rtree(ii, x1, x2, y1, y2);
CREATE VIRTUAL TABLE rt USING rtree(ii, x1, x2, y1, y2, +a1, +a2);
INSERT INTO rt VALUES(NULL, 3, 5, 7, 9);
}
faultsim_save_and_close
+36 -3
View File
@@ -38,11 +38,20 @@ do_test rtree8-1.1.1 {
} {}
do_test rtree8-1.1.2 {
set res [list]
db eval { SELECT * FROM t1 } {
lappend res $x1 $x2
set rc [catch {
db eval { SELECT * FROM t1 } {
lappend res $x1 $x2
if {$id==3} { db eval { DELETE FROM t1 WHERE id>3 } }
}
} msg];
lappend rc $msg
set rc
} {1 {database table is locked}}
do_test rtree8-1.1.2b {
db eval { SELECT * FROM t1 ORDER BY +id } {
if {$id==3} { db eval { DELETE FROM t1 WHERE id>3 } }
}
set res
db eval {SELECT x1, x2 FROM t1}
} {1 3 2 4 3 5}
do_test rtree8-1.1.3 {
execsql { SELECT * FROM t1 }
@@ -170,5 +179,29 @@ do_test rtree8-5.4 {
} {}
do_rtree_integrity_test rtree8-5.5 t2
# 2018-05-24
# The following script caused an assertion fault and/or segfault
# prior to the fix that prevents simultaneous reads and writes on
# the same rtree virtual table.
#
do_test rtree8-6.1 {
db close
sqlite3 db :memory:
db eval {
PRAGMA page_size=512;
CREATE VIRTUAL TABLE t1 USING rtree(id,x1,x2,y1,y2);
WITH RECURSIVE c(x) AS (VALUES(0) UNION ALL SELECT x+1 FROM c WHERE x<49)
INSERT INTO t1 SELECT x, x, x+1, x, x+1 FROM c;
}
set rc [catch {
db eval {SELECT id FROM t1} x {
db eval {DELETE FROM t1 WHERE id=$x(id)}
}
} msg]
lappend rc $msg
} {1 {database table is locked}}
finish_test
+2 -2
View File
@@ -178,7 +178,7 @@ do_execsql_test 4.3 {
reset_db
do_execsql_test 5.1 {
CREATE TABLE t1(x PRIMARY KEY, y);
CREATE VIRTUAL TABLE rt USING rtree(id, x1, x2);
CREATE VIRTUAL TABLE rt USING rtree(id, x1, x2, +d1);
INSERT INTO t1(x) VALUES(1);
INSERT INTO t1(x) SELECT x+1 FROM t1; -- 2
@@ -192,7 +192,7 @@ do_execsql_test 5.1 {
INSERT INTO t1(x) SELECT x+256 FROM t1; -- 512
INSERT INTO t1(x) SELECT x+512 FROM t1; --1024
INSERT INTO rt SELECT x, x, x+1 FROM t1 WHERE x<=5;
INSERT INTO rt SELECT x, x, x+1, printf('x%04xy',x) FROM t1 WHERE x<=5;
}
do_rtree_integrity_test 5.1.1 rt
+80
View File
@@ -0,0 +1,80 @@
# 2018-05-16
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
# This file contains tests for the r-tree module, specifically the
# auxiliary column mechanism.
if {![info exists testdir]} {
set testdir [file join [file dirname [info script]] .. .. test]
}
source [file join [file dirname [info script]] rtree_util.tcl]
source $testdir/tester.tcl
ifcapable !rtree { finish_test ; return }
do_execsql_test rtreeH-100 {
CREATE VIRTUAL TABLE t1 USING rtree(id,x0,x1,y0,y1,+label,+other);
INSERT INTO t1(x0,x1,y0,y1,label) VALUES
(0,10,0,10,'lower-left corner'),
(0,10,90,100,'upper-left corner'),
(90,100,0,10,'lower-right corner'),
(90,100,90,100,'upper-right corner'),
(40,60,40,60,'center'),
(0,5,0,100,'left edge'),
(95,100,0,100,'right edge'),
(0,100,0,5,'bottom edge'),
(0,100,95,100,'top edge'),
(0,100,0,100,'the whole thing'),
(0,50,0,100,'left half'),
(51,100,0,100,'right half'),
(0,100,0,50,'bottom half'),
(0,100,51,100,'top half');
} {}
do_execsql_test rtreeH-101 {
SELECT * FROM t1_rowid ORDER BY rowid
} {1 1 {lower-left corner} {} 2 1 {upper-left corner} {} 3 1 {lower-right corner} {} 4 1 {upper-right corner} {} 5 1 center {} 6 1 {left edge} {} 7 1 {right edge} {} 8 1 {bottom edge} {} 9 1 {top edge} {} 10 1 {the whole thing} {} 11 1 {left half} {} 12 1 {right half} {} 13 1 {bottom half} {} 14 1 {top half} {}}
do_execsql_test rtreeH-102 {
SELECT * FROM t1 WHERE rowid=5;
} {5 40.0 60.0 40.0 60.0 center {}}
do_execsql_test rtreeH-103 {
SELECT * FROM t1 WHERE label='center';
} {5 40.0 60.0 40.0 60.0 center {}}
do_rtree_integrity_test rtreeH-110 t1
do_execsql_test rtreeH-120 {
SELECT label FROM t1 WHERE x1<=50 ORDER BY id
} {{lower-left corner} {upper-left corner} {left edge} {left half}}
do_execsql_test rtreeH-121 {
SELECT label FROM t1 WHERE x1<=50 AND label NOT LIKE '%corner%' ORDER BY id
} {{left edge} {left half}}
do_execsql_test rtreeH-200 {
WITH RECURSIVE
c1(x) AS (VALUES(0) UNION ALL SELECT x+1 FROM c1 WHERE x<99),
c2(y) AS (VALUES(0) UNION ALL SELECT y+1 FROM c2 WHERE y<99)
INSERT INTO t1(id, x0,x1,y0,y1,label)
SELECT 1000+x+y*100, x, x+1, y, y+1, printf('box-%d,%d',x,y) FROM c1, c2;
} {}
do_execsql_test rtreeH-210 {
SELECT label FROM t1 WHERE x0>=48 AND x1<=50 AND y0>=48 AND y1<=50
ORDER BY id;
} {box-48,48 box-49,48 box-48,49 box-49,49}
do_execsql_test rtreeH-300 {
UPDATE t1 SET label='x'||label
WHERE x0>=49 AND x1<=50 AND y0>=49 AND y1<=50;
SELECT label FROM t1 WHERE x0>=48 AND x1<=50 AND y0>=48 AND y1<=50
ORDER BY id;
} {box-48,48 box-49,48 box-48,49 xbox-49,49}
finish_test
+72 -69
View File
@@ -1,18 +1,19 @@
C Remove\sincorrect\sNEVER()\smacro\sadded\sby\sthe\sprevious\scheck-in.
D 2018-05-18T14:19:35.018
C Fix\sthe\sassert()s\sin\sthe\sbyte-code\sengine\sthat\sprove\sthat\scursors\nare\sunidirectional.
D 2018-06-07T18:01:21.263
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F Makefile.in bfc40f350586923e0419d2ea4b559c37ec10ee4b6e210e08c14401f8e340f0da
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
F Makefile.msc 681fb88cccf1fd58c0b9648f6a09b75332206ef72ca76012ad11699c320cec5f
F README.md 7764d56778d567913ef11c82da9ab94aefa0826f7c243351e4e2d7adaef6f373
F VERSION b7c9d1d11cb70ef8e90cfcf3c944aa58a9f801cc2ad487eebb0a110c16dfc2df
F VERSION d3e3afdec1165a5e593dcdfffd8e0f33a2b0186067eb51a073ef6c4aec34923d
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2
F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90
F art/sqlite370.jpg d512473dae7e378a67e28ff96a34da7cb331def2
F autoconf/INSTALL 83e4a25da9fd053c7b3665eaaaf7919707915903
F autoconf/Makefile.am f8c274ee0022cb6d48ff103ab6c6b0733c41b3b02cb8566228dfd602f701e0c2
F autoconf/Makefile.am 465fb475ee5a4b8a63d26c889cb36a4edbff0325b6859eb29a13cdf5c91b005c
F autoconf/Makefile.fallback 22fe523eb36dfce31e0f6349f782eb084e86a5620b2b0b4f84a2d6133f53f5ac
F autoconf/Makefile.msc 6a46d0659d6e4a25346102bcba40a7fb4b0b8b2dc4faabdf0187488c6dd580d6
F autoconf/README.first 6c4f34fe115ff55d4e8dbfa3cecf04a0188292f7
F autoconf/README.txt 4f04b0819303aabaa35fff5f7b257fb0c1ef95f1
@@ -32,7 +33,7 @@ F autoconf/tea/win/rules.vc c511f222b80064096b705dbeb97060ee1d6b6d63
F config.guess 226d9a188c6196f3033ffc651cbc9dcee1a42977
F config.h.in 6376abec766e9a0785178b1823b5a587e9f1ccbc
F config.sub 9ebe4c3b3dab6431ece34f16828b594fb420da55
F configure 80e2dcad8ab88aacc58b55eb0e395f79184b45fcfaa3f36fc20d2e71cfa0a7e4 x
F configure 481df2c668b5c8cd5723dbcda88df8e6796a23884877109d1fe558667a0474bf x
F configure.ac d4529ebb26ae046269334f1dac65f2b1d6927c2efe22b2ec24dce24dfe4f83dd
F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
F doc/lemon.html ac63db056bce24b7368e29319cd1a7eb5f1798cc85922d96a80b6c3a4ff9f51b
@@ -44,8 +45,8 @@ F ext/async/sqlite3async.c 0f3070cc3f5ede78f2b9361fb3b629ce200d7d74
F ext/async/sqlite3async.h f489b080af7e72aec0e1ee6f1d98ab6cf2e4dcef
F ext/expert/README.md b321c2762bb93c18ea102d5a5f7753a4b8bac646cb392b3b437f633caf2020c3
F ext/expert/expert.c d548d603a4cc9e61f446cc179c120c6713511c413f82a4a32b1e1e69d3f086a4
F ext/expert/expert1.test 87e54effda905d991edfe4bcd28098460a568246129ab7263f71b25420ea727f
F ext/expert/sqlite3expert.c 95fdee74be2912d962951d984f1123e55d3f44bd643da7a48ff6ea9426a47f69
F ext/expert/expert1.test baa05800dc1c569faa7ce6232cead0fcedc07fea038b3a2489eaaf710831d546
F ext/expert/sqlite3expert.c 89b7b59be610b929958db02416539a46ac088fd84f81623c4190aff62e92c3c4
F ext/expert/sqlite3expert.h af6354f8ee5c9e025024e63fec3bd640a802afcc3099a44d804752cf0791d811
F ext/expert/test_expert.c d56c194b769bdc90cf829a14c9ecbc1edca9c850b837a4d0b13be14095c32a72
F ext/fts1/README.txt 20ac73b006a70bcfd80069bdaf59214b6cf1db5e
@@ -274,7 +275,7 @@ F ext/misc/carray.c ed96c218ea940b85c9a274c4d9c59fe9491c299147a38a8bba537687bd6c
F ext/misc/closure.c fe928228e8dfb2f00227311c203ccba9c2e5561f4f6de6da87e5b4a30cd8af15
F ext/misc/completion.c e75b8886a2531f9a7ec02dab5f179bb37e6bd46b5da7665a6cbf2dfbe2daa483
F ext/misc/compress.c dd4f8a6d0baccff3c694757db5b430f3bbd821d8686d1fc24df55cf9f035b189
F ext/misc/csv.c d1e324fac3f87f818d684a3d752d1ef76dbcd4fc0db6746ac4034c19d0bcda21
F ext/misc/csv.c 65297bcce8d5acd5aadef42acbe739aef5a2ef5e74c7b73361ca19f3e21de657
F ext/misc/dbdump.c 69ef1be5b210538f77dfcc6fcb55b4b5f5e98b1e0bcfd67d818711e10761db4d
F ext/misc/eval.c 6ea9b22a5fa0dd973b67ca4e53555be177bc0b7b263aadf1024429457c82c0e3
F ext/misc/fileio.c 48c7751c78fc4cdd29d8c862fd2f3f98bbfefa2a3cf1ca1496df4bf02eb8cded
@@ -355,24 +356,25 @@ F ext/repair/test/checkfreelist01.test 3e8aa6aeb4007680c94a8d07b41c339aa635cc782
F ext/repair/test/checkindex01.test 6945d0ffc0c1dc993b2ce88036b26e0f5d6fcc65da70fc9df27c2647bb358b0f
F ext/repair/test/test.tcl 686d76d888dffd021f64260abf29a55c57b2cedfa7fc69150b42b1d6119aac3c
F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761
F ext/rtree/rtree.c 11dc450eec4c86a9b1eee104e478f9556382622a6a7e8080a478567ea975ea69
F ext/rtree/rtree.c cb6d4bd43c118354fe5b5213843da058259467ecdbac0c6f71ead0fd89acf4ec
F ext/rtree/rtree.h 4a690463901cb5e6127cf05eb8e642f127012fd5003830dbc974eca5802d9412
F ext/rtree/rtree1.test 47e2095bebea6813754fd7afa6a20e2b7b4ebcd5cb7dbcb6932b6c9f86bbf972
F ext/rtree/rtree1.test 309afc04d4287542b2cd74f933296832cc681c7b014d9405cb329b62053a5349
F ext/rtree/rtree2.test 5f25b01acd03470067a2d52783b2eb0a50bf836803d4342d20ca39e541220fe2
F ext/rtree/rtree3.test 2cafe8265d1ff28f206fce88d114f208349df482
F ext/rtree/rtree3.test 4ee5d7df86040efe3d8d84f141f2962a7745452200a7cba1db06f86d97050499
F ext/rtree/rtree4.test 304de65d484540111b896827e4261815e5dca4ce28eeecd58be648cd73452c4b
F ext/rtree/rtree5.test 49c9041d713d54560b315c2c7ef7207ee287eba1b20f8266968a06f2e55d3142
F ext/rtree/rtree6.test 593e0d36510d5ac1d1fb39b018274ff17604fe8fdca8cf1f8e16559cea1477f4
F ext/rtree/rtree7.test c8fb2e555b128dd0f0bdb520c61380014f497f8a23c40f2e820acc9f9e4fdce5
F ext/rtree/rtree8.test 649f5a37ec656028a4a32674b9b1183104285a7625a09d2a8f52a1cef72c93f2
F ext/rtree/rtree8.test 924926d7c64ac59fcca0809de472d9dd73c612f54daae1cf992bdd7dac90305b
F ext/rtree/rtree9.test c646f12c8c1c68ef015c6c043d86a0c42488e2e68ed1bb1b0771a7ca246cbabf
F ext/rtree/rtreeA.test 20623ca337ca3bd7e008cc9fb49e44dbe97f1a80b238e10a12bb4afcd0da3776
F ext/rtree/rtreeB.test 4cec297f8e5c588654bbf3c6ed0903f10612be8a2878055dd25faf8c71758bc9
F ext/rtree/rtreeC.test 55e40c4bd9735d9944280f0e664f39374e71bcd9cd3fe4e82786d20b48017fb5
F ext/rtree/rtreeC.test 128928549d22b65c381ab1366760d08703cd75e34f6a7a506ece38f9330b7282
F ext/rtree/rtreeD.test fe46aa7f012e137bd58294409b16c0d43976c3bb92c8f710481e577c4a1100dc
F ext/rtree/rtreeE.test e65d3fc625da1800b412fc8785817327d43ccfec5f5973912d8c9e471928caa9
F ext/rtree/rtreeF.test 81ffa7ef51c4e4618d497a57328c265bf576990c7070633b623b23cd450ed331
F ext/rtree/rtreeG.test 1b9ca6e3effb48f4161edaa463ddeaa8fca4b2526d084f9cbf5dbe4e0184939c
F ext/rtree/rtreeH.test aa08cc4fa8005b4c67446c7110205055b4d6da90e760e6f44b82dfa4cdf8d87a
F ext/rtree/rtree_perf.tcl 6c18c1f23cd48e0f948930c98dfdd37dfccb5195
F ext/rtree/rtree_util.tcl db734b4c5e75fed6acc56d9701f2235345acfdec750b5fc7b587936f5f6bceed
F ext/rtree/rtreecheck.test 4d29103d1e16fcbf90135d1c637b833688492b063b2971dfb5dc6ba76555cfee
@@ -427,37 +429,37 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
F src/alter.c cf7a8af45cb0ace672f47a1b29ab24092a9e8cd8d945a9974e3b5d925f548594
F src/alter.c 819b14b58e71565f8da505a9c1d5d9d904605f85cd64179cf9c7d1edcdad6c25
F src/analyze.c 71fbbeb7b25417592f54d869fe90c28b48e4cecb9926ef9b06d90fb0aec48941
F src/attach.c 4a3138bd771d5426ae4344d8d5e900440af29fabc5ec2f39f69a45010dfbccd7
F src/auth.c 6277d63837357549fe14e723490d6dc1a38768d71c795c5eb5c0f8a99f918f73
F src/backup.c faf17e60b43233c214aae6a8179d24503a61e83b
F src/auth.c a38f3c63c974787ecf75e3213f8cac6568b9a7af7591fb0372ec0517dd16dca8
F src/backup.c 78d3cecfbe28230a3a9a1793e2ead609f469be43e8f486ca996006be551857ab
F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33
F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6
F src/btree.c 8270813c8f0ca91b2802e88ded3755d04ee962a923d431c13bcb6cf3e0c18f63
F src/btree.h 448f15b98ea85dcf7e4eb76f731cadb89636c676ad25dfaac6de77cd66556598
F src/btree.c ae7687faa330562d36cede3375fdc316bff068e9216322d0dfbb3749333e5d3d
F src/btree.h ab639c4b9b210b8f4cd7a3a922af73df9a3f27c1d124267339fd73ef8619f488
F src/btreeInt.h 620ab4c7235f43572cf3ac2ac8723cbdf68073be4d29da24897c7b77dda5fd96
F src/build.c 50ff3e0fa07646b4d797aae0f773efcdb7602f6a5e2f5da27856503f35200889
F src/callback.c fe677cb5f5abb02f7a772a62a98c2f516426081df68856e8f2d5f950929b966a
F src/build.c 5fc41458505331bfb0c175f40b9a13cb335f826bed3ae311aaae000c132d7b16
F src/callback.c 36caff1e7eb7deb58572d59c41cee8f064a11d00297616995c5050ea0cfc1288
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
F src/ctime.c 849d4cebe008cfc6e4799b034a172b4eaf8856b100739632a852732ba66eee48
F src/date.c ebe1dc7c8a347117bb02570f1a931c62dd78f4a2b1b516f4837d45b7d6426957
F src/dbpage.c 8db4c97f630e7d83f884ea75caf1ffd0988c160e9d530194d93721c80821e0f6
F src/dbpage.c 4aa7f26198934dbd002e69418220eae3dbc71b010bbac32bd78faf86b52ce6c3
F src/dbstat.c edabb82611143727511a45ca0859b8cd037851ebe756ae3db289859dd18b6f91
F src/delete.c b0f90749e22d5e41a12dbf940f4811138cf97da54b46b737089b93eb64a2896f
F src/expr.c af4a81a385277510bfc56df87c25d76fc365f98c33bc8797c4a8d84b88e31013
F src/delete.c 4c8c7604277a2041647f96b78f4b9a47858e9217e4fb333d35e7b5ab32c5b57f
F src/expr.c 16f90ae2af2a100bc430a89184afde54878d82f18267e8d00bc4f33e695a7c57
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
F src/fkey.c d617daf66b5515e2b42c1405b2b4984c30ca50fb705ab164271a9bf66c69e331
F src/fkey.c b1da9ef8dc834603bb0d28972378a7ce65897847f9a1e89ab800bbdf24c788ee
F src/func.c e2e3c02621a528a472933fd4733a5da635676f1461be73293f6e9f62f18d4eaa
F src/global.c 9bf034fd560bdd514715170ed8460bb7f823cec113f0569ef3f18a20c7ccd128
F src/hash.c a12580e143f10301ed5166ea4964ae2853d3905a511d4e0c44497245c7ce1f7a
F src/hash.h ab34c5c54a9e9de2e790b24349ba5aab3dbb4fd4
F src/hwtime.h 747c1bbe9df21a92e9c50f3bbec1de841dc5e5da
F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
F src/insert.c 33a2c72b6182e8ddf697d604cc087c77ff5fc512a32b8b624641d41b390e249e
F src/insert.c 76b1dc902e4c3930d9a17a40cd8ee2e94b1fd8cce766672caef164a6d5d4df1d
F src/legacy.c 134ab3e3fae00a0f67a5187981d6935b24b337bcf0f4b3e5c9fa5763da95bf4e
F src/loadext.c 6aae5739198d96c51ae6eb97c4a5b1744c22ed7a5a565a5399a717780d48a36b
F src/main.c b56b2d62d5d11e3f5100b25fca34c13c62a0fe73941f6873454a7fa8a454170d
F src/main.c a086ab7d6e4e3f07bd5789d16f977d425f9482e7b3baeeb2f17bde0e6bfb2bc1
F src/malloc.c 07295435093ce354c6d9063ac05a2eeae28bd251d2e63c48b3d67c12c76f7e18
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de
@@ -477,35 +479,35 @@ F src/os.c 1cb0d1d1b3a4267966dee6e292d2b2cdf88e47c0c59cebff27ecafac052dd165
F src/os.h 48388821692e87da174ea198bf96b1b2d9d83be5dfc908f673ee21fafbe0d432
F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85
F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586
F src/os_unix.c 2b53b0b8ddc580db096252c721729e5f5f2f355b4fc056f8f3fb328aeb3c9e8a
F src/os_unix.c c230a7a24766320d8414afd087edcd43e499fb45e86361f6f4f464f343d965a9
F src/os_win.c ac29c25cde4cfb4adacc59cdec4aa45698ca0e29164ea127859585ccd9faa354
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
F src/pager.c 1bb6a57fa0465296a4d6109a1a64610a0e7adde1f3acf3ef539a9d972908ce8f
F src/pager.h c571b064df842ec8f2e90855dead9acf4cbe0d1b2c05afe0ef0d0145f7fd0388
F src/parse.y 07784439d25f0bc64a656eece4caecc549b147d213f513cdbeb8430345ec2911
F src/parse.y 0b81472496809693a139067fea1fe3f14a7be8aa26c8f18bb327034d1252a06a
F src/pcache.c 135ef0bc6fb2e3b7178d49ab5c9176254c8a691832c1bceb1156b2fbdd0869bd
F src/pcache.h 072f94d29281cffd99e46c1539849f248c4b56ae7684c1f36626797fee375170
F src/pcache1.c 716975564c15eb6679e97f734cec1bfd6c16ac3d4010f05f1f8e509fc7d19880
F src/pragma.c c0d13c0e82a9197aef5533d63300c5b0c8a216ae1fd14ada64e1f12f398d7e82
F src/pragma.c 71c585f1d26e14b931fa4573f587933d6dfddecd9d9001b0f126f74f7306bf87
F src/pragma.h bb83728944b42f6d409c77f5838a8edbdb0fe83046c5496ffc9602b40340a324
F src/prepare.c 95a9dba7a5d032039a77775188cb3b6fb17f2fa1a0b7cd915b30b4b823383ffa
F src/printf.c 1d1b4a568a58d0f32a5ff26c6b98db8a6e1883467f343a6406263cacd2e60c21
F src/prepare.c e966ecc97c3671ff0e96227c8c877b83f2d33ea371ee190bbf1698b36b5605c0
F src/printf.c 7f6f3cba8e0c49c19e30a1ff4e9aeda6e06814dcbad4b664a69e1b6cb6e7e365
F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
F src/resolve.c 6415381a0e9d22c0e7cba33ca4a53f81474190862f5d4838190f5eb5b0b47bc9
F src/resolve.c 14602f46800ba182ea6a490e0f304127d29ac1f724bdadcc639e25d3223fcf6e
F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac
F src/select.c a35d462ee7a3c0856ad7a9d9c8921fbf3d91d911a8f39ad9d61302eb43b24a71
F src/shell.c.in e0f006980883e238555c5ab51bd2dad9fa477c31928419f6d35774288b94853b
F src/sqlite.h.in 34be2d0d18bf4726538793bdc9854cd87f689fda4b3789515134cdbd68188cf4
F src/select.c 8d3176c5258cc83942815ebe75b4c1f8dcf62b5e0f4d37373a14ebf23c046f9f
F src/shell.c.in 4d0ddf10c403710d241bf920163dcf032c21119aebb61e70840942c0eafecdf9
F src/sqlite.h.in 63b07f76731f2b1e55c48fdb9f0508dcc6fbe3971010b8612ffd847c3c56d9a1
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h 9887b27e69c01e79c2cbe74ef73bf01af5b5703d6a7f0a4371e386d7249cb1c7
F src/sqliteInt.h 5abdade4744cf3bd567afb65bb144bb3c61f6132f86813b995a5ca79c7b584e8
F src/sqliteInt.h d2bd297dba08f2390a91c31ff775e0964e9663df5b2910a569fe6f830b8b2beb
F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b
F src/status.c 46e7aec11f79dad50965a5ca5fa9de009f7d6bde08be2156f1538a0a296d4d0e
F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34
F src/tclsqlite.c 916a92de77ec5cbe27818ca194d8cf0c58aa7ad5b87527098f6aa5a6068800ce
F src/test1.c 51aa5f3030217ca45eb62e90944838794d4faaae7a8f60e0330ae01f30bc997b
F src/test2.c 3efb99ab7f1fc8d154933e02ae1378bac9637da5
F src/test3.c b8434949dfb8aff8dfa082c8b592109e77844c2135ed3c492113839b6956255b
F src/test3.c 61798bb0d38b915067a8c8e03f5a534b431181f802659a6616f9b4ff7d872644
F src/test4.c 18ec393bb4d0ad1de729f0b94da7267270f3d8e6
F src/test5.c 328aae2c010c57a9829d255dc099d6899311672d
F src/test6.c e8d839fbc552ce044bec8234561a2d5b8819b48e29548ad0ba400471697946a8
@@ -530,7 +532,7 @@ F src/test_intarray.c 988fc61cb0ff539f4172c0d95f15287c92516f64
F src/test_intarray.h f3b7672f5d1056eac563c0d6ea8480a660b1475c
F src/test_journal.c 619f2aa10e0d7a5f87c0f06825bc61dfce1c6b9c7f3ad990fb13de6c3b8874a3
F src/test_loadext.c 337056bae59f80b9eb00ba82088b39d0f4fe6dfd
F src/test_malloc.c 5201422e2403e66a7a9c2b7d8df806acd8d2a0429822adb7e932f324e7b5b3c6
F src/test_malloc.c dec0aa821b230773aeb3dd11d652c1193f7cedb18a20b25659bc672288115242
F src/test_md5.c 7268e1e8c399d4a5e181b64ac20e1e6f3bc4dd9fc87abac02db145a3d951fa8c
F src/test_multiplex.c e054459f7633f3ff8ce1245da724f9a8be189e4e
F src/test_multiplex.h 5436d03f2d0501d04f3ed50a75819e190495b635
@@ -558,34 +560,34 @@ F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
F src/tokenize.c bbde32eac9eb1280f5292bcdfef66f5a57e43176cbf9347e0efab9f75e133f97
F src/treeview.c 2c5c4bc0a443401db5fd621542150452ddf5055d38edd4eef868bc2b6bfb0260
F src/trigger.c 4ace6d1d5ba9a89822deb287317f33c810440526eafe185c2d8a48c31df1e995
F src/update.c 5be2f501ddc704fc04183bdb28b25eab930bb8553d973429a089ec94fa85cf2b
F src/upsert.c ae4a4823b45c4daf87e8aea8c0f582a8844763271f5ed54ee5956c4c612734f4
F src/update.c 46dc24c6158446aaab45caee09b6d99327cb479268b83ffeb5b701823da3b67b
F src/upsert.c 47edd408cc73f8d3c00a140550d1ad180b407c146285947969dd09874802bf88
F src/utf.c 810fbfebe12359f10bc2a011520a6e10879ab2a163bcb26c74768eab82ea62a5
F src/util.c d9eb0a6c4aae1b00a7369eadd7ca0bbe946cb4c953b6751aa20d357c2f482157
F src/vacuum.c 37730af7540033135909ecaee3667dddec043293428d8718546d0d64ba4a5025
F src/vdbe.c 066a4e1de2ed83e253adfd2e97a684cf562eaa41d31ee7f3d3e4c8aea4485a55
F src/vdbe.h d970d9738efdd09cb2df73e3a40856e7df13e88a3486789c49fcdd322c9eb8a2
F src/vdbeInt.h 95f7adfdc5c8f1353321f55a6c5ec00a90877e3b85af5159e393afb41ff54110
F src/vdbeapi.c 29d2baf9c1233131ec467d7bed1b7c8a03c27579048d768c4b04acf427838858
F src/vdbeaux.c 3b0650dbebebb196010d8af830551e61ea7dcc0e414a2b747f897305b0bd0b8f
F src/vacuum.c 36e7d21a20c0bf6ef4ef7c399d192b5239410b7c4d3c1070fba4e30810d0b855
F src/vdbe.c d7a475cec51c83daf0d348301a1aec77f535832ea946632b5738ff9f087c0edb
F src/vdbe.h e3f43bcc27ff30b0f25a6104d0cb5657e1c4b5e1b5cd2dd2216d5bcc2156a746
F src/vdbeInt.h d299d7a19853463dac418de0d97f2dd9cb4ddb495a45c93364e2daee109ba0ef
F src/vdbeapi.c 765a0bbe01311626417de6cb743f7f25f9f98435c98a9df4bb0714d11014633d
F src/vdbeaux.c daecbbefaf0adfc428cddbfa5164c1d744496ba5dd19f840845ecac652913802
F src/vdbeblob.c f5c70f973ea3a9e915d1693278a5f890dc78594300cf4d54e64f2b0917c94191
F src/vdbemem.c 0cbe9b9560e42b72983cf9e1bceba48f297e51142bfb6b57f3747cf60106b92d
F src/vdbemem.c 803323406d8623a7619ea5d5f74016697eeaed19c02b98ce9c3013e77dbe1c38
F src/vdbesort.c 731a09e5cb9e96b70c394c1b7cf3860fbe84acca7682e178615eb941a3a0ef2f
F src/vdbetrace.c 79d6dbbc479267b255a7de8080eee6e729928a0ef93ed9b0bfa5618875b48392
F src/vtab.c 0e4885495172e1bdf54b12cce23b395ac74ef5729031f15e1bc1e3e6b360ed1a
F src/vtab.c 10ea07dec111de6fb0a4fc87a7ffa4c65fdc088a19dbfaf7d6f2b128f2e8eb7b
F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
F src/wal.c aa9cffc7a2bad6b826a86c8562dd4978398720ed41cb8ee7aa9d054eb8b456a0
F src/wal.h 8de5d2d3de0956d6f6cb48c83a4012d5f227b8fe940f3a349a4b7e85ebcb492a
F src/walker.c da987a20d40145c0a03c07d8fefcb2ed363becc7680d0500d9c79915591f5b1f
F src/where.c 60ec752fcbe9f9e0271ac60548d159a540a1ee47a4f9fedc85e88a3d0e392dd1
F src/whereInt.h cbae2bcd37cfebdb7812a8b188cdb19634ced2b9346470d1c270556b0c33ea53
F src/wherecode.c 728c7f70731430ccdac807a79969873e1af6968bf1c4745dff3f9dd35f636cc8
F src/where.c 7dcb13bbcfd8c926546946556014c8f5aa0829eb8b65a6c18f8d187d265200a5
F src/whereInt.h b09753e74bf92a8b17cf0e41ca94c44432c454544be6699b5311dcc57bf229c6
F src/wherecode.c 3317f2b083a66d3e65a03edf316ade4ccb0a99c9956273282ebb579b95d4ba96
F src/whereexpr.c e90b2e76dcabc81edff56633bf281bc01d93b71e0c81482dc06925ce39f5844a
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/aggnested.test 18b00de006597e960a6b27ccec51474ac66cf1070a87c1933e5694dc02190ef1
F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87
F test/all.test 6ff7b43c2b4b905c74dc4a813d201d0fa64c5783
F test/alter.test b820ab9dcf85f8e3a65bc8326accb2f0c7be64ef
@@ -625,7 +627,7 @@ F test/auth.test 3d6cd8f3978ba55b1202574e6ecd79c6e00914ca44b9bfd6c1fe6fb873fcac8
F test/auth2.test 9eb7fce9f34bf1f50d3f366fb3e606be5a2000a1
F test/auth3.test db21405b95257c24d29273b6b31d0efc59e1d337e3d5804ba2d1fd4897b1ae49
F test/autoanalyze1.test b9cc3f32a990fa56669b668d237c6d53e983554ae80c0604992e18869a0b2dec
F test/autoinc.test 83aad64411583aac9ff0b629159ab4662029ab4e3f47090fce4efd132b304484
F test/autoinc.test 9d202b7dce6571e52b744138eff12610214501acd635abdd72d18736cd06fd22
F test/autoindex1.test a09958fa756129af10b6582bcbf3cbdf11e305e027b393f393caef801159dee0
F test/autoindex2.test 12ef578928102baaa0dc23ad397601a2f4ecb0df
F test/autoindex3.test 2dd997d6590438b53e4f715f9278aa91c9299cf3f81246a0915269c35beb790e
@@ -738,7 +740,7 @@ F test/crashM.test d95f59046fa749b0d0822edf18a717788c8f318d
F test/crashtest1.c 09c1c7d728ccf4feb9e481671e29dda5669bbcc2
F test/createtab.test b5de160630b209c4b8925bdcbbaf48cc90b67fe8
F test/cse.test 277350a26264495e86b1785f34d2d0c8600e021c
F test/csv01.test b99db7e57ee66fb3aa6e5d25af119003bee90bf679c5885711cbf7374f025b73
F test/csv01.test 6e1445b3207d574cff22fc41a8e549dfcf2466ee90546ada97d22a90fa89eb58
F test/ctime.test 78749e6c9a5f0010d67985be80788f841e3cd2da18114e2ed6010399a7d807f3
F test/cursorhint.test 7bc346788390475e77a345da2b92270d04d35856
F test/cursorhint2.test 0078ae1ded4afcf5eb80d06e3a72b6e1c3f1a646aab26eeb583b0a9ec6f0d56e
@@ -771,12 +773,12 @@ F test/e_delete.test ab39084f26ae1f033c940b70ebdbbd523dc4962e
F test/e_droptrigger.test 3cd080807622c13e5bbb61fc9a57bd7754da2412
F test/e_dropview.test 21ce09c361227ddbc9819a5608ee2700c276bdd5
F test/e_expr.test ca8896601ade1e27c6559614c7f32c63d44636fdfa720436a160f09b8bf66c89
F test/e_fkey.test dcdc6ad26b1d4f07636208de4c1c22aae7c0597a685a6c10fe6da91f3191dd96
F test/e_fkey.test 9778696ef9fceacebed8d482d02b47287981faaedf6f73db563ea8a7afb546da
F test/e_fts3.test 8cf40550bb088a6aa187c818c00fabe26ef82900a4cd5c66b427ccafe28bedaa
F test/e_insert.test f02f7f17852b2163732c6611d193f84fc67bc641fb4882c77a464076e5eba80e
F test/e_reindex.test 2bebf7b393e519198b7c654407221cf171a439b8
F test/e_resolve.test a61751c368b109db73df0f20fc75fb47e166b1d8
F test/e_select.test 6fd45fd4a59ec82b6dda7468699dcc0ec1a72538577750b4f90357a62c1d2723
F test/e_select.test c5a669b4d63217aa10094ba737ba3ddd07bd439d4bc7a5b798f6ea32511cbe7c
F test/e_select2.test aceb80ab927d46fba5ce7586ebabf23e2bb0604f
F test/e_totalchanges.test b12ee5809d3e63aeb83238dd501a7bca7fd72c10
F test/e_update.test f46c2554d915c9197548681e8d8c33a267e84528
@@ -965,6 +967,7 @@ F test/in2.test 5d4c61d17493c832f7d2d32bef785119e87bde75
F test/in3.test 3cbf58c87f4052cee3a58b37b6389777505aa0c0
F test/in4.test d2b38cba404bc4320f4fe1b595b3d163f212c068
F test/in5.test 7ae37fcd4a5e198291c6ab5f31a5bb3d15397efe8b75a6736d7a95a7b8dd9e08
F test/in6.test 77c3e1d356d8aeb0864051f0677d3c0a032cf97b7f33a0ba8fa2b04a663f6b7b
F test/incrblob.test c9b96afc292aeff43d6687bcb09b0280aa599822
F test/incrblob2.test a494c9e848560039a23974b9119cfc2cf3ad3bd15cc2694ee6367ae537ef8f1f
F test/incrblob3.test d8d036fde015d4a159cd3cbae9d29003b37227a4
@@ -1050,7 +1053,7 @@ F test/make-where7.tcl 05c16b5d4f5d6512881dfec560cb793915932ef9
F test/malloc.test 18dd1c4188c81ca79cf123527c71b19ee0c31feb9947fdffb0dc6ceb1436816a
F test/malloc3.test 6e88bae6312854a4adb4ecc2a6a5ea8c59b4db778b724ba718e1c43fc8c3c136
F test/malloc4.test 957337613002b7058a85116493a262f679f3a261
F test/malloc5.test f6eb6eca07a4c75f2897bf43a404689b6295bb95ab2e07d4b52eda743f925a27
F test/malloc5.test 2e4ad7684a13389a44a840499cd47173a8d05f22f082d7d083eece433a7a64eb
F test/malloc6.test 2f039d9821927eacae43e1831f815e157659a151
F test/malloc7.test 7c68a32942858bc715284856c5507446bba88c3a
F test/malloc8.test 9b7a3f8cb9cf0b12fff566e80a980b1767bd961d
@@ -1087,7 +1090,7 @@ F test/misc3.test cf3dda47d5dda3e53fc5804a100d3c82be736c9d
F test/misc4.test 0d8be3466adf123a7791a66ba2bc8e8d229e87f3
F test/misc5.test 60e1fc758a93cacd19eb2fafcd1d40d150a05047546c7a92389c98047d621901
F test/misc6.test 953cc693924d88e6117aeba16f46f0bf5abede91
F test/misc7.test 567e223b6497da2226a0340befaf2d663c91ad57a48aede21a35a984a2882d41
F test/misc7.test 349855706310f0de6b91645d199f6874f518627fd057743fa4e3689b60d06efc
F test/misc8.test 8fb0f31d7a8aed484d759773ab8ad12ec746a477f4a67394a4af0e677494c3ca
F test/misuse.test 9e7f78402005e833af71dcab32d048003869eca5abcaccc985d4f8dc1d86bcc7
F test/mjournal.test 9d86e697dcbc5da2c4e8caba9b176b5765fe65e80c88c278b8c09a917e436795
@@ -1128,7 +1131,7 @@ F test/orderby6.test 8b38138ab0972588240b3fca0985d2e400432859
F test/orderby7.test 3d1383d52ade5b9eb3a173b3147fdd296f0202da
F test/orderby8.test 23ef1a5d72bd3adcc2f65561c654295d1b8047bd
F test/orderby9.test 87fb9548debcc2cd141c5299002dd94672fa76a3
F test/oserror.test b32dc34f2363ef18532e3a0a7358e3e7e321974f
F test/oserror.test e7b3416be4b9d5dd2fe0b42dd394daaddbb6c83eeec1f0e47b120b53e0ad3ace
F test/ossfuzz.c c4c4547e2c92ac52f10038b073a03248251a23c1c559728f63a18aeca0e79f03
F test/ossshell.c f125c5bd16e537a2549aa579b328dd1c59905e7ab1338dfc210e755bb7b69f17
F test/ovfl.test 199c482696defceacee8c8e0e0ef36da62726b2f
@@ -1171,7 +1174,7 @@ F test/regexp1.test 497ea812f264d12b6198d6e50a76be4a1973a9d8
F test/regexp2.test 40e894223b3d6672655481493f1be12012f2b33c
F test/reindex.test 44edd3966b474468b823d481eafef0c305022254
F test/releasetest.tcl 5f15ab8056799e9a6e26a310d49236d2e774d6a30d0ec74601e18d4ce146b79c x
F test/resetdb.test 7fda92e443233208ec5e1825b176a9df63fb5bf962248e08b76eb4296c630cdf
F test/resetdb.test 2107b34a8c437183f48eb833905df43818160a55f4ac69bbaf54f356fb2b27bd
F test/resolver01.test f4022acafda7f4d40eca94dbf16bc5fc4ac30ceb
F test/rollback.test 06680159bc6746d0f26276e339e3ae2f951c64812468308838e0a3362d911eaa
F test/rollback2.test bc868d57899dc6972e2b4483faae0e03365a0556941474eec487ae21d8d38bb6
@@ -1211,7 +1214,7 @@ F test/select1.test 2e760bab8f3658b3b97debcf52860d0d2e20aa6cbe8b40e678ddb99871a1
F test/select2.test 352480e0e9c66eda9c3044e412abdf5be0215b56
F test/select3.test 2ce595f8fb8e2ac10071d3b4e424cadd4634a054
F test/select4.test 5389d9895968d1196c457d59b3ee6515d771d328
F test/select5.test e758b8ef94f69b111df4cb819008856655dcd535
F test/select5.test df9ec0d218cedceb4fe7b63262025b547b50a55e59148c6f40b60ca25f1d4546
F test/select6.test 39eac4a5c03650b2b473c532882273283ee8b7a0
F test/select7.test f659f231489349e8c5734e610803d7654207318f
F test/select8.test 8c8f5ae43894c891efc5755ed905467d1d67ad5d
@@ -1239,7 +1242,7 @@ F test/sharedA.test 49d87ec54ab640fbbc3786ee3c01de94aaa482a3a9f834ad3fe92770eb69
F test/sharedB.test 16cc7178e20965d75278f410943109b77b2e645e
F test/shared_err.test 32634e404a3317eeb94abc7a099c556a346fdb8fb3858dbe222a4cbb8926a939
F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304
F test/shell1.test 50154b0c4779df435b9e60ca60104b05f1cc217eab1aa383131359329e73d939
F test/shell1.test 707c03fbd07ac506cfb6fa09da4ee22e2b50453c3db2f404694116eb990168f3
F test/shell2.test e242a9912f44f4c23c3d1d802a83e934e84c853b
F test/shell3.test ac8c2b744014c3e9a0e26bfd829ab65f00923dc1a91ffd044863e9423cc91494
F test/shell4.test 89ad573879a745974ff2df20ff97c5d6ffffbd5d
@@ -1277,7 +1280,7 @@ F test/speed3.test 694affeb9100526007436334cf7d08f3d74b85ef
F test/speed4.test abc0ad3399dcf9703abed2fff8705e4f8e416715
F test/speed4p.explain 6b5f104ebeb34a038b2f714150f51d01143e59aa
F test/speed4p.test 377a0c48e5a92e0b11c1c5ebb1bc9d83a7312c922bc0cb05970ef5d6a96d1f0c
F test/speedtest1.c 20cc4028b0e88392b5a635c2ea5d5e777d569bf7258aead37f8be7a886c38344
F test/speedtest1.c cc7e6b4a7c9f3e3d1a497ae3f75236a832a2ce0f6a9b017f95d996c821605bfb
F test/spellfix.test 951a6405d49d1a23d6b78027d3877b4a33eeb8221dcab5704b499755bb4f552e
F test/spellfix2.test dfc8f519a3fc204cb2dfa8b4f29821ae90f6f8c3
F test/spellfix3.test 0f9efaaa502a0e0a09848028518a6fb096c8ad33
@@ -1583,7 +1586,7 @@ F test/walrofault.test c70cb6e308c443867701856cce92ad8288cd99488fa52afab77cca6cf
F test/walshared.test 0befc811dcf0b287efae21612304d15576e35417
F test/walslow.test c05c68d4dc2700a982f89133ce103a1a84cc285f
F test/walthread.test 14b20fcfa6ae152f5d8e12f5dc8a8a724b7ef189f5d8ef1e2ceab79f2af51747
F test/where.test f19ea3fa31c425b04af42c8b192a5b595ee84498df8d27dcd79ec043b25fbbfb
F test/where.test 6bfcd29db193b814e5736832ffa899b4ff2969a106b718a79375063d5eb02b29
F test/where2.test 478d2170637b9211f593120648858593bf2445a1
F test/where3.test 2341a294e17193a6b1699ea7f192124a5286ca6acfcc3f4b06d16c931fbcda2c
F test/where4.test 4a371bfcc607f41d233701bdec33ac2972908ba8
@@ -1659,7 +1662,7 @@ F tool/mkctimec.tcl dd183b73ae1c28249669741c250525f0407e579a70482371668fd5f130d9
F tool/mkkeywordhash.c 20f366ad3794e1db42e333a6f35fa41a024f2e3528579c9d58eb13eaa3ab4913
F tool/mkmsvcmin.tcl cad0c7b54d7dd92bc87d59f36d4cc4f070eb2e625f14159dc2f5c4204e6a13ea
F tool/mkopcodec.tcl d1b6362bd3aa80d5520d4d6f3765badf01f6c43c
F tool/mkopcodeh.tcl 4ee2a30ccbd900dc4d5cdb61bdab87cd2166cd2affcc78c9cc0b8d22a65b2eee
F tool/mkopcodeh.tcl 17d1ccc05a926e19e3a9679ea3e4d1aaa15ba753e2fa7363e6e81c80e0ef8b86
F tool/mkopts.tcl 680f785fdb09729fd9ac50632413da4eadbdf9071535e3f26d03795828ab07fa
F tool/mkpragmatab.tcl 2144bc8550a6471a029db262a132d2df4b9e0db61b90398bf64f5b7b3f8d92cd
F tool/mkshellc.tcl 1f45770aea226ac093a9c72f718efbb88a2a2833409ec2e1c4cecae4202626f5
@@ -1686,7 +1689,7 @@ F tool/showstat4.c 0682ebea7abf4d3657f53c4a243f2e7eab48eab344ed36a94bb75dcd19a5c
F tool/showwal.c ad9d768f96ca6199ad3a8c9562d679680bd032dd01204ea3e5ea6fb931d81847
F tool/soak1.tcl 8d407956e1a45b485a8e072470a3e629a27037fe
F tool/spaceanal.tcl 4bfd19aad7eb3ce0372ef0255f58035e0bba4ff5e9acfd763a10c6fb365c8dec
F tool/speed-check.sh 4ff9b095cf1a7643f0264e7fb7d23f0b12b7cce587a9de315877c378e90eeaf4
F tool/speed-check.sh 27c7fe178d5b2f7c90a04a127907acda0bfe637fa85b13c43e03e5ed39b008b6
F tool/speedtest.tcl 06c76698485ccf597b9e7dbb1ac70706eb873355
F tool/speedtest16.c ecb6542862151c3e6509bbc00509b234562ae81e
F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
@@ -1728,7 +1731,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 ea6a03a89dc23e860e53e79ec3fddf0ae7072a23b73aef3d2d181b426566b677
R 95f9dad3dedc0c1d42618371aa8f363f
P 439c8162272795b422a0e01b01b832fbc12b39914c9632a674162af8bdecff98
R fe7d026f8be3134e2723fc39eeec5ed5
U drh
Z e422d7782a1b78611c0889726293f8af
Z 8c642b57392b756fd19e94b953870085
+1 -1
View File
@@ -1 +1 @@
3d6625111319c0356c57aaf7b7460fd882c3f00ca668dc43c0abe3403c7c2ba3
4b0b4e14039469b656662312a5f80f086ede293e9ad04c7bc99a202b683a1e55
+1 -1
View File
@@ -142,7 +142,7 @@ static void renameParentFunc(
}
}
zResult = sqlite3MPrintf(db, "%s%s", (zOutput?zOutput:""), zInput),
zResult = sqlite3MPrintf(db, "%s%s", (zOutput?zOutput:""), zInput);
sqlite3_result_text(context, zResult, -1, SQLITE_DYNAMIC);
sqlite3DbFree(db, zOutput);
}
+1 -1
View File
@@ -150,6 +150,7 @@ void sqlite3AuthRead(
int iDb; /* The index of the database the expression refers to */
int iCol; /* Index of column in table */
assert( pExpr->op==TK_COLUMN || pExpr->op==TK_TRIGGER );
if( db->xAuth==0 ) return;
iDb = sqlite3SchemaToIndex(pParse->db, pSchema);
if( iDb<0 ){
@@ -158,7 +159,6 @@ void sqlite3AuthRead(
return;
}
assert( pExpr->op==TK_COLUMN || pExpr->op==TK_TRIGGER );
if( pExpr->op==TK_TRIGGER ){
pTab = pParse->pTriggerTab;
}else{
+3 -3
View File
@@ -382,7 +382,7 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){
** before this function exits.
*/
if( rc==SQLITE_OK && 0==sqlite3BtreeIsInReadTrans(p->pSrc) ){
rc = sqlite3BtreeBeginTrans(p->pSrc, 0);
rc = sqlite3BtreeBeginTrans(p->pSrc, 0, 0);
bCloseTrans = 1;
}
@@ -398,10 +398,10 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){
/* Lock the destination database, if it is not locked already. */
if( SQLITE_OK==rc && p->bDestLocked==0
&& SQLITE_OK==(rc = sqlite3BtreeBeginTrans(p->pDest, 2))
&& SQLITE_OK==(rc = sqlite3BtreeBeginTrans(p->pDest, 2,
(int*)&p->iDestSchema))
){
p->bDestLocked = 1;
sqlite3BtreeGetMeta(p->pDest, BTREE_SCHEMA_VERSION, &p->iDestSchema);
}
/* Do not allow backup if the destination database is in WAL mode
+19 -10
View File
@@ -864,7 +864,11 @@ static int btreeRestoreCursorPosition(BtCursor *pCur){
** back to where it ought to be if this routine returns true.
*/
int sqlite3BtreeCursorHasMoved(BtCursor *pCur){
return pCur->eState!=CURSOR_VALID;
assert( EIGHT_BYTE_ALIGNMENT(pCur)
|| pCur==sqlite3BtreeFakeValidCursor() );
assert( offsetof(BtCursor, eState)==0 );
assert( sizeof(pCur->eState)==1 );
return CURSOR_VALID != *(u8*)pCur;
}
/*
@@ -3296,7 +3300,7 @@ int sqlite3BtreeNewDb(Btree *p){
** when A already has a read lock, we encourage A to give up and let B
** proceed.
*/
int sqlite3BtreeBeginTrans(Btree *p, int wrflag){
int sqlite3BtreeBeginTrans(Btree *p, int wrflag, int *pSchemaVersion){
BtShared *pBt = p->pBt;
int rc = SQLITE_OK;
@@ -3424,12 +3428,17 @@ int sqlite3BtreeBeginTrans(Btree *p, int wrflag){
trans_begun:
if( rc==SQLITE_OK && wrflag ){
/* This call makes sure that the pager has the correct number of
** open savepoints. If the second parameter is greater than 0 and
** the sub-journal is not already open, then it will be opened here.
*/
rc = sqlite3PagerOpenSavepoint(pBt->pPager, p->db->nSavepoint);
if( rc==SQLITE_OK ){
if( pSchemaVersion ){
*pSchemaVersion = get4byte(&pBt->pPage1->aData[40]);
}
if( wrflag ){
/* This call makes sure that the pager has the correct number of
** open savepoints. If the second parameter is greater than 0 and
** the sub-journal is not already open, then it will be opened here.
*/
rc = sqlite3PagerOpenSavepoint(pBt->pPager, p->db->nSavepoint);
}
}
btreeIntegrity(p);
@@ -10080,11 +10089,11 @@ int sqlite3BtreeSetVersion(Btree *pBtree, int iVersion){
pBt->btsFlags &= ~BTS_NO_WAL;
if( iVersion==1 ) pBt->btsFlags |= BTS_NO_WAL;
rc = sqlite3BtreeBeginTrans(pBtree, 0);
rc = sqlite3BtreeBeginTrans(pBtree, 0, 0);
if( rc==SQLITE_OK ){
u8 *aData = pBt->pPage1->aData;
if( aData[18]!=(u8)iVersion || aData[19]!=(u8)iVersion ){
rc = sqlite3BtreeBeginTrans(pBtree, 2);
rc = sqlite3BtreeBeginTrans(pBtree, 2, 0);
if( rc==SQLITE_OK ){
rc = sqlite3PagerWrite(pBt->pPage1->pDbPage);
if( rc==SQLITE_OK ){
+1 -1
View File
@@ -78,7 +78,7 @@ int sqlite3BtreeGetOptimalReserve(Btree*);
int sqlite3BtreeGetReserveNoMutex(Btree *p);
int sqlite3BtreeSetAutoVacuum(Btree *, int);
int sqlite3BtreeGetAutoVacuum(Btree *);
int sqlite3BtreeBeginTrans(Btree*,int);
int sqlite3BtreeBeginTrans(Btree*,int,int*);
int sqlite3BtreeCommitPhaseOne(Btree*, const char *zMaster);
int sqlite3BtreeCommitPhaseTwo(Btree*, int);
int sqlite3BtreeCommit(Btree*);
+4 -2
View File
@@ -2843,6 +2843,7 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead);
addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iTab, 0); VdbeCoverage(v);
regRecord = sqlite3GetTempReg(pParse);
sqlite3MultiWrite(pParse);
sqlite3GenerateIndexKey(pParse,pIndex,iTab,regRecord,0,&iPartIdxLabel,0,0);
sqlite3VdbeAddOp2(v, OP_SorterInsert, iSorter, regRecord);
@@ -2856,12 +2857,13 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
addr1 = sqlite3VdbeAddOp2(v, OP_SorterSort, iSorter, 0); VdbeCoverage(v);
if( IsUniqueIndex(pIndex) ){
int j2 = sqlite3VdbeCurrentAddr(v) + 3;
sqlite3VdbeGoto(v, j2);
int j2 = sqlite3VdbeGoto(v, 1);
addr2 = sqlite3VdbeCurrentAddr(v);
sqlite3VdbeVerifyAbortable(v, OE_Abort);
sqlite3VdbeAddOp4Int(v, OP_SorterCompare, iSorter, j2, regRecord,
pIndex->nKeyCol); VdbeCoverage(v);
sqlite3UniqueConstraint(pParse, OE_Abort, pIndex);
sqlite3VdbeJumpHere(v, j2);
}else{
addr2 = sqlite3VdbeCurrentAddr(v);
}
+2
View File
@@ -406,10 +406,12 @@ FuncDef *sqlite3FindFunction(
if( createFlag && bestScore<FUNC_PERFECT_MATCH &&
(pBest = sqlite3DbMallocZero(db, sizeof(*pBest)+nName+1))!=0 ){
FuncDef *pOther;
u8 *z;
pBest->zName = (const char*)&pBest[1];
pBest->nArg = (u16)nArg;
pBest->funcFlags = enc;
memcpy((char*)&pBest[1], zName, nName+1);
for(z=(u8*)pBest->zName; *z; z++) *z = sqlite3UpperToLower[*z];
pOther = (FuncDef*)sqlite3HashInsert(&db->aFunc, pBest->zName, pBest);
if( pOther==pBest ){
sqlite3DbFree(db, pBest);
+1 -1
View File
@@ -369,7 +369,7 @@ static int dbpageBegin(sqlite3_vtab *pVtab){
int i;
for(i=0; i<db->nDb; i++){
Btree *pBt = db->aDb[i].pBt;
if( pBt ) sqlite3BtreeBeginTrans(pBt, 1);
if( pBt ) sqlite3BtreeBeginTrans(pBt, 1, 0);
}
return SQLITE_OK;
}
+7 -4
View File
@@ -553,13 +553,16 @@ void sqlite3DeleteFrom(
if( IsVirtual(pTab) ){
const char *pVTab = (const char *)sqlite3GetVTable(db, pTab);
sqlite3VtabMakeWritable(pParse, pTab);
sqlite3VdbeAddOp4(v, OP_VUpdate, 0, 1, iKey, pVTab, P4_VTAB);
sqlite3VdbeChangeP5(v, OE_Abort);
assert( eOnePass==ONEPASS_OFF || eOnePass==ONEPASS_SINGLE );
sqlite3MayAbort(pParse);
if( eOnePass==ONEPASS_SINGLE && sqlite3IsToplevel(pParse) ){
pParse->isMultiWrite = 0;
if( eOnePass==ONEPASS_SINGLE ){
sqlite3VdbeAddOp1(v, OP_Close, iTabCur);
if( sqlite3IsToplevel(pParse) ){
pParse->isMultiWrite = 0;
}
}
sqlite3VdbeAddOp4(v, OP_VUpdate, 0, 1, iKey, pVTab, P4_VTAB);
sqlite3VdbeChangeP5(v, OE_Abort);
}else
#endif
{
+1 -1
View File
@@ -3993,7 +3993,7 @@ expr_code_doover:
case TK_COLLATE:
case TK_UPLUS: {
pExpr = pExpr->pLeft;
goto expr_code_doover;
goto expr_code_doover; /* 2018-04-28: Prevent deep recursion. OSSFuzz. */
}
case TK_TRIGGER: {
+7
View File
@@ -331,6 +331,12 @@ static void fkLookupParent(
int iCur = pParse->nTab - 1; /* Cursor number to use */
int iOk = sqlite3VdbeMakeLabel(v); /* jump here if parent key found */
sqlite3VdbeVerifyAbortable(v,
(!pFKey->isDeferred
&& !(pParse->db->flags & SQLITE_DeferFKs)
&& !pParse->pToplevel
&& !pParse->isMultiWrite) ? OE_Abort : OE_Ignore);
/* If nIncr is less than zero, then check at runtime if there are any
** outstanding constraints to resolve. If there are not, there is no need
** to check if deleting this row resolves any outstanding violations.
@@ -738,6 +744,7 @@ void sqlite3FkDropTable(Parse *pParse, SrcList *pName, Table *pTab){
** constraints are violated.
*/
if( (db->flags & SQLITE_DeferFKs)==0 ){
sqlite3VdbeVerifyAbortable(v, OE_Abort);
sqlite3VdbeAddOp2(v, OP_FkIfZero, 0, sqlite3VdbeCurrentAddr(v)+2);
VdbeCoverage(v);
sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_FOREIGNKEY,
+22 -1
View File
@@ -226,11 +226,26 @@ static int autoIncBegin(
Table *pTab /* The table we are writing to */
){
int memId = 0; /* Register holding maximum rowid */
assert( pParse->db->aDb[iDb].pSchema!=0 );
if( (pTab->tabFlags & TF_Autoincrement)!=0
&& (pParse->db->mDbFlags & DBFLAG_Vacuum)==0
){
Parse *pToplevel = sqlite3ParseToplevel(pParse);
AutoincInfo *pInfo;
Table *pSeqTab = pParse->db->aDb[iDb].pSchema->pSeqTab;
/* Verify that the sqlite_sequence table exists and is an ordinary
** rowid table with exactly two columns.
** Ticket d8dc2b3a58cd5dc2918a1d4acb 2018-05-23 */
if( pSeqTab==0
|| !HasRowid(pSeqTab)
|| IsVirtual(pSeqTab)
|| pSeqTab->nCol!=2
){
pParse->nErr++;
pParse->rc = SQLITE_CORRUPT_SEQUENCE;
return 0;
}
pInfo = pToplevel->pAinc;
while( pInfo && pInfo->pTab!=pTab ){ pInfo = pInfo->pNext; }
@@ -1405,6 +1420,7 @@ void sqlite3GenerateConstraintChecks(
Expr *pExpr = pCheck->a[i].pExpr;
if( aiChng && checkConstraintUnchanged(pExpr, aiChng, pkChng) ) continue;
allOk = sqlite3VdbeMakeLabel(v);
sqlite3VdbeVerifyAbortable(v, onError);
sqlite3ExprIfTrue(pParse, pExpr, allOk, SQLITE_JUMPIFNULL);
if( onError==OE_Ignore ){
sqlite3VdbeGoto(v, ignoreDest);
@@ -1514,6 +1530,7 @@ void sqlite3GenerateConstraintChecks(
/* Check to see if the new rowid already exists in the table. Skip
** the following conflict logic if it does not. */
VdbeNoopComment((v, "uniqueness check for ROWID"));
sqlite3VdbeVerifyAbortable(v, onError);
sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, addrRowidOk, regNewData);
VdbeCoverage(v);
@@ -1726,6 +1743,7 @@ void sqlite3GenerateConstraintChecks(
/* Check to see if the new index entry will be unique */
sqlite3ExprCachePush(pParse);
sqlite3VdbeVerifyAbortable(v, onError);
sqlite3VdbeAddOp4Int(v, OP_NoConflict, iThisCur, addrUniqueOk,
regIdx, pIdx->nKeyCol); VdbeCoverage(v);
@@ -1812,10 +1830,12 @@ void sqlite3GenerateConstraintChecks(
default: {
Trigger *pTrigger = 0;
assert( onError==OE_Replace );
sqlite3MultiWrite(pParse);
if( db->flags&SQLITE_RecTriggers ){
pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0);
}
if( pTrigger || sqlite3FkRequired(pParse, pTab, 0, 0) ){
sqlite3MultiWrite(pParse);
}
sqlite3GenerateRowDelete(pParse, pTab, pTrigger, iDataCur, iIdxCur,
regR, nPkField, 0, OE_Replace,
(pIdx==pPk ? ONEPASS_SINGLE : ONEPASS_OFF), iThisCur);
@@ -2335,6 +2355,7 @@ static int xferOptimization(
emptySrcTest = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0); VdbeCoverage(v);
if( pDest->iPKey>=0 ){
addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid);
sqlite3VdbeVerifyAbortable(v, onError);
addr2 = sqlite3VdbeAddOp3(v, OP_NotExists, iDest, 0, regRowid);
VdbeCoverage(v);
sqlite3RowidConstraint(pParse, onError, pDest);
+37 -12
View File
@@ -1808,11 +1808,13 @@ int sqlite3_create_function_v2(
#endif
sqlite3_mutex_enter(db->mutex);
if( xDestroy ){
pArg = (FuncDestructor *)sqlite3DbMallocZero(db, sizeof(FuncDestructor));
pArg = (FuncDestructor *)sqlite3Malloc(sizeof(FuncDestructor));
if( !pArg ){
sqlite3OomFault(db);
xDestroy(p);
goto out;
}
pArg->nRef = 0;
pArg->xDestroy = xDestroy;
pArg->pUserData = p;
}
@@ -1820,7 +1822,7 @@ int sqlite3_create_function_v2(
if( pArg && pArg->nRef==0 ){
assert( rc!=SQLITE_OK );
xDestroy(p);
sqlite3DbFree(db, pArg);
sqlite3_free(pArg);
}
out:
@@ -1858,6 +1860,28 @@ int sqlite3_create_function16(
#endif
/*
** The following is the implementation of an SQL function that always
** fails with an error message stating that the function is used in the
** wrong context. The sqlite3_overload_function() API might construct
** SQL function that use this routine so that the functions will exist
** for name resolution but are actually overloaded by the xFindFunction
** method of virtual tables.
*/
static void sqlite3InvalidFunction(
sqlite3_context *context, /* The function calling context */
int NotUsed, /* Number of arguments to the function */
sqlite3_value **NotUsed2 /* Value of each argument */
){
const char *zName = (const char*)sqlite3_user_data(context);
char *zErr;
UNUSED_PARAMETER2(NotUsed, NotUsed2);
zErr = sqlite3_mprintf(
"unable to use function %s in the requested context", zName);
sqlite3_result_error(context, zErr, -1);
sqlite3_free(zErr);
}
/*
** Declare that a function has been overloaded by a virtual table.
**
@@ -1875,7 +1899,8 @@ int sqlite3_overload_function(
const char *zName,
int nArg
){
int rc = SQLITE_OK;
int rc;
char *zCopy;
#ifdef SQLITE_ENABLE_API_ARMOR
if( !sqlite3SafetyCheckOk(db) || zName==0 || nArg<-2 ){
@@ -1883,13 +1908,13 @@ int sqlite3_overload_function(
}
#endif
sqlite3_mutex_enter(db->mutex);
if( sqlite3FindFunction(db, zName, nArg, SQLITE_UTF8, 0)==0 ){
rc = sqlite3CreateFunc(db, zName, nArg, SQLITE_UTF8,
0, sqlite3InvalidFunction, 0, 0, 0);
}
rc = sqlite3ApiExit(db, rc);
rc = sqlite3FindFunction(db, zName, nArg, SQLITE_UTF8, 0)!=0;
sqlite3_mutex_leave(db->mutex);
return rc;
if( rc ) return SQLITE_OK;
zCopy = sqlite3_mprintf(zName);
if( zCopy==0 ) return SQLITE_NOMEM;
return sqlite3_create_function_v2(db, zName, nArg, SQLITE_UTF8,
zCopy, sqlite3InvalidFunction, 0, 0, sqlite3_free);
}
#ifndef SQLITE_OMIT_TRACE
@@ -4090,7 +4115,7 @@ int sqlite3_snapshot_get(
if( iDb==0 || iDb>1 ){
Btree *pBt = db->aDb[iDb].pBt;
if( 0==sqlite3BtreeIsInTrans(pBt) ){
rc = sqlite3BtreeBeginTrans(pBt, 0);
rc = sqlite3BtreeBeginTrans(pBt, 0, 0);
if( rc==SQLITE_OK ){
rc = sqlite3PagerSnapshotGet(sqlite3BtreePager(pBt), ppSnapshot);
}
@@ -4128,7 +4153,7 @@ int sqlite3_snapshot_open(
if( 0==sqlite3BtreeIsInReadTrans(pBt) ){
rc = sqlite3PagerSnapshotOpen(sqlite3BtreePager(pBt), pSnapshot);
if( rc==SQLITE_OK ){
rc = sqlite3BtreeBeginTrans(pBt, 0);
rc = sqlite3BtreeBeginTrans(pBt, 0, 0);
sqlite3PagerSnapshotOpen(sqlite3BtreePager(pBt), 0);
}
}
@@ -4160,7 +4185,7 @@ int sqlite3_snapshot_recover(sqlite3 *db, const char *zDb){
if( iDb==0 || iDb>1 ){
Btree *pBt = db->aDb[iDb].pBt;
if( 0==sqlite3BtreeIsInReadTrans(pBt) ){
rc = sqlite3BtreeBeginTrans(pBt, 0);
rc = sqlite3BtreeBeginTrans(pBt, 0, 0);
if( rc==SQLITE_OK ){
rc = sqlite3PagerSnapshotRecover(sqlite3BtreePager(pBt));
sqlite3BtreeCommit(pBt);
+1 -1
View File
@@ -3779,7 +3779,7 @@ static int fcntlSizeHint(unixFile *pFile, i64 nByte){
do{
err = osFallocate(pFile->h, buf.st_size, nSize-buf.st_size);
}while( err==EINTR );
if( err ) return SQLITE_IOERR_WRITE;
if( err && err!=EINVAL ) return SQLITE_IOERR_WRITE;
#else
/* If the OS does not have posix_fallocate(), fake it. Write a
** single byte to the last byte in each block that falls entirely
+2
View File
@@ -467,6 +467,7 @@ cmd ::= select(X). {
}
}
%ifndef SQLITE_OMIT_CTE
select(A) ::= WITH wqlist(W) selectnowith(X). {
Select *p = X;
if( p ){
@@ -487,6 +488,7 @@ select(A) ::= WITH RECURSIVE wqlist(W) selectnowith(X). {
}
A = p;
}
%endif /* SQLITE_OMIT_CTE */
select(A) ::= selectnowith(X). {
Select *p = X;
if( p ){
+5 -3
View File
@@ -1564,6 +1564,11 @@ void sqlite3Pragma(
assert( sqlite3NoTempsInRange(pParse,1,7+j) );
sqlite3VdbeAddOp2(v, OP_Rewind, iDataCur, 0); VdbeCoverage(v);
loopTop = sqlite3VdbeAddOp2(v, OP_AddImm, 7, 1);
if( !isQuick ){
/* Sanity check on record header decoding */
sqlite3VdbeAddOp3(v, OP_Column, iDataCur, pTab->nCol-1, 3);
sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG);
}
/* Verify that all NOT NULL columns really are NOT NULL */
for(j=0; j<pTab->nCol; j++){
char *zErr;
@@ -1606,9 +1611,6 @@ void sqlite3Pragma(
sqlite3ExprListDelete(db, pCheck);
}
if( !isQuick ){ /* Omit the remaining tests for quick_check */
/* Sanity check on record header decoding */
sqlite3VdbeAddOp3(v, OP_Column, iDataCur, pTab->nCol-1, 3);
sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG);
/* Validate index entries for the current row */
for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
int jmp2, jmp3, jmp4, jmp5;
+2 -2
View File
@@ -188,7 +188,7 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
** will be closed before this function returns. */
sqlite3BtreeEnter(pDb->pBt);
if( !sqlite3BtreeIsInReadTrans(pDb->pBt) ){
rc = sqlite3BtreeBeginTrans(pDb->pBt, 0);
rc = sqlite3BtreeBeginTrans(pDb->pBt, 0, 0);
if( rc!=SQLITE_OK ){
sqlite3SetString(pzErrMsg, db, sqlite3ErrStr(rc));
goto initone_error_out;
@@ -433,7 +433,7 @@ static void schemaIsValid(Parse *pParse){
** on the b-tree database, open one now. If a transaction is opened, it
** will be closed immediately after reading the meta-value. */
if( !sqlite3BtreeIsInReadTrans(pBt) ){
rc = sqlite3BtreeBeginTrans(pBt, 0);
rc = sqlite3BtreeBeginTrans(pBt, 0, 0);
if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){
sqlite3OomFault(db);
}
+1 -1
View File
@@ -974,7 +974,7 @@ char *sqlite3StrAccumFinish(StrAccum *p){
** an SQLITE_NOMEM error.
*/
static sqlite3_str sqlite3OomStr = {
0, 0, 0, 0, 0, SQLITE_NOMEM
0, 0, 0, 0, 0, SQLITE_NOMEM, 0
};
/* Finalize a string created using sqlite3_str_new().
+24 -21
View File
@@ -75,29 +75,31 @@ static void resolveAlias(
assert( pOrig!=0 );
db = pParse->db;
pDup = sqlite3ExprDup(db, pOrig, 0);
if( pDup==0 ) return;
if( zType[0]!='G' ) incrAggFunctionDepth(pDup, nSubquery);
if( pExpr->op==TK_COLLATE ){
pDup = sqlite3ExprAddCollateString(pParse, pDup, pExpr->u.zToken);
}
ExprSetProperty(pDup, EP_Alias);
if( pDup!=0 ){
if( zType[0]!='G' ) incrAggFunctionDepth(pDup, nSubquery);
if( pExpr->op==TK_COLLATE ){
pDup = sqlite3ExprAddCollateString(pParse, pDup, pExpr->u.zToken);
}
ExprSetProperty(pDup, EP_Alias);
/* Before calling sqlite3ExprDelete(), set the EP_Static flag. This
** prevents ExprDelete() from deleting the Expr structure itself,
** allowing it to be repopulated by the memcpy() on the following line.
** The pExpr->u.zToken might point into memory that will be freed by the
** sqlite3DbFree(db, pDup) on the last line of this block, so be sure to
** make a copy of the token before doing the sqlite3DbFree().
*/
ExprSetProperty(pExpr, EP_Static);
sqlite3ExprDelete(db, pExpr);
memcpy(pExpr, pDup, sizeof(*pExpr));
if( !ExprHasProperty(pExpr, EP_IntValue) && pExpr->u.zToken!=0 ){
assert( (pExpr->flags & (EP_Reduced|EP_TokenOnly))==0 );
pExpr->u.zToken = sqlite3DbStrDup(db, pExpr->u.zToken);
pExpr->flags |= EP_MemToken;
/* Before calling sqlite3ExprDelete(), set the EP_Static flag. This
** prevents ExprDelete() from deleting the Expr structure itself,
** allowing it to be repopulated by the memcpy() on the following line.
** The pExpr->u.zToken might point into memory that will be freed by the
** sqlite3DbFree(db, pDup) on the last line of this block, so be sure to
** make a copy of the token before doing the sqlite3DbFree().
*/
ExprSetProperty(pExpr, EP_Static);
sqlite3ExprDelete(db, pExpr);
memcpy(pExpr, pDup, sizeof(*pExpr));
if( !ExprHasProperty(pExpr, EP_IntValue) && pExpr->u.zToken!=0 ){
assert( (pExpr->flags & (EP_Reduced|EP_TokenOnly))==0 );
pExpr->u.zToken = sqlite3DbStrDup(db, pExpr->u.zToken);
pExpr->flags |= EP_MemToken;
}
sqlite3DbFree(db, pDup);
}
sqlite3DbFree(db, pDup);
ExprSetProperty(pExpr, EP_Alias);
}
@@ -349,6 +351,7 @@ static int lookupName(
testcase( iCol==(-1) );
pExpr->iTable = pNC->uNC.pUpsert->regData + iCol;
eNewExprOp = TK_REGISTER;
ExprSetProperty(pExpr, EP_Alias);
}else
#endif /* SQLITE_OMIT_UPSERT */
{
+33 -6
View File
@@ -817,7 +817,7 @@ static void selectExprDefer(
if( pItem->u.x.iOrderByCol==0 ){
Expr *pExpr = pItem->pExpr;
Table *pTab = pExpr->pTab;
if( pExpr->op==TK_COLUMN && pTab && !IsVirtual(pTab)
if( pExpr->op==TK_COLUMN && pExpr->iColumn>=0 && pTab && !IsVirtual(pTab)
&& (pTab->aCol[pExpr->iColumn].colFlags & COLFLAG_SORTERREF)
){
int j;
@@ -5100,11 +5100,17 @@ static void finalizeAggFunctions(Parse *pParse, AggInfo *pAggInfo){
}
}
/*
** Update the accumulator memory cells for an aggregate based on
** the current cursor position.
**
** If regAcc is non-zero and there are no min() or max() aggregates
** in pAggInfo, then only populate the pAggInfo->nAccumulator accumulator
** registers i register regAcc contains 0. The caller will take care
** of setting and clearing regAcc.
*/
static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){
static void updateAccumulator(Parse *pParse, int regAcc, AggInfo *pAggInfo){
Vdbe *v = pParse->pVdbe;
int i;
int regHit = 0;
@@ -5168,6 +5174,9 @@ static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){
** Another solution would be to change the OP_SCopy used to copy cached
** values to an OP_Copy.
*/
if( regHit==0 && pAggInfo->nAccumulator ){
regHit = regAcc;
}
if( regHit ){
addrHitTest = sqlite3VdbeAddOp1(v, OP_If, regHit); VdbeCoverage(v);
}
@@ -6021,8 +6030,6 @@ int sqlite3Select(
pParse->nMem += pGroupBy->nExpr;
sqlite3VdbeAddOp2(v, OP_Integer, 0, iAbortFlag);
VdbeComment((v, "clear abort flag"));
sqlite3VdbeAddOp2(v, OP_Integer, 0, iUseFlag);
VdbeComment((v, "indicate accumulator empty"));
sqlite3VdbeAddOp3(v, OP_Null, 0, iAMem, iAMem+pGroupBy->nExpr-1);
/* Begin a loop that will extract all source rows in GROUP BY order.
@@ -6155,7 +6162,7 @@ int sqlite3Select(
** the current row
*/
sqlite3VdbeJumpHere(v, addr1);
updateAccumulator(pParse, &sAggInfo);
updateAccumulator(pParse, iUseFlag, &sAggInfo);
sqlite3VdbeAddOp2(v, OP_Integer, 1, iUseFlag);
VdbeComment((v, "indicate data in accumulator"));
@@ -6207,6 +6214,8 @@ int sqlite3Select(
*/
sqlite3VdbeResolveLabel(v, addrReset);
resetAccumulator(pParse, &sAggInfo);
sqlite3VdbeAddOp2(v, OP_Integer, 0, iUseFlag);
VdbeComment((v, "indicate accumulator empty"));
sqlite3VdbeAddOp1(v, OP_Return, regReset);
} /* endif pGroupBy. Begin aggregate queries without GROUP BY: */
@@ -6272,6 +6281,23 @@ int sqlite3Select(
}else
#endif /* SQLITE_OMIT_BTREECOUNT */
{
int regAcc = 0; /* "populate accumulators" flag */
/* If there are accumulator registers but no min() or max() functions,
** allocate register regAcc. Register regAcc will contain 0 the first
** time the inner loop runs, and 1 thereafter. The code generated
** by updateAccumulator() only updates the accumulator registers if
** regAcc contains 0. */
if( sAggInfo.nAccumulator ){
for(i=0; i<sAggInfo.nFunc; i++){
if( sAggInfo.aFunc[i].pFunc->funcFlags&SQLITE_FUNC_NEEDCOLL ) break;
}
if( i==sAggInfo.nFunc ){
regAcc = ++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_Integer, 0, regAcc);
}
}
/* This case runs if the aggregate has no GROUP BY clause. The
** processing is much simpler since there is only a single row
** of output.
@@ -6293,7 +6319,8 @@ int sqlite3Select(
if( pWInfo==0 ){
goto select_end;
}
updateAccumulator(pParse, &sAggInfo);
updateAccumulator(pParse, regAcc, &sAggInfo);
if( regAcc ) sqlite3VdbeAddOp2(v, OP_Integer, 1, regAcc);
if( sqlite3WhereIsOrdered(pWInfo)>0 ){
sqlite3VdbeGoto(v, sqlite3WhereBreakLabel(pWInfo));
VdbeComment((v, "%s() by index",
+34 -15
View File
@@ -2567,8 +2567,7 @@ static void explain_data_prepare(ShellState *p, sqlite3_stmt *pSql){
int nAlloc = 0; /* Allocated size of p->aiIndent[], abYield */
int iOp; /* Index of operation in p->aiIndent[] */
const char *azNext[] = { "Next", "Prev", "VPrev", "VNext", "SorterNext",
"NextIfOpen", "PrevIfOpen", 0 };
const char *azNext[] = { "Next", "Prev", "VPrev", "VNext", "SorterNext", 0 };
const char *azYield[] = { "Yield", "SeekLT", "SeekGT", "RowSetRead",
"Rewind", 0 };
const char *azGoto[] = { "Goto", 0 };
@@ -2972,6 +2971,7 @@ static int shell_exec(
/* Reprepare pStmt before reactiving trace modes */
sqlite3_finalize(pStmt);
sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
if( pArg ) pArg->pStmt = pStmt;
}
restore_debug_trace_modes();
}
@@ -3656,6 +3656,17 @@ static void open_db(ShellState *p, int openFlags){
}
}
/*
** Attempt to close the databaes connection. Report errors.
*/
void close_db(sqlite3 *db){
int rc = sqlite3_close(db);
if( rc ){
utf8_printf(stderr, "Error: sqlite3_close() returns %d: %s\n",
rc, sqlite3_errmsg(db));
}
}
#if HAVE_READLINE || HAVE_EDITLINE
/*
** Readline completion callbacks
@@ -4236,7 +4247,7 @@ static void tryToClone(ShellState *p, const char *zNewDb){
sqlite3_exec(newDb, "COMMIT;", 0, 0, 0);
sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0);
}
sqlite3_close(newDb);
close_db(newDb);
}
/*
@@ -5273,7 +5284,8 @@ static int arExtractCommand(ArCommand *pAr){
"SELECT "
" ($dir || name),"
" writefile(($dir || name), %s, mode, mtime) "
"FROM %s WHERE (%s) AND (data IS NULL OR $dirOnly = 0)";
"FROM %s WHERE (%s) AND (data IS NULL OR $dirOnly = 0)"
" AND name NOT GLOB '*..[/\\]*'";
const char *azExtraArg[] = {
"sqlar_uncompress(data, sz)",
@@ -5553,7 +5565,7 @@ static int arDotCommand(
}
end_ar_command:
if( cmd.db!=pState->db ){
sqlite3_close(cmd.db);
close_db(cmd.db);
}
sqlite3_free(cmd.zSrcTable);
@@ -5676,14 +5688,14 @@ static int do_meta_command(char *zLine, ShellState *p){
SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, zVfs);
if( rc!=SQLITE_OK ){
utf8_printf(stderr, "Error: cannot open \"%s\"\n", zDestFile);
sqlite3_close(pDest);
close_db(pDest);
return 1;
}
open_db(p, 0);
pBackup = sqlite3_backup_init(pDest, "main", p->db, zDb);
if( pBackup==0 ){
utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(pDest));
sqlite3_close(pDest);
close_db(pDest);
return 1;
}
while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK ){}
@@ -5694,7 +5706,7 @@ static int do_meta_command(char *zLine, ShellState *p){
utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(pDest));
rc = 1;
}
sqlite3_close(pDest);
close_db(pDest);
}else
if( c=='b' && n>=3 && strncmp(azArg[0], "bail", n)==0 ){
@@ -6510,7 +6522,7 @@ static int do_meta_command(char *zLine, ShellState *p){
int newFlag = 0; /* True to delete file before opening */
/* Close the existing database */
session_close_all(p);
sqlite3_close(p->db);
close_db(p->db);
p->db = 0;
p->zDbFilename = 0;
sqlite3_free(p->zFreeOnClose);
@@ -6690,14 +6702,14 @@ static int do_meta_command(char *zLine, ShellState *p){
rc = sqlite3_open(zSrcFile, &pSrc);
if( rc!=SQLITE_OK ){
utf8_printf(stderr, "Error: cannot open \"%s\"\n", zSrcFile);
sqlite3_close(pSrc);
close_db(pSrc);
return 1;
}
open_db(p, 0);
pBackup = sqlite3_backup_init(p->db, zDb, pSrc, "main");
if( pBackup==0 ){
utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
sqlite3_close(pSrc);
close_db(pSrc);
return 1;
}
while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK
@@ -6717,7 +6729,7 @@ static int do_meta_command(char *zLine, ShellState *p){
utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
rc = 1;
}
sqlite3_close(pSrc);
close_db(pSrc);
}else
if( c=='s' && strncmp(azArg[0], "scanstats", n)==0 ){
@@ -7401,7 +7413,10 @@ static int do_meta_command(char *zLine, ShellState *p){
initText(&s);
open_db(p, 0);
rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0);
if( rc ) return shellDatabaseError(p->db);
if( rc ){
sqlite3_finalize(pStmt);
return shellDatabaseError(p->db);
}
if( nArg>2 && c=='i' ){
/* It is an historical accident that the .indexes command shows an error
@@ -7409,6 +7424,7 @@ static int do_meta_command(char *zLine, ShellState *p){
** command does not. */
raw_printf(stderr, "Usage: .indexes ?LIKE-PATTERN?\n");
rc = 1;
sqlite3_finalize(pStmt);
goto meta_command_exit;
}
for(ii=0; sqlite3_step(pStmt)==SQLITE_ROW; ii++){
@@ -8228,7 +8244,7 @@ static void usage(int showDetail){
*/
static void verify_uninitialized(void){
if( sqlite3_config(-1)==SQLITE_MISUSE ){
utf8_printf(stdout, "WARNING: attempt to configuration SQLite after"
utf8_printf(stdout, "WARNING: attempt to configure SQLite after"
" initialization.\n");
}
}
@@ -8754,7 +8770,7 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
set_table_name(&data, 0);
if( data.db ){
session_close_all(&data);
sqlite3_close(data.db);
close_db(data.db);
}
sqlite3_free(data.zFreeOnClose);
find_home_dir(1);
@@ -8765,5 +8781,8 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
for(i=0; i<argcToFree; i++) free(argvToFree[i]);
free(argvToFree);
#endif
/* Clear the global data structure so that valgrind will detect memory
** leaks */
memset(&data, 0, sizeof(data));
return rc;
}
+10 -4
View File
@@ -504,6 +504,7 @@ int sqlite3_exec(
#define SQLITE_IOERR_COMMIT_ATOMIC (SQLITE_IOERR | (30<<8))
#define SQLITE_IOERR_ROLLBACK_ATOMIC (SQLITE_IOERR | (31<<8))
#define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8))
#define SQLITE_LOCKED_VTAB (SQLITE_LOCKED | (2<<8))
#define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8))
#define SQLITE_BUSY_SNAPSHOT (SQLITE_BUSY | (2<<8))
#define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8))
@@ -511,6 +512,7 @@ int sqlite3_exec(
#define SQLITE_CANTOPEN_FULLPATH (SQLITE_CANTOPEN | (3<<8))
#define SQLITE_CANTOPEN_CONVPATH (SQLITE_CANTOPEN | (4<<8))
#define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8))
#define SQLITE_CORRUPT_SEQUENCE (SQLITE_CORRUPT | (2<<8))
#define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8))
#define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8))
#define SQLITE_READONLY_ROLLBACK (SQLITE_READONLY | (3<<8))
@@ -6292,6 +6294,10 @@ struct sqlite3_index_info {
/*
** CAPI3REF: Virtual Table Scan Flags
**
** Virtual table implementations are allowed to set the
** [sqlite3_index_info].idxFlags field to some combination of
** these bits.
*/
#define SQLITE_INDEX_SCAN_UNIQUE 1 /* Scan visits at most 1 row */
@@ -8533,11 +8539,11 @@ int sqlite3_vtab_on_conflict(sqlite3 *);
** method of a [virtual table], then it returns true if and only if the
** column is being fetched as part of an UPDATE operation during which the
** column value will not change. Applications might use this to substitute
** a lighter-weight value to return that the corresponding [xUpdate] method
** understands as a "no-change" value.
** a return value that is less expensive to compute and that the corresponding
** [xUpdate] method understands as a "no-change" value.
**
** If the [xColumn] method calls sqlite3_vtab_nochange() and finds that
** the column is not changed by the UPDATE statement, they the xColumn
** the column is not changed by the UPDATE statement, then the xColumn
** method can optionally return without setting a result, without calling
** any of the [sqlite3_result_int|sqlite3_result_xxxxx() interfaces].
** In that case, [sqlite3_value_nochange(X)] will return true for the
@@ -9032,7 +9038,7 @@ SQLITE_EXPERIMENTAL int sqlite3_snapshot_recover(sqlite3 *db, const char *zDb);
** been a prior call to [sqlite3_deserialize(D,S,...)] with the same
** values of D and S.
** The size of the database is written into *P even if the
** SQLITE_SERIALIZE_NOCOPY bit is set but no contigious copy
** SQLITE_SERIALIZE_NOCOPY bit is set but no contiguous copy
** of the database exists.
**
** A call to sqlite3_serialize(D,S,P,F) might return NULL even if the
+1 -1
View File
@@ -4166,6 +4166,7 @@ int sqlite3CreateFunc(sqlite3 *, const char *, int, int, void *,
void (*)(sqlite3_context*,int,sqlite3_value **), void (*)(sqlite3_context*),
FuncDestructor *pDestructor
);
void sqlite3NoopDestructor(void*);
void sqlite3OomFault(sqlite3*);
void sqlite3OomClear(sqlite3*);
int sqlite3ApiExit(sqlite3 *db, int);
@@ -4268,7 +4269,6 @@ int sqlite3VtabCallConnect(Parse*, Table*);
int sqlite3VtabCallDestroy(sqlite3*, int, const char *);
int sqlite3VtabBegin(sqlite3 *, VTable *);
FuncDef *sqlite3VtabOverloadFunction(sqlite3 *,FuncDef*, int nArg, Expr*);
void sqlite3InvalidFunction(sqlite3_context*,int,sqlite3_value**);
sqlite3_int64 sqlite3StmtCurrentTime(sqlite3_context*);
int sqlite3VdbeParameterIndex(Vdbe*, const char*, int);
int sqlite3TransferBindings(sqlite3_stmt *, sqlite3_stmt *);
+1 -1
View File
@@ -133,7 +133,7 @@ static int SQLITE_TCLAPI btree_begin_transaction(
}
pBt = sqlite3TestTextToPtr(argv[1]);
sqlite3BtreeEnter(pBt);
rc = sqlite3BtreeBeginTrans(pBt, 1);
rc = sqlite3BtreeBeginTrans(pBt, 1, 0);
sqlite3BtreeLeave(pBt);
if( rc!=SQLITE_OK ){
Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
+18
View File
@@ -32,6 +32,8 @@ static struct MemFault {
int nRepeat; /* Number of times to repeat the failure */
int nBenign; /* Number of benign failures seen since last config */
int nFail; /* Number of failures seen since last config */
int nOkBefore; /* Successful allocations prior to the first fault */
int nOkAfter; /* Successful allocations after a fault */
u8 enable; /* True if enabled */
int isInstalled; /* True if the fault simulation layer is installed */
int isBenignMode; /* True if malloc failures are considered benign */
@@ -47,18 +49,32 @@ static void sqlite3Fault(void){
cnt++;
}
/*
** This routine exists as a place to set a breakpoint that will
** fire the first time any malloc() fails on a single test case.
** The sqlite3Fault() routine above runs on every malloc() failure.
** This routine only runs on the first such failure.
*/
static void sqlite3FirstFault(void){
static int cnt2 = 0;
cnt2++;
}
/*
** Check to see if a fault should be simulated. Return true to simulate
** the fault. Return false if the fault should not be simulated.
*/
static int faultsimStep(void){
if( likely(!memfault.enable) ){
memfault.nOkAfter++;
return 0;
}
if( memfault.iCountdown>0 ){
memfault.iCountdown--;
memfault.nOkBefore++;
return 0;
}
if( memfault.nFail==0 ) sqlite3FirstFault();
sqlite3Fault();
memfault.nFail++;
if( memfault.isBenignMode>0 ){
@@ -133,6 +149,8 @@ static void faultsimConfig(int nDelay, int nRepeat){
memfault.nRepeat = nRepeat;
memfault.nBenign = 0;
memfault.nFail = 0;
memfault.nOkBefore = 0;
memfault.nOkAfter = 0;
memfault.enable = nDelay>=0;
/* Sometimes, when running multi-threaded tests, the isBenignMode
+9 -5
View File
@@ -845,7 +845,7 @@ static void updateVirtualTable(
int regRowid; /* Register for ephem table rowid */
int iCsr = pSrc->a[0].iCursor; /* Cursor used for virtual table scan */
int aDummy[2]; /* Unused arg for sqlite3WhereOkOnePass() */
int bOnePass; /* True to use onepass strategy */
int eOnePass; /* True to use onepass strategy */
int addr; /* Address of OP_OpenEphemeral */
/* Allocate nArg registers in which to gather the arguments for VUpdate. Then
@@ -890,12 +890,16 @@ static void updateVirtualTable(
sqlite3VdbeAddOp2(v, OP_SCopy, regArg+2+iPk, regArg+1);
}
bOnePass = sqlite3WhereOkOnePass(pWInfo, aDummy);
eOnePass = sqlite3WhereOkOnePass(pWInfo, aDummy);
if( bOnePass ){
/* There is no ONEPASS_MULTI on virtual tables */
assert( eOnePass==ONEPASS_OFF || eOnePass==ONEPASS_SINGLE );
if( eOnePass ){
/* If using the onepass strategy, no-op out the OP_OpenEphemeral coded
** above. */
sqlite3VdbeChangeToNoop(v, addr);
sqlite3VdbeAddOp1(v, OP_Close, iCsr);
}else{
/* Create a record from the argument register contents and insert it into
** the ephemeral table. */
@@ -911,7 +915,7 @@ static void updateVirtualTable(
}
if( bOnePass==0 ){
if( eOnePass==ONEPASS_OFF ){
/* End the virtual table scan */
sqlite3WhereEnd(pWInfo);
@@ -931,7 +935,7 @@ static void updateVirtualTable(
/* End of the ephemeral table scan. Or, if using the onepass strategy,
** jump to here if the scan visited zero rows. */
if( bOnePass==0 ){
if( eOnePass==ONEPASS_OFF ){
sqlite3VdbeAddOp2(v, OP_Next, ephemTab, addr+1); VdbeCoverage(v);
sqlite3VdbeJumpHere(v, addr);
sqlite3VdbeAddOp2(v, OP_Close, ephemTab, 0);
+1
View File
@@ -229,6 +229,7 @@ void sqlite3UpsertDoUpdate(
VdbeComment((v, "%s.%s", pIdx->zName,
pTab->aCol[pPk->aiColumn[i]].zName));
}
sqlite3VdbeVerifyAbortable(v, OE_Abort);
i = sqlite3VdbeAddOp4Int(v, OP_Found, iDataCur, 0, iPk, nPk);
VdbeCoverage(v);
sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CORRUPT, OE_Abort, 0,
+1 -1
View File
@@ -224,7 +224,7 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db, int iDb){
*/
rc = execSql(db, pzErrMsg, "BEGIN");
if( rc!=SQLITE_OK ) goto end_of_vacuum;
rc = sqlite3BtreeBeginTrans(pMain, 2);
rc = sqlite3BtreeBeginTrans(pMain, 2, 0);
if( rc!=SQLITE_OK ) goto end_of_vacuum;
/* Do not attempt to change the page size for a WAL database */
+171 -77
View File
@@ -915,6 +915,9 @@ case OP_Yield: { /* in1, jump */
*/
case OP_HaltIfNull: { /* in3 */
pIn3 = &aMem[pOp->p3];
#ifdef SQLITE_DEBUG
if( pOp->p2==OE_Abort ){ sqlite3VdbeAssertAbortable(p); }
#endif
if( (pIn3->flags & MEM_Null)==0 ) break;
/* Fall through into OP_Halt */
}
@@ -954,6 +957,9 @@ case OP_Halt: {
int pcx;
pcx = (int)(pOp - aOp);
#ifdef SQLITE_DEBUG
if( pOp->p2==OE_Abort ){ sqlite3VdbeAssertAbortable(p); }
#endif
if( pOp->p1==SQLITE_OK && p->pFrame ){
/* Halt the sub-program. Return control to the parent frame. */
pFrame = p->pFrame;
@@ -3196,8 +3202,7 @@ case OP_AutoCommit: {
*/
case OP_Transaction: {
Btree *pBt;
int iMeta;
int iGen;
int iMeta = 0;
assert( p->bIsReader );
assert( p->readOnly==0 || pOp->p2==0 );
@@ -3210,7 +3215,7 @@ case OP_Transaction: {
pBt = db->aDb[pOp->p1].pBt;
if( pBt ){
rc = sqlite3BtreeBeginTrans(pBt, pOp->p2);
rc = sqlite3BtreeBeginTrans(pBt, pOp->p2, &iMeta);
testcase( rc==SQLITE_BUSY_SNAPSHOT );
testcase( rc==SQLITE_BUSY_RECOVERY );
if( rc!=SQLITE_OK ){
@@ -3243,19 +3248,17 @@ case OP_Transaction: {
p->nStmtDefCons = db->nDeferredCons;
p->nStmtDefImmCons = db->nDeferredImmCons;
}
/* Gather the schema version number for checking:
}
assert( pOp->p5==0 || pOp->p4type==P4_INT32 );
if( pOp->p5
&& (iMeta!=pOp->p3
|| db->aDb[pOp->p1].pSchema->iGeneration!=pOp->p4.i)
){
/*
** IMPLEMENTATION-OF: R-03189-51135 As each SQL statement runs, the schema
** version is checked to ensure that the schema has not changed since the
** SQL statement was prepared.
*/
sqlite3BtreeGetMeta(pBt, BTREE_SCHEMA_VERSION, (u32 *)&iMeta);
iGen = db->aDb[pOp->p1].pSchema->iGeneration;
}else{
iGen = iMeta = 0;
}
assert( pOp->p5==0 || pOp->p4type==P4_INT32 );
if( pOp->p5 && (iMeta!=pOp->p3 || iGen!=pOp->p4.i) ){
sqlite3DbFree(db, p->zErrMsg);
p->zErrMsg = sqlite3DbStrDup(db, "database schema has changed");
/* If the schema-cookie from the database file matches the cookie
@@ -3324,6 +3327,8 @@ case OP_ReadCookie: { /* out2 */
*/
case OP_SetCookie: {
Db *pDb;
sqlite3VdbeIncrWriteCounter(p, 0);
assert( pOp->p2<SQLITE_N_BTREE_META );
assert( pOp->p1>=0 && pOp->p1<db->nDb );
assert( DbMaskTest(p->btreeMask, pOp->p1) );
@@ -3362,59 +3367,78 @@ case OP_SetCookie: {
** values need not be contiguous but all P1 values should be small integers.
** It is an error for P1 to be negative.
**
** If P5!=0 then use the content of register P2 as the root page, not
** the value of P2 itself.
**
** There will be a read lock on the database whenever there is an
** open cursor. If the database was unlocked prior to this instruction
** then a read lock is acquired as part of this instruction. A read
** lock allows other processes to read the database but prohibits
** any other process from modifying the database. The read lock is
** released when all cursors are closed. If this instruction attempts
** to get a read lock but fails, the script terminates with an
** SQLITE_BUSY error code.
** Allowed P5 bits:
** <ul>
** <li> <b>0x02 OPFLAG_SEEKEQ</b>: This cursor will only be used for
** equality lookups (implemented as a pair of opcodes OP_SeekGE/OP_IdxGT
** of OP_SeekLE/OP_IdxGT)
** </ul>
**
** The P4 value may be either an integer (P4_INT32) or a pointer to
** a KeyInfo structure (P4_KEYINFO). If it is a pointer to a KeyInfo
** structure, then said structure defines the content and collating
** sequence of the index being opened. Otherwise, if P4 is an integer
** value, it is set to the number of columns in the table.
** object, then table being opened must be an [index b-tree] where the
** KeyInfo object defines the content and collating
** sequence of that index b-tree. Otherwise, if P4 is an integer
** value, then the table being opened must be a [table b-tree] with a
** number of columns no less than the value of P4.
**
** See also: OpenWrite, ReopenIdx
*/
/* Opcode: ReopenIdx P1 P2 P3 P4 P5
** Synopsis: root=P2 iDb=P3
**
** The ReopenIdx opcode works exactly like ReadOpen except that it first
** checks to see if the cursor on P1 is already open with a root page
** number of P2 and if it is this opcode becomes a no-op. In other words,
** The ReopenIdx opcode works like OP_OpenRead except that it first
** checks to see if the cursor on P1 is already open on the same
** b-tree and if it is this opcode becomes a no-op. In other words,
** if the cursor is already open, do not reopen it.
**
** The ReopenIdx opcode may only be used with P5==0 and with P4 being
** a P4_KEYINFO object. Furthermore, the P3 value must be the same as
** every other ReopenIdx or OpenRead for the same cursor number.
** The ReopenIdx opcode may only be used with P5==0 or P5==OPFLAG_SEEKEQ
** and with P4 being a P4_KEYINFO object. Furthermore, the P3 value must
** be the same as every other ReopenIdx or OpenRead for the same cursor
** number.
**
** See the OpenRead opcode documentation for additional information.
** Allowed P5 bits:
** <ul>
** <li> <b>0x02 OPFLAG_SEEKEQ</b>: This cursor will only be used for
** equality lookups (implemented as a pair of opcodes OP_SeekGE/OP_IdxGT
** of OP_SeekLE/OP_IdxGT)
** </ul>
**
** See also: OP_OpenRead, OP_OpenWrite
*/
/* Opcode: OpenWrite P1 P2 P3 P4 P5
** Synopsis: root=P2 iDb=P3
**
** Open a read/write cursor named P1 on the table or index whose root
** page is P2. Or if P5!=0 use the content of register P2 to find the
** root page.
** page is P2 (or whose root page is held in register P2 if the
** OPFLAG_P2ISREG bit is set in P5 - see below).
**
** The P4 value may be either an integer (P4_INT32) or a pointer to
** a KeyInfo structure (P4_KEYINFO). If it is a pointer to a KeyInfo
** structure, then said structure defines the content and collating
** sequence of the index being opened. Otherwise, if P4 is an integer
** value, it is set to the number of columns in the table, or to the
** largest index of any column of the table that is actually used.
** object, then table being opened must be an [index b-tree] where the
** KeyInfo object defines the content and collating
** sequence of that index b-tree. Otherwise, if P4 is an integer
** value, then the table being opened must be a [table b-tree] with a
** number of columns no less than the value of P4.
**
** This instruction works just like OpenRead except that it opens the cursor
** in read/write mode. For a given table, there can be one or more read-only
** cursors or a single read/write cursor but not both.
** Allowed P5 bits:
** <ul>
** <li> <b>0x02 OPFLAG_SEEKEQ</b>: This cursor will only be used for
** equality lookups (implemented as a pair of opcodes OP_SeekGE/OP_IdxGT
** of OP_SeekLE/OP_IdxGT)
** <li> <b>0x08 OPFLAG_FORDELETE</b>: This cursor is used only to seek
** and subsequently delete entries in an index btree. This is a
** hint to the storage engine that the storage engine is allowed to
** ignore. The hint is not used by the official SQLite b*tree storage
** engine, but is used by COMDB2.
** <li> <b>0x10 OPFLAG_P2ISREG</b>: Use the content of register P2
** as the root page, not the value of P2 itself.
** </ul>
**
** See also OpenRead.
** This instruction works like OpenRead except that it opens the cursor
** in read/write mode.
**
** See also: OP_OpenRead, OP_ReopenIdx
*/
case OP_ReopenIdx: {
int nField;
@@ -3470,6 +3494,7 @@ case OP_OpenWrite:
if( pOp->p5 & OPFLAG_P2ISREG ){
assert( p2>0 );
assert( p2<=(p->nMem+1 - p->nCursor) );
assert( pOp->opcode==OP_OpenWrite );
pIn2 = &aMem[p2];
assert( memIsValid(pIn2) );
assert( (pIn2->flags & MEM_Int)!=0 );
@@ -3598,7 +3623,7 @@ case OP_OpenEphemeral: {
rc = sqlite3BtreeOpen(db->pVfs, 0, db, &pCx->pBtx,
BTREE_OMIT_JOURNAL | BTREE_SINGLE | pOp->p5, vfsFlags);
if( rc==SQLITE_OK ){
rc = sqlite3BtreeBeginTrans(pCx->pBtx, 1);
rc = sqlite3BtreeBeginTrans(pCx->pBtx, 1, 0);
}
if( rc==SQLITE_OK ){
/* If a transient index is required, create it by calling
@@ -4006,6 +4031,25 @@ seek_not_found:
break;
}
/* Opcode: SeekHit P1 P2 * * *
** Synopsis: seekHit=P2
**
** Set the seekHit flag on cursor P1 to the value in P2.
** The seekHit flag is used by the IfNoHope opcode.
**
** P1 must be a valid b-tree cursor. P2 must be a boolean value,
** either 0 or 1.
*/
case OP_SeekHit: {
VdbeCursor *pC;
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
assert( pOp->p2==0 || pOp->p2==1 );
pC->seekHit = pOp->p2 & 1;
break;
}
/* Opcode: Found P1 P2 P3 P4 *
** Synopsis: key=r[P3@P4]
**
@@ -4040,7 +4084,34 @@ seek_not_found:
** advanced in either direction. In other words, the Next and Prev
** opcodes do not work after this operation.
**
** See also: Found, NotExists, NoConflict
** See also: Found, NotExists, NoConflict, IfNoHope
*/
/* Opcode: IfNoHope P1 P2 P3 P4 *
** Synopsis: key=r[P3@P4]
**
** Register P3 is the first of P4 registers that form an unpacked
** record.
**
** Cursor P1 is on an index btree. If the seekHit flag is set on P1, then
** this opcode is a no-op. But if the seekHit flag of P1 is clear, then
** check to see if there is any entry in P1 that matches the
** prefix identified by P3 and P4. If no entry matches the prefix,
** jump to P2. Otherwise fall through.
**
** This opcode behaves like OP_NotFound if the seekHit
** flag is clear and it behaves like OP_Noop if the seekHit flag is set.
**
** This opcode is used in IN clause processing for a multi-column key.
** If an IN clause is attached to an element of the key other than the
** left-most element, and if there are no matches on the most recent
** seek over the whole key, then it might be that one of the key element
** to the left is prohibiting a match, and hence there is "no hope" of
** any match regardless of how many IN clause elements are checked.
** In such a case, we abandon the IN clause search early, using this
** opcode. The opcode name comes from the fact that the
** jump is taken if there is "no hope" of achieving a match.
**
** See also: NotFound, SeekHit
*/
/* Opcode: NoConflict P1 P2 P3 P4 *
** Synopsis: key=r[P3@P4]
@@ -4065,6 +4136,14 @@ seek_not_found:
**
** See also: NotFound, Found, NotExists
*/
case OP_IfNoHope: { /* jump, in3 */
VdbeCursor *pC;
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
if( pC->seekHit ) break;
/* Fall through into OP_NotFound */
}
case OP_NoConflict: /* jump, in3 */
case OP_NotFound: /* jump, in3 */
case OP_Found: { /* jump, in3 */
@@ -4213,7 +4292,7 @@ case OP_NotExists: /* jump, in3 */
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
#ifdef SQLITE_DEBUG
pC->seekOp = 0;
pC->seekOp = OP_SeekRowid;
#endif
assert( pC->isTable );
assert( pC->eCurType==CURTYPE_BTREE );
@@ -4287,11 +4366,8 @@ case OP_NewRowid: { /* out2 */
pOut = out2Prerelease(p, pOp);
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
pC = p->apCsr[pOp->p1];
if( !pC->isTable ){
rc = SQLITE_CORRUPT_BKPT;
goto abort_due_to_error;
}
assert( pC!=0 );
assert( pC->isTable );
assert( pC->eCurType==CURTYPE_BTREE );
assert( pC->uc.pCursor!=0 );
{
@@ -4460,6 +4536,7 @@ case OP_InsertInt: {
assert( (pOp->p5 & OPFLAG_ISNOOP) || pC->isTable );
assert( pOp->p4type==P4_TABLE || pOp->p4type>=P4_STATIC );
REGISTER_TRACE(pOp->p2, pData);
sqlite3VdbeIncrWriteCounter(p, pC);
if( pOp->opcode==OP_Insert ){
pKey = &aMem[pOp->p3];
@@ -4574,6 +4651,7 @@ case OP_Delete: {
assert( pC->eCurType==CURTYPE_BTREE );
assert( pC->uc.pCursor!=0 );
assert( pC->deferredMoveto==0 );
sqlite3VdbeIncrWriteCounter(p, pC);
#ifdef SQLITE_DEBUG
if( pOp->p4type==P4_TABLE && HasRowid(pOp->p4.pTab) && pOp->p5==0 ){
@@ -4742,10 +4820,10 @@ 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
** If P3!=0 then this opcode is allowed to make an ephemeral 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
** moves caused by other cursors that "save" 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.
@@ -4868,6 +4946,9 @@ case OP_NullRow: {
assert( pC->uc.pCursor!=0 );
sqlite3BtreeClearCursor(pC->uc.pCursor);
}
#ifdef SQLITE_DEBUG
if( pC->seekOp==0 ) pC->seekOp = OP_NullRow;
#endif
break;
}
@@ -5054,12 +5135,7 @@ case OP_Rewind: { /* jump */
** If P5 is positive and the jump is taken, then event counter
** number P5-1 in the prepared statement is incremented.
**
** See also: Prev, NextIfOpen
*/
/* Opcode: NextIfOpen P1 P2 P3 P4 P5
**
** This opcode works just like Next except that if cursor P1 is not
** open it behaves a no-op.
** See also: Prev
*/
/* Opcode: Prev P1 P2 P3 P4 P5
**
@@ -5087,11 +5163,6 @@ case OP_Rewind: { /* jump */
** If P5 is positive and the jump is taken, then event counter
** number P5-1 in the prepared statement is incremented.
*/
/* Opcode: PrevIfOpen P1 P2 P3 P4 P5
**
** This opcode works just like Prev except that if cursor P1 is not
** open it behaves a no-op.
*/
/* Opcode: SorterNext P1 P2 * * P5
**
** This opcode works just like OP_Next except that P1 must be a
@@ -5106,10 +5177,6 @@ case OP_SorterNext: { /* jump */
assert( isSorter(pC) );
rc = sqlite3VdbeSorterNext(db, pC);
goto next_tail;
case OP_PrevIfOpen: /* jump */
case OP_NextIfOpen: /* jump */
if( p->apCsr[pOp->p1]==0 ) break;
/* Fall through */
case OP_Prev: /* jump */
case OP_Next: /* jump */
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
@@ -5120,17 +5187,17 @@ case OP_Next: /* jump */
assert( pC->eCurType==CURTYPE_BTREE );
assert( pOp->opcode!=OP_Next || pOp->p4.xAdvance==sqlite3BtreeNext );
assert( pOp->opcode!=OP_Prev || pOp->p4.xAdvance==sqlite3BtreePrevious );
assert( pOp->opcode!=OP_NextIfOpen || pOp->p4.xAdvance==sqlite3BtreeNext );
assert( pOp->opcode!=OP_PrevIfOpen || pOp->p4.xAdvance==sqlite3BtreePrevious);
/* The Next opcode is only used after SeekGT, SeekGE, and Rewind.
/* The Next opcode is only used after SeekGT, SeekGE, Rewind, and Found.
** The Prev opcode is only used after SeekLT, SeekLE, and Last. */
assert( pOp->opcode!=OP_Next || pOp->opcode!=OP_NextIfOpen
assert( pOp->opcode!=OP_Next
|| pC->seekOp==OP_SeekGT || pC->seekOp==OP_SeekGE
|| pC->seekOp==OP_Rewind || pC->seekOp==OP_Found);
assert( pOp->opcode!=OP_Prev || pOp->opcode!=OP_PrevIfOpen
|| pC->seekOp==OP_Rewind || pC->seekOp==OP_Found
|| pC->seekOp==OP_NullRow);
assert( pOp->opcode!=OP_Prev
|| pC->seekOp==OP_SeekLT || pC->seekOp==OP_SeekLE
|| pC->seekOp==OP_Last );
|| pC->seekOp==OP_Last
|| pC->seekOp==OP_NullRow);
rc = pOp->p4.xAdvance(pC->uc.pCursor, pOp->p3);
next_tail:
@@ -5192,6 +5259,7 @@ case OP_IdxInsert: { /* in2 */
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
pC = p->apCsr[pOp->p1];
sqlite3VdbeIncrWriteCounter(p, pC);
assert( pC!=0 );
assert( isSorter(pC)==(pOp->opcode==OP_SorterInsert) );
pIn2 = &aMem[pOp->p2];
@@ -5238,6 +5306,7 @@ case OP_IdxDelete: {
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
assert( pC->eCurType==CURTYPE_BTREE );
sqlite3VdbeIncrWriteCounter(p, pC);
pCrsr = pC->uc.pCursor;
assert( pCrsr!=0 );
assert( pOp->p5==0 );
@@ -5460,6 +5529,7 @@ case OP_Destroy: { /* out2 */
int iMoved;
int iDb;
sqlite3VdbeIncrWriteCounter(p, 0);
assert( p->readOnly==0 );
assert( pOp->p1>1 );
pOut = out2Prerelease(p, pOp);
@@ -5509,6 +5579,7 @@ case OP_Destroy: { /* out2 */
case OP_Clear: {
int nChange;
sqlite3VdbeIncrWriteCounter(p, 0);
nChange = 0;
assert( p->readOnly==0 );
assert( DbMaskTest(p->btreeMask, pOp->p2) );
@@ -5558,13 +5629,14 @@ case OP_ResetSorter: {
** Allocate a new b-tree in the main database file if P1==0 or in the
** TEMP database file if P1==1 or in an attached database if
** P1>1. The P3 argument must be 1 (BTREE_INTKEY) for a rowid table
** it must be 2 (BTREE_BLOBKEY) for a index or WITHOUT ROWID table.
** it must be 2 (BTREE_BLOBKEY) for an index or WITHOUT ROWID table.
** The root page number of the new b-tree is stored in register P2.
*/
case OP_CreateBtree: { /* out2 */
int pgno;
Db *pDb;
sqlite3VdbeIncrWriteCounter(p, 0);
pOut = out2Prerelease(p, pOp);
pgno = 0;
assert( pOp->p3==BTREE_INTKEY || pOp->p3==BTREE_BLOBKEY );
@@ -5584,6 +5656,7 @@ case OP_CreateBtree: { /* out2 */
** Run the SQL statement or statements specified in the P4 string.
*/
case OP_SqlExec: {
sqlite3VdbeIncrWriteCounter(p, 0);
db->nSqlExec++;
rc = sqlite3_exec(db, pOp->p4.z, 0, 0, 0);
db->nSqlExec--;
@@ -5673,6 +5746,7 @@ case OP_LoadAnalysis: {
** schema consistent with what is on disk.
*/
case OP_DropTable: {
sqlite3VdbeIncrWriteCounter(p, 0);
sqlite3UnlinkAndDeleteTable(db, pOp->p1, pOp->p4.z);
break;
}
@@ -5686,6 +5760,7 @@ case OP_DropTable: {
** schema consistent with what is on disk.
*/
case OP_DropIndex: {
sqlite3VdbeIncrWriteCounter(p, 0);
sqlite3UnlinkAndDeleteIndex(db, pOp->p1, pOp->p4.z);
break;
}
@@ -5699,6 +5774,7 @@ case OP_DropIndex: {
** schema consistent with what is on disk.
*/
case OP_DropTrigger: {
sqlite3VdbeIncrWriteCounter(p, 0);
sqlite3UnlinkAndDeleteTrigger(db, pOp->p1, pOp->p4.z);
break;
}
@@ -6745,7 +6821,7 @@ case OP_VFilter: { /* jump */
** If the VColumn opcode is being used to fetch the value of
** an unchanging column during an UPDATE operation, then the P5
** value is 1. Otherwise, P5 is 0. The P5 value is returned
** by sqlite3_vtab_nochange() routine can can be used
** by sqlite3_vtab_nochange() routine and can be used
** by virtual table implementations to return special "no-change"
** marks which can be more efficient, depending on the virtual table.
*/
@@ -6908,6 +6984,7 @@ case OP_VUpdate: {
|| pOp->p5==OE_Abort || pOp->p5==OE_Ignore || pOp->p5==OE_Replace
);
assert( p->readOnly==0 );
sqlite3VdbeIncrWriteCounter(p, 0);
pVtab = pOp->p4.pVtab->pVtab;
if( pVtab==0 || NEVER(pVtab->pModule==0) ){
rc = SQLITE_LOCKED;
@@ -7225,6 +7302,22 @@ case OP_CursorHint: {
}
#endif /* SQLITE_ENABLE_CURSOR_HINTS */
#ifdef SQLITE_DEBUG
/* Opcode: Abortable * * * * *
**
** Verify that an Abort can happen. Assert if an Abort at this point
** might cause database corruption. This opcode only appears in debugging
** builds.
**
** An Abort is safe if either there have been no writes, or if there is
** an active statement journal.
*/
case OP_Abortable: {
sqlite3VdbeAssertAbortable(p);
break;
}
#endif
/* Opcode: Noop * * * * *
**
** Do nothing. This instruction is often useful as a jump
@@ -7236,8 +7329,9 @@ case OP_CursorHint: {
** This opcode records information from the optimizer. It is the
** the same as a no-op. This opcodesnever appears in a real VM program.
*/
default: { /* This is really OP_Noop and OP_Explain */
default: { /* This is really OP_Noop, OP_Explain */
assert( pOp->opcode==OP_Noop || pOp->opcode==OP_Explain );
break;
}
+5
View File
@@ -197,6 +197,11 @@ void sqlite3VdbeEndCoroutine(Vdbe*,int);
# define sqlite3VdbeVerifyNoMallocRequired(A,B)
# define sqlite3VdbeVerifyNoResultRow(A)
#endif
#if defined(SQLITE_DEBUG)
void sqlite3VdbeVerifyAbortable(Vdbe *p, int);
#else
# define sqlite3VdbeVerifyAbortable(A,B)
#endif
VdbeOp *sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp,int iLineno);
#ifndef SQLITE_OMIT_EXPLAIN
void sqlite3VdbeExplain(Parse*,u8,const char*,...);
+10
View File
@@ -85,6 +85,7 @@ struct VdbeCursor {
Bool isEphemeral:1; /* True for an ephemeral table */
Bool useRandomRowid:1; /* Generate new record numbers semi-randomly */
Bool isOrdered:1; /* True if the table is not BTREE_UNORDERED */
Bool seekHit:1; /* See the OP_SeekHit and OP_IfNoHope opcodes */
Btree *pBtx; /* Separate file holding temporary table */
i64 seqCount; /* Sequence counter */
int *aAltMap; /* Mapping from table to index column numbers */
@@ -379,6 +380,7 @@ struct Vdbe {
int nOp; /* Number of instructions in the program */
#ifdef SQLITE_DEBUG
int rcApp; /* errcode set by sqlite3_result_error_code() */
u32 nWrite; /* Number of write operations that have occurred */
#endif
u16 nResColumn; /* Number of columns in one row of the result set */
u8 errorAction; /* Recovery action to do in case of an error */
@@ -514,6 +516,14 @@ int sqlite3VdbeSorterRewind(const VdbeCursor *, int *);
int sqlite3VdbeSorterWrite(const VdbeCursor *, Mem *);
int sqlite3VdbeSorterCompare(const VdbeCursor *, Mem *, int, int *);
#ifdef SQLITE_DEBUG
void sqlite3VdbeIncrWriteCounter(Vdbe*, VdbeCursor*);
void sqlite3VdbeAssertAbortable(Vdbe*);
#else
# define sqlite3VdbeIncrWriteCounter(V,C)
# define sqlite3VdbeAssertAbortable(V)
#endif
#if !defined(SQLITE_OMIT_SHARED_CACHE)
void sqlite3VdbeEnter(Vdbe*);
#else
-22
View File
@@ -787,28 +787,6 @@ sqlite3_int64 sqlite3StmtCurrentTime(sqlite3_context *p){
return *piTime;
}
/*
** The following is the implementation of an SQL function that always
** fails with an error message stating that the function is used in the
** wrong context. The sqlite3_overload_function() API might construct
** SQL function that use this routine so that the functions will exist
** for name resolution but are actually overloaded by the xFindFunction
** method of virtual tables.
*/
void sqlite3InvalidFunction(
sqlite3_context *context, /* The function calling context */
int NotUsed, /* Number of arguments to the function */
sqlite3_value **NotUsed2 /* Value of each argument */
){
const char *zName = context->pFunc->zName;
char *zErr;
UNUSED_PARAMETER2(NotUsed, NotUsed2);
zErr = sqlite3_mprintf(
"unable to use function %s in the requested context", zName);
sqlite3_result_error(context, zErr, -1);
sqlite3_free(zErr);
}
/*
** Create a new aggregate context for p and return a pointer to
** its pMem->z element.
+48 -9
View File
@@ -603,6 +603,32 @@ int sqlite3VdbeAssertMayAbort(Vdbe *v, int mayAbort){
}
#endif /* SQLITE_DEBUG - the sqlite3AssertMayAbort() function */
#ifdef SQLITE_DEBUG
/*
** Increment the nWrite counter in the VDBE if the cursor is not an
** ephemeral cursor, or if the cursor argument is NULL.
*/
void sqlite3VdbeIncrWriteCounter(Vdbe *p, VdbeCursor *pC){
if( pC==0
|| (pC->eCurType!=CURTYPE_SORTER
&& pC->eCurType!=CURTYPE_PSEUDO
&& !pC->isEphemeral)
){
p->nWrite++;
}
}
#endif
#ifdef SQLITE_DEBUG
/*
** Assert if an Abort at this point in time might result in a corrupt
** database.
*/
void sqlite3VdbeAssertAbortable(Vdbe *p){
assert( p->nWrite==0 || p->usesStmtJournal );
}
#endif
/*
** This routine is called after all opcodes have been inserted. It loops
** through all the opcodes and fixes up some details.
@@ -663,7 +689,6 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){
break;
}
case OP_Next:
case OP_NextIfOpen:
case OP_SorterNext: {
pOp->p4.xAdvance = sqlite3BtreeNext;
pOp->p4type = P4_ADVANCE;
@@ -673,8 +698,7 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){
assert( pOp->p2>=0 );
break;
}
case OP_Prev:
case OP_PrevIfOpen: {
case OP_Prev: {
pOp->p4.xAdvance = sqlite3BtreePrevious;
pOp->p4type = P4_ADVANCE;
/* The code generator never codes any of these opcodes as a jump
@@ -762,6 +786,17 @@ void sqlite3VdbeVerifyNoResultRow(Vdbe *p){
}
#endif
/*
** Generate code (a single OP_Abortable opcode) that will
** verify that the VDBE program can safely call Abort in the current
** context.
*/
#if defined(SQLITE_DEBUG)
void sqlite3VdbeVerifyAbortable(Vdbe *p, int onError){
if( onError==OE_Abort ) sqlite3VdbeAddOp0(p, OP_Abortable);
}
#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
@@ -2995,6 +3030,9 @@ int sqlite3VdbeReset(Vdbe *p){
sqlite3DbFree(db, p->zErrMsg);
p->zErrMsg = 0;
p->pResultSet = 0;
#ifdef SQLITE_DEBUG
p->nWrite = 0;
#endif
/* Save profiling information from this VDBE run.
*/
@@ -4089,7 +4127,7 @@ int sqlite3VdbeRecordCompareWithSkip(
u32 idx1; /* Offset of first type in header */
int rc = 0; /* Return value */
Mem *pRhs = pPKey2->aMem; /* Next field of pPKey2 to compare */
KeyInfo *pKeyInfo = pPKey2->pKeyInfo;
KeyInfo *pKeyInfo;
const unsigned char *aKey1 = (const unsigned char *)pKey1;
Mem mem1;
@@ -4184,7 +4222,7 @@ int sqlite3VdbeRecordCompareWithSkip(
if( (d1+mem1.n) > (unsigned)nKey1 ){
pPKey2->errCode = (u8)SQLITE_CORRUPT_BKPT;
return 0; /* Corruption */
}else if( pKeyInfo->aColl[i] ){
}else if( (pKeyInfo = pPKey2->pKeyInfo)->aColl[i] ){
mem1.enc = pKeyInfo->enc;
mem1.db = pKeyInfo->db;
mem1.flags = MEM_Str;
@@ -4235,7 +4273,7 @@ int sqlite3VdbeRecordCompareWithSkip(
}
if( rc!=0 ){
if( pKeyInfo->aSortOrder[i] ){
if( pPKey2->pKeyInfo->aSortOrder[i] ){
rc = -rc;
}
assert( vdbeRecordCompareDebug(nKey1, pKey1, pPKey2, rc) );
@@ -4244,10 +4282,11 @@ int sqlite3VdbeRecordCompareWithSkip(
}
i++;
if( i==pPKey2->nField ) break;
pRhs++;
d1 += sqlite3VdbeSerialTypeLen(serial_type);
idx1 += sqlite3VarintLen(serial_type);
}while( idx1<(unsigned)szHdr1 && i<pPKey2->nField && d1<=(unsigned)nKey1 );
}while( idx1<(unsigned)szHdr1 && d1<=(unsigned)nKey1 );
/* No memory allocation is ever used on mem1. Prove this using
** the following assert(). If the assert() fails, it indicates a
@@ -4259,7 +4298,7 @@ int sqlite3VdbeRecordCompareWithSkip(
** value. */
assert( CORRUPT_DB
|| vdbeRecordCompareDebug(nKey1, pKey1, pPKey2, pPKey2->default_rc)
|| pKeyInfo->db->mallocFailed
|| pPKey2->pKeyInfo->db->mallocFailed
);
pPKey2->eqSeen = 1;
return pPKey2->default_rc;
@@ -4585,7 +4624,7 @@ int sqlite3VdbeIdxKeyCompare(
if( rc ){
return rc;
}
*res = sqlite3VdbeRecordCompare(m.n, m.z, pUnpacked);
*res = sqlite3VdbeRecordCompareWithSkip(m.n, m.z, pUnpacked, 0);
sqlite3VdbeMemRelease(&m);
return SQLITE_OK;
}
+1 -1
View File
@@ -800,7 +800,7 @@ void sqlite3VdbeMemSetInt64(Mem *pMem, i64 val){
}
/* A no-op destructor */
static void sqlite3NoopDestructor(void *p){ UNUSED_PARAMETER(p); }
void sqlite3NoopDestructor(void *p){ UNUSED_PARAMETER(p); }
/*
** Set the value stored in *pMem should already be a NULL.
+13 -10
View File
@@ -1049,9 +1049,6 @@ FuncDef *sqlite3VtabOverloadFunction(
void *pArg = 0;
FuncDef *pNew;
int rc = 0;
char *zLowerName;
unsigned char *z;
/* Check to see the left operand is a column in a virtual table */
if( NEVER(pExpr==0) ) return pDef;
@@ -1066,16 +1063,22 @@ FuncDef *sqlite3VtabOverloadFunction(
if( pMod->xFindFunction==0 ) return pDef;
/* Call the xFindFunction method on the virtual table implementation
** to see if the implementation wants to overload this function
** to see if the implementation wants to overload this function.
**
** Though undocumented, we have historically always invoked xFindFunction
** with an all lower-case function name. Continue in this tradition to
** avoid any chance of an incompatibility.
*/
zLowerName = sqlite3DbStrDup(db, pDef->zName);
if( zLowerName ){
for(z=(unsigned char*)zLowerName; *z; z++){
*z = sqlite3UpperToLower[*z];
#ifdef SQLITE_DEBUG
{
int i;
for(i=0; pDef->zName[i]; i++){
unsigned char x = (unsigned char)pDef->zName[i];
assert( x==sqlite3UpperToLower[x] );
}
rc = pMod->xFindFunction(pVtab, nArg, zLowerName, &xSFunc, &pArg);
sqlite3DbFree(db, zLowerName);
}
#endif
rc = pMod->xFindFunction(pVtab, nArg, pDef->zName, &xSFunc, &pArg);
if( rc==0 ){
return pDef;
}
+9 -2
View File
@@ -5083,10 +5083,17 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
for(j=pLevel->u.in.nIn, pIn=&pLevel->u.in.aInLoop[j-1]; j>0; j--, pIn--){
sqlite3VdbeJumpHere(v, pIn->addrInTop+1);
if( pIn->eEndLoopOp!=OP_Noop ){
if( pIn->nPrefix ){
assert( pLoop->wsFlags & WHERE_IN_EARLYOUT );
sqlite3VdbeAddOp4Int(v, OP_IfNoHope, pLevel->iIdxCur,
sqlite3VdbeCurrentAddr(v)+2,
pIn->iBase, pIn->nPrefix);
VdbeCoverage(v);
}
sqlite3VdbeAddOp2(v, pIn->eEndLoopOp, pIn->iCur, pIn->addrInTop);
VdbeCoverage(v);
VdbeCoverageIf(v, pIn->eEndLoopOp==OP_PrevIfOpen);
VdbeCoverageIf(v, pIn->eEndLoopOp==OP_NextIfOpen);
VdbeCoverageIf(v, pIn->eEndLoopOp==OP_Prev);
VdbeCoverageIf(v, pIn->eEndLoopOp==OP_Next);
}
sqlite3VdbeJumpHere(v, pIn->addrInTop-1);
}
+3
View File
@@ -82,6 +82,8 @@ struct WhereLevel {
struct InLoop {
int iCur; /* The VDBE cursor used by this IN operator */
int addrInTop; /* Top of the IN loop */
int iBase; /* Base register of multi-key index record */
int nPrefix; /* Number of prior entires in the key */
u8 eEndLoopOp; /* IN Loop terminator. OP_Next or OP_Prev */
} *aInLoop; /* Information about each nested IN operator */
} in; /* Used when pWLoop->wsFlags&WHERE_IN_ABLE */
@@ -555,3 +557,4 @@ void sqlite3WhereTabFuncArgs(Parse*, struct SrcList_item*, WhereClause*);
#define WHERE_SKIPSCAN 0x00008000 /* Uses the skip-scan algorithm */
#define WHERE_UNQ_WANTED 0x00010000 /* WHERE_ONEROW would have been helpful*/
#define WHERE_PARTIALIDX 0x00020000 /* The automatic index is partial */
#define WHERE_IN_EARLYOUT 0x00040000 /* Perhaps quit IN loops early */
+15 -1
View File
@@ -591,7 +591,14 @@ static int codeEqualityTerm(
sqlite3VdbeAddOp1(v, OP_IsNull, iOut); VdbeCoverage(v);
if( i==iEq ){
pIn->iCur = iTab;
pIn->eEndLoopOp = bRev ? OP_PrevIfOpen : OP_NextIfOpen;
pIn->eEndLoopOp = bRev ? OP_Prev : OP_Next;
if( iEq>0 && (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0 ){
pIn->iBase = iReg - i;
pIn->nPrefix = i;
pLoop->wsFlags |= WHERE_IN_EARLYOUT;
}else{
pIn->nPrefix = 0;
}
}else{
pIn->eEndLoopOp = OP_Noop;
}
@@ -1658,6 +1665,9 @@ Bitmask sqlite3WhereCodeOneLoopStart(
** above has already left the cursor sitting on the correct row,
** so no further seeking is needed */
}else{
if( pLoop->wsFlags & WHERE_IN_EARLYOUT ){
sqlite3VdbeAddOp1(v, OP_SeekHit, iIdxCur);
}
op = aStartOp[(start_constraints<<2) + (startEq<<1) + bRev];
assert( op!=0 );
sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint);
@@ -1721,6 +1731,10 @@ Bitmask sqlite3WhereCodeOneLoopStart(
testcase( op==OP_IdxLE ); VdbeCoverageIf(v, op==OP_IdxLE );
}
if( pLoop->wsFlags & WHERE_IN_EARLYOUT ){
sqlite3VdbeAddOp2(v, OP_SeekHit, iIdxCur, 1);
}
/* Seek the table cursor, if required */
if( omitTable ){
/* pIdx is a covering index. No need to access the main table. */
+1 -1
View File
@@ -65,7 +65,7 @@ do_test aggnested-2.0 {
t1.*
FROM t1;
}
} {A,B,B 3 33 333 3333}
} {A,B,B 1 11 111 1111}
db2 close
##################### Test cases for ticket [bfbf38e5e9956ac69f] ############
+165
View File
@@ -25,6 +25,11 @@ ifcapable {!autoinc} {
return
}
if {[permutation]=="inmemory_journal"} {
finish_test
return
}
sqlite3_db_config_lookaside db 0 0 0
# The database is initially empty.
@@ -684,4 +689,164 @@ do_execsql_test autoinc-11.1 {
SELECT seq FROM sqlite_sequence WHERE name='t11';
} {5}
# 2018-05-23 ticket d8dc2b3a58cd5dc2918a1d4acbba4676a23ada4c
# Does not crash if the sqlite_sequence table schema is missing
# or corrupt.
#
do_test autoinc-12.1 {
db close
forcedelete test.db
sqlite3 db test.db
db eval {
CREATE TABLE fake_sequence(name TEXT PRIMARY KEY,seq) WITHOUT ROWID;
PRAGMA writable_schema=on;
UPDATE sqlite_master SET
sql=replace(sql,'fake_','sqlite_'),
name='sqlite_sequence',
tbl_name='sqlite_sequence'
WHERE name='fake_sequence';
}
db close
sqlite3 db test.db
set res [catch {db eval {
CREATE TABLE t1(a INTEGER PRIMARY KEY AUTOINCREMENT, b TEXT);
INSERT INTO t1(b) VALUES('one');
}} msg]
lappend res $msg
} {1 {database disk image is malformed}}
do_test autoinc-12.2 {
db close
forcedelete test.db
sqlite3 db test.db
db eval {
CREATE TABLE t1(a INTEGER PRIMARY KEY AUTOINCREMENT, b TEXT);
INSERT INTO t1(b) VALUES('one');
PRAGMA writable_schema=on;
UPDATE sqlite_master SET
sql=replace(sql,'sqlite_','x_'),
name='x_sequence',
tbl_name='x_sequence'
WHERE name='sqlite_sequence';
}
db close
sqlite3 db test.db
set res [catch {db eval {
INSERT INTO t1(b) VALUES('two');
}} msg]
lappend res $msg
} {1 {database disk image is malformed}}
ifcapable vtab {
set err "database disk image is malformed"
} else {
set err {malformed database schema (sqlite_sequence) - near "VIRTUAL": syntax error}
}
do_test autoinc-12.3 {
db close
forcedelete test.db
sqlite3 db test.db
db eval {
CREATE TABLE t1(a INTEGER PRIMARY KEY AUTOINCREMENT, b TEXT);
INSERT INTO t1(b) VALUES('one');
PRAGMA writable_schema=on;
UPDATE sqlite_master SET
sql='CREATE VIRTUAL TABLE sqlite_sequence USING sqlite_dbpage'
WHERE name='sqlite_sequence';
}
db close
sqlite3 db test.db
set res [catch {db eval {
INSERT INTO t1(b) VALUES('two');
}} msg]
lappend res $msg
} [list 1 $err]
do_test autoinc-12.4 {
db close
forcedelete test.db
sqlite3 db test.db
db eval {
CREATE TABLE t1(a INTEGER PRIMARY KEY AUTOINCREMENT, b TEXT);
INSERT INTO t1(b) VALUES('one');
CREATE TABLE fake(name TEXT PRIMARY KEY,seq) WITHOUT ROWID;
}
set root1 [db one {SELECT rootpage FROM sqlite_master
WHERE name='sqlite_sequence'}]
set root2 [db one {SELECT rootpage FROM sqlite_master
WHERE name='fake'}]
db eval {
PRAGMA writable_schema=on;
UPDATE sqlite_master SET rootpage=$root2
WHERE name='sqlite_sequence';
UPDATE sqlite_master SET rootpage=$root1
WHERE name='fake';
}
db close
sqlite3 db test.db
set res [catch {db eval {
INSERT INTO t1(b) VALUES('two');
}} msg]
lappend res $msg
} {1 {database disk image is malformed}}
breakpoint
do_test autoinc-12.5 {
db close
forcedelete test.db
sqlite3 db test.db
db eval {
CREATE TABLE t1(a INTEGER PRIMARY KEY AUTOINCREMENT, b TEXT);
INSERT INTO t1(b) VALUES('one');
PRAGMA writable_schema=on;
UPDATE sqlite_master SET
sql='CREATE TABLE sqlite_sequence(x)'
WHERE name='sqlite_sequence';
}
db close
sqlite3 db test.db
set res [catch {db eval {
INSERT INTO t1(b) VALUES('two');
}} msg]
lappend res $msg
} {1 {database disk image is malformed}}
do_test autoinc-12.6 {
db close
forcedelete test.db
sqlite3 db test.db
db eval {
CREATE TABLE t1(a INTEGER PRIMARY KEY AUTOINCREMENT, b TEXT);
INSERT INTO t1(b) VALUES('one');
PRAGMA writable_schema=on;
UPDATE sqlite_master SET
sql='CREATE TABLE sqlite_sequence(x,y INTEGER PRIMARY KEY)'
WHERE name='sqlite_sequence';
}
db close
sqlite3 db test.db
set res [catch {db eval {
INSERT INTO t1(b) VALUES('two'),('three'),('four');
INSERT INTO t1(b) VALUES('five');
PRAGMA integrity_check;
}} msg]
lappend res $msg
} {0 ok}
do_test autoinc-12.7 {
db close
forcedelete test.db
sqlite3 db test.db
db eval {
CREATE TABLE t1(a INTEGER PRIMARY KEY AUTOINCREMENT, b TEXT);
INSERT INTO t1(b) VALUES('one');
PRAGMA writable_schema=on;
UPDATE sqlite_master SET
sql='CREATE TABLE sqlite_sequence(y INTEGER PRIMARY KEY,x)'
WHERE name='sqlite_sequence';
}
db close
sqlite3 db test.db
set res [catch {db eval {
INSERT INTO t1(b) VALUES('two'),('three'),('four');
INSERT INTO t1(b) VALUES('five');
PRAGMA integrity_check;
}} msg]
lappend res $msg
} {0 ok}
finish_test
+9
View File
@@ -148,4 +148,13 @@ do_catchsql_test 4.3 {
USING csv(filename='FileDoesNotExist.csv');
} {1 {cannot open 'FileDoesNotExist.csv' for reading}}
# 2018-06-02
# Problem with single-column CSV support reported on the mailing list
# by Trent W. Buck.
#
do_execsql_test 4.4 {
CREATE VIRTUAL TABLE temp.trent USING csv(data='1');
SELECT * FROM trent;
} {1}
finish_test
+31 -15
View File
@@ -24,7 +24,24 @@
set testdir [file dirname $argv0]
source $testdir/tester.tcl
proc eqp {sql {db db}} { uplevel execsql [list "EXPLAIN QUERY PLAN $sql"] $db }
proc eqp {sql {db db}} {
uplevel [subst -nocommands {
set eqpres [list]
$db eval "$sql" {
lappend eqpres [set detail]
}
set eqpres
}]
}
proc do_detail_test {tn sql res} {
set normalres [list {*}$res]
uplevel [subst -nocommands {
do_test $tn {
eqp { $sql }
} {$normalres}
}]
}
###########################################################################
### SECTION 2: Enabling Foreign Key Support
@@ -970,20 +987,20 @@ do_test e_fkey-25.1 {
);
}
} {}
do_execsql_test e_fkey-25.2 {
do_detail_test e_fkey-25.2 {
PRAGMA foreign_keys = OFF;
EXPLAIN QUERY PLAN DELETE FROM artist WHERE 1;
EXPLAIN QUERY PLAN SELECT rowid FROM track WHERE trackartist = ?;
} {
0 0 0 {SCAN TABLE artist}
0 0 0 {SCAN TABLE track}
{SCAN TABLE artist}
{SCAN TABLE track}
}
do_execsql_test e_fkey-25.3 {
do_detail_test e_fkey-25.3 {
PRAGMA foreign_keys = ON;
EXPLAIN QUERY PLAN DELETE FROM artist WHERE 1;
} {
0 0 0 {SCAN TABLE artist}
0 0 0 {SCAN TABLE track}
{SCAN TABLE artist}
{SCAN TABLE track}
}
do_test e_fkey-25.4 {
execsql {
@@ -1097,21 +1114,20 @@ do_test e_fkey-27.1 {
do_test e_fkey-27.2 {
eqp { INSERT INTO artist VALUES(?, ?) }
} {}
do_execsql_test e_fkey-27.3 {
do_detail_test e_fkey-27.3 {
EXPLAIN QUERY PLAN UPDATE artist SET artistid = ?, artistname = ?
} {
0 0 0 {SCAN TABLE artist}
0 0 0 {SEARCH TABLE track USING COVERING INDEX trackindex (trackartist=?)}
0 0 0 {SEARCH TABLE track USING COVERING INDEX trackindex (trackartist=?)}
{SCAN TABLE artist}
{SEARCH TABLE track USING COVERING INDEX trackindex (trackartist=?)}
{SEARCH TABLE track USING COVERING INDEX trackindex (trackartist=?)}
}
do_execsql_test e_fkey-27.4 {
do_detail_test e_fkey-27.4 {
EXPLAIN QUERY PLAN DELETE FROM artist
} {
0 0 0 {SCAN TABLE artist}
0 0 0 {SEARCH TABLE track USING COVERING INDEX trackindex (trackartist=?)}
{SCAN TABLE artist}
{SEARCH TABLE track USING COVERING INDEX trackindex (trackartist=?)}
}
###########################################################################
### SECTION 4.1: Composite Foreign Key Constraints
###########################################################################
+13 -13
View File
@@ -801,7 +801,7 @@ do_select_tests e_select-4.1 {
4 "SELECT z2.* FROM z1,z2 LIMIT 1" {{} 21}
5 "SELECT z2.*, z1.* FROM z1,z2 LIMIT 1" {{} 21 51.65 -59.58 belfries}
6 "SELECT count(*), * FROM z1" {6 63 born -26}
6 "SELECT count(*), * FROM z1" {6 51.65 -59.58 belfries}
7 "SELECT max(a), * FROM z1" {63 63 born -26}
8 "SELECT *, min(a) FROM z1" {-5 {} 75 -5}
@@ -939,13 +939,13 @@ do_execsql_test e_select-4.6.0 {
INSERT INTO a2 VALUES(10, 4);
} {}
do_select_tests e_select-4.6 {
1 "SELECT one, two, count(*) FROM a1" {4 10 4}
2 "SELECT one, two, count(*) FROM a1 WHERE one<3" {2 3 2}
1 "SELECT one, two, count(*) FROM a1" {1 1 4}
2 "SELECT one, two, count(*) FROM a1 WHERE one<3" {1 1 2}
3 "SELECT one, two, count(*) FROM a1 WHERE one>3" {4 10 1}
4 "SELECT *, count(*) FROM a1 JOIN a2" {4 10 10 4 16}
5 "SELECT *, sum(three) FROM a1 NATURAL JOIN a2" {3 6 2 3}
6 "SELECT *, sum(three) FROM a1 NATURAL JOIN a2" {3 6 2 3}
7 "SELECT group_concat(three, ''), a1.* FROM a1 NATURAL JOIN a2" {12 3 6}
4 "SELECT *, count(*) FROM a1 JOIN a2" {1 1 1 1 16}
5 "SELECT *, sum(three) FROM a1 NATURAL JOIN a2" {1 1 1 3}
6 "SELECT *, sum(three) FROM a1 NATURAL JOIN a2" {1 1 1 3}
7 "SELECT group_concat(three, ''), a1.* FROM a1 NATURAL JOIN a2" {12 1 1}
}
# EVIDENCE-OF: R-04486-07266 Or, if the dataset contains zero rows, then
@@ -1128,7 +1128,7 @@ do_select_tests e_select-4.13 {
2.1 "SELECT up FROM c1 GROUP BY up HAVING down>10" {y}
2.2 "SELECT up FROM c1 GROUP BY up HAVING up='y'" {y}
2.3 "SELECT i, j FROM c2 GROUP BY i>4 HAVING i>6" {9 36}
2.3 "SELECT i, j FROM c2 GROUP BY i>4 HAVING j>6" {5 10}
}
# EVIDENCE-OF: R-23927-54081 Each expression in the result-set is then
@@ -1154,12 +1154,12 @@ do_select_tests e_select-4.15 {
# for the same row.
#
do_select_tests e_select-4.15 {
1 "SELECT i, j FROM c2 GROUP BY i%2" {8 28 9 36}
2 "SELECT i, j FROM c2 GROUP BY i%2 HAVING j<30" {8 28}
3 "SELECT i, j FROM c2 GROUP BY i%2 HAVING j>30" {9 36}
4 "SELECT i, j FROM c2 GROUP BY i%2 HAVING j>30" {9 36}
1 "SELECT i, j FROM c2 GROUP BY i%2" {2 1 1 0}
2 "SELECT i, j FROM c2 GROUP BY i%2 HAVING j<30" {2 1 1 0}
3 "SELECT i, j FROM c2 GROUP BY i%2 HAVING j>30" {}
4 "SELECT i, j FROM c2 GROUP BY i%2 HAVING j>30" {}
5 "SELECT count(*), i, k FROM c2 NATURAL JOIN c3 GROUP BY substr(k, 1, 1)"
{2 5 boron 2 2 helium 1 3 lithium}
{2 4 beryllium 2 1 hydrogen 1 3 lithium}
}
# EVIDENCE-OF: R-19334-12811 Each group of input dataset rows
+77
View File
@@ -0,0 +1,77 @@
# 2018-06-07
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
#
# A multi-key index that uses an IN operator on one of the keys other
# than the left-most key is able to abort the IN-operator loop early
# if key terms further to the left do not match.
#
# Call this the "multikey-IN-operator early-out optimization" or
# just "IN-early-out" optimization for short.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix in6
do_test in6-1.1 {
db eval {
CREATE TABLE t1(a,b,c,d);
WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<100)
INSERT INTO t1(a,b,c,d)
SELECT 100, 200+x/2, 300+x/5, x FROM c;
CREATE INDEX t1abc ON t1(a,b,c);
}
set ::sqlite_search_count 0
db eval {
SELECT d FROM t1
WHERE a=99
AND b IN (200,205,201,204)
AND c IN (304,302,309,308);
}
} {}
do_test in6-1.2 {
set ::sqlite_search_count
} {0} ;# Without the IN-early-out optimization, this value would be 15
# The multikey-IN-operator early-out optimization does not apply
# when the IN operator is on the left-most column of the index.
#
do_test in6-1.3 {
db eval {
EXPLAIN
SELECT d FROM t1
WHERE a IN (98,99,100,101)
AND b=200 AND c=300;
}
} {~/(IfNoHope|SeekHit)/}
set sqlite_search_count 0
do_execsql_test in6-1.4 {
SELECT d FROM t1
WHERE a=100
AND b IN (200,201,202,204)
AND c IN (300,302,301,305)
ORDER BY +d;
} {1 2 3 4 5 8 9}
do_test in6-1.5 {
set ::sqlite_search_count
} {39}
do_execsql_test in6-2.1 {
CREATE TABLE t2(e INT UNIQUE, f TEXT);
SELECT d, f FROM t1 LEFT JOIN t2 ON (e=d)
WHERE a=100
AND b IN (200,201,202,204)
AND c IN (300,302,301,305)
ORDER BY +d;
} {1 {} 2 {} 3 {} 4 {} 5 {} 8 {} 9 {}}
finish_test
+5 -2
View File
@@ -174,8 +174,11 @@ do_test malloc5-2.2 {
execsql {
COMMIT;
}
list $nRelease $data
} [list $pgalloc [list 1 2 3 4 5 6]]
value_in_range $::pgalloc $::mrange $nRelease
} [value_in_range $::pgalloc $::mrange]
do_test malloc5-2.2.1 {
set data
} {1 2 3 4 5 6}
do_test malloc5-3.1 {
# Simple test to show that if two pagers are opened from within this
+19 -14
View File
@@ -270,22 +270,27 @@ forcedelete test.db-journal
sqlite3 db test.db
ifcapable explain {
do_execsql_test misc7-14.1 {
do_execsql_test misc7-14.0 {
CREATE TABLE abc(a PRIMARY KEY, b, c);
EXPLAIN QUERY PLAN SELECT * FROM abc AS t2 WHERE rowid = 1;
}
do_eqp_test misc7-14.1 {
SELECT * FROM abc AS t2 WHERE rowid = 1;
} {
0 0 0 {SEARCH TABLE abc AS t2 USING INTEGER PRIMARY KEY (rowid=?)}
}
do_execsql_test misc7-14.2 {
EXPLAIN QUERY PLAN SELECT * FROM abc AS t2 WHERE a = 1;
} {0 0 0
{SEARCH TABLE abc AS t2 USING INDEX sqlite_autoindex_abc_1 (a=?)}
}
do_execsql_test misc7-14.3 {
EXPLAIN QUERY PLAN SELECT * FROM abc AS t2 ORDER BY a;
} {0 0 0
{SCAN TABLE abc AS t2 USING INDEX sqlite_autoindex_abc_1}
}
QUERY PLAN
`--SEARCH TABLE abc AS t2 USING INTEGER PRIMARY KEY (rowid=?)
}
do_eqp_test misc7-14.2 {
SELECT * FROM abc AS t2 WHERE a = 1;
} {
QUERY PLAN
`--SEARCH TABLE abc AS t2 USING INDEX sqlite_autoindex_abc_1 (a=?)
}
do_eqp_test misc7-14.3 {
SELECT * FROM abc AS t2 ORDER BY a;
} {
QUERY PLAN
`--SCAN TABLE abc AS t2 USING INDEX sqlite_autoindex_abc_1
}
}
db close
+2 -2
View File
@@ -55,11 +55,11 @@ if {![clang_sanitize_address]} {
do_test 1.1.1 {
set ::log [list]
list [catch {
for {set i 0} {$i < 2000} {incr i} { sqlite3 dbh_$i test.db -readonly 1 }
for {set i 0} {$i < 20000} {incr i} { sqlite3 dbh_$i test.db -readonly 1 }
} msg] $msg
} {1 {unable to open database file}}
do_test 1.1.2 {
catch { for {set i 0} {$i < 2000} {incr i} { dbh_$i close } }
catch { for {set i 0} {$i < 20000} {incr i} { dbh_$i close } }
} {1}
do_re_test 1.1.3 {
lindex $::log 0
+20
View File
@@ -15,13 +15,30 @@ set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix resetdb
do_not_use_codec
ifcapable !vtab||!compound {
finish_test
return
}
# In the "inmemory_journal" permutation, each new connection executes
# "PRAGMA journal_mode = memory". This fails with SQLITE_BUSY if attempted
# on a wal mode database with existing connections. For this and a few
# other reasons, this test is not run as part of "inmemory_journal".
#
# Permutation "journaltest" does not support wal mode.
#
if {[permutation]=="inmemory_journal"
|| [permutation]=="journaltest"
} {
finish_test
return
}
# Create a sample database
do_execsql_test 100 {
PRAGMA auto_vacuum = 0;
PRAGMA page_size=4096;
CREATE TABLE t1(a,b);
WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<20)
@@ -82,6 +99,7 @@ db2 close
forcedelete test.db
sqlite3 db test.db
do_execsql_test 300 {
PRAGMA auto_vacuum = 0;
PRAGMA page_size=8192;
PRAGMA journal_mode=WAL;
CREATE TABLE t1(a,b);
@@ -118,6 +136,8 @@ do_test 330 {
} db2
} {1 {file is not a database}}
db2 cache flush ;# Required by permutation "prepare".
# Reset the database yet again. Verify that the page size and
# journal mode are preserved.
#
+1 -1
View File
@@ -154,7 +154,7 @@ do_test select5-5.5 {
execsql {
SELECT a, b FROM t2 GROUP BY a;
}
} {1 4 6 4}
} {1 2 6 4}
# Test rendering of columns for the GROUP BY clause.
#
+13
View File
@@ -637,6 +637,19 @@ do_test shell1-3.23b.4 {
catchcmd "test.db" ".stats OFF BAD"
} {1 {Usage: .stats ?on|off?}}
# Ticket 7be932dfa60a8a6b3b26bcf7623ec46e0a403ddb 2018-06-07
# Adverse interaction between .stats and .eqp
#
do_test shell1-3.23b.5 {
catchcmd "test.db" [string map {"\n " "\n"} {
CREATE TEMP TABLE t1(x);
INSERT INTO t1 VALUES(1),(2);
.stats on
.eqp full
SELECT * FROM t1;
}]
} {/1\n2\n/}
# .tables ?TABLE? List names of tables
# If TABLE specified, only list tables matching
# LIKE pattern TABLE.
+53 -6
View File
@@ -1247,10 +1247,11 @@ void testset_rtree(int p1, int p2){
unsigned mxCoord;
unsigned x0, x1, y0, y1, z0, z1;
unsigned iStep;
unsigned mxRowid;
int *aCheck = sqlite3_malloc( sizeof(int)*g.szTest*500 );
mxCoord = 15000;
n = g.szTest*500;
mxRowid = 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)");
@@ -1277,7 +1278,7 @@ void testset_rtree(int p1, int p2){
speedtest1_exec("INSERT INTO t1 SELECT * FROM rt1");
speedtest1_end_test();
n = g.szTest*100;
n = g.szTest*200;
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;
@@ -1290,7 +1291,7 @@ void testset_rtree(int p1, int p2){
speedtest1_end_test();
if( g.bVerify ){
n = g.szTest*100;
n = g.szTest*200;
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;
@@ -1306,7 +1307,7 @@ void testset_rtree(int p1, int p2){
speedtest1_end_test();
}
n = g.szTest*100;
n = g.szTest*200;
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;
@@ -1319,7 +1320,7 @@ void testset_rtree(int p1, int p2){
speedtest1_end_test();
if( g.bVerify ){
n = g.szTest*100;
n = g.szTest*200;
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;
@@ -1336,7 +1337,7 @@ void testset_rtree(int p1, int p2){
}
n = g.szTest*100;
n = g.szTest*200;
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)");
@@ -1373,6 +1374,52 @@ void testset_rtree(int p1, int p2){
speedtest1_run();
}
speedtest1_end_test();
n = g.szTest*50;
speedtest1_begin_test(150, "%d UPDATEs using rowid", n);
speedtest1_prepare("UPDATE rt1 SET x0=x0+100, x1=x1+100 WHERE id=?1");
for(i=1; i<=n; i++){
sqlite3_bind_int(g.pStmt, 1, (i*251)%mxRowid + 1);
speedtest1_run();
}
speedtest1_end_test();
n = g.szTest*5;
speedtest1_begin_test(155, "%d UPDATEs using one-dimensional overlap", n);
speedtest1_prepare("UPDATE rt1 SET x0=x0-100, x1=x1-100"
" WHERE y1>=?1 AND y0<=?1+5");
iStep = mxCoord/n;
for(i=0; i<n; i++){
sqlite3_bind_int(g.pStmt, 1, i*iStep);
speedtest1_run();
aCheck[i] = atoi(g.zResult);
}
speedtest1_end_test();
n = g.szTest*50;
speedtest1_begin_test(160, "%d DELETEs using rowid", n);
speedtest1_prepare("DELETE FROM rt1 WHERE id=?1");
for(i=1; i<=n; i++){
sqlite3_bind_int(g.pStmt, 1, (i*257)%mxRowid + 1);
speedtest1_run();
}
speedtest1_end_test();
n = g.szTest*5;
speedtest1_begin_test(165, "%d DELETEs using one-dimensional overlap", n);
speedtest1_prepare("DELETE FROM rt1 WHERE y1>=?1 AND y0<=?1+5");
iStep = mxCoord/n;
for(i=0; i<n; i++){
sqlite3_bind_int(g.pStmt, 1, i*iStep);
speedtest1_run();
aCheck[i] = atoi(g.zResult);
}
speedtest1_end_test();
speedtest1_begin_test(170, "Restore deleted entries using INSERT OR IGNORE");
speedtest1_exec("INSERT OR IGNORE INTO rt1 SELECT * FROM t1");
speedtest1_end_test();
}
#endif /* SQLITE_ENABLE_RTREE */
+2 -2
View File
@@ -490,12 +490,12 @@ ifcapable subquery {
count {
SELECT * FROM t1 WHERE x IN (1,7) AND y IN (9,10) ORDER BY 1;
}
} {2 1 9 5}
} {2 1 9 4}
do_test where-5.15 {
count {
SELECT * FROM t1 WHERE x IN (1,7) AND y IN (9,16) ORDER BY 1;
}
} {2 1 9 3 1 16 9}
} {2 1 9 3 1 16 8}
do_test where-5.100 {
db eval {
SELECT w, x, y FROM t1 WHERE x IN (1,5) AND y IN (9,8,3025,1000,3969)
+2 -1
View File
@@ -75,6 +75,7 @@ while {![eof $in]} {
if {[regexp {^case OP_} $line]} {
set line [split $line]
set name [string trim [lindex $line 1] :]
if {$name=="OP_Abortable"} continue; # put OP_Abortable last
set op($name) -1
set jump($name) 0
set in1($name) 0
@@ -113,7 +114,7 @@ while {![eof $in]} {
#
puts "/* Automatically generated. Do not edit */"
puts "/* See the tool/mkopcodeh.tcl script for details */"
foreach name {OP_Noop OP_Explain} {
foreach name {OP_Noop OP_Explain OP_Abortable} {
set jump($name) 0
set in1($name) 0
set in2($name) 0
+5 -1
View File
@@ -41,8 +41,12 @@ doExplain=0
doCachegrind=1
doVdbeProfile=0
doWal=1
doDiff=1
while test "$1" != ""; do
case $1 in
--nodiff)
doDiff=0
;;
--reprepare)
SPEEDTEST_OPTS="$SPEEDTEST_OPTS $1"
;;
@@ -179,6 +183,6 @@ if test $doVdbeProfile -eq 1; then
tclsh ../sqlite/tool/vdbe_profile.tcl >vdbeprofile-$NAME.txt
open vdbeprofile-$NAME.txt
fi
if test "$NAME" != "$BASELINE" -a $doVdbeProfile -ne 1; then
if test "$NAME" != "$BASELINE" -a $doVdbeProfile -ne 1 -a $doDiff -ne 0; then
fossil test-diff --tk -c 20 cout-$BASELINE.txt cout-$NAME.txt
fi