Compare commits

..

174 Commits

Author SHA1 Message Date
drh 1a8a0d3f1a Attempt to fix the build on beagleboard.
FossilOrigin-Name: 3ac75725a66730566105ad184a988a8f80f51055
2014-05-05 20:21:52 +00:00
mistachkin c254ff62c1 Centralize and reform use of the Win32 related include files.
FossilOrigin-Name: 857f2baf9b722e4eb1ac0d50fe03e32d5176185b
2014-05-05 18:24:47 +00:00
mistachkin 0e56c52e1d Merge updates from trunk.
FossilOrigin-Name: a3cfd81339267c87db511cedf35ec209ee1f1a72
2014-05-05 17:45:44 +00:00
mistachkin fdf9f045b7 Fix several header file comments. No changes to code.
FossilOrigin-Name: dd6eb5d1eb4d50023a008fac116497ede29600c1
2014-05-05 17:43:28 +00:00
mistachkin 72de9addc7 Enhance the Win32 VFS I/O retry logic.
FossilOrigin-Name: 4760504396bcf44528eb8de9ed7aa5d9659c54b6
2014-05-02 22:39:54 +00:00
mistachkin b91ca38514 Merge updates from trunk.
FossilOrigin-Name: 598a3875ce98015e9a38db54bd0cb6290424c3d8
2014-05-02 21:42:31 +00:00
mistachkin 4a11505be9 Merge updates from trunk.
FossilOrigin-Name: c4d1d8a0db48f523d1624f2468261c171152c0f7
2014-05-02 21:38:02 +00:00
dan a153643b07 Fix a broken test case in fuzz.test.
FossilOrigin-Name: faa469355eabb2c407f24638b090725448aac37f
2014-05-02 14:54:56 +00:00
drh e724d3d26a Add a comment explaining why WhereLoop cost adjustments are omitted for
skip-scan loops.

FossilOrigin-Name: 3bc43594aaeee9225c0590677fcce480bedcb37b
2014-05-02 00:09:40 +00:00
dan 3852413246 Fix an obscure problem to do with temp register allocation that could occur if more than one simple SELECT within a compound SELECT uses a partial sort.
FossilOrigin-Name: 427409ae106cdab7892a6b50fe30c5f52de5addc
2014-05-01 20:26:48 +00:00
drh c5f246eb37 Add #ifdefs for test coverage. Add a testcase().
FossilOrigin-Name: be2702ce35c713b33c9b7689643b45fb0de6af2a
2014-05-01 20:24:21 +00:00
dan e03d76254c Update a test case in wal2.test that explicitly corrupts a checksum in the wal file to account for the fact that the first byte of said checksum may initially be 0xFF.
FossilOrigin-Name: 2b935bdea1452505f36dc8c7aad49e6c42f4eceb
2014-05-01 10:19:16 +00:00
dan 5da73e1a09 Fix a problem in calculating the costs of "OR" scans.
FossilOrigin-Name: 9bbca48b42e4fe16f2188e18dc736da30a96435c
2014-04-30 18:11:55 +00:00
dan 4243e27f22 Modify the way the costs of various query plans are estimated. If the user supplies a likelihood() value (or equivalent) on an indexed WHERE constraint, use it to estimate the number of index rows visited.
FossilOrigin-Name: 90e36676476e8db00658772e6c938242f766d306
2014-04-30 15:22:25 +00:00
dan 8164722c58 Add text to the header comment of whereLoopAddBtree() describing how the costs of various b-tree loops are estimated.
FossilOrigin-Name: 05e6e16cb28c9ffb4596bd2ef81f687c5403ecbb
2014-04-30 15:00:16 +00:00
dan 75525cbe24 Update a couple of test cases to account for the fact that this branch prefers an index scan and partial sort over a full-table scan and full external sort.
FossilOrigin-Name: 9b975bf33cd8fc28c64183a9642bf9fb436a4746
2014-04-30 14:53:21 +00:00
dan 4a6b8a05cd Fix a couple of out-of-date comments in where.c.
FossilOrigin-Name: eefeda32d54efbbdf7d20b719299eda48b891fae
2014-04-30 14:47:01 +00:00
drh 253666e520 Improved rendering of LogEst values corresponding to real values near 0.0
in the tool/logest.c utility program.

FossilOrigin-Name: 32910c8c595858245bb7ecfe3aa0f90eeae641af
2014-04-30 14:22:38 +00:00
drh 224155dd1c Fix long-standing typos in comments.
FossilOrigin-Name: b9f91317c34d07769a95dc2f905a6ccabceb64a3
2014-04-30 13:19:09 +00:00
dan 264d2b97a9 Test that the default values used when sqlite_stat1 data is not available are calculated correctly. Fixes for the same.
FossilOrigin-Name: e2d42f909de85a0586389f2dc0e654f7af2e351a
2014-04-29 19:01:57 +00:00
dan e4618fb30d Merge trunk changes into this branch.
FossilOrigin-Name: d74299f037f3a6a4b3bce8b4d1c76c407c1f3b3e
2014-04-29 16:46:24 +00:00
dan 09e1df6c00 Ignore likelihood() values on indexed IPK lookups.
FossilOrigin-Name: 5bb7757a7b32a74482d3e93e9c9eea02273fe981
2014-04-29 16:10:22 +00:00
dan 67a03cfd6e Fix a test case so that it updates sqlite_stat1 consistently.
FossilOrigin-Name: 2dc5a0b55567f13f0528ed17242e680cde2f2a29
2014-04-29 12:01:35 +00:00
dan 7de2a1faf6 Do not reduce the number of rows scanned at all for "IS NOT NULL" constraints. Fix a bug in calculating the number of rows visited by scans of partial indicies.
FossilOrigin-Name: a8ae93f0cffa116df0ba34d46a53f49d42dace41
2014-04-28 20:11:20 +00:00
dan 42685f211e The trunk assumes that an open range constraint on an indexed term (col>?) term matches 1/4 of the indexed rows, and that a closed constraint (col BETWEEN ? AND ?) matches 1/64. Change this branch to do the same.
FossilOrigin-Name: 4047ac75e2a8f0b330255501c42e4f04e5ab500d
2014-04-28 19:34:06 +00:00
drh 65e6b0dd12 Add the sqlite3_rtree_query_callback() API to the RTree virtual table.
(Cherrypick from the sessions branch.)

FossilOrigin-Name: af2cbe64adab5f9e3b0f3da00d06428088589d7f
2014-04-28 17:56:19 +00:00
dan 6b6828625b Update unordered.test to take into account for the fact that SQLite now prefers a full-table scan over a non-covering index scan that visits a large percentage of the table rows.
FossilOrigin-Name: 20f468dfbcb247e51446fad411a6e6cc0d130411
2014-04-28 15:11:25 +00:00
dan 9881d60d17 Add an extra column to a table in analyze9.test to give the planner a little more reason to select an index.
FossilOrigin-Name: 1b95544f84bf83c28cc15f6d0690fdf8a6bb3941
2014-04-28 12:08:23 +00:00
dan b51926e67c Update test script analyze3.test to account for the fact that SQLite now prefers a full-table scan over a non-covering index scan that visits a large percentage of the table rows.
FossilOrigin-Name: 35f46a55d866b9a87c1321aab8e0cfe86ccadb93
2014-04-28 10:00:59 +00:00
dan e3bfbb7284 Modify internal function whereLoopAdjustCost() so that it does not prefer a skip-scan over a regular index scan even if the regular scan uses a subset of the WHERE terms used by the skip-scan.
FossilOrigin-Name: 88a5758dcce891eb7be15432ebdc9f80071d413b
2014-04-28 09:35:31 +00:00
dan 440e6ff3b0 Fix an error in estimating of the number of rows visited by a range scan.
FossilOrigin-Name: d491de62fce69d93e89f65f7713972f7c2c451f7
2014-04-28 08:49:54 +00:00
dan 2dd3cdcfab Fix an sqlite3_stmt_status() problem caused by recent changs on this branch.
FossilOrigin-Name: dee204092421a239f9f60ab83c3a5b3e24d1baea
2014-04-26 20:21:14 +00:00
drh 1f8bb4b0a8 Update requirements marks to fix typos in the requirements text.
No changes to code.

FossilOrigin-Name: f5a263658187250044afc1a74000e6f6962733ca
2014-04-26 19:23:14 +00:00
drh 453e0261df Allow the xfer optimization to proceed if the DEFAULT on the very first
column of the two tables is different.  This is a refinement of the
fix for ticket [f67b41381a].

FossilOrigin-Name: 349f483499dd685a8da94923b6bd810a52e5e236
2014-04-26 17:52:08 +00:00
dan 9940e2aa45 Avoid transfering records between tables unless the default values for all columns are the same. Fix for [f67b41381a].
FossilOrigin-Name: f8c4c495e6de1f124d205383d4bafa46accbff5c
2014-04-26 14:07:57 +00:00
dan 8ad1d8ba38 If the user provides likelihood() data for a WHERE clause term used as part of an index key, have the planner use it when calculating the expected number of rows visited by the loop.
FossilOrigin-Name: c51efaa5d29ee0a91b9e6a83a8dd82530670811a
2014-04-25 20:22:45 +00:00
drh b79c718f1a Add test cases to ensure correct operation of joins with a virtual table
that include DISTINCT and ORDER BY clauses.  Verification for ticket
[388d01d4bb8f9].

FossilOrigin-Name: 5ada136f43ce744ae8c349eff39838eb44611b6e
2014-04-25 17:37:16 +00:00
dan cfc9df76e1 Store values loaded from the stat1 table as logarithmic values in memory.
FossilOrigin-Name: 1bd74c49ddab6f53bb6eaa57907eff44c2580dd6
2014-04-25 15:01:01 +00:00
drh 9dfaf621d1 Make sure ORDER BY clauses on joins that involve virtual tables and that
have a DISTINCT clause work correctly.  This is a candidate fix for
ticket [388d01d4bb8f9].  Test cases for that ticket will be checked in
separately.

FossilOrigin-Name: 171138122690faafde0dcab0201b90bdf02d3637
2014-04-25 14:42:17 +00:00
drh a01c7c70fd When VDBE_PROFILE is enabled, ignore negative opcode times, which sometimes
occur, perhaps due to context swaps.

FossilOrigin-Name: 4e88042f9d3e678914da96c0eb276f3d8fca5a94
2014-04-25 12:35:31 +00:00
dan aa9933c115 Changes to the way the planner calculates the costs of various table and index scans. Some test cases still failing.
FossilOrigin-Name: c5a6ec0a880652dc8f4593d9f7acd58ddc3dc5f3
2014-04-24 20:04:49 +00:00
drh f0582f43dd Comment tweaks on the test case for the [b75a9ca6b0] bug fix.
FossilOrigin-Name: 65d2544af9adc1e2f1d193e57f8be0422fb0d5eb
2014-04-21 13:36:54 +00:00
dan 374cd78c1d Avoid discarding an ORDER BY clause in the case where an identical GROUP BY clauses uses an index to group, but not sort, the rows. Fix for [b75a9ca6b0].
FossilOrigin-Name: de9a490f594183f337a2ec9e0f87792eac83548b
2014-04-21 13:21:56 +00:00
drh b355c2cc12 Clean up the proper-subset cost adjustment logic to make it more compact
and easier to read and so that full branch test coverage is more easily
obtained.

FossilOrigin-Name: 9a5d38c79d2482a23bcfbc3ff35ca4fa269c768d
2014-04-18 22:20:31 +00:00
drh 71794dbaeb Add the SQLITE_RUNTIME_BYTEORDER compile-time option to force SQLite to check
the processor byte-order at run-time.  Add additional compile-time byte order
checks for ARM, PPC, and SPARC.

FossilOrigin-Name: 2c5363873a6f990a0abaacac6303acd46b48befc
2014-04-18 00:49:29 +00:00
drh 2cf4acbd9f Add the SQLITE_TESTCTRL_BYTEORDER test control to interrogate SQLite's notion
of the processor byte order and whether the byte order is known at compile-time
or determined at run-time.

FossilOrigin-Name: 9c6961967ae00e563ebe2859eaf2639a79f2cb01
2014-04-18 00:06:02 +00:00
drh 65b9ac5224 Make sure the undocumented sqlite_rename_parent() function does not
crash even if it is invoked with NULL arguments.
Ticket [264b970c4379fd4b94]

FossilOrigin-Name: c6fa8d0d82805be230f672eabccdfa5680d4ddfd
2014-04-14 19:48:25 +00:00
drh d249090450 Remove the unused second argument from sqlite3ExprCachePop(). Add an
ALWAYS() on an always-true conditional in sqlite3VdbeResolveLabel().

FossilOrigin-Name: ab23abf392175d3e256ff619b13abbbe732a49ed
2014-04-13 19:28:15 +00:00
drh 87744513e7 Make sure column cache elements are cleared correctly when jumping over
code for key generation in a partial index. 
Fix for ticket [2ea3e9fe6379fc3f6].

FossilOrigin-Name: 3122b8364082be783821da01d4af2af6a9586327
2014-04-13 19:15:49 +00:00
drh d83cad235a Modify the OR-clause handling so that it can safely deal with OR-clause
with 17 or more terms.  Fix for ticket [10fb063b1179be53ea0b53bb].

FossilOrigin-Name: a67b5312f63909737c052fe58ab5772d45530d49
2014-04-10 02:24:48 +00:00
drh 48e080b26c Performance improvements when reading large blobs, especially if
SQLITE_DIRECT_OVERFLOW_READ is defined.

FossilOrigin-Name: 2312eb6a9eb31051db4e0baf19e033ba39adc7b1
2014-04-04 18:49:19 +00:00
drh 853546d047 Merge changes to the query planner that strive to ensure that any index
usage that is a proper subset of some other index usage always has a slightly
higher cost.

FossilOrigin-Name: 683dd379a293b2f330e1e4cd746f190527fe48ee
2014-04-04 18:20:35 +00:00
drh 1fb6a11072 Ensure the "PRAGMA journal_mode=WAL" works coming from any other journal_mode
with ATTACH-ed databases.

FossilOrigin-Name: e54330b43127e46fc6494748cbb353a6fc91cfd7
2014-04-04 14:12:52 +00:00
drh c438df1be0 Use OP_Copy instead of OP_SCopy when moving results out of a subquery,
to prevent the subquery results from changing out from under the outer
query.  Fix for ticket [1e64dd782a126f48d78].

FossilOrigin-Name: d5513dfa23baa0b0a095aaf17d19aacd30dcef61
2014-04-03 16:29:31 +00:00
drh 831116d164 Fix a typo in the "Synopsis:" comment for the OP_VFilter opcode.
FossilOrigin-Name: 48ecdd4aff03741f96c070dced69c3c273b652cb
2014-04-03 14:31:00 +00:00
drh 54d0d2dd9a In the command-line shell, run set writable_schema before running the
".clone" command.

FossilOrigin-Name: 9d2ae6342c8afa904bec591ebe134ff7f536b71c
2014-04-03 00:32:13 +00:00
drh a38c9516e8 Remove an unnecessary conditional, replacing it with an assert().
Improvements to comments.

FossilOrigin-Name: 834bf1c367e1ccd498c7f9f843be2d2aa11ffb3c
2014-04-01 01:24:34 +00:00
drh 4c417181c2 Fix a compiler warning when SQLITE_DIRECT_OVERFLOW_READ is defined.
Minor performance enhancement and size reduction.

FossilOrigin-Name: 96385dc460545807a5c8fcf6280a971700f84866
2014-03-31 23:57:41 +00:00
drh e4529c5724 Merge in the latest changes and fixes from trunk.
FossilOrigin-Name: f6211540c9d66a08dc580dd733e4f4a98968ae30
2014-03-31 22:03:32 +00:00
drh d3c156638a Remove an unnecessary conditional.
FossilOrigin-Name: 7473c4dfc10a47594affa6f4e071a08dc8838c0c
2014-03-31 20:05:20 +00:00
drh 3fb183d2f7 Also make sure an index that is a proper subset of some other index has a
higher cost than that other index.  Add test cases.

FossilOrigin-Name: b7830d232b073a197aa1092e78cb24e88cb10fd3
2014-03-31 19:49:00 +00:00
drh 53cd10afcd Make sure that an index that covers a proper superset of the WHERE clause
terms of some other index has a lower cost than the other index.

FossilOrigin-Name: ea8b0910040198751551b0b960e6b783913607df
2014-03-31 18:24:18 +00:00
drh b663587890 Avoid a (harmless) buffer overread that is possible on an OOM when
MEMSYS5 is engaged.

FossilOrigin-Name: b3296267fb67b9f59719a37093253062edde3746
2014-03-31 13:42:42 +00:00
drh 7a4b1642a7 Experiments in picking better query plans, especially when the usage of one
index is a subset of another.

FossilOrigin-Name: 8f869ca7a6eaa9ca7a08102290e6c606735f9090
2014-03-29 21:16:07 +00:00
drh 70c93204ea Disable the wal64k.test script for non-unix systems since it depends on
unix-only features.

FossilOrigin-Name: 27deb6e49bcc76714dbdc61b34748603155ac770
2014-03-28 14:41:35 +00:00
drh 36ed03428d Fix a harmless compiler warning.
FossilOrigin-Name: a4e47150f32b3a4120b1f89ccc66d633d829e3bb
2014-03-28 12:56:57 +00:00
drh a1f7c0a21c Enhance the sqlite3VdbeRecordCompare() routines so that if they encounter
database corruption, they will set the UnpackedRecord.isCorrupt field and
return 0.  The sqlite3BtreeMovetoUnpacked() routine detects this and returns
SQLITE_CORRUPT, causing the corruption to be reported back to the top-level.

FossilOrigin-Name: 7fa85eaaaf6d211378620d728a759fdfe30a15b0
2014-03-28 03:12:48 +00:00
drh 27de5c5cb6 Minor cleanup of the code in the query planner that computes the costs
estimates for the various plans.  There are no changes to the costs at this
time.  But the code is slightly more readable now and that might facilitate
future enhancements.

FossilOrigin-Name: 9b4d7226bcee38be5ac68a54bee03b4179cb69fc
2014-03-27 18:36:34 +00:00
drh 382bdeabef Enhance the logest.c utility with new operators: "dup", "inv", "log", and
"nlogn".  Provide help on an invalid input.

FossilOrigin-Name: b4bd2a062c4baf5f622d61b7411f00de5904ef56
2014-03-27 14:05:38 +00:00
dan 68916c9fd3 Add an extra test case for the potential buffer overread patched by [28ddecff04].
FossilOrigin-Name: f585f5d7a0f9bf8c590388654a3638231eba8892
2014-03-26 15:14:59 +00:00
drh d9c131c366 Add a test case to verify that the previous change avoids excess buffer
overread in sqlite3VdbeRecordCompare().

FossilOrigin-Name: 2b28e8d582cf10936fa1faca04a16ca2eeead66f
2014-03-26 15:05:56 +00:00
drh 182ea4e324 Earlier detection of corruption in sqlite3VdbeRecordCompare() in order to
avoid a potential buffer overread.

FossilOrigin-Name: 28ddecff044dbc2dff50a7d8406ab67dfe06587f
2014-03-26 14:51:07 +00:00
drh e2ac506704 Add an assert() and a comment to clarify the operation of the
vdbeRecordCompareInt() routine.

FossilOrigin-Name: 851abdb8fd9b5a8a6ce21db53d30dbac3c430cc7
2014-03-26 12:02:38 +00:00
drh 5e8980ddb1 Adjust the repeat counts on several tests in speedtest1 so that the relative
time spent on the test is roughly the same regardless of --size.

FossilOrigin-Name: 7922809ee0d3978ce9221fbb7df63aa0684d0c4d
2014-03-25 20:28:38 +00:00
drh c872966ef4 Add another performance test case to speedtest1. This case is another
ORDER BY test but this time without LIMIT.

FossilOrigin-Name: 9ab7ffd59209aef0ffbf384b3902a93fd3b86a6d
2014-03-25 17:45:49 +00:00
drh 0c60c1fe66 Add an ORDER BY test case to speedtest1.c
FossilOrigin-Name: 588122641e57e957813d329ea071e13ccbde5acd
2014-03-25 14:54:36 +00:00
drh 86dd3716b9 Detect when a VdbeCursor is still pointing at a valid row but that row has
moved, and invalidated the return from prior sqlite3BtreeDataFetch() or
sqlite3BtreeKeyFetch() calls.

FossilOrigin-Name: e6798871ce94961135762669af418cd78540c121
2014-03-25 11:00:21 +00:00
dan b22f38a779 Remove unused variables Parse.nColCache and Parse.iColCache.
FossilOrigin-Name: 4d7551ce464c8038147e81667368924f2a7485a6
2014-03-24 16:30:06 +00:00
drh 3d1d90a13d Fix arithmetic operators so that they do not change the affinity of their
input operands.  Ticket [a8a0d2996a].

FossilOrigin-Name: 221f8f944703108e47d789fa8ce6c00fe2abcbb6
2014-03-24 15:00:15 +00:00
dan 4979088506 Avoid attempting to mmap memory from an offset that is not a multiple of the system page size on systems with page sizes larger than 32KB.
FossilOrigin-Name: db7d62c8d58eb1e8654a762c9b199ae4e2759038
2014-03-24 11:23:17 +00:00
drh 323913c880 Avoid a possible use of an uninitialized variable following an I/O or OOM
error.

FossilOrigin-Name: 641408a1395bfc911ca619ef9e5f073b913d856b
2014-03-23 16:29:23 +00:00
drh dbfca2b7f8 Clear the sort-order flags on the KeyInfo object associated with the
OP_Compare/OP_Jump of the block-sort logic, in order to make the OP_Jump
fully testable.

FossilOrigin-Name: 9b2838f23e5f52369eeb078f60bd231cc54362f8
2014-03-22 02:19:53 +00:00
drh c83a6bed04 Increase the version number to 3.8.5.
FossilOrigin-Name: 9760879d086b61476890927f01806a93798d4eee
2014-03-22 01:52:17 +00:00
drh 59b8f2e108 Fix the ORDER BY optimization logic so that it will do a block-sort on
a partial DESC ORDER BY.  This enhancement uncovered a memory leak in
pushUntoSorter() which is also fixed.

FossilOrigin-Name: c36f74611cf17ad2ff198a2ac2054d7ab451a72c
2014-03-22 00:27:14 +00:00
drh 9a4444778f Add the ability to use indices for the first few terms of an ORDER BY clause,
then sort in batches to handle the later terms.

FossilOrigin-Name: fa06a6fed9f48322d9b89721799ba12c46efa898
2014-03-21 20:58:42 +00:00
drh 8e1ee88c88 Change the names of SRT_DistTable and SRT_Table used by CTE to more
meaningful SRT_DistFifo and SRT_Fifo, respectively.  Simplify the
IgnorableOrderby() macro in the process.

FossilOrigin-Name: 45d8cc678d128f1dda6469864215a8ed9de4366a
2014-03-21 19:56:09 +00:00
dan 9afccba269 Avoid leaking memory in an obscure case where the flattener adds an ORDER BY clause to the recursive part of a recursive query.
FossilOrigin-Name: 1f413aca00015100224273480e1ce39a76bf93ab
2014-03-21 19:27:54 +00:00
drh cc08fa48b8 Merge the OFFSET-on-query-without-FROM fix from trunk.
FossilOrigin-Name: 71e9ae72c272dc86720b2bfe719f57de437c400b
2014-03-21 18:45:19 +00:00
drh a22a75e5ca Fix the OFFSET clause so that it works correctly on queries that lack
a FROM clause.  Ticket [07d6a0453d4ed8].

FossilOrigin-Name: 179ef81648b0ad557df78b7712f216b876b6fb65
2014-03-21 18:16:23 +00:00
drh e99b9cdc70 New test case for block-sorting.
FossilOrigin-Name: e70cfa28aa393661ccc742ecd5e672d807bdd0a9
2014-03-21 15:24:07 +00:00
drh f9f1bdb0c8 Merge trunk fixes for "x IN (?)" handling.
FossilOrigin-Name: eca35871c34374ca9189c7c9b6d490ac3c30357f
2014-03-20 20:56:49 +00:00
drh 5b1420e046 Remove a testcase() that is now always true due to the "x IN (?)" optimization.
Add an ALWAYS() around a conditional in the parser that cannot be false.

FossilOrigin-Name: d5a1530bdc7ace053d05d1a037551110021d3758
2014-03-20 19:04:56 +00:00
dan 9bc21b535e Only use the direct-overflow-read optimization if all data from the overflow page in question is being read.
FossilOrigin-Name: d8e1f75ddf10f3c0b21acd5455f90fdcea54a948
2014-03-20 18:56:35 +00:00
drh 8ad0de3f72 Fix the EXPLAIN indenter in the command-line shell to correctly
handle NextIfOpen and PrevIfOpen opcodes.

FossilOrigin-Name: 01944c53f5c129f48ce8842faaedcf5607dd381e
2014-03-20 18:45:27 +00:00
drh fbb24d1092 The "x IN (?)" optimization in check-ins [2ff3b25f40] and [e68b427afb] is
incorrect, as demonstrated by the in4-5.1 test case in this check-in.
The "COLLATE binary" that was being added to the RHS of IN was overriding
the implicit collating sequence of the LHS.  This change defines the EP_Generic
expression node property that blocks all affinity or collating sequence
information in the expression subtree and adds that property to the expression
taken from RHS of the IN operator.

FossilOrigin-Name: 2ea4a9f75f46eaa928ba17e9e91bc0432750d46d
2014-03-20 17:03:30 +00:00
drh 4ef7efad5e Fix harmless compiler warnings.
FossilOrigin-Name: b1435f26b07b2208cfcca557f96342a5bd0d5328
2014-03-20 15:14:08 +00:00
drh 0a8d14261c Previous check-in is not quite correct. "x IN (?)" is not exactly the same
as "x==?" do to collation and affinity issues.  The correct converstion should
be to "x==(+? COLLATE binary)".  The current check-in fixes this problem and
provides test cases.  Ticket [e39d032577df69]

FossilOrigin-Name: 2ff3b25f40fd117c8a2da1d1a3625f6b167b7b16
2014-03-20 14:56:47 +00:00
drh 2b59b3a4c8 Convert expressions of the form "X IN (?)" with exactly one value on the
RHS of the IN into equality tests:  "X=?".  Add test cases to verify that
statements work correctly on this corner case.
Fix for ticket [e39d032577df6942].

FossilOrigin-Name: e68b427afbc82e201c64474117851aa4c9eb0c92
2014-03-20 13:26:47 +00:00
drh 0c8a934cb4 Fix an unnecessarily obtuse use of a bitmask flag.
FossilOrigin-Name: ca3140813198ab7ce470cf86334e55207f3461f9
2014-03-20 12:17:35 +00:00
dan bc76063cd2 Add a test to ensure os_unix.c works with 64KiB OS pages.
FossilOrigin-Name: e3d2be3ba47cdaafd26347620ae3bc2813203f16
2014-03-20 09:42:09 +00:00
dan 781e34cde3 Add an experimental fix to avoid attempting to mmap memory from an offset that is not a multiple of the system page size on systems with page sizes larger than 32KB.
FossilOrigin-Name: 6f3a5c24d254fc6faf607b505bdef4a7aafc21af
2014-03-20 08:59:47 +00:00
drh db1cc09c72 Merge the vdbesort.c optimization from trunk.
FossilOrigin-Name: e4bfffb988283c077778c60696be0d285ad66c3c
2014-03-19 23:42:51 +00:00
drh 6284db908a Fix query planner weights associated with choosing block-sorting. Fix
block sorting of tables with collating functions.  Fix various test cases.
All "veryquick" tests are now passing, though more tests need to be added.

FossilOrigin-Name: 01afbf97c0ff29667806e9a7c4d74ca717819de5
2014-03-19 23:24:49 +00:00
dan 344510e62b Avoid some unnecessary calls to sqlite3VdbeRecordUnpack() that were being made when merging data from two or more temp files together in vdbesort.c
FossilOrigin-Name: 707ea170b3e26965b7e3982f7554d122d130b9a6
2014-03-19 20:01:25 +00:00
drh 65ea12cb4a Make it possible for block-sort to use the OP_SorterOpen sorter in addition
to a generic OP_OpenEphemeral.

FossilOrigin-Name: 7ce2daafd39a117041bfdd0a7132e2764fe7a74b
2014-03-19 17:41:36 +00:00
drh 26d7e7c6b7 Fix a problem in the block-sort logic that can arise if the VDBE opcode
array is resized while the block-sort logic is being coded.  "make test"
now runs to completion, though there are still 17 failures.

FossilOrigin-Name: 62f3a22050e0f11c789374f8a3785df0a84c24cb
2014-03-19 16:56:58 +00:00
drh ba194369ad Avoid reusing temporary registers in co-routines when doing
block-sorting.

FossilOrigin-Name: 463d921b519b08648a715e987c430f06b06bae84
2014-03-19 15:17:24 +00:00
drh ea6c36e204 Make sure the where.c query planner never reports that the number of ORDER BY
terms that are satisfied by indices is negative.

FossilOrigin-Name: b186d8d15a10d5e8fcae9ae72e8624d71831f5bd
2014-03-19 14:30:55 +00:00
drh 079a307259 First attempt at getting block-sort to work. This is an incremental check-in.
There are many problems still to be worked out.

FossilOrigin-Name: 59742dd4c5259883850044d0938248b009ebd045
2014-03-19 14:10:55 +00:00
drh ddba0c227e Make the partial-ORDER-BY information in the query planner available to the
SELECT code generator.  Still doesn't make a difference in the generated code.

FossilOrigin-Name: e258df236b7de70087c8227cb209080e55b9bf9c
2014-03-18 20:33:42 +00:00
drh d2de861cbe Adjust the query planner to keep track of the number of ORDER BY terms
satisfied.  Still doesn't do anything with this information.  Some tests
fail after this check-in, but all failures are believed to be benign.  The
failures will be addressed at a later stage.

FossilOrigin-Name: 59d49b7fc49fa290e04a02653e7268c85836b27e
2014-03-18 18:59:07 +00:00
drh 0401acec91 Experiments with the optimization of ORDER BY and GROUP BY clauses.
FossilOrigin-Name: b150902579d708b454efd5f8750e26a816f7f1a6
2014-03-18 15:30:27 +00:00
drh 0e682099a1 Clean up some obsolete "register" declarations in printf.c.
FossilOrigin-Name: ecd9d3f9453be0bb8e312d8027fd1a9e55882f36
2014-03-17 15:06:57 +00:00
drh a70a073b3f Performance enhancements and size reduction for sqlite3VXPrintf()
FossilOrigin-Name: eb071eb58cf675bd6cd9dd46aed9d57fbb7a77e8
2014-03-17 14:24:27 +00:00
drh 18c7e40ca3 Fix a harmless compiler warning that crops up with SQLITE_MAX_MMAP_SIZE=0.
FossilOrigin-Name: 1277932b7e8bb36c7070ffafbf110a8e128c267b
2014-03-14 11:46:10 +00:00
dan d88e521f59 Fix an obscure bug causing sqlite3_close() to fail if there are virtual tables on the disconnect list when it is called.
FossilOrigin-Name: 6504aa47a8ebb13827be017c4cb4b2dc3c4c55f4
2014-03-12 19:38:38 +00:00
dan 82d25da5b0 Changes to FTS to ensure that it does not access the database from within the xConnect method.
FossilOrigin-Name: c67a52c356416cc200f51f9168d942e78db11d34
2014-03-12 19:20:36 +00:00
dan 87af14a639 Prevent the rtree module from reading sqlite_stat1 data from the wrong database.
FossilOrigin-Name: 7ce03c1b5552d830300575c5b41a874db7a2ec77
2014-03-12 12:44:46 +00:00
drh 926345e027 Remove a stray C99-style comment.
FossilOrigin-Name: f500e87d6ec6fa43c13f4e94edf32789f36e4233
2014-03-11 23:44:10 +00:00
drh 036dbec01c Combine the various boolean fields of the BtCursor object into a single
bit-vector.  This allows setting or clearing more than one boolean at a
time and makes the overflow-pgno-cache branch faster than trunk on 
speedtest1.

FossilOrigin-Name: 968fec44d7fde3adbd3e9603e4282351f0d4bda1
2014-03-11 23:40:44 +00:00
dan 5a500afd57 Enable the b-tree cursor objects overflow page-number cache, which is normally enabled only for incr-blob cursors, for all cursors.
FossilOrigin-Name: da59198505990a4fe832be7932117c7e014955b7
2014-03-11 20:33:04 +00:00
drh 468108628c Version 3.8.4.1
FossilOrigin-Name: 018d317b1257ce68a92908b05c9c7cf1494050d0
2014-03-11 15:27:36 +00:00
drh 8073c70b33 Update version number to 3.8.4.1
FossilOrigin-Name: 33f5694fa42d9a521ca081de4ddd1e9dc8952b16
2014-03-11 15:25:43 +00:00
dan 3afca7d18c Add a test to see what happens if an rtree constructor encounters an SQLITE_BUSY error. No changes to code.
FossilOrigin-Name: 5527e23636eee192030f6a3c41628030b6c50bb8
2014-03-11 09:19:26 +00:00
drh 89212fb9f9 Adjustments to the cost computation for the skip-scan query plan, to take
into account the fact that a seek has to occur on each skip.

FossilOrigin-Name: 0769eebd028ce31375cf93509a1d3687f7b117eb
2014-03-10 20:12:31 +00:00
drh b06a4ec1f0 Attempt to work around MSVC's treatment of __LINE__ as a non-constant value
in "Edit and Continue" mode by avoiding the use of __LINE__ when
SQLITE_VDBE_COVERAGE is not defined.

FossilOrigin-Name: 0a5318bc272b844e937cb1df3a07224034bc3450
2014-03-10 18:03:09 +00:00
drh 55aeee4b48 Version 3.8.4
FossilOrigin-Name: 530a1ee7dc2435f80960ce4710a3c2d2bfaaccc5
2014-03-10 12:20:37 +00:00
dan b72cad14d0 Fix a bug causing "SELECT char()" to return SQLITE_NOMEM.
FossilOrigin-Name: ba39df9d4f7ffc6475ae0dc794f7d3f58c486de8
2014-03-08 19:07:03 +00:00
drh f3ccc38a69 Improved comment on the pager.c PERSIST rollback journal delete logic
inside of hasHotJournal().  No changes to code.

FossilOrigin-Name: e5b17a9d07a35c9b44ff977ba81b93d745d26a11
2014-03-07 14:57:07 +00:00
mistachkin eb443925ef Revise change from the previous check-in to clarify the situation when handling open journal files, regardless of journal mode.
FossilOrigin-Name: 1c318ef3b76e9a9a5ff2f156a9acddfc1bda0949
2014-03-07 03:31:35 +00:00
mistachkin 8879481868 Avoid calling sqlite3OsDelete() on a file that is open, since this causes Windows to run *very* slowly. Comes up on error recovery in journal_mode=PERSIST.
FossilOrigin-Name: fdc651e2ec7a0babee669e24fd56632e7cd5f0e9
2014-03-07 02:29:56 +00:00
dan f0ec2a5ea7 Do not run corruptH.test in mmap mode.
FossilOrigin-Name: c0d54b4e41cba84dc5934e0fcd03fe422fe5c92b
2014-03-06 18:16:45 +00:00
drh fe70510aa7 Improved EXPLAIN indentation of a loop in the ANALYZE logic for STAT4.
Mark the not-found jump of a seek operation in that loop as never taken.

FossilOrigin-Name: 0a4200f95cf46ad620b9fd91f4444114a0c74730
2014-03-06 13:38:37 +00:00
dan 0df163a9f0 Remove a branch that is never taken from where.c.
FossilOrigin-Name: 4a4997221f3d61c1411a993053b40c787beea736
2014-03-06 12:36:26 +00:00
mistachkin 378d01aa94 Cosmetic change to the shell in-memory database warning to skip coloring the trailing period.
FossilOrigin-Name: c87d8e07ec596d5f0ef3003cfeb226d4b7c49549
2014-03-06 02:15:42 +00:00
drh b6e8fd105c Fix some incorrect comments and typos in comments. Add testcase() macros
to some of the new record comparison code.

FossilOrigin-Name: b83cfe899d84fe9d61540e9984321ca30401638c
2014-03-06 01:56:33 +00:00
mistachkin 62117159d0 Better loadable extension handling in the Win32 VFS when compiled for Cygwin.
FossilOrigin-Name: 29b0a4f158785449b6f3da6fcceeb63442c9711c
2014-03-06 00:30:27 +00:00
mistachkin 0d71d121ae Better support for MinGW 4.x.
FossilOrigin-Name: 170e0585202eec6882e9513eba05e6d5767bfc5b
2014-03-06 00:28:57 +00:00
drh dc90d3d8af Always include the ctype.h header in the spellfix.c extension.
FossilOrigin-Name: bfd75f471a607b442d8cd8a7070491a158e8fb1a
2014-03-05 19:36:52 +00:00
dan a6eaa635cc Avoid running a couple of test cases that use realloc() extensively if SQLITE_MEMDEBUG is defined.
FossilOrigin-Name: e406d4bb786a34cdd5dd23ed39f35dfce3e1cabd
2014-03-05 19:13:32 +00:00
drh fc5717cc99 Fix a harmless compiler warning on MSVC.
FossilOrigin-Name: 0723effc9ccae7c660fb847b36ce9324e0cb5042
2014-03-05 19:04:46 +00:00
dan 03af2168db Add SQLITE_OMIT_CTE to the list of compile options that might be returned by "PRAGMA compile_options".
FossilOrigin-Name: f33f2b3f924347e3da26741d153749330cb645ec
2014-03-05 17:29:34 +00:00
dan 13ef14afc1 Add tests to join.test to verify that it is not possible to use more than 64 tables in a join.
FossilOrigin-Name: ef1a998625e1fc051732228844388d6c59665382
2014-03-05 16:15:07 +00:00
drh 6d1626eb7c Count the number of elements in a SrcList object using an "int" rather than
a "u8", to avoid overflows and to work around an issue in the C compiler on
AIX.

FossilOrigin-Name: eee2a13f2caa48b7b8a693680edc2bbc9275292c
2014-03-05 15:52:43 +00:00
dan 1496566560 Add a test case for the problem fixed by [1d134ba2ed].
FossilOrigin-Name: d4fbc05df9501a09623d420fcd5b2bce3a57201b
2014-03-05 15:04:36 +00:00
drh 817492630a When converting a result type from TEXT to BLOB using the
sqlite3_value_blob() interface, continue to report SQLITE_TEXT as
the true type from sqlite3_value_text() as long as that text is still
valid.  The maintains legacy behavior from before the noMemType change.

FossilOrigin-Name: 1d134ba2edbdb8c0cf9e99590a69cd17e0b874a9
2014-03-05 14:40:22 +00:00
drh b1a1c29a07 Separate the column NULL value constant into a separate routine for greater
commonality with the sessions branch.

FossilOrigin-Name: 12cbebb997705e37769460e00a4aaa52c12f305e
2014-03-05 12:47:55 +00:00
dan ef4668bc05 Remove the redundant memType field from struct Mem.
FossilOrigin-Name: 9e8528578966e4f1a16d63333de648fd8cdaf0f2
2014-03-05 11:48:35 +00:00
dan d520041bc0 Do not run corruptI.test with the mmap permutation.
FossilOrigin-Name: 378b290da85cadc1acba081322d1f0e8d7694e17
2014-03-05 11:22:33 +00:00
mistachkin afc14f72ef Experimental simplification of memory flags/type handling.
FossilOrigin-Name: bac2820e13a79d91d0f8938c643134a9d6900327
2014-03-05 01:29:18 +00:00
drh 19c6d96aec Avoid indexing off the front end of an array when creating a view with
two or more blank column names in the SELECT statement that defines the view.

FossilOrigin-Name: 554501f158534f9c27fd51900589c2ab7cf300d8
2014-03-04 21:19:51 +00:00
dan 052c6784ee Fix a problem with "DEFAULT (-(-9223372036854775808))" clauses in ALTER TABLE ... ADD COLUMN commands.
FossilOrigin-Name: e072cb3ee2a03d786c08230cecc6e970de2cec5b
2014-03-04 21:00:20 +00:00
drh d1053a4314 Fix a potential memory use-after-free problem following an OOM error.
FossilOrigin-Name: 767ccb1fa11b3e7b895fb8c2e91f79e3b4202907
2014-03-04 18:06:04 +00:00
drh ed79b45cf7 Fix an assert() so that it takes OOM errors into account.
FossilOrigin-Name: 53f6ec792f5f62fcdbf25e0fce5545dd1c3048a4
2014-03-04 16:21:18 +00:00
dan a4660bd695 Ensure that BtreeMovetoUnpacked() does not try to invoke xRecordCompare when it is set to NULL.
FossilOrigin-Name: 2879234b7c373be422af3fe180cae9840943e29a
2014-03-04 16:05:25 +00:00
drh 5f1d536b53 Improve clarity of presentation in the sqlite3VdbeMemFromBtree() routine.
FossilOrigin-Name: 9830c343bc954b828f6ca752f8ae63e2c0a980c1
2014-03-04 13:18:23 +00:00
mistachkin b64fa0adf7 Fix comment in test.
FossilOrigin-Name: 1e57f67b20a1c01ede36d684be628e9270bf109a
2014-03-04 12:07:24 +00:00
mistachkin ad4b262545 Fix minor typos in the new test file.
FossilOrigin-Name: 3cbb9b1b4f8c5c2735799e84dc80614586222cd2
2014-03-04 11:54:35 +00:00
dan 5810d0315b Add tests to verify the fix for bug [4ef7e3cfca].
FossilOrigin-Name: 62410bb8a7b33efcd13bce8fd75b83523922adb8
2014-03-04 11:35:20 +00:00
mistachkin 9d42cc994c Fix name resolution problem in sub-selects within triggers, ticket [4ef7e3cfca].
FossilOrigin-Name: 5bcd0b1ca5d73ffbe7978ee9d73fe5e769e3d3a2
2014-03-04 11:29:42 +00:00
mistachkin ffe6bc2b93 Fix harmless compiler warning.
FossilOrigin-Name: 8d18a803bdeab290a6e9ff26911897f5f8683876
2014-03-04 11:16:20 +00:00
drh d34ab07507 Refactor the sqlite3VdbeRecordCompare() routine used to compare btree records.
Create fast-track special case routines to handle the common cases more
quickly.  This gives a significant performance boost.

FossilOrigin-Name: 3325ad5bdc2f81f63b556d6f4d0589d89b142b2b
2014-03-04 04:12:56 +00:00
mistachkin 14eec74a5b Merge updates from trunk.
FossilOrigin-Name: ed0bfcfadc07507a38f2c2387d85515ba1eb2722
2014-02-27 05:47:31 +00:00
mistachkin edb4ece65e Merge updates from trunk.
FossilOrigin-Name: 854d410ad3a2bb3af5465d933ac9535fe3f22bfe
2014-02-24 21:23:07 +00:00
mistachkin 835c19bb9a Merge updates from trunk.
FossilOrigin-Name: 09cf240a7fb4022aeb1d7ae2a2455b5f97b53d68
2014-02-21 10:48:03 +00:00
mistachkin 5b4627e957 Better loadable extension handling in the Win32 VFS when compiled for Cygwin.
FossilOrigin-Name: 6676475c47558a52cb2632e92a541e13d143b2dc
2014-02-21 05:44:18 +00:00
mistachkin 491451dead Enhance the Win32 VFS I/O retry logic.
FossilOrigin-Name: adba783c702b05f83e0bee3eb1bc9e40cdec3785
2014-02-18 05:18:36 +00:00
mistachkin 65acf373c9 Use the modern MinGW major version macro, not the deprecated one.
FossilOrigin-Name: 057c16ee9786efcad6372a29b02d743ff3d628ff
2014-02-16 19:20:00 +00:00
mistachkin a7b3b63524 Better support for MinGW 4.x.
FossilOrigin-Name: e147230767383ed9f64085b613fd18508f74be21
2014-02-14 23:35:49 +00:00
mistachkin 2e72791781 Fix comment.
FossilOrigin-Name: 8364af392da2946acd84633b45684e6fba5c39ed
2013-11-26 01:13:18 +00:00
mistachkin f74b9e0965 Further work on Windows header file reform.
FossilOrigin-Name: 540f5525160b516de282136ca77f909115a51630
2013-11-26 01:00:31 +00:00
mistachkin 9598ae2c11 Merge updates from trunk.
FossilOrigin-Name: c5ab4378756965b0c2ab218e5ec59c40898b89ea
2013-11-26 00:33:25 +00:00
mistachkin f3a4c7c2c7 Correct line-endings in the new header file.
FossilOrigin-Name: 94219b9f1ff59ea408c7ded167ee28b00c0f38c1
2013-11-25 09:37:24 +00:00
mistachkin 8bc5262915 Initial work on isolating usage of the Windows header file.
FossilOrigin-Name: 0d42c6b830ee50f45539d73e3948ed3bc50a11d1
2013-11-25 09:36:07 +00:00
123 changed files with 5645 additions and 2020 deletions
+4
View File
@@ -239,8 +239,10 @@ SRC = \
$(TOP)/src/os.c \
$(TOP)/src/os.h \
$(TOP)/src/os_common.h \
$(TOP)/src/os_setup.h \
$(TOP)/src/os_unix.c \
$(TOP)/src/os_win.c \
$(TOP)/src/os_win.h \
$(TOP)/src/pager.c \
$(TOP)/src/pager.h \
$(TOP)/src/parse.y \
@@ -457,6 +459,8 @@ HDR = \
opcodes.h \
$(TOP)/src/os.h \
$(TOP)/src/os_common.h \
$(TOP)/src/os_setup.h \
$(TOP)/src/os_win.h \
$(TOP)/src/pager.h \
$(TOP)/src/pcache.h \
parse.h \
+4
View File
@@ -637,8 +637,10 @@ SRC = \
$(TOP)\src\os.c \
$(TOP)\src\os.h \
$(TOP)\src\os_common.h \
$(TOP)\src\os_setup.h \
$(TOP)\src\os_unix.c \
$(TOP)\src\os_win.c \
$(TOP)\src\os_win.h \
$(TOP)\src\pager.c \
$(TOP)\src\pager.h \
$(TOP)\src\parse.y \
@@ -858,6 +860,8 @@ HDR = \
opcodes.h \
$(TOP)\src\os.h \
$(TOP)\src\os_common.h \
$(TOP)\src\os_setup.h \
$(TOP)\src\os_win.h \
$(TOP)\src\pager.h \
$(TOP)\src\pcache.h \
parse.h \
+4
View File
@@ -262,8 +262,10 @@ SRC = \
$(TOP)/src/os.c \
$(TOP)/src/os.h \
$(TOP)/src/os_common.h \
$(TOP)/src/os_setup.h \
$(TOP)/src/os_unix.c \
$(TOP)/src/os_win.c \
$(TOP)/src/os_win.h \
$(TOP)/src/pager.c \
$(TOP)/src/pager.h \
$(TOP)/src/parse.y \
@@ -416,6 +418,8 @@ HDR = \
opcodes.h \
$(TOP)/src/os.h \
$(TOP)/src/os_common.h \
$(TOP)/src/os_setup.h \
$(TOP)/src/os_win.h \
$(TOP)/src/pager.h \
$(TOP)/src/pcache.h \
parse.h \
+1 -1
View File
@@ -1 +1 @@
3.8.4
3.8.5
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.62 for sqlite 3.8.4.
# Generated by GNU Autoconf 2.62 for sqlite 3.8.5.
#
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
# 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
@@ -743,8 +743,8 @@ SHELL=${CONFIG_SHELL-/bin/sh}
# Identity of this package.
PACKAGE_NAME='sqlite'
PACKAGE_TARNAME='sqlite'
PACKAGE_VERSION='3.8.4'
PACKAGE_STRING='sqlite 3.8.4'
PACKAGE_VERSION='3.8.5'
PACKAGE_STRING='sqlite 3.8.5'
PACKAGE_BUGREPORT=''
# Factoring default headers for most tests.
@@ -1483,7 +1483,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.8.4 to adapt to many kinds of systems.
\`configure' configures sqlite 3.8.5 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1548,7 +1548,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
short | recursive ) echo "Configuration of sqlite 3.8.4:";;
short | recursive ) echo "Configuration of sqlite 3.8.5:";;
esac
cat <<\_ACEOF
@@ -1664,7 +1664,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
sqlite configure 3.8.4
sqlite configure 3.8.5
generated by GNU Autoconf 2.62
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
@@ -1678,7 +1678,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.8.4, which was
It was created by sqlite $as_me 3.8.5, which was
generated by GNU Autoconf 2.62. Invocation command line was
$ $0 $@
@@ -14021,7 +14021,7 @@ exec 6>&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.8.4, which was
This file was extended by sqlite $as_me 3.8.5, which was
generated by GNU Autoconf 2.62. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -14074,7 +14074,7 @@ Report bugs to <bug-autoconf@gnu.org>."
_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_version="\\
sqlite config.status 3.8.4
sqlite config.status 3.8.5
configured by $0, generated by GNU Autoconf 2.62,
with options \\"`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
+37 -7
View File
@@ -1410,10 +1410,7 @@ static int fts3InitVtab(
** addition of a %_stat table so that it can use incremental merge.
*/
if( !isFts4 && !isCreate ){
int rc2 = SQLITE_OK;
fts3DbExec(&rc2, db, "SELECT 1 FROM %Q.'%q_stat' WHERE id=2",
p->zDb, p->zName);
if( rc2==SQLITE_OK ) p->bHasStat = 1;
p->bHasStat = 2;
}
/* Figure out the page-size for the database. This is required in order to
@@ -3320,7 +3317,34 @@ static int fts3SyncMethod(sqlite3_vtab *pVtab){
}
/*
** Implementation of xBegin() method. This is a no-op.
** If it is currently unknown whether or not the FTS table has an %_stat
** table (if p->bHasStat==2), attempt to determine this (set p->bHasStat
** to 0 or 1). Return SQLITE_OK if successful, or an SQLite error code
** if an error occurs.
*/
static int fts3SetHasStat(Fts3Table *p){
int rc = SQLITE_OK;
if( p->bHasStat==2 ){
const char *zFmt ="SELECT 1 FROM %Q.sqlite_master WHERE tbl_name='%q_stat'";
char *zSql = sqlite3_mprintf(zFmt, p->zDb, p->zName);
if( zSql ){
sqlite3_stmt *pStmt = 0;
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
if( rc==SQLITE_OK ){
int bHasStat = (sqlite3_step(pStmt)==SQLITE_ROW);
rc = sqlite3_finalize(pStmt);
if( rc==SQLITE_OK ) p->bHasStat = bHasStat;
}
sqlite3_free(zSql);
}else{
rc = SQLITE_NOMEM;
}
}
return rc;
}
/*
** Implementation of xBegin() method.
*/
static int fts3BeginMethod(sqlite3_vtab *pVtab){
Fts3Table *p = (Fts3Table*)pVtab;
@@ -3331,7 +3355,7 @@ static int fts3BeginMethod(sqlite3_vtab *pVtab){
TESTONLY( p->inTransaction = 1 );
TESTONLY( p->mxSavepoint = -1; );
p->nLeafAdd = 0;
return SQLITE_OK;
return fts3SetHasStat(p);
}
/*
@@ -3580,6 +3604,10 @@ static int fts3RenameMethod(
sqlite3 *db = p->db; /* Database connection */
int rc; /* Return Code */
/* At this point it must be known if the %_stat table exists or not.
** So bHasStat may not be 2. */
rc = fts3SetHasStat(p);
/* As it happens, the pending terms table is always empty here. This is
** because an "ALTER TABLE RENAME TABLE" statement inside a transaction
** always opens a savepoint transaction. And the xSavepoint() method
@@ -3587,7 +3615,9 @@ static int fts3RenameMethod(
** PendingTermsFlush() in in case that changes.
*/
assert( p->nPendingData==0 );
rc = sqlite3Fts3PendingTermsFlush(p);
if( rc==SQLITE_OK ){
rc = sqlite3Fts3PendingTermsFlush(p);
}
if( p->zContentTbl==0 ){
fts3DbExec(&rc, db,
+1 -1
View File
@@ -223,7 +223,7 @@ struct Fts3Table {
int nNodeSize; /* Soft limit for node size */
u8 bFts4; /* True for FTS4, false for FTS3 */
u8 bHasStat; /* True if %_stat table exists */
u8 bHasStat; /* True if %_stat table exists (2==unknown) */
u8 bHasDocsize; /* True if %_docsize table exists */
u8 bDescIdx; /* True if doclists are in reverse order */
u8 bIgnoreSavepoint; /* True to ignore xSavepoint invocations */
+4
View File
@@ -5271,6 +5271,10 @@ int sqlite3Fts3UpdateMethod(
int nChng = 0; /* Net change in number of documents */
int bInsertDone = 0;
/* At this point it must be known if the %_stat table exists or not.
** So bHasStat may not be 2. */
assert( p->bHasStat==0 || p->bHasStat==1 );
assert( p->pSegments==0 );
assert(
nArg==1 /* DELETE operations */
+1 -1
View File
@@ -26,8 +26,8 @@ SQLITE_EXTENSION_INIT1
# define NEVER(X) 0
typedef unsigned char u8;
typedef unsigned short u16;
# include <ctype.h>
#endif
#include <ctype.h>
#ifndef SQLITE_OMIT_VIRTUALTABLE
+785 -749
View File
File diff suppressed because it is too large Load Diff
+11 -8
View File
@@ -120,12 +120,13 @@ proc execsql_intout {sql} {
# Test that it is possible to open an existing database that contains
# r-tree tables.
#
do_test rtree-1.4.1 {
execsql {
CREATE VIRTUAL TABLE t1 USING rtree(ii, x1, x2);
INSERT INTO t1 VALUES(1, 5.0, 10.0);
INSERT INTO t1 VALUES(2, 15.0, 20.0);
}
do_execsql_test rtree-1.4.1a {
CREATE VIRTUAL TABLE t1 USING rtree(ii, x1, x2);
INSERT INTO t1 VALUES(1, 5.0, 10.0);
SELECT substr(hex(data),1,40) FROM t1_node;
} {00000001000000000000000140A0000041200000}
do_execsql_test rtree-1.4.1b {
INSERT INTO t1 VALUES(2, 15.0, 20.0);
} {}
do_test rtree-1.4.2 {
db close
@@ -435,16 +436,18 @@ do_test rtree-11.2 {
# Test on-conflict clause handling.
#
db_delete_and_reopen
do_execsql_test 12.0 {
do_execsql_test 12.0.1 {
CREATE VIRTUAL TABLE t1 USING rtree_i32(idx, x1, x2, y1, y2);
INSERT INTO t1 VALUES(1, 1, 2, 3, 4);
SELECT substr(hex(data),1,56) FROM t1_node;
} {00000001000000000000000100000001000000020000000300000004}
do_execsql_test 12.0.2 {
INSERT INTO t1 VALUES(2, 2, 3, 4, 5);
INSERT INTO t1 VALUES(3, 3, 4, 5, 6);
CREATE TABLE source(idx, x1, x2, y1, y2);
INSERT INTO source VALUES(5, 8, 8, 8, 8);
INSERT INTO source VALUES(2, 7, 7, 7, 7);
}
db_save_and_close
foreach {tn sql_template testdata} {
+9 -9
View File
@@ -57,31 +57,31 @@ do_test rtree6-1.1 {
do_test rtree6-1.2 {
rtree_strategy {SELECT * FROM t1 WHERE x1>10}
} {Ea}
} {E0}
do_test rtree6-1.3 {
rtree_strategy {SELECT * FROM t1 WHERE x1<10}
} {Ca}
} {C0}
do_test rtree6-1.4 {
rtree_strategy {SELECT * FROM t1,t2 WHERE k=ii AND x1<10}
} {Ca}
} {C0}
do_test rtree6-1.5 {
rtree_strategy {SELECT * FROM t1,t2 WHERE k=+ii AND x1<10}
} {Ca}
} {C0}
do_eqp_test rtree6.2.1 {
SELECT * FROM t1,t2 WHERE k=+ii AND x1<10
} {
0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 2:Ca}
0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 2:C0}
0 1 1 {SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid=?)}
}
do_eqp_test rtree6.2.2 {
SELECT * FROM t1,t2 WHERE k=ii AND x1<10
} {
0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 2:Ca}
0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 2:C0}
0 1 1 {SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid=?)}
}
@@ -95,7 +95,7 @@ do_eqp_test rtree6.2.3 {
do_eqp_test rtree6.2.4 {
SELECT * FROM t1,t2 WHERE v=10 and x1<10 and x2>10
} {
0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 2:CaEb}
0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 2:C0E1}
0 1 1 {SEARCH TABLE t2 USING AUTOMATIC COVERING INDEX (v=?)}
}
@@ -126,7 +126,7 @@ do_test rtree6.3.2 {
x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND
x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5
}
} {EaEaEaEaEaEaEaEaEaEaEaEaEaEaEaEaEaEaEaEa}
} {E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0}
do_test rtree6.3.3 {
rtree_strategy {
SELECT * FROM t3 WHERE
@@ -137,7 +137,7 @@ do_test rtree6.3.3 {
x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND
x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5
}
} {EaEaEaEaEaEaEaEaEaEaEaEaEaEaEaEaEaEaEaEa}
} {E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0}
do_execsql_test rtree6-3.4 {
SELECT * FROM t3 WHERE x1>0.5 AND x1>0.8 AND x1>1.1
+1 -1
View File
@@ -41,7 +41,7 @@ ifcapable rtree_int_only {
INSERT INTO t1 VALUES(9223372036854775807, 150, 150, 400, 400);
SELECT rtreenode(2, data) FROM t1_node;
}
} {{{1073741824 0.000000 0.000000 100.000000 100.000000} {2147483646 0.000000 0.000000 200.000000 200.000000} {4294967296 0.000000 0.000000 300.000000 300.000000} {8589934592 20.000000 20.000000 150.000000 150.000000} {9223372036854775807 150.000000 150.000000 400.000000 400.000000}}}
} {{{1073741824 0 0 100 100} {2147483646 0 0 200 200} {4294967296 0 0 300 300} {8589934592 20 20 150 150} {9223372036854775807 150 150 400 400}}}
}
finish_test
+118 -7
View File
@@ -29,7 +29,7 @@ do_eqp_test 1.1 {
WHERE t.x>=min_x AND t.x<=max_x AND t.y>=min_y AND t.x<=max_y
} {
0 0 1 {SCAN TABLE t}
0 1 0 {SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:DdBcDbBa}
0 1 0 {SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0}
}
do_eqp_test 1.2 {
@@ -37,7 +37,7 @@ do_eqp_test 1.2 {
WHERE t.x>=min_x AND t.x<=max_x AND t.y>=min_y AND t.x<=max_y
} {
0 0 0 {SCAN TABLE t}
0 1 1 {SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:DdBcDbBa}
0 1 1 {SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0}
}
do_eqp_test 1.3 {
@@ -45,7 +45,7 @@ do_eqp_test 1.3 {
WHERE t.x>=min_x AND t.x<=max_x AND t.y>=min_y AND ?<=max_y
} {
0 0 0 {SCAN TABLE t}
0 1 1 {SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:DdBcDbBa}
0 1 1 {SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0}
}
do_eqp_test 1.5 {
@@ -82,7 +82,7 @@ do_eqp_test 2.1 {
WHERE t.x>=min_x AND t.x<=max_x AND t.y>=min_y AND t.x<=max_y
} {
0 0 1 {SCAN TABLE t}
0 1 0 {SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:DdBcDbBa}
0 1 0 {SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0}
}
do_eqp_test 2.2 {
@@ -90,7 +90,7 @@ do_eqp_test 2.2 {
WHERE t.x>=min_x AND t.x<=max_x AND t.y>=min_y AND t.x<=max_y
} {
0 0 0 {SCAN TABLE t}
0 1 1 {SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:DdBcDbBa}
0 1 1 {SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0}
}
do_eqp_test 2.3 {
@@ -98,7 +98,7 @@ do_eqp_test 2.3 {
WHERE t.x>=min_x AND t.x<=max_x AND t.y>=min_y AND ?<=max_y
} {
0 0 0 {SCAN TABLE t}
0 1 1 {SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:DdBcDbBa}
0 1 1 {SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0}
}
do_eqp_test 2.5 {
@@ -158,5 +158,116 @@ do_execsql_test 4.3 {
SELECT b, a FROM t2 LEFT JOIN t1 ON (+a = +b);
} {1 1 3 {}}
finish_test
#--------------------------------------------------------------------
# Test that the sqlite_stat1 data is used correctly.
#
reset_db
do_execsql_test 5.1 {
CREATE TABLE t1(x PRIMARY KEY, y);
CREATE VIRTUAL TABLE rt USING rtree(id, x1, x2);
INSERT INTO t1(x) VALUES(1);
INSERT INTO t1(x) SELECT x+1 FROM t1; -- 2
INSERT INTO t1(x) SELECT x+2 FROM t1; -- 4
INSERT INTO t1(x) SELECT x+4 FROM t1; -- 8
INSERT INTO t1(x) SELECT x+8 FROM t1; -- 16
INSERT INTO t1(x) SELECT x+16 FROM t1; -- 32
INSERT INTO t1(x) SELECT x+32 FROM t1; -- 64
INSERT INTO t1(x) SELECT x+64 FROM t1; -- 128
INSERT INTO t1(x) SELECT x+128 FROM t1; -- 256
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;
}
# First test a query with no ANALYZE data at all. The outer loop is
# real table "t1".
#
do_eqp_test 5.2 {
SELECT * FROM t1, rt WHERE x==id;
} {
0 0 0 {SCAN TABLE t1}
0 1 1 {SCAN TABLE rt VIRTUAL TABLE INDEX 1:}
}
# Now create enough ANALYZE data to tell SQLite that virtual table "rt"
# contains very few rows. This causes it to move "rt" to the outer loop.
#
do_execsql_test 5.3 {
ANALYZE;
DELETE FROM sqlite_stat1 WHERE tbl='t1';
}
db close
sqlite3 db test.db
do_eqp_test 5.4 {
SELECT * FROM t1, rt WHERE x==id;
} {
0 0 1 {SCAN TABLE rt VIRTUAL TABLE INDEX 2:}
0 1 0 {SEARCH TABLE t1 USING INDEX sqlite_autoindex_t1_1 (x=?)}
}
# Delete the ANALYZE data. "t1" should be the outer loop again.
#
do_execsql_test 5.5 { DROP TABLE sqlite_stat1; }
db close
sqlite3 db test.db
do_eqp_test 5.6 {
SELECT * FROM t1, rt WHERE x==id;
} {
0 0 0 {SCAN TABLE t1}
0 1 1 {SCAN TABLE rt VIRTUAL TABLE INDEX 1:}
}
# This time create and attach a database that contains ANALYZE data for
# tables of the same names as those used internally by virtual table
# "rt". Check that the rtree module is not fooled into using this data.
# Table "t1" should remain the outer loop.
#
do_test 5.7 {
db backup test.db2
sqlite3 db2 test.db2
db2 eval {
ANALYZE;
DELETE FROM sqlite_stat1 WHERE tbl='t1';
}
db2 close
db close
sqlite3 db test.db
execsql { ATTACH 'test.db2' AS aux; }
} {}
do_eqp_test 5.8 {
SELECT * FROM t1, rt WHERE x==id;
} {
0 0 0 {SCAN TABLE t1}
0 1 1 {SCAN TABLE rt VIRTUAL TABLE INDEX 1:}
}
#--------------------------------------------------------------------
# Test that having a second connection drop the sqlite_stat1 table
# before it is required by rtreeConnect() does not cause problems.
#
ifcapable rtree {
reset_db
do_execsql_test 6.1 {
CREATE TABLE t1(x);
CREATE VIRTUAL TABLE rt USING rtree(id, x1, x2);
INSERT INTO t1 VALUES(1);
INSERT INTO rt VALUES(1,2,3);
ANALYZE;
}
db close
sqlite3 db test.db
do_execsql_test 6.2 { SELECT * FROM t1 } {1}
do_test 6.3 {
sqlite3 db2 test.db
db2 eval { DROP TABLE sqlite_stat1 }
db2 close
execsql { SELECT * FROM rt }
} {1 2.0 3.0}
db close
}
finish_test
+57
View File
@@ -0,0 +1,57 @@
# 2014 March 11
#
# 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.
#
#***********************************************************************
#
# Miscellaneous tests for errors in the rtree constructor.
#
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
source $testdir/lock_common.tcl
ifcapable !rtree {
finish_test
return
}
set testprefix rtreeD
#-------------------------------------------------------------------------
# Test that if an SQLITE_BUSY is encountered within the vtable
# constructor, a relevant error message is returned.
#
do_multiclient_test tn {
do_test 1.$tn.1 {
sql1 {
CREATE TABLE t1(a, b);
INSERT INTO t1 VALUES(1,2);
CREATE VIRTUAL TABLE rt USING rtree(id, minx, maxx, miny, maxy);
INSERT INTO rt VALUES(1,2,3,4,5);
}
} {}
do_test 1.$tn.2 {
sql2 { SELECT * FROM t1; }
} {1 2}
do_test 1.$tn.3 {
sql1 { BEGIN EXCLUSIVE; INSERT INTO t1 VALUES(3, 4); }
} {}
do_test 1.$tn.4 {
list [catch { sql2 { SELECT * FROM rt } } msg] $msg
} {1 {database is locked}}
}
finish_test
+129
View File
@@ -0,0 +1,129 @@
# 2010 August 28
#
# 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, it tests
# that new-style custom r-tree queries (geometry callbacks) work.
#
if {![info exists testdir]} {
set testdir [file join [file dirname [info script]] .. .. test]
}
source $testdir/tester.tcl
ifcapable !rtree { finish_test ; return }
ifcapable rtree_int_only { finish_test; return }
#-------------------------------------------------------------------------
# Test the example 2d "circle" geometry callback.
#
register_circle_geom db
do_execsql_test rtreeE-1.1 {
PRAGMA page_size=512;
CREATE VIRTUAL TABLE rt1 USING rtree(id,x0,x1,y0,y1);
/* A tight pattern of small boxes near 0,0 */
WITH RECURSIVE
x(x) AS (VALUES(0) UNION ALL SELECT x+1 FROM x WHERE x<4),
y(y) AS (VALUES(0) UNION ALL SELECT y+1 FROM y WHERE y<4)
INSERT INTO rt1 SELECT x+5*y, x, x+2, y, y+2 FROM x, y;
/* A looser pattern of small boxes near 100, 0 */
WITH RECURSIVE
x(x) AS (VALUES(0) UNION ALL SELECT x+1 FROM x WHERE x<4),
y(y) AS (VALUES(0) UNION ALL SELECT y+1 FROM y WHERE y<4)
INSERT INTO rt1 SELECT 100+x+5*y, x*3+100, x*3+102, y*3, y*3+2 FROM x, y;
/* A looser pattern of larger boxes near 0, 200 */
WITH RECURSIVE
x(x) AS (VALUES(0) UNION ALL SELECT x+1 FROM x WHERE x<4),
y(y) AS (VALUES(0) UNION ALL SELECT y+1 FROM y WHERE y<4)
INSERT INTO rt1 SELECT 200+x+5*y, x*7, x*7+15, y*7+200, y*7+215 FROM x, y;
} {}
# Queries against each of the three clusters */
do_execsql_test rtreeE-1.1 {
SELECT id FROM rt1 WHERE id MATCH Qcircle(0.0, 0.0, 50.0, 3) ORDER BY id;
} {0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24}
do_execsql_test rtreeE-1.2 {
SELECT id FROM rt1 WHERE id MATCH Qcircle(100.0, 0.0, 50.0, 3) ORDER BY id;
} {100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124}
do_execsql_test rtreeE-1.3 {
SELECT id FROM rt1 WHERE id MATCH Qcircle(0.0, 200.0, 50.0, 3) ORDER BY id;
} {200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224}
# The Qcircle geometry function gives a lower score to larger leaf-nodes.
# This causes the 200s to sort before the 100s and the 0s to sort before
# last.
#
do_execsql_test rtreeE-1.4 {
SELECT id FROM rt1 WHERE id MATCH Qcircle(0,0,1000,3) AND id%100==0
} {200 100 0}
# Exclude odd rowids on a depth-first search
do_execsql_test rtreeE-1.5 {
SELECT id FROM rt1 WHERE id MATCH Qcircle(0,0,1000,4) ORDER BY +id
} {0 2 4 6 8 10 12 14 16 18 20 22 24 100 102 104 106 108 110 112 114 116 118 120 122 124 200 202 204 206 208 210 212 214 216 218 220 222 224}
# Exclude odd rowids on a breadth-first search.
do_execsql_test rtreeE-1.6 {
SELECT id FROM rt1 WHERE id MATCH Qcircle(0,0,1000,5) ORDER BY +id
} {0 2 4 6 8 10 12 14 16 18 20 22 24 100 102 104 106 108 110 112 114 116 118 120 122 124 200 202 204 206 208 210 212 214 216 218 220 222 224}
# Construct a large 2-D RTree with thousands of random entries.
#
do_test rtreeE-2.1 {
db eval {
CREATE TABLE t2(id,x0,x1,y0,y1);
CREATE VIRTUAL TABLE rt2 USING rtree(id,x0,x1,y0,y1);
BEGIN;
}
expr srand(0)
for {set i 1} {$i<=10000} {incr i} {
set dx [expr {int(rand()*40)+1}]
set dy [expr {int(rand()*40)+1}]
set x0 [expr {int(rand()*(10000 - $dx))}]
set x1 [expr {$x0+$dx}]
set y0 [expr {int(rand()*(10000 - $dy))}]
set y1 [expr {$y0+$dy}]
set id [expr {$i+10000}]
db eval {INSERT INTO t2 VALUES($id,$x0,$x1,$y0,$y1)}
}
db eval {
INSERT INTO rt2 SELECT * FROM t2;
COMMIT;
}
} {}
for {set i 1} {$i<=200} {incr i} {
set dx [expr {int(rand()*100)}]
set dy [expr {int(rand()*100)}]
set x0 [expr {int(rand()*(10000 - $dx))}]
set x1 [expr {$x0+$dx}]
set y0 [expr {int(rand()*(10000 - $dy))}]
set y1 [expr {$y0+$dy}]
set ans [db eval {SELECT id FROM t2 WHERE x1>=$x0 AND x0<=$x1 AND y1>=$y0 AND y0<=$y1 ORDER BY id}]
do_execsql_test rtreeE-2.2.$i {
SELECT id FROM rt2 WHERE id MATCH breadthfirstsearch($x0,$x1,$y0,$y1) ORDER BY id
} $ans
}
# Run query that have very deep priority queues
#
set ans [db eval {SELECT id FROM t2 WHERE x1>=0 AND x0<=5000 AND y1>=0 AND y0<=5000 ORDER BY id}]
do_execsql_test rtreeE-2.3 {
SELECT id FROM rt2 WHERE id MATCH breadthfirstsearch(0,5000,0,5000) ORDER BY id
} $ans
set ans [db eval {SELECT id FROM t2 WHERE x1>=0 AND x0<=10000 AND y1>=0 AND y0<=10000 ORDER BY id}]
do_execsql_test rtreeE-2.4 {
SELECT id FROM rt2 WHERE id MATCH breadthfirstsearch(0,10000,0,10000) ORDER BY id
} $ans
finish_test
+61 -6
View File
@@ -21,6 +21,16 @@ extern "C" {
#endif
typedef struct sqlite3_rtree_geometry sqlite3_rtree_geometry;
typedef struct sqlite3_rtree_query_info sqlite3_rtree_query_info;
/* The double-precision datatype used by RTree depends on the
** SQLITE_RTREE_INT_ONLY compile-time option.
*/
#ifdef SQLITE_RTREE_INT_ONLY
typedef sqlite3_int64 sqlite3_rtree_dbl;
#else
typedef double sqlite3_rtree_dbl;
#endif
/*
** Register a geometry callback named zGeom that can be used as part of an
@@ -31,11 +41,7 @@ typedef struct sqlite3_rtree_geometry sqlite3_rtree_geometry;
int sqlite3_rtree_geometry_callback(
sqlite3 *db,
const char *zGeom,
#ifdef SQLITE_RTREE_INT_ONLY
int (*xGeom)(sqlite3_rtree_geometry*, int n, sqlite3_int64 *a, int *pRes),
#else
int (*xGeom)(sqlite3_rtree_geometry*, int n, double *a, int *pRes),
#endif
int (*xGeom)(sqlite3_rtree_geometry*, int, sqlite3_rtree_dbl*,int*),
void *pContext
);
@@ -47,11 +53,60 @@ int sqlite3_rtree_geometry_callback(
struct sqlite3_rtree_geometry {
void *pContext; /* Copy of pContext passed to s_r_g_c() */
int nParam; /* Size of array aParam[] */
double *aParam; /* Parameters passed to SQL geom function */
sqlite3_rtree_dbl *aParam; /* Parameters passed to SQL geom function */
void *pUser; /* Callback implementation user data */
void (*xDelUser)(void *); /* Called by SQLite to clean up pUser */
};
/*
** Register a 2nd-generation geometry callback named zScore that can be
** used as part of an R-Tree geometry query as follows:
**
** SELECT ... FROM <rtree> WHERE <rtree col> MATCH $zQueryFunc(... params ...)
*/
int sqlite3_rtree_query_callback(
sqlite3 *db,
const char *zQueryFunc,
int (*xQueryFunc)(sqlite3_rtree_query_info*),
void *pContext,
void (*xDestructor)(void*)
);
/*
** A pointer to a structure of the following type is passed as the
** argument to scored geometry callback registered using
** sqlite3_rtree_query_callback().
**
** Note that the first 5 fields of this structure are identical to
** sqlite3_rtree_geometry. This structure is a subclass of
** sqlite3_rtree_geometry.
*/
struct sqlite3_rtree_query_info {
void *pContext; /* pContext from when function registered */
int nParam; /* Number of function parameters */
sqlite3_rtree_dbl *aParam; /* value of function parameters */
void *pUser; /* callback can use this, if desired */
void (*xDelUser)(void*); /* function to free pUser */
sqlite3_rtree_dbl *aCoord; /* Coordinates of node or entry to check */
unsigned int *anQueue; /* Number of pending entries in the queue */
int nCoord; /* Number of coordinates */
int iLevel; /* Level of current node or entry */
int mxLevel; /* The largest iLevel value in the tree */
sqlite3_int64 iRowid; /* Rowid for current entry */
sqlite3_rtree_dbl rParentScore; /* Score of parent node */
int eParentWithin; /* Visibility of parent node */
int eWithin; /* OUT: Visiblity */
sqlite3_rtree_dbl rScore; /* OUT: Write the score here */
};
/*
** Allowed values for sqlite3_rtree_query.eWithin and .eParentWithin.
*/
#define NOT_WITHIN 0 /* Object completely outside of query region */
#define PARTLY_WITHIN 1 /* Object partially overlaps query region */
#define FULLY_WITHIN 2 /* Object fully contained within query region */
#ifdef __cplusplus
} /* end of the 'extern "C"' block */
+5 -1
View File
@@ -121,8 +121,10 @@ SRC = \
$(TOP)/src/os.c \
$(TOP)/src/os.h \
$(TOP)/src/os_common.h \
$(TOP)/src/os_setup.h \
$(TOP)/src/os_unix.c \
$(TOP)/src/os_win.c \
$(TOP)/src/os_win.h \
$(TOP)/src/pager.c \
$(TOP)/src/pager.h \
$(TOP)/src/parse.y \
@@ -339,6 +341,8 @@ HDR = \
opcodes.h \
$(TOP)/src/os.h \
$(TOP)/src/os_common.h \
$(TOP)/src/os_setup.h \
$(TOP)/src/os_win.h \
$(TOP)/src/pager.h \
$(TOP)/src/pcache.h \
parse.h \
@@ -476,7 +480,7 @@ parse.c: $(TOP)/src/parse.y lemon $(TOP)/addopcodes.awk
mv parse.h parse.h.temp
$(NAWK) -f $(TOP)/addopcodes.awk parse.h.temp >parse.h
sqlite3.h: $(TOP)/src/sqlite.h.in $(TOP)/manifest.uuid $(TOP)/VERSION
sqlite3.h: $(TOP)/src/sqlite.h.in $(TOP)/manifest.uuid $(TOP)/VERSION $(TOP)/ext/rtree/sqlite3rtree.h
tclsh $(TOP)/tool/mksqlite3h.tcl $(TOP) >sqlite3.h
keywordhash.h: $(TOP)/tool/mkkeywordhash.c
+126 -112
View File
@@ -1,12 +1,12 @@
C Fix\smore\sinstances\sof\sassuming\s'char'\sis\ssigned.\s\sAnd,\smake\ssure\sto\snever\sshift\na\ssigned\sinteger.
D 2014-03-04T04:04:33.269
C Attempt\sto\sfix\sthe\sbuild\son\sbeagleboard.
D 2014-05-05T20:21:52.937
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81
F Makefile.in dd2b1aba364ff9b05de41086f74407f285c57670
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
F Makefile.msc fdacba6fb574868c71fde6db6b77789a383a4c19
F Makefile.vxworks db21ed42a01d5740e656b16f92cb5d8d5e5dd315
F Makefile.msc d1d9474b660e87a0134acd33693281883cb328b1
F Makefile.vxworks 034289efa9d591b04b1a73598623119c306cbba0
F README.md 64f270c43c38c46de749e419c22f0ae2f4499fe8
F VERSION 0dc30ad5cf90736d5fd9e540c9f05c542658abe7
F VERSION 9f823c026c6a32fc5f84d212a8aae0a221dba45c
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
F addopcodes.awk 9eb448a552d5c0185cf62c463f9c173cedae3811
F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2
@@ -38,7 +38,7 @@ F autoconf/tea/win/rules.vc c511f222b80064096b705dbeb97060ee1d6b6d63
F config.guess 226d9a188c6196f3033ffc651cbc9dcee1a42977
F config.h.in 0921066a13130082764ab4ab6456f7b5bebe56de
F config.sub 9ebe4c3b3dab6431ece34f16828b594fb420da55
F configure e12e1a4f031354f9af735bcb377941a72dc2cca5 x
F configure 5de98fac90452f876511fee8a35565a55dfb191f x
F configure.ac 4cf9f60785143fa141b10962ccc885d973792e9a
F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
F doc/lemon.html 334dbf6621b8fb8790297ec1abf3cfa4621709d1
@@ -78,9 +78,9 @@ F ext/fts3/README.content fdc666a70d5257a64fee209f97cf89e0e6e32b51
F ext/fts3/README.syntax a19711dc5458c20734b8e485e75fb1981ec2427a
F ext/fts3/README.tokenizers e0a8b81383ea60d0334d274fadf305ea14a8c314
F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d
F ext/fts3/fts3.c 3fe91e36a0304ad4b35020f0e22ff37e95873166
F ext/fts3/fts3.c 41b1920b9a8657963f09cb93b208c2671c5568db
F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe
F ext/fts3/fts3Int.h eb5f8029589f3d8f1dc7fd50c773326a640388b1
F ext/fts3/fts3Int.h bdeb9015405e8facffb8fc7e09174521a2a780f4
F ext/fts3/fts3_aux.c 5c211e17a64885faeb16b9ba7772f9d5445c2365
F ext/fts3/fts3_expr.c 5165c365cb5a035f5be8bb296f7aa3211d43e4ac
F ext/fts3/fts3_hash.c 29b986e43f4e9dd40110eafa377dc0d63c422c60
@@ -96,7 +96,7 @@ F ext/fts3/fts3_tokenizer.h 64c6ef6c5272c51ebe60fc607a896e84288fcbc3
F ext/fts3/fts3_tokenizer1.c 5c98225a53705e5ee34824087478cf477bdb7004
F ext/fts3/fts3_unicode.c 92391b4b4fb043564c6539ea9b8661e3bcba47b9
F ext/fts3/fts3_unicode2.c 0113d3acf13429e6dc38e0647d1bc71211c31a4d
F ext/fts3/fts3_write.c cdebe72171a217b1465032dec103f8d17f7dad4d
F ext/fts3/fts3_write.c 74c00329006c3ed6325ba4e5ab7c9b5fc99c8934
F ext/fts3/fts3speed.tcl b54caf6a18d38174f1a6e84219950d85e98bb1e9
F ext/fts3/mkfts3amal.tcl 252ecb7fe6467854f2aa237bf2c390b74e71f100
F ext/fts3/tool/fts3view.c 6cfc5b67a5f0e09c0d698f9fd012c784bfaa9197
@@ -114,35 +114,37 @@ F ext/misc/nextchar.c 35c8b8baacb96d92abbb34a83a997b797075b342
F ext/misc/percentile.c bcbee3c061b884eccb80e21651daaae8e1e43c63
F ext/misc/regexp.c af92cdaa5058fcec1451e49becc7ba44dba023dc
F ext/misc/rot13.c 1ac6f95f99b575907b9b09c81a349114cf9be45a
F ext/misc/spellfix.c 3548c433f473c2054e080b6382771636fcaa2c4c
F ext/misc/spellfix.c 93f3961074cebe63c31fcefe62ca2a032ee8dfed
F ext/misc/totype.c 4a167594e791abeed95e0a8db028822b5e8fe512
F ext/misc/vfslog.c fe40fab5c077a40477f7e5eba994309ecac6cc95
F ext/misc/vtshim.c babb0dc2bf116029e3e7c9a618b8a1377045303e
F ext/misc/wholenumber.c 784b12543d60702ebdd47da936e278aa03076212
F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761
F ext/rtree/rtree.c a4e18b2c150adad20aecbeb3408cd235a0a57441
F ext/rtree/rtree.c 6f70db93e0e42c369325c5cddcf2024c5a87ca43
F ext/rtree/rtree.h 834dbcb82dc85b2481cde6a07cdadfddc99e9b9e
F ext/rtree/rtree1.test cf679265ecafff494a768ac9c2f43a70915a6290
F ext/rtree/rtree1.test e2da4aaa426918d27122d1a1066c6ecf8409a514
F ext/rtree/rtree2.test acbb3a4ce0f4fbc2c304d2b4b784cfa161856bba
F ext/rtree/rtree3.test a494da55c30ee0bc9b01a91c80c81b387b22d2dc
F ext/rtree/rtree4.test c8fe384f60ebd49540a5fecc990041bf452eb6e0
F ext/rtree/rtree5.test 6a510494f12454bf57ef28f45bc7764ea279431e
F ext/rtree/rtree6.test fe0bd377a21c68ce2826129d14354c884cb1f354
F ext/rtree/rtree6.test 756585abc51727fec97c77852476445c10c0ee95
F ext/rtree/rtree7.test 1fa710b9e6bf997a0c1a537b81be7bb6fded1971
F ext/rtree/rtree8.test db79c812f9e4a11f9b1f3f9934007884610a713a
F ext/rtree/rtree9.test d86ebf08ff6328895613ed577dd8a2a37c472c34
F ext/rtree/rtreeA.test ace05e729a36e342d40cf94e9efc7b4723d9dcdf
F ext/rtree/rtreeB.test 983e567b49b5dca165940f66b87e161aa30e82b2
F ext/rtree/rtreeC.test 03975565f40a0bee165f613143e4dec716dd5a59
F ext/rtree/rtreeB.test c85f9ce78766c4e68b8b89fbf2979ee9cfa82b4e
F ext/rtree/rtreeC.test df158dcc81f1a43ce7eef361af03c48ec91f1e06
F ext/rtree/rtreeD.test 636630357638f5983701550b37f0f5867130d2ca
F ext/rtree/rtreeE.test 388c1c8602c3ce55c15f03b509e9cf545fb7c41f
F ext/rtree/rtree_perf.tcl 6c18c1f23cd48e0f948930c98dfdd37dfccb5195
F ext/rtree/rtree_util.tcl 06aab2ed5b826545bf215fff90ecb9255a8647ea
F ext/rtree/sqlite3rtree.h c34c1e41d1ab80bb8ad09aae402c9c956871a765
F ext/rtree/sqlite3rtree.h 83349d519fe5f518b3ea025d18dd1fe51b1684bd
F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de
F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
F magic.txt f439556c5ce01ced70987e5ee86549a45165d9ff
F main.mk 3ae543fa446525c1dec55f58de67f41b78651812
F main.mk 601f43d91e6c7043127ec192bf85c9a1ae940621
F mkopcodec.awk c2ff431854d702cdd2d779c9c0d1f58fa16fa4ea
F mkopcodeh.awk c6b3fa301db6ef7ac916b14c60868aeaec1337b5
F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83
@@ -156,81 +158,83 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
F sqlite3.1 3d8b83c91651f53472ca17599dae3457b8b89494
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
F src/alter.c 5d99edbac5bc416032772b723ee30182ee6e5de0
F src/analyze.c 69761e1677142d180a9f55250dee2952f45e4793
F src/alter.c b00900877f766f116f9e16116f1ccacdc21d82f1
F src/analyze.c 3596f863bb80126fe56ba217df5932749271efc8
F src/attach.c 3801129015ef59d76bf23c95ef9b0069d18a0c52
F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34
F src/backup.c a729e63cf5cd1829507cb7b8e89f99b95141bb53
F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb
F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7
F src/btree.c 7a81c2c6b5c0bf6334b4247e709c639c573fbcc1
F src/btree.h 9e0f97c01b972f779eb7655cfb4f8727fd6dc26f
F src/btreeInt.h 0be66063468a520e4d66b80c7a1dc26d04ee6ea4
F src/build.c 00ce613bc2256e525c9195cb10d0df7bcc48d1f0
F src/btree.c 6c9b51abd404ce5b78b173b6f2248e8cb824758c
F src/btree.h d79306df4ed9181b48916737fe8871a4392c4594
F src/btreeInt.h cf180d86b2e9e418f638d65baa425c4c69c0e0e3
F src/build.c 02665ca158431a0926b10cbd7d8178a4c9fc4a22
F src/callback.c 174e3c8656bc29f91d710ab61550d16eea34be98
F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
F src/ctime.c 77779efbe78dd678d84bfb4fc2e87b6b6ad8dccd
F src/ctime.c 0231df905e2c4abba4483ee18ffc05adc321df2a
F src/date.c 593c744b2623971e45affd0bde347631bdfa4625
F src/delete.c cdd57149543bb28304d8f717c243f2a86b1fc280
F src/expr.c 014b8087a15c4c314bdd798cb1cb0b32693f8b40
F src/delete.c bcf8f72126cea80fc3d5bc5494cf19b3f8935aaf
F src/expr.c 4f9e497c66e2f25a4d139357a778c84d5713207c
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
F src/fkey.c 5269ef07b100763134f71b889327c333bd0989cf
F src/func.c f4499b39d66b71825514334ce67b32ff14bd19f5
F src/func.c 2945bb2c4cdc0ac43733046285a4434310be1811
F src/global.c 1d7bb7ea8254ae6a68ed9bfaf65fcb3d1690b486
F src/hash.c d139319967164f139c8d1bb8a11b14db9c4ba3cd
F src/hash.h 8890a25af81fb85a9ad7790d32eedab4b994da22
F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08
F src/insert.c d3d1164299faa53b5347f8ff676d3787537fa9e5
F src/insert.c ab34bea5af4fee9f956a0805a32463fb7f674d00
F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d
F src/legacy.c 0df0b1550b9cc1f58229644735e317ac89131f12
F src/lempar.c cdf0a000315332fc9b50b62f3b5e22e080a0952b
F src/loadext.c 867c7b330b740c6c917af9956b13b81d0a048303
F src/main.c e054917b1beb3081b0f23e8bdd3d6c0e12933dd3
F src/main.c 0a8cfb6b2899649880e5874ac9bfd1c6f7c6a4a3
F src/malloc.c 0203ebce9152c6a0e5de520140b8ba65187350be
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c c0c990fcaddff810ea277b4fb5d9138603dd5d4b
F src/mem2.c dce31758da87ec2cfa52ba4c5df1aed6e07d8e8f
F src/mem3.c 61c9d47b792908c532ca3a62b999cf21795c6534
F src/mem5.c aeb019f271ea53de83d651ec526877e6ba863450
F src/mem5.c 74670012946c4adc8a6ad84d03acc80959c3e529
F src/memjournal.c 0683aac6cab6ec2b5374c0db37c0deb2436a3785
F src/mutex.c d3b66a569368015e0fcb1ac15f81c119f504d3bc
F src/mutex.h 5bc526e19dccc412b7ff04642f6fdad3fdfdabea
F src/mutex_noop.c 7682796b7d8d39bf1c138248858efcd10c9e1553
F src/mutex_unix.c c3a4e00f96ba068a8dbef34084465979aaf369cc
F src/mutex_w32.c 6108c88e1cb38d8fbb3534b170793815cbedbf97
F src/mutex_w32.c ab08c0fc54b71979370ca7c8f42fc64a9f211ebb
F src/notify.c 976dd0f6171d4588e89e874fcc765e92914b6d30
F src/os.c 1b147e4cf7cc39e618115c14a086aed44bc91ace
F src/os.h 4a46270a64e9193af4a0aaa3bc2c66dc07c29b3f
F src/os.h 60d419395e32a8029fa380a80a3da2e9030f635e
F src/os_common.h 92815ed65f805560b66166e3583470ff94478f04
F src/os_unix.c 18f7f95dc6bcb9cf4d4a238d8e2de96611bc2ae5
F src/os_win.c c47f107fc5c9d3466c06ea4aa35822f3568e81ee
F src/pager.c 0ffa313a30ed6d061d9c6601b7b175cc50a1cab7
F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa
F src/os_unix.c ae4b5240af4619d711301d7992396e182585269f
F src/os_win.c 485d06a93965f306c7281fca0937829292367234
F src/os_win.h 057344a6720b4c8405d9bd98f58cb37a6ee46c25
F src/pager.c ab62a24218d87dda1be641f6c5ad291bff78fd94
F src/pager.h ffd5607f7b3e4590b415b007a4382f693334d428
F src/parse.y 2613ca5d609c2f3d71dd297351f010bcec16e1e0
F src/parse.y 22d6a074e5f5a7258947a1dc55a9bf946b765dd0
F src/pcache.c d8eafac28290d4bb80332005435db44991d07fc2
F src/pcache.h a5e4f5d9f5d592051d91212c5949517971ae6222
F src/pcache1.c 102e6f5a2fbc646154463eb856d1fd716867b64c
F src/pragma.c a46ee83671f5c95f53d2ceeb5e1a818d7b1df99a
F src/pragma.c 810ef31ccfaa233201dcf100637a9777cc24e897
F src/prepare.c 677521ab7132615a8a26107a1d1c3132f44ae337
F src/printf.c 85d07756e45d7496d19439dcae3e6e9e0090f269
F src/printf.c e5a0005f8b3de21f85da6a709d2fbee76775bf4b
F src/random.c d10c1f85b6709ca97278428fd5db5bbb9c74eece
F src/resolve.c ca8b99d894164435f5c55cb304c1b8121705c51e
F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0
F src/select.c 780bbf39e401091845ba745a38326eabe5d44293
F src/shell.c 7bf07bcacb181ecc3fc3ccacfdfeb4084aee67ed
F src/sqlite.h.in a2ef671f92747a5a1c8a47bad5c585a8dd9eca80
F src/resolve.c 273d5f47c4e2c05b2d3d2bffeda939551ab59e66
F src/rowset.c a9c9aae3234b44a6d7c6f5a3cadf90dce1e627be
F src/select.c 089c4d46f067a5cccae93524c6377f981ba99bd9
F src/shell.c 2afe7a7154e97be0c74c5feacf09626bda8493be
F src/sqlite.h.in bde98816e1ba0c9ffef50afe7b32f4e5a8f54fe0
F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e
F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc
F src/sqliteInt.h bf529055591dd81ec92a84d35dba0854642f6cc2
F src/sqliteInt.h b2947801eccefd7ba3e5f14e1353289351a83cf3
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
F src/tclsqlite.c e87c99e28a145943666b51b212dacae35fcea0bd
F src/test1.c 2401eee14a4309a7cfe2aeb2f30ad517a1d9c299
F src/test1.c 899bddeb0c7fb2b8062de6f03af4a4e4f48f9df5
F src/test2.c 7355101c085304b90024f2261e056cdff13c6c35
F src/test3.c 1c0e5d6f080b8e33c1ce8b3078e7013fdbcd560c
F src/test4.c 9b32d22f5f150abe23c1830e2057c4037c45b3df
F src/test5.c 41e6e732f14a54c7b47f753e364700760f6521b0
F src/test5.c 5a34feec76d9b3a86aab30fd4f6cc9c48cbab4c1
F src/test6.c 41cacf3b0dd180823919bf9e1fbab287c9266723
F src/test7.c 72b732baa5642f795655ba1126ea032af46ecfd2
F src/test8.c 54ccd7b1df5062f0ecbf50a8f7b618f8b1f13b20
@@ -238,12 +242,12 @@ F src/test9.c bea1e8cf52aa93695487badedd6e1886c321ea60
F src/test_async.c 21e11293a2f72080eda70e1124e9102044531cd8
F src/test_autoext.c dea8a01a7153b9adc97bd26161e4226329546e12
F src/test_backup.c 3875e899222b651e18b662f86e0e50daa946344e
F src/test_btree.c 5b89601dcb42a33ba8b820a6b763cc9cb48bac16
F src/test_config.c 0336e0bdbe541b4af89d7e3dd0656e8e6b51e585
F src/test_btree.c 2e9978eca99a9a4bfa8cae949efb00886860a64f
F src/test_config.c dabaa32868974e1ae39770cc17d7e066a9c38e6d
F src/test_demovfs.c 69b2085076654ebc18014cbc6386f04409c959a9
F src/test_devsym.c e7498904e72ba7491d142d5c83b476c4e76993bc
F src/test_fs.c ced436e3d4b8e4681328409b8081051ce614e28f
F src/test_func.c f8235719dff4bf9ffee04c55a190af8782ce9ab5
F src/test_func.c d3013ce36f19ac72a99c73864930fd1fa41832f8
F src/test_hexio.c abfdecb6fa58c354623978efceb088ca18e379cd
F src/test_init.c 66b33120ffe9cd853b5a905ec850d51151337b32
F src/test_intarray.c 87847c71c3c36889c0bcc9c4baf9d31881665d61
@@ -255,62 +259,62 @@ F src/test_multiplex.c 9f304bf04170c91c0318238d512df2da039eb1c8
F src/test_multiplex.h 110a8c4d356e0aa464ca8730375608a9a0b61ae1
F src/test_mutex.c 293042d623ebba969160f471a82aa1551626454f
F src/test_onefile.c 0396f220561f3b4eedc450cef26d40c593c69a25
F src/test_osinst.c 90a845c8183013d80eccb1f29e8805608516edba
F src/test_osinst.c 3d0340bc31a9f3d8a3547e0272373e80f78dde25
F src/test_pcache.c a5cd24730cb43c5b18629043314548c9169abb00
F src/test_quota.c 30c64f0ef84734f2231a686df41ed882b0c59bc0
F src/test_quota.h 8761e463b25e75ebc078bd67d70e39b9c817a0cb
F src/test_rtree.c f3d1d12538dccb75fd916e3fa58f250edbdd3b47
F src/test_quota.c 65f6348fec0f2b3020c907247fb47556b214abb9
F src/test_quota.h 2a8ad1952d1d2ca9af0ce0465e56e6c023b5e15d
F src/test_rtree.c fdd8d29ca5165c7857987a2ba263fac5c69e231f
F src/test_schema.c cd12a2223c3a394f4d07bb93bdf6d344c5c121b6
F src/test_server.c a2615049954cbb9cfb4a62e18e2f0616e4dc38fe
F src/test_sqllog.c c1c1bbedbcaf82b93d83e4f9dd990e62476a680e
F src/test_stat.c 9898687a6c2beca733b0dd6fe19163d987826d31
F src/test_superlock.c 2b97936ca127d13962c3605dbc9a4ef269c424cd
F src/test_syscall.c 16dbe79fb320fadb5acd7a0a59f49e52ab2d2091
F src/test_syscall.c 2e21ca7f7dc54a028f1967b63f1e76155c356f9b
F src/test_tclvar.c f4dc67d5f780707210d6bb0eb6016a431c04c7fa
F src/test_thread.c 1e133a40b50e9c035b00174035b846e7eef481cb
F src/test_vfs.c e72f555ef7a59080f898fcf1a233deb9eb704ea9
F src/test_vfstrace.c 3a0ab304682fecbceb689e7d9b904211fde11d78
F src/test_vfstrace.c bab9594adc976cbe696ff3970728830b4c5ed698
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
F src/tokenize.c 6da2de6e12218ccb0aea5184b56727d011f4bee7
F src/trigger.c a80036fcbd992729adc7cd34a875d59a71fa10cc
F src/trigger.c 66f3470b03b52b395e839155786966e3e037fddb
F src/update.c 5b3e74a03b3811e586b4f2b4cbd7c49f01c93115
F src/utf.c 6dc9ec9f1b3db43ae8ba0365377f11df1ee4c01c
F src/util.c c46c90459ef9bdc0c6c73803cf4c55425b4771cf
F src/util.c 2b5fb283a190aacdb286f7835a447c45b345b83c
F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179
F src/vdbe.c 75c3f5d27ab79af214646cf37d7551bc8cec09c2
F src/vdbe.h d189f92468a17a6f04daeec9df3b767f50557b21
F src/vdbeInt.h 9ccca0bc7646c918d065943e44bead4bf5de213d
F src/vdbeapi.c 5bc41aaea448a7fc250902c418f1795859be3820
F src/vdbeaux.c b3bd75b2dfe314fb411c967034314b5316342820
F src/vdbeblob.c d939997de046b8fcc607cfee4248f3d33dbcca50
F src/vdbemem.c 2d7918e4c80546d943414668b1485b2581f58a28
F src/vdbesort.c 46801acb342e5e4c07ba1777fe58880c143abb59
F src/vdbe.c 7f359193bf2366cc914a9ece093ebf284e56acdc
F src/vdbe.h 394464909ed682334aa3d5831aae0c2fe2abef94
F src/vdbeInt.h e6d83e5bfd62fc6685ba1ed6153f7099f82de9f7
F src/vdbeapi.c 0ed6053f947edd0b30f64ce5aeb811872a3450a4
F src/vdbeaux.c e493f38758c4b8f4ca2007cf6a700bd405d192f3
F src/vdbeblob.c 9205ce9d3b064d9600f8418a897fc88b5687d9ac
F src/vdbemem.c 6fc77594c60f6155404f3f8d71bf36d1fdeb4447
F src/vdbesort.c 4abb7c0f8f19b7d7d82f4558d5da1a30fdf9ea38
F src/vdbetrace.c 6f52bc0c51e144b7efdcfb2a8f771167a8816767
F src/vtab.c 21b932841e51ebd7d075e2d0ad1415dce8d2d5fd
F src/wal.c 76e7fc6de229bea8b30bb2539110f03a494dc3a8
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
F src/walker.c 11edb74d587bc87b33ca96a5173e3ec1b8389e45
F src/where.c 2269342f82ea97596564bdc981c362a5177b72c5
F src/whereInt.h 921f935af8b684ffb49705610bda7284db1db138
F src/where.c 91dfd382273c3f67fcdc0ac4728f9140f91c6ab3
F src/whereInt.h 6804c2e5010378568c2bb1350477537755296a46
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
F test/aggnested.test 45c0201e28045ad38a530b5a144b73cd4aa2cfd6
F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87
F test/all.test 6ff7b43c2b4b905c74dc4a813d201d0fa64c5783
F test/alter.test e88dfa77e020c2b48e52a8020c70171ab828e079
F test/alter.test 547dc2d292644301ac9a7dda22b319b74f9c08d2
F test/alter2.test 7ea05c7d92ac99349a802ef7ada17294dd647060
F test/alter3.test 49c9d9fba2b8fcdce2dedeca97bbf1f369cc548d
F test/alter4.test 8e93bf7a7e6919b14b0c9a6c1e4908bcf21b0165
F test/alter4.test d6c011fa0d6227abba762498cafbb607c9609e93
F test/altermalloc.test e81ac9657ed25c6c5bb09bebfa5a047cd8e4acfc
F test/amatch1.test b5ae7065f042b7f4c1c922933f4700add50cdb9f
F test/analyze.test 1772936d66471c65221e437b6d1999c3a03166c4
F test/analyze3.test 412f690dfe95b337475e3e78a84a85d25f6f125d
F test/analyze3.test bf41f0f680dd1e0d44eed5e769531e93a5320275
F test/analyze4.test eff2df19b8dd84529966420f29ea52edc6b56213
F test/analyze5.test 765c4e284aa69ca172772aa940946f55629bc8c4
F test/analyze6.test d31defa011a561b938b4608d3538c1b4e0b5e92c
F test/analyze7.test bb1409afc9e8629e414387ef048b8e0e3e0bdc4f
F test/analyze8.test 093d15c1c888eed5034304a98c992f7360130b88
F test/analyze9.test e072a5172d55afcba98d6ca6a219ce8878c2f5c9
F test/analyze9.test 623e02a99a78fa12fe5def2fd559032d5d887e0f
F test/analyzeA.test 1a5c40079894847976d983ca39c707aaa44b6944
F test/analyzeB.test 8bf35ee0a548aea831bf56762cb8e7fdb1db083d
F test/async.test 1d0e056ba1bb9729283a0f22718d3a25e82c277b
@@ -328,7 +332,7 @@ F test/auth.test 5bdf154eb28c0e4bbc0473f335858c0d96171768
F test/auth2.test c3b415b76c033bedb81292118fb7c01f5f10cbcd
F test/auth3.test a4755e6a2a2fea547ffe63c874eb569e60a28eb5
F test/autoinc.test c58912526998a39e11f66b533e23cfabea7f25b7
F test/autoindex1.test d4dfe14001dfcb74cfbd7107f45a79fc1ab6183e
F test/autoindex1.test 762ff3f8e25d852aae55c6462ca166a80c0cde61
F test/autovacuum.test 941892505d2c0f410a0cb5970dfa1c7c4e5f6e74
F test/autovacuum_ioerr2.test 8a367b224183ad801e0e24dcb7d1501f45f244b4
F test/avtrans.test 0252654f4295ddda3b2cce0e894812259e655a85
@@ -361,7 +365,7 @@ F test/btreefault.test c2bcb542685eea44621275cfedbd8a13f65201e3
F test/busy.test 76b4887f8b9160ba903c1ac22e8ff406ad6ae2f0
F test/cache.test 13bc046b26210471ca6f2889aceb1ea52dc717de
F test/capi2.test 011c16da245fdc0106a2785035de6b242c05e738
F test/capi3.test 6cdd49656bd62a296924f4d2fcfd05cd2a298369
F test/capi3.test 71bcf2fbd36a9732f617766dfd752552c8e491b5
F test/capi3b.test efb2b9cfd127efa84433cd7a2d72ce0454ae0dc4
F test/capi3c.test a21869e4d50d5dbb7e566e328fc0bc7c2efa6a32
F test/capi3d.test 6d0fc0a86d73f42dd19a7d8b7761ab9bc02277d0
@@ -402,9 +406,10 @@ F test/corruptC.test 02405cf7ed0c1e989060e1aab6d02ffbc3906fbb
F test/corruptD.test b3c205fac7952b1de645ce44bb02335cd9e3e040
F test/corruptE.test 193b4ca4e927e77c1d5f4f56203ddc998432a7ee
F test/corruptF.test be9fde98e4c93648f1ba52b74e5318edc8f59fe4
F test/corruptG.test 58ec333a01997fe655e34e5bea52b7a2a6b9704d
F test/corruptH.test 9d8186f6f8751efdfd445d8546fd98f073499039
F test/corruptI.test d9eca60cb373215d97e0994bf104f9a37e1ac0fc
F test/corruptG.test 1ab3bf97ee7bdba70e0ff3ba2320657df55d1804
F test/corruptH.test 88ed71a086e13591c917aac6de32750e7c7281cb
F test/corruptI.test b3e4203d420490fc3d3062711597bc1dea06a789
F test/cost.test 04842adec34311d70c3f3c5fd698b22be54138fd
F test/count.test 42a251178e32f617eda33f76236a7f79825a50b5
F test/coveridxscan.test cdb47d01acc4a634a34fd25abe85189e0d0f1e62
F test/crash.test fb9dc4a02dcba30d4aa5c2c226f98b220b2b959f
@@ -430,14 +435,14 @@ F test/descidx1.test 6d03b44c8538fe0eb4924e19fba10cdd8f3c9240
F test/descidx2.test 9f1a0c83fd57f8667c82310ca21b30a350888b5d
F test/descidx3.test 09ddbe3f5295f482d2f8b687cf6db8bad7acd9a2
F test/diskfull.test 106391384780753ea6896b7b4f005d10e9866b6e
F test/distinct.test c7b194ef95dbddb32d77acbbab2e023c6eed0cb2
F test/distinct.test 086e70c765f172e8974e9f83b9ac5ca03c154e77
F test/distinctagg.test 1a6ef9c87a58669438fc771450d7a72577417376
F test/e_createtable.test ee95d48664503d40f6cc9ef4a7d03216188e2ada
F test/e_createtable.test ed82efcedc4b3656b27a5fcd12335cdb7e20eeee
F test/e_delete.test d5186e2f5478b659f16a2c8b66c09892823e542a
F test/e_droptrigger.test 3cd080807622c13e5bbb61fc9a57bd7754da2412
F test/e_dropview.test 0c9f7f60989164a70a67a9d9c26d1083bc808306
F test/e_expr.test 5c71d183fbf519a4769fd2e2124afdc70b5b1f42
F test/e_fkey.test 630597377549af579d34faaf64c6959a5a68ef76
F test/e_fkey.test a1783fe1f759e1990e6a11adfcf0702dac4d0707
F test/e_fts3.test 5c02288842e4f941896fd44afdef564dd5fc1459
F test/e_insert.test 1e44f84d2abe44d66e4fbf198be4b20e3cc724a0
F test/e_reindex.test 396b7b4f0a66863b4e95116a67d93b227193e589
@@ -451,7 +456,7 @@ F test/enc.test e54531cd6bf941ee6760be041dff19a104c7acea
F test/enc2.test 83437a79ba1545a55fb549309175c683fb334473
F test/enc3.test 90683ad0e6ea587b9d5542ca93568af9a9858c40
F test/enc4.test c8f1ce3618508fd0909945beb8b8831feef2c020
F test/eqp.test 57c6c604c2807fb5531731c5323133453c24afac
F test/eqp.test 90b56d03a93a2e7bb90f88be6083a8ea53f11a0e
F test/errmsg.test f31592a594b44ee121371d25ddd5d63497bb3401
F test/eval.test bc269c365ba877554948441e91ad5373f9f91be3
F test/exclusive.test c7ebbc756eacf544c108b15eed64d7d4e5f86b75
@@ -522,7 +527,7 @@ F test/fts3ak.test bd14deafe9d1586e8e9bf032411026ac4f8c925d
F test/fts3al.test 07d64326e79bbdbab20ee87fc3328fbf01641c9f
F test/fts3am.test 218aa6ba0dfc50c7c16b2022aac5c6be593d08d8
F test/fts3an.test a49ccadc07a2f7d646ec1b81bc09da2d85a85b18
F test/fts3ao.test 71b0675e3df5c512a5a03daaa95ee1916de23dda
F test/fts3ao.test 3e4e3d5e75c076520341d0bdf4eb17c00e8cbde2
F test/fts3atoken.test fca30fd86db9241d571c637751e9a8a2f50f1451
F test/fts3auto.test b981fea19b132b4e6878f50d7c1f369b28f68eb9
F test/fts3aux1.test f8f287a4a73f381f8fa15b6a70f36245f903d221
@@ -534,7 +539,7 @@ F test/fts3conf.test ee8500c86dd58ec075e8831a1e216a79989436de
F test/fts3corrupt.test 2710b77983cc7789295ddbffea52c1d3b7506dbb
F test/fts3corrupt2.test 6d96efae2f8a6af3eeaf283aba437e6d0e5447ba
F test/fts3cov.test e0fb00d8b715ddae4a94c305992dfc3ef70353d7
F test/fts3d.test c8a193513a269ec4c205ca09645e26e0bc71b860
F test/fts3d.test 597b0b76e41f0d672e2731c4d7b631d628efd13f
F test/fts3defer.test 0be4440b73a2e651fc1e472066686d6ada4b9963
F test/fts3defer2.test a3b6cbeabaf28c9398652a4d101ea224d9358479
F test/fts3defer3.test dd53fc13223c6d8264a98244e9b19abd35ed71cd
@@ -573,13 +578,13 @@ F test/fts4merge4.test c19c85ca1faa7b6d536832b49c12e1867235f584
F test/fts4noti.test aed33ba44808852dcb24bf70fa132e7bf530f057
F test/fts4unicode.test 01ec3fe2a7c3cfff3b4c0581b83caa11b33efa36
F test/full.test 6b3c8fb43c6beab6b95438c1675374b95fab245d
F test/func.test 00667bbeac044d007f6f021af1b9f6150f0c7ff8
F test/func.test c2cbfc23d554c5bf8678d0fb271aa4f8ef94839c
F test/func2.test 772d66227e4e6684b86053302e2d74a2500e1e0f
F test/func3.test dbccee9133cfef1473c59ec07b5f0262b9d72f9a
F test/func4.test 6beacdfcb0e18c358e6c2dcacf1b65d1fa80955f
F test/func5.test cdd224400bc3e48d891827cc913a57051a426fa4
F test/fuzz-oss1.test 4912e528ec9cf2f42134456933659d371c9e0d74
F test/fuzz.test 77fd50afc12847af50fcf1941679d90adebadde6
F test/fuzz.test 96083052bf5765e4518c1ba686ce2bab785670d1
F test/fuzz2.test 207d0f9d06db3eaf47a6b7bfc835b8e2fc397167
F test/fuzz3.test efd384b896c647b61a2c1848ba70d42aad60a7b3
F test/fuzz_common.tcl a87dfbb88c2a6b08a38e9a070dabd129e617b45b
@@ -592,7 +597,7 @@ F test/icu.test 70df4faca133254c042d02ae342c0a141f2663f4
F test/in.test 047c4671328e9032ab95666a67021adbbd36e98e
F test/in2.test 5d4c61d17493c832f7d2d32bef785119e87bde75
F test/in3.test 3cbf58c87f4052cee3a58b37b6389777505aa0c0
F test/in4.test 64f3cc1acde1b9161ccdd8e5bde3daefdb5b2617
F test/in4.test 41c1c031aa46b1eb4411df2687ed2ed498da23b5
F test/in5.test 99f9a40af01711b06d2d614ecfe96129f334fba3
F test/incrblob.test e81846d214f3637622620fbde7cd526781cfe328
F test/incrblob2.test bf4d549aa4a466d7fbe3e3a3693d3861263d5600
@@ -609,7 +614,7 @@ F test/index2.test ee83c6b5e3173a3d7137140d945d9a5d4fdfb9d6
F test/index3.test 55a90cff99834305e8141df7afaef39674b57062
F test/index4.test ab92e736d5946840236cd61ac3191f91a7856bf6
F test/index5.test fc07c14193c0430814e7a08b5da46888ee795c33
F test/index6.test 936979c3a1e87b81feaed2d00505665bf142d764
F test/index6.test fb370966ac3cd0989053dd5385757b5c3e24ab6a
F test/index7.test a3baf9a625bda7fd49471e99aeae04095fbfeecf
F test/indexedby.test b2f22f3e693a53813aa3f50b812eb609ba6df1ec
F test/indexfault.test 31d4ab9a7d2f6e9616933eb079722362a883eb1d
@@ -630,7 +635,7 @@ F test/ioerr3.test d3cec5e1a11ad6d27527d0d38573fbff14c71bdd
F test/ioerr4.test f130fe9e71008577b342b8874d52984bd04ede2c
F test/ioerr5.test 2edfa4fb0f896f733071303b42224df8bedd9da4
F test/ioerr6.test a395a6ab144b26a9e3e21059a1ab6a7149cca65b
F test/join.test 8d63cc4d230a7affafa4b6ab0b97c49b8ccb365c
F test/join.test 559b81eb56ae350246f9c25986aa52c81c725c7e
F test/join2.test f2171c265e57ee298a27e57e7051d22962f9f324
F test/join3.test 6f0c774ff1ba0489e6c88a3e77b9d3528fb4fda0
F test/join4.test 1a352e4e267114444c29266ce79e941af5885916
@@ -647,7 +652,7 @@ F test/lastinsert.test 42e948fd6442f07d60acbd15d33fb86473e0ef63
F test/laststmtchanges.test ae613f53819206b3222771828d024154d51db200
F test/like.test e191e536d0fcd722a6b965e7cd1ee0bfd12a5991
F test/like2.test 3b2ee13149ba4a8a60b59756f4e5d345573852da
F test/limit.test cc0ab63385239b63c72452b0e93700bf5e8f0b99
F test/limit.test 3d7df19c35ac672a11f7de406cd3205d592babbb
F test/loadext.test 648cb95f324d1775c54a55c12271b2d1156b633b
F test/loadext2.test 0408380b57adca04004247179837a18e866a74f7
F test/lock.test 87af515b0c4cf928576d0f89946d67d7c265dfb4
@@ -721,7 +726,9 @@ F test/orderby1.test 9b524aff9147288da43a6d7ddfdcff47fa2303c6
F test/orderby2.test bc11009f7cd99d96b1b11e57b199b00633eb5b04
F test/orderby3.test 8619d06a3debdcd80a27c0fdea5c40b468854b99
F test/orderby4.test 4d39bfbaaa3ae64d026ca2ff166353d2edca4ba4
F test/orderby5.test 0eb82d5890c3f3d0563966560cfdc984ea69e30c
F test/orderby5.test 8f08a54836d21fb7c70245360751aedd1c2286fb
F test/orderby6.test 8b38138ab0972588240b3fca0985d2e400432859
F test/orderby7.test 3d1383d52ade5b9eb3a173b3147fdd296f0202da
F test/oserror.test 50417780d0e0d7cd23cf12a8277bb44024765df3
F test/pager1.test 1acbdb14c5952a72dd43129cabdbf69aaa3ed1fa
F test/pager2.test 67b8f40ae98112bcdba1f2b2d03ea83266418c71
@@ -784,7 +791,7 @@ F test/select6.test e76bd10a56988f15726c097a5d5a7966fe82d3b2
F test/select7.test 7fd2ef598cfabb6b9ff6ac13973b91d0527df49d
F test/select8.test 391de11bdd52339c30580dabbbbe97e3e9a3c79d
F test/select9.test aebc2bb0c3bc44606125033cbcaac2c8d1f33a95
F test/selectA.test 77adaffe9704cb80e301ebaeff4b107b58d435c5
F test/selectA.test 64b88a80271c1710966e50e633380696b60a12a4
F test/selectB.test 954e4e49cf1f896d61794e440669e03a27ceea25
F test/selectC.test 871fb55d884d3de5943c4057ebd22c2459e71977
F test/selectD.test b0f02a04ef7737decb24e08be2c39b9664b43394
@@ -808,10 +815,11 @@ F test/shell3.test 5e8545ec72c4413a0e8d4c6be56496e3c257ca29
F test/shell4.test aa4eef8118b412d1a01477a53426ece169ea86a9
F test/shell5.test bb755ea9144b8078a752fc56223582627070b5f1
F test/shortread1.test bb591ef20f0fd9ed26d0d12e80eee6d7ac8897a3
F test/show_speedtest1_rtree.tcl 32e6c5f073d7426148a6936a0408f4b5b169aba5
F test/shrink.test 8c70f62b6e8eb4d54533de6d65bd06b1b9a17868
F test/sidedelete.test f0ad71abe6233e3b153100f3b8d679b19a488329
F test/skipscan1.test 8c777ffd9dad6ee6d2568160cb2158f0b5cd9dd2
F test/skipscan2.test 5a4db0799c338ddbacb154aaa5589c0254b36a8d
F test/skipscan1.test bed8cbe9d554c8c27afb6c88500f704c86a9196f
F test/skipscan2.test d77f79cdbba25f0f6f35298136cff21a7d7a553a
F test/soak.test 0b5b6375c9f4110c828070b826b3b4b0bb65cd5f
F test/softheap1.test 40562fe6cac6d9827b7b42b86d45aedf12c15e24
F test/sort.test 0e4456e729e5a92a625907c63dcdedfbe72c5dc5
@@ -823,7 +831,7 @@ F test/speed3.test d32043614c08c53eafdc80f33191d5bd9b920523
F test/speed4.test abc0ad3399dcf9703abed2fff8705e4f8e416715
F test/speed4p.explain 6b5f104ebeb34a038b2f714150f51d01143e59aa
F test/speed4p.test 0e51908951677de5a969b723e03a27a1c45db38b
F test/speedtest1.c 1603da7b4897716f9df15bd71b0310f56ec3181e
F test/speedtest1.c d29c8048beb7ea9254191f3fde9414709166a920
F test/spellfix.test 61309f5efbec53603b3f86457d34a504f80abafe
F test/sqllimits1.test b1aae27cc98eceb845e7f7adf918561256e31298
F test/stat.test 76fd746b85459e812a0193410fb599f0531f22de
@@ -834,7 +842,7 @@ F test/subselect.test d24fd8757daf97dafd2e889c73ea4c4272dcf4e4
F test/substr.test 18f57c4ca8a598805c4d64e304c418734d843c1a
F test/superlock.test 1cde669f68d2dd37d6c9bd35eee1d95491ae3fc2
F test/sync.test a34cd43e98b7fb84eabbf38f7ed8f7349b3f3d85
F test/syscall.test a653783d985108c4912cc64d341ffbbb55ad2806
F test/syscall.test d2fdaad713f103ac611fe7ef9b724c7b69f8149c
F test/sysfault.test fa776e60bf46bdd3ae69f0b73e46ee3977a58ae6
F test/table.test 580d23530187026d4502fae74a490f0408cf2cc7
F test/tableapi.test 2674633fa95d80da917571ebdd759a14d9819126
@@ -870,6 +878,7 @@ F test/tkt-3fe897352e.test 27e26eb0f1811aeba4d65aba43a4c52e99da5e70
F test/tkt-4a03edc4c8.test 91c0e135888cdc3d4eea82406a44b05c8c1648d0
F test/tkt-4c86b126f2.test cbcc611becd0396890169ab23102dd70048bbc9a
F test/tkt-4dd95f6943.test 3d0ce415d2ee15d3d564121960016b9c7be79407
F test/tkt-4ef7e3cfca.test 3965ae11cc9cf6e334f9d7d3c1e20bf8d56254b1
F test/tkt-54844eea3f.test a12b851128f46a695e4e378cca67409b9b8f5894
F test/tkt-5d863f876e.test c9f36ca503fa154a3655f92a69d2c30da1747bfa
F test/tkt-5e10420e8d.test 904d1687b3c06d43e5b3555bbcf6802e7c0ffd84
@@ -889,9 +898,11 @@ F test/tkt-94c04eaadb.test f738c57c7f68ab8be1c054415af7774617cb6223
F test/tkt-9d68c883.test 458f7d82a523d7644b54b497c986378a7d8c8b67
F test/tkt-9f2eb3abac.test 85bc63e749f050e6a61c8f9207f1eee65c9d3395
F test/tkt-a7b7803e.test 159ef554234fa1f9fb318c751b284bd1cf858da4
F test/tkt-a8a0d2996a.test eb597379dbcefa24765763d7f682c00cb5924fa9
F test/tkt-b1d3a2e531.test 8f7576e41ca179289ee1a8fee28386fd8e4b0550
F test/tkt-b351d95f9.test d14a503c414c5c58fdde3e80f9a3cfef986498c0
F test/tkt-b72787b1.test a95e8cdad0b98af1853ac7f0afd4ab27b77bf5f3
F test/tkt-b75a9ca6b0.test 97cc2d5eeaf82799eb42138c0a1ff64370238ce4
F test/tkt-bd484a090c.test 60460bf946f79a79712b71f202eda501ca99b898
F test/tkt-bdc6bbbb38.test fc38bb09bdd440e3513a1f5f98fc60a075182d7d
F test/tkt-c48d99d690.test ba61977d62ab612fc515b3c488a6fbd6464a2447
@@ -900,6 +911,7 @@ F test/tkt-d11f09d36e.test d999b548fef885d1d1afa49a0e8544ecf436869d
F test/tkt-d635236375.test 9d37e988b47d87505bc9445be0ca447002df5d09
F test/tkt-d82e3f3721.test bcc0dfba658d15bab30fd4a9320c9e35d214ce30
F test/tkt-f3e5abed55.test d5a0126118142d13e27f6ce9f4c47096e9321c00
F test/tkt-f67b41381a.test a23bc124c981662db712167bacd0ed8ad11abac9
F test/tkt-f777251dc7a.test af6531446c64bfd268416f07b4df7be7f9c749d2
F test/tkt-f7b4edec.test d998a08ff2b18b7f62edce8e3044317c45efe6c7
F test/tkt-f973c7ac31.test 28ef85c7f015477916795246d8286aeda39d4ead
@@ -1017,9 +1029,9 @@ F test/types2.test 3555aacf8ed8dc883356e59efc314707e6247a84
F test/types3.test 99e009491a54f4dc02c06bdbc0c5eea56ae3e25a
F test/unique.test 93f8b2ef5ea51b9495f8d6493429b1fd0f465264
F test/unixexcl.test cd6c765f75e50e8e2c2ba763149e5d340ea19825
F test/unordered.test ef85ac8f2f3c93ed2b9e811b684de73175fc464c
F test/unordered.test ca7adce0419e4ca0c50f039885e76ed2c531eda8
F test/update.test 1b6c488a8f993d090b7ee9ad0e234faa161b3aeb
F test/uri.test 63e03df051620a18f794b4f4adcdefb3c23b6751
F test/uri.test 23662b7b61958b0f0e47082de7d06341ccf85d5b
F test/utf16align.test 54cd35a27c005a9b6e7815d887718780b6a462ae
F test/vacuum.test ce91c39f7f91a4273bf620efad21086b5aa6ef1d
F test/vacuum2.test af432e6e3bfc0ea20a80cb86a03c7d9876d38324
@@ -1027,7 +1039,7 @@ F test/vacuum3.test 77ecdd54592b45a0bcb133339f99f1ae0ae94d0d
F test/vacuum4.test d3f8ecff345f166911568f397d2432c16d2867d9
F test/varint.test ab7b110089a08b9926ed7390e7e97bdefeb74102
F test/veryquick.test 57ab846bacf7b90cf4e9a672721ea5c5b669b661
F test/view.test 4057630287bfa5955628fe90a13d4c225d1c7352
F test/view.test f311691d696a5cc27e3c1b875cec1b0866b4ccd9
F test/vtab1.test b631d147b198cfd7903ab5fed028eb2a3d321dc6
F test/vtab2.test 7bcffc050da5c68f4f312e49e443063e2d391c0d
F test/vtab3.test baad99fd27217f5d6db10660522e0b7192446de1
@@ -1045,13 +1057,14 @@ F test/vtabE.test 7c4693638d7797ce2eda17af74292b97e705cc61
F test/vtabF.test fd5ad376f5a34fe0891df1f3cddb4fe7c3eb077e
F test/vtab_alter.test 9e374885248f69e251bdaacf480b04a197f125e5
F test/vtab_err.test 0d4d8eb4def1d053ac7c5050df3024fd47a3fbd8
F test/vtab_shared.test 6acafaae7126c9f49be72c2f57eb8bef3024f1cb
F test/wal.test 40073e54359d43354925b2b700b7eebd5e207285
F test/wal2.test a8e3963abf6b232cf0b852b09b53665ef34007af
F test/vtab_shared.test ea8778d5b0df200adef2ca7c00c3c37d4375f772
F test/wal.test 885f32b2b390b30b4aa3dbb0e568f8f78d40f5cc
F test/wal2.test 1f841d2048080d32f552942e333fd99ce541dada
F test/wal3.test b22eb662bcbc148c5f6d956eaf94b047f7afe9c0
F test/wal4.test 4744e155cd6299c6bd99d3eab1c82f77db9cdb3c
F test/wal5.test 8f888b50f66b78821e61ed0e233ded5de378224b
F test/wal6.test 527581f5527bf9c24394991e2be83000aace5f9e
F test/wal64k.test 163655ecd2cb8afef4737cac2a40fdd2eeaf20b8
F test/wal7.test 2ae8f427d240099cc4b2dfef63cff44e2a68a1bd
F test/wal8.test 75c42e1bc4545c277fed212f8fc9b7723cd02216
F test/wal9.test 378e76a9ad09cd9bee06c172ad3547b0129a6750
@@ -1073,7 +1086,7 @@ F test/walslow.test e7be6d9888f83aa5d3d3c7c08aa9b5c28b93609a
F test/walthread.test de8dbaf6d9e41481c460ba31ca61e163d7348f8e
F test/where.test 28b64e93428961b07b0d486778d63fd672948f6b
F test/where2.test 455a2eb2666e66c1e84e2cb5815173a85e6237db
F test/where3.test d28c51f257e60be30f74308fa385ceeddfb54a6e
F test/where3.test 1ad55ba900bd7747f98b6082e65bd3e442c5004e
F test/where4.test d8420ceeb8323a41ceff1f1841fc528e824e1ecf
F test/where5.test fdf66f96d29a064b63eb543e28da4dfdccd81ad2
F test/where6.test 5da5a98cec820d488e82708301b96cb8c18a258b
@@ -1084,17 +1097,18 @@ F test/where9.test 4f3eab951353a3ae164befc521c777dfa903e46c
F test/whereA.test 4d253178d135ec46d1671e440cd8f2b916aa6e6b
F test/whereB.test 0def95db3bdec220a731c7e4bec5930327c1d8c5
F test/whereC.test d6f4ecd4fa2d9429681a5b22a25d2bda8e86ab8a
F test/whereD.test 6c2feb79ef1f68381b07f39017fe5f9b96da8d62
F test/whereD.test fd9120e262f9da3c45940f52aefeef4d15b904e5
F test/whereE.test b3a055eef928c992b0a33198a7b8dc10eea5ad2f
F test/whereF.test 5b2ba0dbe8074aa13e416b37c753991f0a2492d7
F test/whereG.test 2a3d5181decc801b36600fa1c40b0dad2ccc267f
F test/whereG.test 0ac23e5e8311b69d87245f4a85112de321031658
F test/whereH.test e4b07f7a3c2f5d31195cd33710054c78667573b2
F test/wherelimit.test 5e9fd41e79bb2b2d588ed999d641d9c965619b31
F test/wild001.test bca33f499866f04c24510d74baf1e578d4e44b1c
F test/win32heap.test ea19770974795cff26e11575e12d422dbd16893c
F test/win32lock.test 7a6bd73a5dcdee39b5bb93e92395e1773a194361
F test/win32longpath.test 169c75a3b2e43481f4a62122510210c67b08f26d
F test/with1.test 268081a6b14817a262ced4d0ee34d4d2a1dd2068
F test/with2.test 2fe78fcd8deef2a0f9cfc49bfc755911d0b3fd64
F test/with2.test ee227a663586aa09771cafd4fa269c5217eaf775
F test/withM.test e97f2a8c506ab3ea9eab94e6f6072f6cc924c991
F test/without_rowid1.test e00a0a9dc9f0be651f011d61e8a32b7add5afb30
F test/without_rowid2.test af260339f79d13cb220288b67cd287fbcf81ad99
@@ -1116,16 +1130,16 @@ F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5
F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce
F tool/lemon.c 07aba6270d5a5016ba8107b09e431eea4ecdc123
F tool/lempar.c 01ca97f87610d1dac6d8cd96ab109ab1130e76dc
F tool/logest.c 7ad625cac3d54012b27d468b7af6612f78b9ba75
F tool/logest.c eef612f8adf4d0993dafed0416064cf50d5d33c6
F tool/mkautoconfamal.sh f8d8dbf7d62f409ebed5134998bf5b51d7266383
F tool/mkkeywordhash.c c9e05e4a7bcab8fab9f583d5b321fb72f565ad97
F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e
F tool/mkpragmatab.tcl 78a77b2c554d534c6f2dc903130186ed15715460
F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97
F tool/mksqlite3c-noext.tcl 8bce31074e4cbe631bb7676526a048335f4c9f02
F tool/mksqlite3c.tcl ed5b4e9ca8bf209ff401059a16362f37710fd8b8
F tool/mksqlite3c-noext.tcl 1712d3d71256ca1f297046619c89e77a4d7c8f6d
F tool/mksqlite3c.tcl ba274df71f5e6534b0a913c7c48eabfcbd0934b6
F tool/mksqlite3h.tcl ba24038056f51fde07c0079c41885ab85e2cff12
F tool/mksqlite3internalh.tcl 3dca7bb5374cee003379b8cbac73714f610ef795
F tool/mksqlite3internalh.tcl b6514145a7d5321b47e64e19b8116cc44f973eb1
F tool/mkvsix.tcl 6477fb9dab838b7eea1eed50658ff1cda04850b5
F tool/offsets.c fe4262fdfa378e8f5499a42136d17bf3b98f6091
F tool/omittest.tcl 34d7ac01fe4fd18e3637f64abe12c40eca0f6b97
@@ -1154,7 +1168,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01
F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff
P 979da752e6f8767a61a8efed824ffad9605d0f4c
R 76afae803c9615945e7c1ed11c396a45
P 857f2baf9b722e4eb1ac0d50fe03e32d5176185b
R 13f47e22fa817432bd25922bb1ff1b2f
U drh
Z 4679453e8217252329a19e88ce1ddc0d
Z 55108ca91e730f32aa309dbf16d83499
+1 -1
View File
@@ -1 +1 @@
f10130ede433a19b3945753f23962871c8d2dcf3
3ac75725a66730566105ad184a988a8f80f51055
+1
View File
@@ -116,6 +116,7 @@ static void renameParentFunc(
int token; /* Type of token */
UNUSED_PARAMETER(NotUsed);
if( zInput==0 || zOld==0 ) return;
for(z=zInput; *z; z=z+n){
n = sqlite3GetToken(z, &token);
if( token==TK_REFERENCES ){
+23 -9
View File
@@ -1178,7 +1178,10 @@ static void analyzeOneTable(
callStatGet(v, regStat4, STAT_GET_NLT, regLt);
callStatGet(v, regStat4, STAT_GET_NDLT, regDLt);
sqlite3VdbeAddOp4Int(v, seekOp, iTabCur, addrNext, regSampleRowid, 0);
VdbeCoverage(v);
/* We know that the regSampleRowid row exists because it was read by
** the previous loop. Thus the not-found jump of seekOp will never
** be taken */
VdbeCoverageNeverTaken(v);
#ifdef SQLITE_ENABLE_STAT3
sqlite3ExprCodeGetColumnOfTable(v, pTab, iTabCur,
pIdx->aiColumn[0], regSample);
@@ -1192,7 +1195,7 @@ static void analyzeOneTable(
sqlite3VdbeAddOp3(v, OP_MakeRecord, regTabname, 6, regTemp);
sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur+1, regNewRowid);
sqlite3VdbeAddOp3(v, OP_Insert, iStatCur+1, regTemp, regNewRowid);
sqlite3VdbeAddOp2(v, OP_Goto, 0, addrNext);
sqlite3VdbeAddOp2(v, OP_Goto, 1, addrNext); /* P1==1 for end-of-loop */
sqlite3VdbeJumpHere(v, addrIsNull);
}
#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */
@@ -1368,6 +1371,7 @@ static void decodeIntArray(
char *zIntArray, /* String containing int array to decode */
int nOut, /* Number of slots in aOut[] */
tRowcnt *aOut, /* Store integers here */
LogEst *aLog, /* Or, if aOut==0, here */
Index *pIndex /* Handle extra flags for this index, if not NULL */
){
char *z = zIntArray;
@@ -1386,7 +1390,17 @@ static void decodeIntArray(
v = v*10 + c - '0';
z++;
}
aOut[i] = v;
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
if( aOut ){
aOut[i] = v;
}else
#else
assert( aOut==0 );
UNUSED_PARAMETER(aOut);
#endif
{
aLog[i] = sqlite3LogEst(v);
}
if( *z==' ' ) z++;
}
#ifndef SQLITE_ENABLE_STAT3_OR_STAT4
@@ -1442,12 +1456,12 @@ static int analysisLoader(void *pData, int argc, char **argv, char **NotUsed){
z = argv[2];
if( pIndex ){
decodeIntArray((char*)z, pIndex->nKeyCol+1, pIndex->aiRowEst, pIndex);
if( pIndex->pPartIdxWhere==0 ) pTable->nRowEst = pIndex->aiRowEst[0];
decodeIntArray((char*)z, pIndex->nKeyCol+1, 0, pIndex->aiRowLogEst, pIndex);
if( pIndex->pPartIdxWhere==0 ) pTable->nRowLogEst = pIndex->aiRowLogEst[0];
}else{
Index fakeIdx;
fakeIdx.szIdxRow = pTable->szTabRow;
decodeIntArray((char*)z, 1, &pTable->nRowEst, &fakeIdx);
decodeIntArray((char*)z, 1, 0, &pTable->nRowLogEst, &fakeIdx);
pTable->szTabRow = fakeIdx.szIdxRow;
}
@@ -1639,9 +1653,9 @@ static int loadStatTbl(
pPrevIdx = pIdx;
}
pSample = &pIdx->aSample[pIdx->nSample];
decodeIntArray((char*)sqlite3_column_text(pStmt,1), nCol, pSample->anEq, 0);
decodeIntArray((char*)sqlite3_column_text(pStmt,2), nCol, pSample->anLt, 0);
decodeIntArray((char*)sqlite3_column_text(pStmt,3), nCol, pSample->anDLt,0);
decodeIntArray((char*)sqlite3_column_text(pStmt,1),nCol,pSample->anEq,0,0);
decodeIntArray((char*)sqlite3_column_text(pStmt,2),nCol,pSample->anLt,0,0);
decodeIntArray((char*)sqlite3_column_text(pStmt,3),nCol,pSample->anDLt,0,0);
/* Take a copy of the sample. Add two 0x00 bytes the end of the buffer.
** This is in case the sample record is corrupted. In that case, the
+137 -96
View File
@@ -446,16 +446,11 @@ static int cursorHoldsMutex(BtCursor *p){
}
#endif
#ifndef SQLITE_OMIT_INCRBLOB
/*
** Invalidate the overflow page-list cache for cursor pCur, if any.
** Invalidate the overflow cache of the cursor passed as the first argument.
** on the shared btree structure pBt.
*/
static void invalidateOverflowCache(BtCursor *pCur){
assert( cursorHoldsMutex(pCur) );
sqlite3_free(pCur->aOverflow);
pCur->aOverflow = 0;
}
#define invalidateOverflowCache(pCur) (pCur->curFlags &= ~BTCF_ValidOvfl)
/*
** Invalidate the overflow page-list cache for all cursors opened
@@ -469,6 +464,7 @@ static void invalidateAllOverflowCache(BtShared *pBt){
}
}
#ifndef SQLITE_OMIT_INCRBLOB
/*
** This function is called before modifying the contents of a table
** to invalidate any incrblob cursors that are open on the
@@ -491,16 +487,14 @@ static void invalidateIncrblobCursors(
BtShared *pBt = pBtree->pBt;
assert( sqlite3BtreeHoldsMutex(pBtree) );
for(p=pBt->pCursor; p; p=p->pNext){
if( p->isIncrblobHandle && (isClearTable || p->info.nKey==iRow) ){
if( (p->curFlags & BTCF_Incrblob)!=0 && (isClearTable || p->info.nKey==iRow) ){
p->eState = CURSOR_INVALID;
}
}
}
#else
/* Stub functions when INCRBLOB is omitted */
#define invalidateOverflowCache(x)
#define invalidateAllOverflowCache(x)
/* Stub function when INCRBLOB is omitted */
#define invalidateIncrblobCursors(x,y,z)
#endif /* SQLITE_OMIT_INCRBLOB */
@@ -746,20 +740,32 @@ static int btreeRestoreCursorPosition(BtCursor *pCur){
** at is deleted out from under them.
**
** This routine returns an error code if something goes wrong. The
** integer *pHasMoved is set to one if the cursor has moved and 0 if not.
** integer *pHasMoved is set as follows:
**
** 0: The cursor is unchanged
** 1: The cursor is still pointing at the same row, but the pointers
** returned by sqlite3BtreeKeyFetch() or sqlite3BtreeDataFetch()
** might now be invalid because of a balance() or other change to the
** b-tree.
** 2: The cursor is no longer pointing to the row. The row might have
** been deleted out from under the cursor.
*/
int sqlite3BtreeCursorHasMoved(BtCursor *pCur, int *pHasMoved){
int rc;
if( pCur->eState==CURSOR_VALID ){
*pHasMoved = 0;
return SQLITE_OK;
}
rc = restoreCursorPosition(pCur);
if( rc ){
*pHasMoved = 1;
*pHasMoved = 2;
return rc;
}
if( pCur->eState!=CURSOR_VALID || NEVER(pCur->skipNext!=0) ){
*pHasMoved = 1;
*pHasMoved = 2;
}else{
*pHasMoved = 0;
*pHasMoved = 1;
}
return SQLITE_OK;
}
@@ -2161,6 +2167,7 @@ int sqlite3BtreeSetCacheSize(Btree *p, int mxPage){
return SQLITE_OK;
}
#if SQLITE_MAX_MMAP_SIZE>0
/*
** Change the limit on the amount of the database file that may be
** memory mapped.
@@ -2173,6 +2180,7 @@ int sqlite3BtreeSetMmapLimit(Btree *p, sqlite3_int64 szMmap){
sqlite3BtreeLeave(p);
return SQLITE_OK;
}
#endif /* SQLITE_MAX_MMAP_SIZE>0 */
/*
** Change the way data is synced to disk in order to increase or decrease
@@ -2549,7 +2557,8 @@ static int countValidCursors(BtShared *pBt, int wrOnly){
BtCursor *pCur;
int r = 0;
for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){
if( (wrOnly==0 || pCur->wrFlag) && pCur->eState!=CURSOR_FAULT ) r++;
if( (wrOnly==0 || (pCur->curFlags & BTCF_WriteFlag)!=0)
&& pCur->eState!=CURSOR_FAULT ) r++;
}
return r;
}
@@ -3624,7 +3633,8 @@ static int btreeCursor(
pCur->pKeyInfo = pKeyInfo;
pCur->pBtree = p;
pCur->pBt = pBt;
pCur->wrFlag = (u8)wrFlag;
assert( wrFlag==0 || wrFlag==BTCF_WriteFlag );
pCur->curFlags = wrFlag;
pCur->pNext = pBt->pCursor;
if( pCur->pNext ){
pCur->pNext->pPrev = pCur;
@@ -3694,7 +3704,7 @@ int sqlite3BtreeCloseCursor(BtCursor *pCur){
releasePage(pCur->apPage[i]);
}
unlockBtreeIfUnused(pBt);
invalidateOverflowCache(pCur);
sqlite3DbFree(pBtree->db, pCur->aOverflow);
/* sqlite3_free(pCur); */
sqlite3BtreeLeave(pBtree);
}
@@ -3733,7 +3743,7 @@ int sqlite3BtreeCloseCursor(BtCursor *pCur){
if( pCur->info.nSize==0 ){
int iPage = pCur->iPage;
btreeParseCell(pCur->apPage[iPage],pCur->aiIdx[iPage],&pCur->info);
pCur->validNKey = 1;
pCur->curFlags |= BTCF_ValidNKey;
}else{
assertCellInfo(pCur);
}
@@ -3743,8 +3753,8 @@ int sqlite3BtreeCloseCursor(BtCursor *pCur){
#define getCellInfo(pCur) \
if( pCur->info.nSize==0 ){ \
int iPage = pCur->iPage; \
btreeParseCell(pCur->apPage[iPage],pCur->aiIdx[iPage],&pCur->info); \
pCur->validNKey = 1; \
btreeParseCell(pCur->apPage[iPage],pCur->aiIdx[iPage],&pCur->info); \
pCur->curFlags |= BTCF_ValidNKey; \
}else{ \
assertCellInfo(pCur); \
}
@@ -3915,10 +3925,12 @@ static int copyPayload(
/*
** This function is used to read or overwrite payload information
** for the entry that the pCur cursor is pointing to. If the eOp
** parameter is 0, this is a read operation (data copied into
** buffer pBuf). If it is non-zero, a write (data copied from
** buffer pBuf).
** for the entry that the pCur cursor is pointing to. The eOp
** argument is interpreted as follows:
**
** 0: The operation is a read. Populate the overflow cache.
** 1: The operation is a write. Populate the overflow cache.
** 2: The operation is a read. Do not populate the overflow cache.
**
** A total of "amt" bytes are read or written beginning at "offset".
** Data is read to or from the buffer pBuf.
@@ -3926,11 +3938,11 @@ static int copyPayload(
** The content being read or written might appear on the main page
** or be scattered out on multiple overflow pages.
**
** If the BtCursor.isIncrblobHandle flag is set, and the current
** cursor entry uses one or more overflow pages, this function
** allocates space for and lazily popluates the overflow page-list
** cache array (BtCursor.aOverflow). Subsequent calls use this
** cache to make seeking to the supplied offset more efficient.
** If the current cursor entry uses one or more overflow pages and the
** eOp argument is not 2, this function may allocate space for and lazily
** popluates the overflow page-list cache array (BtCursor.aOverflow).
** Subsequent calls use this cache to make seeking to the supplied offset
** more efficient.
**
** Once an overflow page-list cache has been allocated, it may be
** invalidated if some other cursor writes to the same table, or if
@@ -3954,15 +3966,22 @@ static int accessPayload(
int iIdx = 0;
MemPage *pPage = pCur->apPage[pCur->iPage]; /* Btree page of current entry */
BtShared *pBt = pCur->pBt; /* Btree this cursor belongs to */
#ifdef SQLITE_DIRECT_OVERFLOW_READ
int bEnd; /* True if reading to end of data */
#endif
assert( pPage );
assert( pCur->eState==CURSOR_VALID );
assert( pCur->aiIdx[pCur->iPage]<pPage->nCell );
assert( cursorHoldsMutex(pCur) );
assert( eOp!=2 || offset==0 ); /* Always start from beginning for eOp==2 */
getCellInfo(pCur);
aPayload = pCur->info.pCell + pCur->info.nHeader;
nKey = (pPage->intKey ? 0 : (int)pCur->info.nKey);
#ifdef SQLITE_DIRECT_OVERFLOW_READ
bEnd = (offset+amt==nKey+pCur->info.nData);
#endif
if( NEVER(offset+amt > nKey+pCur->info.nData)
|| &aPayload[pCur->info.nLocal] > &pPage->aData[pBt->usableSize]
@@ -3977,7 +3996,7 @@ static int accessPayload(
if( a+offset>pCur->info.nLocal ){
a = pCur->info.nLocal - offset;
}
rc = copyPayload(&aPayload[offset], pBuf, a, eOp, pPage->pDbPage);
rc = copyPayload(&aPayload[offset], pBuf, a, (eOp & 0x01), pPage->pDbPage);
offset = 0;
pBuf += a;
amt -= a;
@@ -3991,21 +4010,30 @@ static int accessPayload(
nextPage = get4byte(&aPayload[pCur->info.nLocal]);
#ifndef SQLITE_OMIT_INCRBLOB
/* If the isIncrblobHandle flag is set and the BtCursor.aOverflow[]
** has not been allocated, allocate it now. The array is sized at
** one entry for each overflow page in the overflow chain. The
** page number of the first overflow page is stored in aOverflow[0],
** etc. A value of 0 in the aOverflow[] array means "not yet known"
** (the cache is lazily populated).
/* If the BtCursor.aOverflow[] has not been allocated, allocate it now.
** Except, do not allocate aOverflow[] for eOp==2.
**
** The aOverflow[] array is sized at one entry for each overflow page
** in the overflow chain. The page number of the first overflow page is
** stored in aOverflow[0], etc. A value of 0 in the aOverflow[] array
** means "not yet known" (the cache is lazily populated).
*/
if( pCur->isIncrblobHandle && !pCur->aOverflow ){
if( eOp!=2 && (pCur->curFlags & BTCF_ValidOvfl)==0 ){
int nOvfl = (pCur->info.nPayload-pCur->info.nLocal+ovflSize-1)/ovflSize;
pCur->aOverflow = (Pgno *)sqlite3MallocZero(sizeof(Pgno)*nOvfl);
/* nOvfl is always positive. If it were zero, fetchPayload would have
** been used instead of this routine. */
if( ALWAYS(nOvfl) && !pCur->aOverflow ){
rc = SQLITE_NOMEM;
if( nOvfl>pCur->nOvflAlloc ){
Pgno *aNew = (Pgno*)sqlite3DbRealloc(
pCur->pBtree->db, pCur->aOverflow, nOvfl*2*sizeof(Pgno)
);
if( aNew==0 ){
rc = SQLITE_NOMEM;
}else{
pCur->nOvflAlloc = nOvfl*2;
pCur->aOverflow = aNew;
}
}
if( rc==SQLITE_OK ){
memset(pCur->aOverflow, 0, nOvfl*sizeof(Pgno));
pCur->curFlags |= BTCF_ValidOvfl;
}
}
@@ -4013,22 +4041,19 @@ static int accessPayload(
** entry for the first required overflow page is valid, skip
** directly to it.
*/
if( pCur->aOverflow && pCur->aOverflow[offset/ovflSize] ){
if( (pCur->curFlags & BTCF_ValidOvfl)!=0 && pCur->aOverflow[offset/ovflSize] ){
iIdx = (offset/ovflSize);
nextPage = pCur->aOverflow[iIdx];
offset = (offset%ovflSize);
}
#endif
for( ; rc==SQLITE_OK && amt>0 && nextPage; iIdx++){
#ifndef SQLITE_OMIT_INCRBLOB
/* If required, populate the overflow page-list cache. */
if( pCur->aOverflow ){
if( (pCur->curFlags & BTCF_ValidOvfl)!=0 ){
assert(!pCur->aOverflow[iIdx] || pCur->aOverflow[iIdx]==nextPage);
pCur->aOverflow[iIdx] = nextPage;
}
#endif
if( offset>=ovflSize ){
/* The only reason to read this page is to obtain the page
@@ -4036,13 +4061,17 @@ static int accessPayload(
** data is not required. So first try to lookup the overflow
** page-list cache, if any, then fall back to the getOverflowPage()
** function.
**
** Note that the aOverflow[] array must be allocated because eOp!=2
** here. If eOp==2, then offset==0 and this branch is never taken.
*/
#ifndef SQLITE_OMIT_INCRBLOB
if( pCur->aOverflow && pCur->aOverflow[iIdx+1] ){
assert( eOp!=2 );
assert( pCur->curFlags & BTCF_ValidOvfl );
if( pCur->aOverflow[iIdx+1] ){
nextPage = pCur->aOverflow[iIdx+1];
} else
#endif
}else{
rc = getOverflowPage(pBt, nextPage, 0, &nextPage);
}
offset -= ovflSize;
}else{
/* Need to read this page properly. It contains some of the
@@ -4064,13 +4093,15 @@ static int accessPayload(
** 3) the database is file-backed, and
** 4) there is no open write-transaction, and
** 5) the database is not a WAL database,
** 6) all data from the page is being read.
**
** then data can be read directly from the database file into the
** output buffer, bypassing the page-cache altogether. This speeds
** up loading large records that span many overflow pages.
*/
if( eOp==0 /* (1) */
if( (eOp&0x01)==0 /* (1) */
&& offset==0 /* (2) */
&& (bEnd || a==ovflSize) /* (6) */
&& pBt->inTransaction==TRANS_READ /* (4) */
&& (fd = sqlite3PagerFile(pBt->pPager))->pMethods /* (3) */
&& pBt->pPage1->aData[19]==0x01 /* (5) */
@@ -4087,12 +4118,12 @@ static int accessPayload(
{
DbPage *pDbPage;
rc = sqlite3PagerAcquire(pBt->pPager, nextPage, &pDbPage,
(eOp==0 ? PAGER_GET_READONLY : 0)
((eOp&0x01)==0 ? PAGER_GET_READONLY : 0)
);
if( rc==SQLITE_OK ){
aPayload = sqlite3PagerGetData(pDbPage);
nextPage = get4byte(aPayload);
rc = copyPayload(&aPayload[offset+4], pBuf, a, eOp, pDbPage);
rc = copyPayload(&aPayload[offset+4], pBuf, a, (eOp&0x01), pDbPage);
sqlite3PagerUnref(pDbPage);
offset = 0;
}
@@ -4186,10 +4217,13 @@ static const void *fetchPayload(
assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
assert( cursorHoldsMutex(pCur) );
assert( pCur->aiIdx[pCur->iPage]<pCur->apPage[pCur->iPage]->nCell );
assert( pCur->info.nSize>0 );
#if 0
if( pCur->info.nSize==0 ){
btreeParseCell(pCur->apPage[pCur->iPage], pCur->aiIdx[pCur->iPage],
&pCur->info);
}
#endif
*pAmt = pCur->info.nLocal;
return (void*)(pCur->info.pCell + pCur->info.nHeader);
}
@@ -4240,14 +4274,14 @@ static int moveToChild(BtCursor *pCur, u32 newPgno){
return SQLITE_CORRUPT_BKPT;
}
rc = getAndInitPage(pBt, newPgno, &pNewPage,
pCur->wrFlag==0 ? PAGER_GET_READONLY : 0);
(pCur->curFlags & BTCF_WriteFlag)==0 ? PAGER_GET_READONLY : 0);
if( rc ) return rc;
pCur->apPage[i+1] = pNewPage;
pCur->aiIdx[i+1] = 0;
pCur->iPage++;
pCur->info.nSize = 0;
pCur->validNKey = 0;
pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
if( pNewPage->nCell<1 || pNewPage->intKey!=pCur->apPage[i]->intKey ){
return SQLITE_CORRUPT_BKPT;
}
@@ -4305,7 +4339,7 @@ static void moveToParent(BtCursor *pCur){
releasePage(pCur->apPage[pCur->iPage]);
pCur->iPage--;
pCur->info.nSize = 0;
pCur->validNKey = 0;
pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
}
/*
@@ -4352,7 +4386,7 @@ static int moveToRoot(BtCursor *pCur){
return SQLITE_OK;
}else{
rc = getAndInitPage(pCur->pBtree->pBt, pCur->pgnoRoot, &pCur->apPage[0],
pCur->wrFlag==0 ? PAGER_GET_READONLY : 0);
(pCur->curFlags & BTCF_WriteFlag)==0 ? PAGER_GET_READONLY : 0);
if( rc!=SQLITE_OK ){
pCur->eState = CURSOR_INVALID;
return rc;
@@ -4379,8 +4413,7 @@ static int moveToRoot(BtCursor *pCur){
pCur->aiIdx[0] = 0;
pCur->info.nSize = 0;
pCur->atLast = 0;
pCur->validNKey = 0;
pCur->curFlags &= ~(BTCF_AtLast|BTCF_ValidNKey|BTCF_ValidOvfl);
if( pRoot->nCell>0 ){
pCur->eState = CURSOR_VALID;
@@ -4443,7 +4476,7 @@ static int moveToRightmost(BtCursor *pCur){
if( rc==SQLITE_OK ){
pCur->aiIdx[pCur->iPage] = pPage->nCell-1;
pCur->info.nSize = 0;
pCur->validNKey = 0;
pCur->curFlags &= ~BTCF_ValidNKey;
}
return rc;
}
@@ -4482,7 +4515,7 @@ int sqlite3BtreeLast(BtCursor *pCur, int *pRes){
assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
/* If the cursor already points to the last entry, this is a no-op. */
if( CURSOR_VALID==pCur->eState && pCur->atLast ){
if( CURSOR_VALID==pCur->eState && (pCur->curFlags & BTCF_AtLast)!=0 ){
#ifdef SQLITE_DEBUG
/* This block serves to assert() that the cursor really does point
** to the last entry in the b-tree. */
@@ -4505,7 +4538,12 @@ int sqlite3BtreeLast(BtCursor *pCur, int *pRes){
assert( pCur->eState==CURSOR_VALID );
*pRes = 0;
rc = moveToRightmost(pCur);
pCur->atLast = rc==SQLITE_OK ?1:0;
if( rc==SQLITE_OK ){
pCur->curFlags |= BTCF_AtLast;
}else{
pCur->curFlags &= ~BTCF_AtLast;
}
}
}
return rc;
@@ -4556,14 +4594,14 @@ int sqlite3BtreeMovetoUnpacked(
/* If the cursor is already positioned at the point we are trying
** to move to, then just return without doing any work */
if( pCur->eState==CURSOR_VALID && pCur->validNKey
if( pCur->eState==CURSOR_VALID && (pCur->curFlags & BTCF_ValidNKey)!=0
&& pCur->apPage[0]->intKey
){
if( pCur->info.nKey==intKey ){
*pRes = 0;
return SQLITE_OK;
}
if( pCur->atLast && pCur->info.nKey<intKey ){
if( (pCur->curFlags & BTCF_AtLast)!=0 && pCur->info.nKey<intKey ){
*pRes = -1;
return SQLITE_OK;
}
@@ -4571,12 +4609,13 @@ int sqlite3BtreeMovetoUnpacked(
if( pIdxKey ){
xRecordCompare = sqlite3VdbeFindCompare(pIdxKey);
pIdxKey->isCorrupt = 0;
assert( pIdxKey->default_rc==1
|| pIdxKey->default_rc==0
|| pIdxKey->default_rc==-1
);
}else{
xRecordCompare = 0; /* Not actually used. Avoids a compiler warning. */
xRecordCompare = 0; /* All keys are integers */
}
rc = moveToRoot(pCur);
@@ -4611,7 +4650,7 @@ int sqlite3BtreeMovetoUnpacked(
assert( biasRight==0 || biasRight==1 );
idx = upr>>(1-biasRight); /* idx = biasRight ? upr : (lwr+upr)/2; */
pCur->aiIdx[pCur->iPage] = (u16)idx;
if( pPage->intKey ){
if( xRecordCompare==0 ){
for(;;){
i64 nCellKey;
pCell = findCell(pPage, idx) + pPage->childPtrSize;
@@ -4629,7 +4668,7 @@ int sqlite3BtreeMovetoUnpacked(
if( lwr>upr ){ c = +1; break; }
}else{
assert( nCellKey==intKey );
pCur->validNKey = 1;
pCur->curFlags |= BTCF_ValidNKey;
pCur->info.nKey = nCellKey;
pCur->aiIdx[pCur->iPage] = (u16)idx;
if( !pPage->leaf ){
@@ -4686,7 +4725,7 @@ int sqlite3BtreeMovetoUnpacked(
goto moveto_finish;
}
pCur->aiIdx[pCur->iPage] = (u16)idx;
rc = accessPayload(pCur, 0, nCell, (unsigned char*)pCellKey, 0);
rc = accessPayload(pCur, 0, nCell, (unsigned char*)pCellKey, 2);
if( rc ){
sqlite3_free(pCellKey);
goto moveto_finish;
@@ -4694,6 +4733,7 @@ int sqlite3BtreeMovetoUnpacked(
c = xRecordCompare(nCell, pCellKey, pIdxKey, 0);
sqlite3_free(pCellKey);
}
assert( pIdxKey->isCorrupt==0 || c==0 );
if( c<0 ){
lwr = idx+1;
}else if( c>0 ){
@@ -4703,6 +4743,7 @@ int sqlite3BtreeMovetoUnpacked(
*pRes = 0;
rc = SQLITE_OK;
pCur->aiIdx[pCur->iPage] = (u16)idx;
if( pIdxKey->isCorrupt ) rc = SQLITE_CORRUPT;
goto moveto_finish;
}
if( lwr>upr ) break;
@@ -4731,7 +4772,7 @@ moveto_next_layer:
}
moveto_finish:
pCur->info.nSize = 0;
pCur->validNKey = 0;
pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
return rc;
}
@@ -4776,6 +4817,7 @@ int sqlite3BtreeNext(BtCursor *pCur, int *pRes){
assert( *pRes==0 || *pRes==1 );
assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
if( pCur->eState!=CURSOR_VALID ){
invalidateOverflowCache(pCur);
rc = restoreCursorPosition(pCur);
if( rc!=SQLITE_OK ){
*pRes = 0;
@@ -4809,7 +4851,7 @@ int sqlite3BtreeNext(BtCursor *pCur, int *pRes){
testcase( idx>pPage->nCell );
pCur->info.nSize = 0;
pCur->validNKey = 0;
pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
if( idx>=pPage->nCell ){
if( !pPage->leaf ){
rc = moveToChild(pCur, get4byte(&pPage->aData[pPage->hdrOffset+8]));
@@ -4870,7 +4912,7 @@ int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){
assert( pRes!=0 );
assert( *pRes==0 || *pRes==1 );
assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
pCur->atLast = 0;
pCur->curFlags &= ~(BTCF_AtLast|BTCF_ValidOvfl);
if( pCur->eState!=CURSOR_VALID ){
if( ALWAYS(pCur->eState>=CURSOR_REQUIRESEEK) ){
rc = btreeRestoreCursorPosition(pCur);
@@ -4915,7 +4957,7 @@ int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){
moveToParent(pCur);
}
pCur->info.nSize = 0;
pCur->validNKey = 0;
pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
pCur->aiIdx[pCur->iPage]--;
pPage = pCur->apPage[pCur->iPage];
@@ -6940,7 +6982,7 @@ int sqlite3BtreeInsert(
}
assert( cursorHoldsMutex(pCur) );
assert( pCur->wrFlag && pBt->inTransaction==TRANS_WRITE
assert( (pCur->curFlags & BTCF_WriteFlag)!=0 && pBt->inTransaction==TRANS_WRITE
&& (pBt->btsFlags & BTS_READ_ONLY)==0 );
assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) );
@@ -6973,7 +7015,7 @@ int sqlite3BtreeInsert(
/* If the cursor is currently on the last row and we are appending a
** new row onto the end, set the "loc" to avoid an unnecessary btreeMoveto()
** call */
if( pCur->validNKey && nKey>0 && pCur->info.nKey==nKey-1 ){
if( (pCur->curFlags&BTCF_ValidNKey)!=0 && nKey>0 && pCur->info.nKey==nKey-1 ){
loc = -1;
}
}
@@ -7026,7 +7068,7 @@ int sqlite3BtreeInsert(
/* If no error has occurred and pPage has an overflow cell, call balance()
** to redistribute the cells within the tree. Since balance() may move
** the cursor, zero the BtCursor.info.nSize and BtCursor.validNKey
** the cursor, zero the BtCursor.info.nSize and BTCF_ValidNKey
** variables.
**
** Previous versions of SQLite called moveToRoot() to move the cursor
@@ -7046,7 +7088,7 @@ int sqlite3BtreeInsert(
*/
pCur->info.nSize = 0;
if( rc==SQLITE_OK && pPage->nOverflow ){
pCur->validNKey = 0;
pCur->curFlags &= ~(BTCF_ValidNKey);
rc = balance(pCur);
/* Must make sure nOverflow is reset to zero even if the balance()
@@ -7078,7 +7120,7 @@ int sqlite3BtreeDelete(BtCursor *pCur){
assert( cursorHoldsMutex(pCur) );
assert( pBt->inTransaction==TRANS_WRITE );
assert( (pBt->btsFlags & BTS_READ_ONLY)==0 );
assert( pCur->wrFlag );
assert( pCur->curFlags & BTCF_WriteFlag );
assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) );
assert( !hasReadConflicts(p, pCur->pgnoRoot) );
@@ -7423,6 +7465,15 @@ int sqlite3BtreeClearTable(Btree *p, int iTable, int *pnChange){
return rc;
}
/*
** Delete all information from the single table that pCur is open on.
**
** This routine only work for pCur on an ephemeral table.
*/
int sqlite3BtreeClearTableOfCursor(BtCursor *pCur){
return sqlite3BtreeClearTable(pCur->pBtree, pCur->pgnoRoot, 0);
}
/*
** Erase all information in a table and add the root of the table to
** the freelist. Except, the root of the principle table (the one on
@@ -8382,7 +8433,7 @@ int sqlite3BtreePutData(BtCursor *pCsr, u32 offset, u32 amt, void *z){
int rc;
assert( cursorHoldsMutex(pCsr) );
assert( sqlite3_mutex_held(pCsr->pBtree->db->mutex) );
assert( pCsr->isIncrblobHandle );
assert( pCsr->curFlags & BTCF_Incrblob );
rc = restoreCursorPosition(pCsr);
if( rc!=SQLITE_OK ){
@@ -8411,7 +8462,7 @@ int sqlite3BtreePutData(BtCursor *pCsr, u32 offset, u32 amt, void *z){
** (d) there are no conflicting read-locks, and
** (e) the cursor points at a valid row of an intKey table.
*/
if( !pCsr->wrFlag ){
if( (pCsr->curFlags & BTCF_WriteFlag)==0 ){
return SQLITE_READONLY;
}
assert( (pCsr->pBt->btsFlags & BTS_READ_ONLY)==0
@@ -8424,20 +8475,10 @@ int sqlite3BtreePutData(BtCursor *pCsr, u32 offset, u32 amt, void *z){
}
/*
** Set a flag on this cursor to cache the locations of pages from the
** overflow list for the current row. This is used by cursors opened
** for incremental blob IO only.
**
** This function sets a flag only. The actual page location cache
** (stored in BtCursor.aOverflow[]) is allocated and used by function
** accessPayload() (the worker function for sqlite3BtreeData() and
** sqlite3BtreePutData()).
** Mark this cursor as an incremental blob cursor.
*/
void sqlite3BtreeCacheOverflow(BtCursor *pCur){
assert( cursorHoldsMutex(pCur) );
assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
invalidateOverflowCache(pCur);
pCur->isIncrblobHandle = 1;
void sqlite3BtreeIncrblobCursor(BtCursor *pCur){
pCur->curFlags |= BTCF_Incrblob;
}
#endif
+5 -2
View File
@@ -63,7 +63,9 @@ int sqlite3BtreeOpen(
int sqlite3BtreeClose(Btree*);
int sqlite3BtreeSetCacheSize(Btree*,int);
int sqlite3BtreeSetMmapLimit(Btree*,sqlite3_int64);
#if SQLITE_MAX_MMAP_SIZE>0
int sqlite3BtreeSetMmapLimit(Btree*,sqlite3_int64);
#endif
int sqlite3BtreeSetPagerFlags(Btree*,unsigned);
int sqlite3BtreeSyncDisabled(Btree*);
int sqlite3BtreeSetPageSize(Btree *p, int nPagesize, int nReserve, int eFix);
@@ -113,6 +115,7 @@ int sqlite3BtreeIncrVacuum(Btree *);
int sqlite3BtreeDropTable(Btree*, int, int*);
int sqlite3BtreeClearTable(Btree*, int, int*);
int sqlite3BtreeClearTableOfCursor(BtCursor*);
void sqlite3BtreeTripAllCursors(Btree*, int);
void sqlite3BtreeGetMeta(Btree *pBtree, int idx, u32 *pValue);
@@ -187,7 +190,7 @@ char *sqlite3BtreeIntegrityCheck(Btree*, int *aRoot, int nRoot, int, int*);
struct Pager *sqlite3BtreePager(Btree*);
int sqlite3BtreePutData(BtCursor*, u32 offset, u32 amt, void*);
void sqlite3BtreeCacheOverflow(BtCursor *);
void sqlite3BtreeIncrblobCursor(BtCursor *);
void sqlite3BtreeClearCursor(BtCursor *);
int sqlite3BtreeSetVersion(Btree *pBt, int iVersion);
void sqlite3BtreeCursorHints(BtCursor *, unsigned int mask);
+14 -11
View File
@@ -496,27 +496,30 @@ struct BtCursor {
BtShared *pBt; /* The BtShared this cursor points to */
BtCursor *pNext, *pPrev; /* Forms a linked list of all cursors */
struct KeyInfo *pKeyInfo; /* Argument passed to comparison function */
#ifndef SQLITE_OMIT_INCRBLOB
Pgno *aOverflow; /* Cache of overflow page locations */
#endif
Pgno pgnoRoot; /* The root page of this tree */
CellInfo info; /* A parse of the cell we are pointing at */
i64 nKey; /* Size of pKey, or last integer key */
void *pKey; /* Saved key that was cursor's last known position */
i64 nKey; /* Size of pKey, or last integer key */
void *pKey; /* Saved key that was cursor last known position */
Pgno pgnoRoot; /* The root page of this tree */
int nOvflAlloc; /* Allocated size of aOverflow[] array */
int skipNext; /* Prev() is noop if negative. Next() is noop if positive */
u8 wrFlag; /* True if writable */
u8 atLast; /* Cursor pointing to the last entry */
u8 validNKey; /* True if info.nKey is valid */
u8 curFlags; /* zero or more BTCF_* flags defined below */
u8 eState; /* One of the CURSOR_XXX constants (see below) */
#ifndef SQLITE_OMIT_INCRBLOB
u8 isIncrblobHandle; /* True if this cursor is an incr. io handle */
#endif
u8 hints; /* As configured by CursorSetHints() */
i16 iPage; /* Index of current page in apPage */
u16 aiIdx[BTCURSOR_MAX_DEPTH]; /* Current index in apPage[i] */
MemPage *apPage[BTCURSOR_MAX_DEPTH]; /* Pages from root to current page */
};
/*
** Legal values for BtCursor.curFlags
*/
#define BTCF_WriteFlag 0x01 /* True if a write cursor */
#define BTCF_ValidNKey 0x02 /* True if info.nKey is valid */
#define BTCF_ValidOvfl 0x04 /* True if aOverflow is valid */
#define BTCF_AtLast 0x08 /* Cursor is pointing ot the last entry */
#define BTCF_Incrblob 0x10 /* True if an incremental I/O handle */
/*
** Potential values for BtCursor.eState.
**
+30 -23
View File
@@ -905,7 +905,7 @@ void sqlite3StartTable(
pTable->iPKey = -1;
pTable->pSchema = db->aDb[iDb].pSchema;
pTable->nRef = 1;
pTable->nRowEst = 1048576;
pTable->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) );
assert( pParse->pNewTable==0 );
pParse->pNewTable = pTable;
@@ -2680,7 +2680,7 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
sqlite3GenerateIndexKey(pParse,pIndex,iTab,regRecord,0,&iPartIdxLabel,0,0);
sqlite3VdbeAddOp2(v, OP_SorterInsert, iSorter, regRecord);
sqlite3VdbeResolveLabel(v, iPartIdxLabel);
sqlite3ResolvePartIdxLabel(pParse, iPartIdxLabel);
sqlite3VdbeAddOp2(v, OP_Next, iTab, addr1+1); VdbeCoverage(v);
sqlite3VdbeJumpHere(v, addr1);
if( memRootPage<0 ) sqlite3VdbeAddOp2(v, OP_Clear, tnum, iDb);
@@ -2730,15 +2730,15 @@ Index *sqlite3AllocateIndexObject(
nByte = ROUND8(sizeof(Index)) + /* Index structure */
ROUND8(sizeof(char*)*nCol) + /* Index.azColl */
ROUND8(sizeof(tRowcnt)*(nCol+1) + /* Index.aiRowEst */
ROUND8(sizeof(LogEst)*(nCol+1) + /* Index.aiRowLogEst */
sizeof(i16)*nCol + /* Index.aiColumn */
sizeof(u8)*nCol); /* Index.aSortOrder */
p = sqlite3DbMallocZero(db, nByte + nExtra);
if( p ){
char *pExtra = ((char*)p)+ROUND8(sizeof(Index));
p->azColl = (char**)pExtra; pExtra += ROUND8(sizeof(char*)*nCol);
p->aiRowEst = (tRowcnt*)pExtra; pExtra += sizeof(tRowcnt)*(nCol+1);
p->aiColumn = (i16*)pExtra; pExtra += sizeof(i16)*nCol;
p->azColl = (char**)pExtra; pExtra += ROUND8(sizeof(char*)*nCol);
p->aiRowLogEst = (LogEst*)pExtra; pExtra += sizeof(LogEst)*(nCol+1);
p->aiColumn = (i16*)pExtra; pExtra += sizeof(i16)*nCol;
p->aSortOrder = (u8*)pExtra;
p->nColumn = nCol;
p->nKeyCol = nCol - 1;
@@ -2968,7 +2968,7 @@ Index *sqlite3CreateIndex(
if( db->mallocFailed ){
goto exit_create_index;
}
assert( EIGHT_BYTE_ALIGNMENT(pIndex->aiRowEst) );
assert( EIGHT_BYTE_ALIGNMENT(pIndex->aiRowLogEst) );
assert( EIGHT_BYTE_ALIGNMENT(pIndex->azColl) );
pIndex->zName = zExtra;
zExtra += nName + 1;
@@ -3249,7 +3249,7 @@ exit_create_index:
** Since we do not know, guess 1 million. aiRowEst[1] is an estimate of the
** number of rows in the table that match any particular value of the
** first column of the index. aiRowEst[2] is an estimate of the number
** of rows that match any particular combiniation of the first 2 columns
** of rows that match any particular combination of the first 2 columns
** of the index. And so forth. It must always be the case that
*
** aiRowEst[N]<=aiRowEst[N-1]
@@ -3260,20 +3260,27 @@ exit_create_index:
** are based on typical values found in actual indices.
*/
void sqlite3DefaultRowEst(Index *pIdx){
tRowcnt *a = pIdx->aiRowEst;
/* 10, 9, 8, 7, 6 */
LogEst aVal[] = { 33, 32, 30, 28, 26 };
LogEst *a = pIdx->aiRowLogEst;
int nCopy = MIN(ArraySize(aVal), pIdx->nKeyCol);
int i;
tRowcnt n;
assert( a!=0 );
a[0] = pIdx->pTable->nRowEst;
if( a[0]<10 ) a[0] = 10;
n = 10;
for(i=1; i<=pIdx->nKeyCol; i++){
a[i] = n;
if( n>5 ) n--;
}
if( pIdx->onError!=OE_None ){
a[pIdx->nKeyCol] = 1;
/* Set the first entry (number of rows in the index) to the estimated
** number of rows in the table. Or 10, if the estimated number of rows
** in the table is less than that. */
a[0] = pIdx->pTable->nRowLogEst;
if( a[0]<33 ) a[0] = 33; assert( 33==sqlite3LogEst(10) );
/* Estimate that a[1] is 10, a[2] is 9, a[3] is 8, a[4] is 7, a[5] is
** 6 and each subsequent value (if any) is 5. */
memcpy(&a[1], aVal, nCopy*sizeof(LogEst));
for(i=nCopy+1; i<=pIdx->nKeyCol; i++){
a[i] = 23; assert( 23==sqlite3LogEst(5) );
}
assert( 0==sqlite3LogEst(1) );
if( pIdx->onError!=OE_None ) a[pIdx->nKeyCol] = 0;
}
/*
@@ -3473,7 +3480,7 @@ SrcList *sqlite3SrcListEnlarge(
assert( iStart<=pSrc->nSrc );
/* Allocate additional space if needed */
if( pSrc->nSrc+nExtra>pSrc->nAlloc ){
if( (u32)pSrc->nSrc+nExtra>pSrc->nAlloc ){
SrcList *pNew;
int nAlloc = pSrc->nSrc+nExtra;
int nGot;
@@ -3485,7 +3492,7 @@ SrcList *sqlite3SrcListEnlarge(
}
pSrc = pNew;
nGot = (sqlite3DbMallocSize(db, pNew) - sizeof(*pSrc))/sizeof(pSrc->a[0])+1;
pSrc->nAlloc = (u8)nGot;
pSrc->nAlloc = nGot;
}
/* Move existing slots that come after the newly inserted slots
@@ -3493,7 +3500,7 @@ SrcList *sqlite3SrcListEnlarge(
for(i=pSrc->nSrc-1; i>=iStart; i--){
pSrc->a[i+nExtra] = pSrc->a[i];
}
pSrc->nSrc += (i8)nExtra;
pSrc->nSrc += nExtra;
/* Zero the newly allocated slots */
memset(&pSrc->a[iStart], 0, sizeof(pSrc->a[0])*nExtra);
+3
View File
@@ -215,6 +215,9 @@ static const char * const azCompileOpt[] = {
#ifdef SQLITE_OMIT_COMPOUND_SELECT
"OMIT_COMPOUND_SELECT",
#endif
#ifdef SQLITE_OMIT_CTE
"OMIT_CTE",
#endif
#ifdef SQLITE_OMIT_DATETIME_FUNCS
"OMIT_DATETIME_FUNCS",
#endif
+16 -2
View File
@@ -739,7 +739,7 @@ void sqlite3GenerateRowIndexDelete(
&iPartIdxLabel, pPrior, r1);
sqlite3VdbeAddOp3(v, OP_IdxDelete, iIdxCur+i, r1,
pIdx->uniqNotNull ? pIdx->nKeyCol : pIdx->nColumn);
sqlite3VdbeResolveLabel(v, iPartIdxLabel);
sqlite3ResolvePartIdxLabel(pParse, iPartIdxLabel);
pPrior = pIdx;
}
}
@@ -758,10 +758,11 @@ void sqlite3GenerateRowIndexDelete(
**
** If *piPartIdxLabel is not NULL, fill it in with a label and jump
** to that label if pIdx is a partial index that should be skipped.
** The label should be resolved using sqlite3ResolvePartIdxLabel().
** A partial index should be skipped if its WHERE clause evaluates
** to false or null. If pIdx is not a partial index, *piPartIdxLabel
** will be set to zero which is an empty label that is ignored by
** sqlite3VdbeResolveLabel().
** sqlite3ResolvePartIdxLabel().
**
** The pPrior and regPrior parameters are used to implement a cache to
** avoid unnecessary register loads. If pPrior is not NULL, then it is
@@ -794,6 +795,7 @@ int sqlite3GenerateIndexKey(
if( pIdx->pPartIdxWhere ){
*piPartIdxLabel = sqlite3VdbeMakeLabel(v);
pParse->iPartIdxTab = iDataCur;
sqlite3ExprCachePush(pParse);
sqlite3ExprIfFalse(pParse, pIdx->pPartIdxWhere, *piPartIdxLabel,
SQLITE_JUMPIFNULL);
}else{
@@ -821,3 +823,15 @@ int sqlite3GenerateIndexKey(
sqlite3ReleaseTempRange(pParse, regBase, nCol);
return regBase;
}
/*
** If a prior call to sqlite3GenerateIndexKey() generated a jump-over label
** because it was a partial index, then this routine should be called to
** resolve that label.
*/
void sqlite3ResolvePartIdxLabel(Parse *pParse, int iLabel){
if( iLabel ){
sqlite3VdbeResolveLabel(pParse->pVdbe, iLabel);
sqlite3ExprCachePop(pParse);
}
}
+24 -22
View File
@@ -33,6 +33,7 @@
char sqlite3ExprAffinity(Expr *pExpr){
int op;
pExpr = sqlite3ExprSkipCollate(pExpr);
if( pExpr->flags & EP_Generic ) return SQLITE_AFF_NONE;
op = pExpr->op;
if( op==TK_SELECT ){
assert( pExpr->flags&EP_xIsSelect );
@@ -65,7 +66,11 @@ char sqlite3ExprAffinity(Expr *pExpr){
** If a memory allocation error occurs, that fact is recorded in pParse->db
** and the pExpr parameter is returned unchanged.
*/
Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr *pExpr, Token *pCollName){
Expr *sqlite3ExprAddCollateToken(
Parse *pParse, /* Parsing context */
Expr *pExpr, /* Add the "COLLATE" clause to this expression */
const Token *pCollName /* Name of collating sequence */
){
if( pCollName->n>0 ){
Expr *pNew = sqlite3ExprAlloc(pParse->db, TK_COLLATE, pCollName, 1);
if( pNew ){
@@ -118,6 +123,7 @@ CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){
Expr *p = pExpr;
while( p ){
int op = p->op;
if( p->flags & EP_Generic ) break;
if( op==TK_CAST || op==TK_UPLUS ){
p = p->pLeft;
continue;
@@ -949,7 +955,6 @@ ExprList *sqlite3ExprListDup(sqlite3 *db, ExprList *p, int flags){
if( p==0 ) return 0;
pNew = sqlite3DbMallocRaw(db, sizeof(*pNew) );
if( pNew==0 ) return 0;
pNew->iECursor = 0;
pNew->nExpr = i = p->nExpr;
if( (flags & EXPRDUP_REDUCE)==0 ) for(i=1; i<p->nExpr; i+=i){}
pNew->a = pItem = sqlite3DbMallocRaw(db, i*sizeof(p->a[0]) );
@@ -1062,7 +1067,6 @@ Select *sqlite3SelectDup(sqlite3 *db, Select *p, int flags){
pNew->selFlags = p->selFlags & ~SF_UsesEphemeral;
pNew->addrOpenEphm[0] = -1;
pNew->addrOpenEphm[1] = -1;
pNew->addrOpenEphm[2] = -1;
pNew->nSelectRow = p->nSelectRow;
pNew->pWith = withDup(db, p->pWith);
return pNew;
@@ -1630,7 +1634,6 @@ int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){
*prNotFound = rMayHaveNull = ++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_Null, 0, *prNotFound);
}else{
testcase( pParse->nQueryLoop>0 );
pParse->nQueryLoop = 0;
if( pX->pLeft->iColumn<0 && !ExprHasProperty(pX, EP_xIsSelect) ){
eType = IN_INDEX_ROWID;
@@ -1880,7 +1883,7 @@ int sqlite3CodeSubselect(
if( testAddr>=0 ){
sqlite3VdbeJumpHere(v, testAddr);
}
sqlite3ExprCachePop(pParse, 1);
sqlite3ExprCachePop(pParse);
return rReg;
}
@@ -2015,7 +2018,7 @@ static void sqlite3ExprCodeIN(
}
}
sqlite3ReleaseTempReg(pParse, r1);
sqlite3ExprCachePop(pParse, 1);
sqlite3ExprCachePop(pParse);
VdbeComment((v, "end IN expr"));
}
#endif /* SQLITE_OMIT_SUBQUERY */
@@ -2198,15 +2201,14 @@ void sqlite3ExprCachePush(Parse *pParse){
/*
** Remove from the column cache any entries that were added since the
** the previous N Push operations. In other words, restore the cache
** to the state it was in N Pushes ago.
** the previous sqlite3ExprCachePush operation. In other words, restore
** the cache to the state it was in prior the most recent Push.
*/
void sqlite3ExprCachePop(Parse *pParse, int N){
void sqlite3ExprCachePop(Parse *pParse){
int i;
struct yColCache *p;
assert( N>0 );
assert( pParse->iCacheLevel>=N );
pParse->iCacheLevel -= N;
assert( pParse->iCacheLevel>=1 );
pParse->iCacheLevel--;
#ifdef SQLITE_DEBUG
if( pParse->db->flags & SQLITE_VdbeAddopTrace ){
printf("POP to %d\n", pParse->iCacheLevel);
@@ -2335,7 +2337,7 @@ void sqlite3ExprCodeMove(Parse *pParse, int iFrom, int iTo, int nReg){
int i;
struct yColCache *p;
assert( iFrom>=iTo+nReg || iFrom+nReg<=iTo );
sqlite3VdbeAddOp3(pParse->pVdbe, OP_Move, iFrom, iTo, nReg-1);
sqlite3VdbeAddOp3(pParse->pVdbe, OP_Move, iFrom, iTo, nReg);
for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
int x = p->iReg;
if( x>=iFrom && x<iFrom+nReg ){
@@ -2684,7 +2686,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
sqlite3ExprCacheRemove(pParse, target, 1);
sqlite3ExprCachePush(pParse);
sqlite3ExprCode(pParse, pFarg->a[i].pExpr, target);
sqlite3ExprCachePop(pParse, 1);
sqlite3ExprCachePop(pParse);
}
sqlite3VdbeResolveLabel(v, endCoalesce);
break;
@@ -2736,9 +2738,9 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
}
sqlite3ExprCachePush(pParse); /* Ticket 2ea2425d34be */
sqlite3ExprCodeExprList(pParse, pFarg, r1,
sqlite3ExprCodeExprList(pParse, pFarg, r1,
SQLITE_ECEL_DUP|SQLITE_ECEL_FACTOR);
sqlite3ExprCachePop(pParse, 1); /* Ticket 2ea2425d34be */
sqlite3ExprCachePop(pParse); /* Ticket 2ea2425d34be */
}else{
r1 = 0;
}
@@ -2958,13 +2960,13 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
testcase( aListelem[i+1].pExpr->op==TK_COLUMN );
sqlite3ExprCode(pParse, aListelem[i+1].pExpr, target);
sqlite3VdbeAddOp2(v, OP_Goto, 0, endLabel);
sqlite3ExprCachePop(pParse, 1);
sqlite3ExprCachePop(pParse);
sqlite3VdbeResolveLabel(v, nextCase);
}
if( (nExpr&1)!=0 ){
sqlite3ExprCachePush(pParse);
sqlite3ExprCode(pParse, pEList->a[nExpr-1].pExpr, target);
sqlite3ExprCachePop(pParse, 1);
sqlite3ExprCachePop(pParse);
}else{
sqlite3VdbeAddOp2(v, OP_Null, 0, target);
}
@@ -3543,7 +3545,7 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
sqlite3ExprCachePush(pParse);
sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull);
sqlite3VdbeResolveLabel(v, d2);
sqlite3ExprCachePop(pParse, 1);
sqlite3ExprCachePop(pParse);
break;
}
case TK_OR: {
@@ -3551,7 +3553,7 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull);
sqlite3ExprCachePush(pParse);
sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull);
sqlite3ExprCachePop(pParse, 1);
sqlite3ExprCachePop(pParse);
break;
}
case TK_NOT: {
@@ -3697,7 +3699,7 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull);
sqlite3ExprCachePush(pParse);
sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull);
sqlite3ExprCachePop(pParse, 1);
sqlite3ExprCachePop(pParse);
break;
}
case TK_OR: {
@@ -3707,7 +3709,7 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
sqlite3ExprCachePush(pParse);
sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull);
sqlite3VdbeResolveLabel(v, d2);
sqlite3ExprCachePop(pParse, 1);
sqlite3ExprCachePop(pParse);
break;
}
case TK_NOT: {
+1 -1
View File
@@ -1017,7 +1017,7 @@ static void charFunc(
){
unsigned char *z, *zOut;
int i;
zOut = z = sqlite3_malloc( argc*4 );
zOut = z = sqlite3_malloc( argc*4+1 );
if( z==0 ){
sqlite3_result_error_nomem(context);
return;
+16 -8
View File
@@ -101,13 +101,13 @@ const char *sqlite3IndexAffinityStr(Vdbe *v, Index *pIdx){
** Compute the affinity string for table pTab, if it has not already been
** computed. As an optimization, omit trailing SQLITE_AFF_NONE affinities.
**
** If the affinity exists (if it is no entirely SQLITE_AFF_NONE values and
** If the affinity exists (if it is no entirely SQLITE_AFF_NONE values) and
** if iReg>0 then code an OP_Affinity opcode that will set the affinities
** for register iReg and following. Or if affinities exists and iReg==0,
** then just set the P4 operand of the previous opcode (which should be
** an OP_MakeRecord) to the affinity string.
**
** A column affinity string has one character column:
** A column affinity string has one character per column:
**
** Character Column affinity
** ------------------------------
@@ -148,10 +148,9 @@ void sqlite3TableAffinity(Vdbe *v, Table *pTab, int iReg){
/*
** Return non-zero if the table pTab in database iDb or any of its indices
** have been opened at any point in the VDBE program beginning at location
** iStartAddr throught the end of the program. This is used to see if
** have been opened at any point in the VDBE program. This is used to see if
** a statement of the form "INSERT INTO <iDb, pTab> SELECT ..." can
** run without using temporary table for the results of the SELECT.
** run without using a temporary table for the results of the SELECT.
*/
static int readsTable(Parse *p, int iDb, Table *pTab){
Vdbe *v = sqlite3GetVdbe(p);
@@ -1866,15 +1865,24 @@ static int xferOptimization(
return 0; /* Both tables must have the same INTEGER PRIMARY KEY */
}
for(i=0; i<pDest->nCol; i++){
if( pDest->aCol[i].affinity!=pSrc->aCol[i].affinity ){
Column *pDestCol = &pDest->aCol[i];
Column *pSrcCol = &pSrc->aCol[i];
if( pDestCol->affinity!=pSrcCol->affinity ){
return 0; /* Affinity must be the same on all columns */
}
if( !xferCompatibleCollation(pDest->aCol[i].zColl, pSrc->aCol[i].zColl) ){
if( !xferCompatibleCollation(pDestCol->zColl, pSrcCol->zColl) ){
return 0; /* Collating sequence must be the same on all columns */
}
if( pDest->aCol[i].notNull && !pSrc->aCol[i].notNull ){
if( pDestCol->notNull && !pSrcCol->notNull ){
return 0; /* tab2 must be NOT NULL if tab1 is */
}
/* Default values for second and subsequent columns need to match. */
if( i>0
&& ((pDestCol->zDflt==0)!=(pSrcCol->zDflt==0)
|| (pDestCol->zDflt && strcmp(pDestCol->zDflt, pSrcCol->zDflt)!=0))
){
return 0; /* Default values must be the same for all columns */
}
}
for(pDestIdx=pDest->pIndex; pDestIdx; pDestIdx=pDestIdx->pNext){
if( pDestIdx->onError!=OE_None ){
+17
View File
@@ -800,6 +800,7 @@ static void disconnectAllVtab(sqlite3 *db){
}
}
}
sqlite3VtabUnlockList(db);
sqlite3BtreeLeaveAll(db);
#else
UNUSED_PARAMETER(db);
@@ -3204,6 +3205,22 @@ int sqlite3_test_control(int op, ...){
break;
}
/*
** sqlite3_test_control(SQLITE_TESTCTRL_BYTEORDER);
**
** The integer returned reveals the byte-order of the computer on which
** SQLite is running:
**
** 1 big-endian, determined at run-time
** 10 little-endian, determined at run-time
** 432101 big-endian, determined at compile-time
** 123410 little-endian, determined at compile-time
*/
case SQLITE_TESTCTRL_BYTEORDER: {
rc = SQLITE_BYTEORDER*100 + SQLITE_LITTLEENDIAN*10 + SQLITE_BIGENDIAN;
break;
}
/* sqlite3_test_control(SQLITE_TESTCTRL_RESERVE, sqlite3 *db, int N)
**
** Set the nReserve size to N for the main database on the database
+1 -1
View File
@@ -248,7 +248,7 @@ static void *memsys5MallocUnsafe(int nByte){
** block. If not, then split a block of the next larger power of
** two in order to create a new free block of size iLogsize.
*/
for(iBin=iLogsize; mem5.aiFreelist[iBin]<0 && iBin<=LOGMAX; iBin++){}
for(iBin=iLogsize; iBin<=LOGMAX && mem5.aiFreelist[iBin]<0; iBin++){}
if( iBin>LOGMAX ){
testcase( sqlite3GlobalConfig.xLog!=0 );
sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes", nByte);
+5
View File
@@ -19,6 +19,11 @@
*/
#ifdef SQLITE_MUTEX_W32
/*
** Include the header file for the Windows VFS.
*/
#include "os_win.h"
/*
** Each recursive mutex is an instance of the following structure.
*/
+3 -76
View File
@@ -21,83 +21,10 @@
#define _SQLITE_OS_H_
/*
** Figure out if we are dealing with Unix, Windows, or some other
** operating system. After the following block of preprocess macros,
** all of SQLITE_OS_UNIX, SQLITE_OS_WIN, and SQLITE_OS_OTHER
** will defined to either 1 or 0. One of the four will be 1. The other
** three will be 0.
** Attempt to automatically detect the operating system and setup the
** necessary pre-processor macros for it.
*/
#if defined(SQLITE_OS_OTHER)
# if SQLITE_OS_OTHER==1
# undef SQLITE_OS_UNIX
# define SQLITE_OS_UNIX 0
# undef SQLITE_OS_WIN
# define SQLITE_OS_WIN 0
# else
# undef SQLITE_OS_OTHER
# endif
#endif
#if !defined(SQLITE_OS_UNIX) && !defined(SQLITE_OS_OTHER)
# define SQLITE_OS_OTHER 0
# ifndef SQLITE_OS_WIN
# if defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__BORLANDC__)
# define SQLITE_OS_WIN 1
# define SQLITE_OS_UNIX 0
# else
# define SQLITE_OS_WIN 0
# define SQLITE_OS_UNIX 1
# endif
# else
# define SQLITE_OS_UNIX 0
# endif
#else
# ifndef SQLITE_OS_WIN
# define SQLITE_OS_WIN 0
# endif
#endif
#if SQLITE_OS_WIN
# include <windows.h>
#endif
/*
** Determine if we are dealing with Windows NT.
**
** We ought to be able to determine if we are compiling for win98 or winNT
** using the _WIN32_WINNT macro as follows:
**
** #if defined(_WIN32_WINNT)
** # define SQLITE_OS_WINNT 1
** #else
** # define SQLITE_OS_WINNT 0
** #endif
**
** However, vs2005 does not set _WIN32_WINNT by default, as it ought to,
** so the above test does not work. We'll just assume that everything is
** winNT unless the programmer explicitly says otherwise by setting
** SQLITE_OS_WINNT to 0.
*/
#if SQLITE_OS_WIN && !defined(SQLITE_OS_WINNT)
# define SQLITE_OS_WINNT 1
#endif
/*
** Determine if we are dealing with WindowsCE - which has a much
** reduced API.
*/
#if defined(_WIN32_WCE)
# define SQLITE_OS_WINCE 1
#else
# define SQLITE_OS_WINCE 0
#endif
/*
** Determine if we are dealing with WinRT, which provides only a subset of
** the full Win32 API.
*/
#if !defined(SQLITE_OS_WINRT)
# define SQLITE_OS_WINRT 0
#endif
#include "os_setup.h"
/* If the SET_FULLSYNC macro is not defined above, then make it
** a no-op
+57
View File
@@ -0,0 +1,57 @@
/*
** 2013 November 25
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
******************************************************************************
**
** This file contains pre-processor directives related to operating system
** detection and/or setup.
*/
#ifndef _OS_SETUP_H_
#define _OS_SETUP_H_
/*
** Figure out if we are dealing with Unix, Windows, or some other operating
** system.
**
** After the following block of preprocess macros, all of SQLITE_OS_UNIX,
** SQLITE_OS_WIN, and SQLITE_OS_OTHER will defined to either 1 or 0. One of
** the three will be 1. The other two will be 0.
*/
#if defined(SQLITE_OS_OTHER)
# if SQLITE_OS_OTHER==1
# undef SQLITE_OS_UNIX
# define SQLITE_OS_UNIX 0
# undef SQLITE_OS_WIN
# define SQLITE_OS_WIN 0
# else
# undef SQLITE_OS_OTHER
# endif
#endif
#if !defined(SQLITE_OS_UNIX) && !defined(SQLITE_OS_OTHER)
# define SQLITE_OS_OTHER 0
# ifndef SQLITE_OS_WIN
# if defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) || \
defined(__MINGW32__) || defined(__BORLANDC__)
# define SQLITE_OS_WIN 1
# define SQLITE_OS_UNIX 0
# else
# define SQLITE_OS_WIN 0
# define SQLITE_OS_UNIX 1
# endif
# else
# define SQLITE_OS_UNIX 0
# endif
#else
# ifndef SQLITE_OS_WIN
# define SQLITE_OS_WIN 0
# endif
#endif
#endif /* _OS_SETUP_H_ */
+59 -23
View File
@@ -323,6 +323,7 @@ static int posixFchown(int fd, uid_t uid, gid_t gid){
/* Forward reference */
static int openDirectory(const char*, int*);
static int unixGetpagesize(void);
/*
** Many system calls are accessed through pointer-to-functions so that
@@ -446,6 +447,9 @@ static struct unix_syscall {
#define osMremap ((void*(*)(void*,size_t,size_t,int,...))aSyscall[23].pCurrent)
#endif
{ "getpagesize", (sqlite3_syscall_ptr)unixGetpagesize, 0 },
#define osGetpagesize ((int(*)(void))aSyscall[24].pCurrent)
}; /* End of the overrideable system calls */
/*
@@ -4105,6 +4109,36 @@ static int unixShmSystemLock(
return rc;
}
/*
** Return the system page size.
**
** This function should not be called directly by other code in this file.
** Instead, it should be called via macro osGetpagesize().
*/
static int unixGetpagesize(void){
#if defined(_BSD_SOURCE)
return getpagesize();
#else
return (int)sysconf(_SC_PAGESIZE);
#endif
}
/*
** Return the minimum number of 32KB shm regions that should be mapped at
** a time, assuming that each mapping must be an integer multiple of the
** current system page-size.
**
** Usually, this is 1. The exception seems to be systems that are configured
** to use 64KB pages - in this case each mapping must cover at least two
** shm regions.
*/
static int unixShmRegionPerMap(void){
int shmsz = 32*1024; /* SHM region size */
int pgsz = osGetpagesize(); /* System page size */
assert( ((pgsz-1)&pgsz)==0 ); /* Page size must be a power of 2 */
if( pgsz<shmsz ) return 1;
return pgsz/shmsz;
}
/*
** Purge the unixShmNodeList list of all entries with unixShmNode.nRef==0.
@@ -4116,10 +4150,11 @@ static void unixShmPurge(unixFile *pFd){
unixShmNode *p = pFd->pInode->pShmNode;
assert( unixMutexHeld() );
if( p && p->nRef==0 ){
int nShmPerMap = unixShmRegionPerMap();
int i;
assert( p->pInode==pFd->pInode );
sqlite3_mutex_free(p->mutex);
for(i=0; i<p->nRegion; i++){
for(i=0; i<p->nRegion; i+=nShmPerMap){
if( p->h>=0 ){
osMunmap(p->apRegion[i], p->szRegion);
}else{
@@ -4326,6 +4361,8 @@ static int unixShmMap(
unixShm *p;
unixShmNode *pShmNode;
int rc = SQLITE_OK;
int nShmPerMap = unixShmRegionPerMap();
int nReqRegion;
/* If the shared-memory file has not yet been opened, open it now. */
if( pDbFd->pShm==0 ){
@@ -4341,9 +4378,12 @@ static int unixShmMap(
assert( pShmNode->h>=0 || pDbFd->pInode->bProcessLock==1 );
assert( pShmNode->h<0 || pDbFd->pInode->bProcessLock==0 );
if( pShmNode->nRegion<=iRegion ){
/* Minimum number of regions required to be mapped. */
nReqRegion = ((iRegion+nShmPerMap) / nShmPerMap) * nShmPerMap;
if( pShmNode->nRegion<nReqRegion ){
char **apNew; /* New apRegion[] array */
int nByte = (iRegion+1)*szRegion; /* Minimum required file size */
int nByte = nReqRegion*szRegion; /* Minimum required file size */
struct stat sStat; /* Used by fstat() */
pShmNode->szRegion = szRegion;
@@ -4392,17 +4432,19 @@ static int unixShmMap(
/* Map the requested memory region into this processes address space. */
apNew = (char **)sqlite3_realloc(
pShmNode->apRegion, (iRegion+1)*sizeof(char *)
pShmNode->apRegion, nReqRegion*sizeof(char *)
);
if( !apNew ){
rc = SQLITE_IOERR_NOMEM;
goto shmpage_out;
}
pShmNode->apRegion = apNew;
while(pShmNode->nRegion<=iRegion){
while( pShmNode->nRegion<nReqRegion ){
int nMap = szRegion*nShmPerMap;
int i;
void *pMem;
if( pShmNode->h>=0 ){
pMem = osMmap(0, szRegion,
pMem = osMmap(0, nMap,
pShmNode->isReadonly ? PROT_READ : PROT_READ|PROT_WRITE,
MAP_SHARED, pShmNode->h, szRegion*(i64)pShmNode->nRegion
);
@@ -4418,8 +4460,11 @@ static int unixShmMap(
}
memset(pMem, 0, szRegion);
}
pShmNode->apRegion[pShmNode->nRegion] = pMem;
pShmNode->nRegion++;
for(i=0; i<nShmPerMap; i++){
pShmNode->apRegion[pShmNode->nRegion+i] = &((char*)pMem)[szRegion*i];
}
pShmNode->nRegion += nShmPerMap;
}
}
@@ -4633,19 +4678,6 @@ static void unixUnmapfile(unixFile *pFd){
}
}
/*
** Return the system page size.
*/
static int unixGetPagesize(void){
#if HAVE_MREMAP
return 512;
#elif defined(_BSD_SOURCE)
return getpagesize();
#else
return (int)sysconf(_SC_PAGESIZE);
#endif
}
/*
** Attempt to set the size of the memory mapping maintained by file
** descriptor pFd to nNew bytes. Any existing mapping is discarded.
@@ -4682,8 +4714,12 @@ static void unixRemapfile(
if( (pFd->ctrlFlags & UNIXFILE_RDONLY)==0 ) flags |= PROT_WRITE;
if( pOrig ){
const int szSyspage = unixGetPagesize();
#if HAVE_MREMAP
i64 nReuse = pFd->mmapSize;
#else
const int szSyspage = osGetpagesize();
i64 nReuse = (pFd->mmapSize & ~(szSyspage-1));
#endif
u8 *pReq = &pOrig[nReuse];
/* Unmap any pages of the existing mapping that cannot be reused. */
@@ -7429,7 +7465,7 @@ int sqlite3_os_init(void){
/* Double-check that the aSyscall[] array has been constructed
** correctly. See ticket [bb3a86e890c8e96ab] */
assert( ArraySize(aSyscall)==24 );
assert( ArraySize(aSyscall)==25 );
/* Register all VFSes defined in the aVfs[] array */
for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){
+56 -8
View File
@@ -15,16 +15,16 @@
#include "sqliteInt.h"
#if SQLITE_OS_WIN /* This file is used for Windows only */
#ifdef __CYGWIN__
# include <sys/cygwin.h>
# include <errno.h> /* amalgamator: keep */
#endif
/*
** Include code that is common to all os_*.c files
*/
#include "os_common.h"
/*
** Include the header file for the Windows VFS.
*/
#include "os_win.h"
/*
** Compiling and using WAL mode requires several APIs that are only
** available in Windows platforms based on the NT kernel.
@@ -1836,6 +1836,32 @@ static int winLogErrorAtLine(
static int winIoerrRetry = SQLITE_WIN32_IOERR_RETRY;
static int winIoerrRetryDelay = SQLITE_WIN32_IOERR_RETRY_DELAY;
/*
** The "winIoerrCanRetry1" macro is used to determine if a particular I/O
** error code obtained via GetLastError() is eligible to be retried. It
** must accept the error code DWORD as its only argument and should return
** non-zero if the error code is transient in nature and the operation
** responsible for generating the original error might succeed upon being
** retried. The argument to this macro should be a variable.
**
** Additionally, a macro named "winIoerrCanRetry2" may be defined. If it
** is defined, it will be consulted only when the macro "winIoerrCanRetry1"
** returns zero. The "winIoerrCanRetry2" macro is completely optional and
** may be used to include additional error codes in the set that should
** result in the failing I/O operation being retried by the caller. If
** defined, the "winIoerrCanRetry2" macro must exhibit external semantics
** identical to those of the "winIoerrCanRetry1" macro.
*/
#if !defined(winIoerrCanRetry1)
#define winIoerrCanRetry1(a) (((a)==ERROR_ACCESS_DENIED) || \
((a)==ERROR_SHARING_VIOLATION) || \
((a)==ERROR_LOCK_VIOLATION) || \
((a)==ERROR_DEV_NOT_EXIST) || \
((a)==ERROR_NETNAME_DELETED) || \
((a)==ERROR_SEM_TIMEOUT) || \
((a)==ERROR_NETWORK_UNREACHABLE))
#endif
/*
** If a ReadFile() or WriteFile() error occurs, invoke this routine
** to see if it should be retried. Return TRUE to retry. Return FALSE
@@ -1849,13 +1875,18 @@ static int winRetryIoerr(int *pnRetry, DWORD *pError){
}
return 0;
}
if( e==ERROR_ACCESS_DENIED ||
e==ERROR_LOCK_VIOLATION ||
e==ERROR_SHARING_VIOLATION ){
if( winIoerrCanRetry1(e) ){
sqlite3_win32_sleep(winIoerrRetryDelay*(1+*pnRetry));
++*pnRetry;
return 1;
}
#if defined(winIoerrCanRetry2)
else if( winIoerrCanRetry2(e) ){
sqlite3_win32_sleep(winIoerrRetryDelay*(1+*pnRetry));
++*pnRetry;
return 1;
}
#endif
if( pError ){
*pError = e;
}
@@ -5137,8 +5168,25 @@ static int winFullPathname(
*/
static void *winDlOpen(sqlite3_vfs *pVfs, const char *zFilename){
HANDLE h;
#if defined(__CYGWIN__)
int nFull = pVfs->mxPathname+1;
char *zFull = sqlite3MallocZero( nFull );
void *zConverted = 0;
if( zFull==0 ){
OSTRACE(("DLOPEN name=%s, handle=%p\n", zFilename, (void*)0));
return 0;
}
if( winFullPathname(pVfs, zFilename, nFull, zFull)!=SQLITE_OK ){
sqlite3_free(zFull);
OSTRACE(("DLOPEN name=%s, handle=%p\n", zFilename, (void*)0));
return 0;
}
zConverted = winConvertFromUtf8Filename(zFull);
sqlite3_free(zFull);
#else
void *zConverted = winConvertFromUtf8Filename(zFilename);
UNUSED_PARAMETER(pVfs);
#endif
if( zConverted==0 ){
OSTRACE(("DLOPEN name=%s, handle=%p\n", zFilename, (void*)0));
return 0;
+67
View File
@@ -0,0 +1,67 @@
/*
** 2013 November 25
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
******************************************************************************
**
** This file contains code that is specific to Windows.
*/
#ifndef _OS_WIN_H_
#define _OS_WIN_H_
/*
** Include the primary Windows SDK header file.
*/
#include "windows.h"
#ifdef __CYGWIN__
# include <sys/cygwin.h>
# include <errno.h> /* amalgamator: dontcache */
#endif
/*
** Determine if we are dealing with Windows NT.
**
** We ought to be able to determine if we are compiling for Windows 9x or
** Windows NT using the _WIN32_WINNT macro as follows:
**
** #if defined(_WIN32_WINNT)
** # define SQLITE_OS_WINNT 1
** #else
** # define SQLITE_OS_WINNT 0
** #endif
**
** However, Visual Studio 2005 does not set _WIN32_WINNT by default, as
** it ought to, so the above test does not work. We'll just assume that
** everything is Windows NT unless the programmer explicitly says otherwise
** by setting SQLITE_OS_WINNT to 0.
*/
#if SQLITE_OS_WIN && !defined(SQLITE_OS_WINNT)
# define SQLITE_OS_WINNT 1
#endif
/*
** Determine if we are dealing with Windows CE - which has a much reduced
** API.
*/
#if defined(_WIN32_WCE)
# define SQLITE_OS_WINCE 1
#else
# define SQLITE_OS_WINCE 0
#endif
/*
** Determine if we are dealing with WinRT, which provides only a subset of
** the full Win32 API.
*/
#if !defined(SQLITE_OS_WINRT)
# define SQLITE_OS_WINRT 0
#endif
#endif /* _OS_WIN_H_ */
+10 -9
View File
@@ -1624,12 +1624,11 @@ static int writeMasterJournal(Pager *pPager, const char *zMaster){
if( !zMaster
|| pPager->journalMode==PAGER_JOURNALMODE_MEMORY
|| pPager->journalMode==PAGER_JOURNALMODE_OFF
|| !isOpen(pPager->jfd)
){
return SQLITE_OK;
}
pPager->setMaster = 1;
assert( isOpen(pPager->jfd) );
assert( pPager->journalHdr <= pPager->journalOff );
/* Calculate the length in bytes and the checksum of zMaster */
@@ -4889,15 +4888,17 @@ static int hasHotJournal(Pager *pPager, int *pExists){
if( rc==SQLITE_OK && !locked ){
Pgno nPage; /* Number of pages in database file */
/* Check the size of the database file. If it consists of 0 pages,
** then delete the journal file. See the header comment above for
** the reasoning here. Delete the obsolete journal file under
** a RESERVED lock to avoid race conditions and to avoid violating
** [H33020].
*/
rc = pagerPagecount(pPager, &nPage);
if( rc==SQLITE_OK ){
if( nPage==0 ){
/* If the database is zero pages in size, that means that either (1) the
** journal is a remnant from a prior database with the same name where
** the database file but not the journal was deleted, or (2) the initial
** transaction that populates a new database is being rolled back.
** In either case, the journal file can be deleted. However, take care
** not to delete the journal file if it is already open due to
** journal_mode=PERSIST.
*/
if( nPage==0 && !jrnlOpen ){
sqlite3BeginBenignMalloc();
if( pagerLockDb(pPager, RESERVED_LOCK)==SQLITE_OK ){
sqlite3OsDelete(pVfs, pPager->zJournal, 0);
+27
View File
@@ -1020,6 +1020,33 @@ expr(A) ::= expr(W) between_op(N) expr(X) AND expr(Y). [BETWEEN] {
*/
A.pExpr = sqlite3PExpr(pParse, TK_INTEGER, 0, 0, &sqlite3IntTokens[N]);
sqlite3ExprDelete(pParse->db, X.pExpr);
}else if( Y->nExpr==1 ){
/* Expressions of the form:
**
** expr1 IN (?1)
** expr1 NOT IN (?2)
**
** with exactly one value on the RHS can be simplified to something
** like this:
**
** expr1 == ?1
** expr1 <> ?2
**
** But, the RHS of the == or <> is marked with the EP_Generic flag
** so that it may not contribute to the computation of comparison
** affinity or the collating sequence to use for comparison. Otherwise,
** the semantics would be subtly different from IN or NOT IN.
*/
Expr *pRHS = Y->a[0].pExpr;
Y->a[0].pExpr = 0;
sqlite3ExprListDelete(pParse->db, Y);
/* pRHS cannot be NULL because a malloc error would have been detected
** before now and control would have never reached this point */
if( ALWAYS(pRHS) ){
pRHS->flags &= ~EP_Collate;
pRHS->flags |= EP_Generic;
}
A.pExpr = sqlite3PExpr(pParse, N ? TK_NE : TK_EQ, X.pExpr, pRHS, 0);
}else{
A.pExpr = sqlite3PExpr(pParse, TK_IN, X.pExpr, 0, 0);
if( A.pExpr ){
+9 -7
View File
@@ -824,7 +824,7 @@ void sqlite3Pragma(
** size of historical compatibility.
*/
case PragTyp_DEFAULT_CACHE_SIZE: {
static const int iLn = __LINE__+2;
static const int iLn = VDBE_OFFSET_LINENO(2);
static const VdbeOpList getCacheSize[] = {
{ OP_Transaction, 0, 0, 0}, /* 0 */
{ OP_ReadCookie, 0, 1, BTREE_DEFAULT_CACHE_SIZE}, /* 1 */
@@ -1087,7 +1087,7 @@ void sqlite3Pragma(
** file. Before writing to meta[6], check that meta[3] indicates
** that this really is an auto-vacuum capable database.
*/
static const int iLn = __LINE__+2;
static const int iLn = VDBE_OFFSET_LINENO(2);
static const VdbeOpList setMeta6[] = {
{ OP_Transaction, 0, 1, 0}, /* 0 */
{ OP_ReadCookie, 0, 1, BTREE_LARGEST_ROOT_PAGE},
@@ -1488,13 +1488,15 @@ void sqlite3Pragma(
sqlite3VdbeAddOp2(v, OP_Null, 0, 2);
sqlite3VdbeAddOp2(v, OP_Integer,
(int)sqlite3LogEstToInt(pTab->szTabRow), 3);
sqlite3VdbeAddOp2(v, OP_Integer, (int)pTab->nRowEst, 4);
sqlite3VdbeAddOp2(v, OP_Integer,
(int)sqlite3LogEstToInt(pTab->nRowLogEst), 4);
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 4);
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, pIdx->zName, 0);
sqlite3VdbeAddOp2(v, OP_Integer,
(int)sqlite3LogEstToInt(pIdx->szIdxRow), 3);
sqlite3VdbeAddOp2(v, OP_Integer, (int)pIdx->aiRowEst[0], 4);
sqlite3VdbeAddOp2(v, OP_Integer,
(int)sqlite3LogEstToInt(pIdx->aiRowLogEst[0]), 4);
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 4);
}
}
@@ -1790,7 +1792,7 @@ void sqlite3Pragma(
** messages have been generated, output OK. Otherwise output the
** error message
*/
static const int iLn = __LINE__+2;
static const int iLn = VDBE_OFFSET_LINENO(2);
static const VdbeOpList endCode[] = {
{ OP_AddImm, 1, 0, 0}, /* 0 */
{ OP_IfNeg, 1, 0, 0}, /* 1 */
@@ -1875,7 +1877,7 @@ void sqlite3Pragma(
sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0,
sqlite3MPrintf(db, "*** in database %s ***\n", db->aDb[i].zName),
P4_DYNAMIC);
sqlite3VdbeAddOp2(v, OP_Move, 2, 4);
sqlite3VdbeAddOp3(v, OP_Move, 2, 4, 1);
sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 2);
sqlite3VdbeAddOp2(v, OP_ResultRow, 2, 1);
sqlite3VdbeJumpHere(v, addr);
@@ -1928,7 +1930,7 @@ void sqlite3Pragma(
sqlite3VdbeAddOp0(v, OP_Halt);
sqlite3VdbeJumpHere(v, jmp4);
sqlite3VdbeJumpHere(v, jmp2);
sqlite3VdbeResolveLabel(v, jmp3);
sqlite3ResolvePartIdxLabel(pParse, jmp3);
}
sqlite3VdbeAddOp2(v, OP_Next, iDataCur, loopTop); VdbeCoverage(v);
sqlite3VdbeJumpHere(v, loopTop-1);
+84 -77
View File
@@ -134,20 +134,6 @@ static char et_getdigit(LONGDOUBLE_TYPE *val, int *cnt){
}
#endif /* SQLITE_OMIT_FLOATING_POINT */
/*
** Append N space characters to the given string buffer.
*/
void sqlite3AppendSpace(StrAccum *pAccum, int N){
static const char zSpaces[] = " ";
while( N>=(int)sizeof(zSpaces)-1 ){
sqlite3StrAccumAppend(pAccum, zSpaces, sizeof(zSpaces)-1);
N -= sizeof(zSpaces)-1;
}
if( N>0 ){
sqlite3StrAccumAppend(pAccum, zSpaces, N);
}
}
/*
** Set the StrAccum object to an error mode.
*/
@@ -237,11 +223,9 @@ void sqlite3VXPrintf(
}
for(; (c=(*fmt))!=0; ++fmt){
if( c!='%' ){
int amt;
bufpt = (char *)fmt;
amt = 1;
while( (c=(*++fmt))!='%' && c!=0 ) amt++;
sqlite3StrAccumAppend(pAccum, bufpt, amt);
while( (c=(*++fmt))!='%' && c!=0 ){};
sqlite3StrAccumAppend(pAccum, bufpt, (int)(fmt - bufpt));
if( c==0 ) break;
}
if( (c=(*++fmt))==0 ){
@@ -422,10 +406,8 @@ void sqlite3VXPrintf(
*(--bufpt) = zOrd[x*2];
}
{
register const char *cset; /* Use registers for speed */
register int base;
cset = &aDigits[infop->charset];
base = infop->base;
const char *cset = &aDigits[infop->charset];
u8 base = infop->base;
do{ /* Convert to ascii */
*(--bufpt) = cset[longvalue%base];
longvalue = longvalue/base;
@@ -729,29 +711,89 @@ void sqlite3VXPrintf(
** "length" characters long. The field width is "width". Do
** the output.
*/
if( !flag_leftjustify ){
register int nspace;
nspace = width-length;
if( nspace>0 ){
sqlite3AppendSpace(pAccum, nspace);
}
}
if( length>0 ){
sqlite3StrAccumAppend(pAccum, bufpt, length);
}
if( flag_leftjustify ){
register int nspace;
nspace = width-length;
if( nspace>0 ){
sqlite3AppendSpace(pAccum, nspace);
}
}
width -= length;
if( width>0 && !flag_leftjustify ) sqlite3AppendSpace(pAccum, width);
sqlite3StrAccumAppend(pAccum, bufpt, length);
if( width>0 && flag_leftjustify ) sqlite3AppendSpace(pAccum, width);
if( zExtra ) sqlite3_free(zExtra);
}/* End for loop over the format string */
} /* End of function */
/*
** Append N bytes of text from z to the StrAccum object.
** Enlarge the memory allocation on a StrAccum object so that it is
** able to accept at least N more bytes of text.
**
** Return the number of bytes of text that StrAccum is able to accept
** after the attempted enlargement. The value returned might be zero.
*/
static int sqlite3StrAccumEnlarge(StrAccum *p, int N){
char *zNew;
assert( p->nChar+N >= p->nAlloc ); /* Only called if really needed */
if( p->accError ){
testcase(p->accError==STRACCUM_TOOBIG);
testcase(p->accError==STRACCUM_NOMEM);
return 0;
}
if( !p->useMalloc ){
N = p->nAlloc - p->nChar - 1;
setStrAccumError(p, STRACCUM_TOOBIG);
return N;
}else{
char *zOld = (p->zText==p->zBase ? 0 : p->zText);
i64 szNew = p->nChar;
szNew += N + 1;
if( szNew > p->mxAlloc ){
sqlite3StrAccumReset(p);
setStrAccumError(p, STRACCUM_TOOBIG);
return 0;
}else{
p->nAlloc = (int)szNew;
}
if( p->useMalloc==1 ){
zNew = sqlite3DbRealloc(p->db, zOld, p->nAlloc);
}else{
zNew = sqlite3_realloc(zOld, p->nAlloc);
}
if( zNew ){
if( zOld==0 && p->nChar>0 ) memcpy(zNew, p->zText, p->nChar);
p->zText = zNew;
}else{
sqlite3StrAccumReset(p);
setStrAccumError(p, STRACCUM_NOMEM);
return 0;
}
}
return N;
}
/*
** Append N space characters to the given string buffer.
*/
void sqlite3AppendSpace(StrAccum *p, int N){
if( p->nChar+N >= p->nAlloc && (N = sqlite3StrAccumEnlarge(p, N))<=0 ) return;
while( (N--)>0 ) p->zText[p->nChar++] = ' ';
}
/*
** The StrAccum "p" is not large enough to accept N new bytes of z[].
** So enlarge if first, then do the append.
**
** This is a helper routine to sqlite3StrAccumAppend() that does special-case
** work (enlarging the buffer) using tail recursion, so that the
** sqlite3StrAccumAppend() routine can use fast calling semantics.
*/
static void enlargeAndAppend(StrAccum *p, const char *z, int N){
N = sqlite3StrAccumEnlarge(p, N);
if( N>0 ){
memcpy(&p->zText[p->nChar], z, N);
p->nChar += N;
}
}
/*
** Append N bytes of text from z to the StrAccum object. Increase the
** size of the memory allocation for StrAccum if necessary.
*/
void sqlite3StrAccumAppend(StrAccum *p, const char *z, int N){
assert( z!=0 );
@@ -759,43 +801,8 @@ void sqlite3StrAccumAppend(StrAccum *p, const char *z, int N){
assert( N>=0 );
assert( p->accError==0 || p->nAlloc==0 );
if( p->nChar+N >= p->nAlloc ){
char *zNew;
if( p->accError ){
testcase(p->accError==STRACCUM_TOOBIG);
testcase(p->accError==STRACCUM_NOMEM);
return;
}
if( !p->useMalloc ){
N = p->nAlloc - p->nChar - 1;
setStrAccumError(p, STRACCUM_TOOBIG);
if( N<=0 ){
return;
}
}else{
char *zOld = (p->zText==p->zBase ? 0 : p->zText);
i64 szNew = p->nChar;
szNew += N + 1;
if( szNew > p->mxAlloc ){
sqlite3StrAccumReset(p);
setStrAccumError(p, STRACCUM_TOOBIG);
return;
}else{
p->nAlloc = (int)szNew;
}
if( p->useMalloc==1 ){
zNew = sqlite3DbRealloc(p->db, zOld, p->nAlloc);
}else{
zNew = sqlite3_realloc(zOld, p->nAlloc);
}
if( zNew ){
if( zOld==0 && p->nChar>0 ) memcpy(zNew, p->zText, p->nChar);
p->zText = zNew;
}else{
sqlite3StrAccumReset(p);
setStrAccumError(p, STRACCUM_NOMEM);
return;
}
}
enlargeAndAppend(p,z,N);
return;
}
assert( p->zText );
memcpy(&p->zText[p->nChar], z, N);
+2
View File
@@ -337,6 +337,8 @@ static int lookupName(
}else if( op!=TK_INSERT && sqlite3StrICmp("old",zTab)==0 ){
pExpr->iTable = 0;
pTab = pParse->pTriggerTab;
}else{
pTab = 0;
}
if( pTab ){
+3 -3
View File
@@ -112,8 +112,8 @@ struct RowSet {
struct RowSetEntry *pFresh; /* Source of new entry objects */
struct RowSetEntry *pForest; /* List of binary trees of entries */
u16 nFresh; /* Number of objects on pFresh */
u8 rsFlags; /* Various flags */
u8 iBatch; /* Current insert batch */
u16 rsFlags; /* Various flags */
int iBatch; /* Current insert batch */
};
/*
@@ -447,7 +447,7 @@ int sqlite3RowSetNext(RowSet *p, i64 *pRowid){
** on pRowSet->pEntry, then sort those entires into the forest at
** pRowSet->pForest so that they can be tested.
*/
int sqlite3RowSetTest(RowSet *pRowSet, u8 iBatch, sqlite3_int64 iRowid){
int sqlite3RowSetTest(RowSet *pRowSet, int iBatch, sqlite3_int64 iRowid){
struct RowSetEntry *p, *pTree;
/* This routine is never called after sqlite3RowSetNext() */
+219 -119
View File
@@ -14,6 +14,34 @@
*/
#include "sqliteInt.h"
/*
** An instance of the following object is used to record information about
** how to process the DISTINCT keyword, to simplify passing that information
** into the selectInnerLoop() routine.
*/
typedef struct DistinctCtx DistinctCtx;
struct DistinctCtx {
u8 isTnct; /* True if the DISTINCT keyword is present */
u8 eTnctType; /* One of the WHERE_DISTINCT_* operators */
int tabTnct; /* Ephemeral table used for DISTINCT processing */
int addrTnct; /* Address of OP_OpenEphemeral opcode for tabTnct */
};
/*
** An instance of the following object is used to record information about
** the ORDER BY (or GROUP BY) clause of query is being coded.
*/
typedef struct SortCtx SortCtx;
struct SortCtx {
ExprList *pOrderBy; /* The ORDER BY (or GROUP BY clause) */
int nOBSat; /* Number of ORDER BY terms satisfied by indices */
int iECursor; /* Cursor number for the sorter */
int regReturn; /* Register holding block-output return address */
int labelBkOut; /* Start label for the block-output subroutine */
int addrSortIndex; /* Address of the OP_SorterOpen or OP_OpenEphemeral */
u8 sortFlags; /* Zero or more SORTFLAG_* bits */
};
#define SORTFLAG_UseSorter 0x01 /* Use SorterOpen instead of OpenEphemeral */
/*
** Delete all the content of a Select structure but do not deallocate
@@ -87,7 +115,6 @@ Select *sqlite3SelectNew(
assert( pOffset==0 || pLimit!=0 );
pNew->addrOpenEphm[0] = -1;
pNew->addrOpenEphm[1] = -1;
pNew->addrOpenEphm[2] = -1;
if( db->mallocFailed ) {
clearSelect(db, pNew);
if( pNew!=&standin ) sqlite3DbFree(db, pNew);
@@ -419,34 +446,73 @@ static int sqliteProcessJoin(Parse *pParse, Select *p){
return 0;
}
/* Forward reference */
static KeyInfo *keyInfoFromExprList(
Parse *pParse, /* Parsing context */
ExprList *pList, /* Form the KeyInfo object from this ExprList */
int iStart, /* Begin with this column of pList */
int nExtra /* Add this many extra columns to the end */
);
/*
** Insert code into "v" that will push the record on the top of the
** stack into the sorter.
** Insert code into "v" that will push the record in register regData
** into the sorter.
*/
static void pushOntoSorter(
Parse *pParse, /* Parser context */
ExprList *pOrderBy, /* The ORDER BY clause */
SortCtx *pSort, /* Information about the ORDER BY clause */
Select *pSelect, /* The whole SELECT statement */
int regData /* Register holding data to be sorted */
){
Vdbe *v = pParse->pVdbe;
int nExpr = pOrderBy->nExpr;
int regBase = sqlite3GetTempRange(pParse, nExpr+2);
int regRecord = sqlite3GetTempReg(pParse);
int nExpr = pSort->pOrderBy->nExpr;
int regRecord = ++pParse->nMem;
int regBase = pParse->nMem+1;
int nOBSat = pSort->nOBSat;
int op;
pParse->nMem += nExpr+2; /* nExpr+2 registers allocated at regBase */
sqlite3ExprCacheClear(pParse);
sqlite3ExprCodeExprList(pParse, pOrderBy, regBase, 0);
sqlite3VdbeAddOp2(v, OP_Sequence, pOrderBy->iECursor, regBase+nExpr);
sqlite3ExprCodeExprList(pParse, pSort->pOrderBy, regBase, 0);
sqlite3VdbeAddOp2(v, OP_Sequence, pSort->iECursor, regBase+nExpr);
sqlite3ExprCodeMove(pParse, regData, regBase+nExpr+1, 1);
sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nExpr + 2, regRecord);
if( pSelect->selFlags & SF_UseSorter ){
sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase+nOBSat, nExpr+2-nOBSat,regRecord);
if( nOBSat>0 ){
int regPrevKey; /* The first nOBSat columns of the previous row */
int addrFirst; /* Address of the OP_IfNot opcode */
int addrJmp; /* Address of the OP_Jump opcode */
VdbeOp *pOp; /* Opcode that opens the sorter */
int nKey; /* Number of sorting key columns, including OP_Sequence */
KeyInfo *pKI; /* Original KeyInfo on the sorter table */
regPrevKey = pParse->nMem+1;
pParse->nMem += pSort->nOBSat;
nKey = nExpr - pSort->nOBSat + 1;
addrFirst = sqlite3VdbeAddOp1(v, OP_IfNot, regBase+nExpr); VdbeCoverage(v);
sqlite3VdbeAddOp3(v, OP_Compare, regPrevKey, regBase, pSort->nOBSat);
pOp = sqlite3VdbeGetOp(v, pSort->addrSortIndex);
if( pParse->db->mallocFailed ) return;
pOp->p2 = nKey + 1;
pKI = pOp->p4.pKeyInfo;
memset(pKI->aSortOrder, 0, pKI->nField); /* Makes OP_Jump below testable */
sqlite3VdbeChangeP4(v, -1, (char*)pKI, P4_KEYINFO);
pOp->p4.pKeyInfo = keyInfoFromExprList(pParse, pSort->pOrderBy, nOBSat, 1);
addrJmp = sqlite3VdbeCurrentAddr(v);
sqlite3VdbeAddOp3(v, OP_Jump, addrJmp+1, 0, addrJmp+1); VdbeCoverage(v);
pSort->labelBkOut = sqlite3VdbeMakeLabel(v);
pSort->regReturn = ++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_Gosub, pSort->regReturn, pSort->labelBkOut);
sqlite3VdbeAddOp1(v, OP_ResetSorter, pSort->iECursor);
sqlite3VdbeJumpHere(v, addrFirst);
sqlite3VdbeAddOp3(v, OP_Move, regBase, regPrevKey, pSort->nOBSat);
sqlite3VdbeJumpHere(v, addrJmp);
}
if( pSort->sortFlags & SORTFLAG_UseSorter ){
op = OP_SorterInsert;
}else{
op = OP_IdxInsert;
}
sqlite3VdbeAddOp2(v, op, pOrderBy->iECursor, regRecord);
sqlite3ReleaseTempReg(pParse, regRecord);
sqlite3ReleaseTempRange(pParse, regBase, nExpr+2);
sqlite3VdbeAddOp2(v, op, pSort->iECursor, regRecord);
if( pSelect->iLimit ){
int addr1, addr2;
int iLimit;
@@ -459,8 +525,8 @@ static void pushOntoSorter(
sqlite3VdbeAddOp2(v, OP_AddImm, iLimit, -1);
addr2 = sqlite3VdbeAddOp0(v, OP_Goto);
sqlite3VdbeJumpHere(v, addr1);
sqlite3VdbeAddOp1(v, OP_Last, pOrderBy->iECursor);
sqlite3VdbeAddOp1(v, OP_Delete, pOrderBy->iECursor);
sqlite3VdbeAddOp1(v, OP_Last, pSort->iECursor);
sqlite3VdbeAddOp1(v, OP_Delete, pSort->iECursor);
sqlite3VdbeJumpHere(v, addr2);
}
}
@@ -473,7 +539,7 @@ static void codeOffset(
int iOffset, /* Register holding the offset counter */
int iContinue /* Jump here to skip the current record */
){
if( iOffset>0 && iContinue!=0 ){
if( iOffset>0 ){
int addr;
sqlite3VdbeAddOp2(v, OP_AddImm, iOffset, -1);
addr = sqlite3VdbeAddOp1(v, OP_IfNeg, iOffset); VdbeCoverage(v);
@@ -534,19 +600,6 @@ static int checkForMultiColumnSelectError(
}
#endif
/*
** An instance of the following object is used to record information about
** how to process the DISTINCT keyword, to simplify passing that information
** into the selectInnerLoop() routine.
*/
typedef struct DistinctCtx DistinctCtx;
struct DistinctCtx {
u8 isTnct; /* True if the DISTINCT keyword is present */
u8 eTnctType; /* One of the WHERE_DISTINCT_* operators */
int tabTnct; /* Ephemeral table used for DISTINCT processing */
int addrTnct; /* Address of OP_OpenEphemeral opcode for tabTnct */
};
/*
** This routine generates the code for the inside of the inner loop
** of a SELECT.
@@ -561,7 +614,7 @@ static void selectInnerLoop(
Select *p, /* The complete select statement being coded */
ExprList *pEList, /* List of values being extracted */
int srcTab, /* Pull data from this table */
ExprList *pOrderBy, /* If not NULL, sort results using this key */
SortCtx *pSort, /* If not NULL, info on how to process ORDER BY */
DistinctCtx *pDistinct, /* If not NULL, info on how to process DISTINCT */
SelectDest *pDest, /* How to dispose of the results */
int iContinue, /* Jump here to continue with next row */
@@ -578,7 +631,9 @@ static void selectInnerLoop(
assert( v );
assert( pEList!=0 );
hasDistinct = pDistinct ? pDistinct->eTnctType : WHERE_DISTINCT_NOOP;
if( pOrderBy==0 && !hasDistinct ){
if( pSort && pSort->pOrderBy==0 ) pSort = 0;
if( pSort==0 && !hasDistinct ){
assert( iContinue!=0 );
codeOffset(v, p->iOffset, iContinue);
}
@@ -668,7 +723,7 @@ static void selectInnerLoop(
break;
}
}
if( pOrderBy==0 ){
if( pSort==0 ){
codeOffset(v, p->iOffset, iContinue);
}
}
@@ -699,7 +754,8 @@ static void selectInnerLoop(
/* Store the result as data using a unique key.
*/
case SRT_DistTable:
case SRT_Fifo:
case SRT_DistFifo:
case SRT_Table:
case SRT_EphemTab: {
int r1 = sqlite3GetTempReg(pParse);
@@ -707,8 +763,8 @@ static void selectInnerLoop(
testcase( eDest==SRT_EphemTab );
sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nResultCol, r1);
#ifndef SQLITE_OMIT_CTE
if( eDest==SRT_DistTable ){
/* If the destination is DistTable, then cursor (iParm+1) is open
if( eDest==SRT_DistFifo ){
/* If the destination is DistFifo, then cursor (iParm+1) is open
** on an ephemeral index. If the current row is already present
** in the index, do not write it to the output. If not, add the
** current row to the index and proceed with writing it to the
@@ -716,11 +772,11 @@ static void selectInnerLoop(
int addr = sqlite3VdbeCurrentAddr(v) + 4;
sqlite3VdbeAddOp4Int(v, OP_Found, iParm+1, addr, r1, 0); VdbeCoverage(v);
sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm+1, r1);
assert( pOrderBy==0 );
assert( pSort==0 );
}
#endif
if( pOrderBy ){
pushOntoSorter(pParse, pOrderBy, p, r1);
if( pSort ){
pushOntoSorter(pParse, pSort, p, r1);
}else{
int r2 = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp2(v, OP_NewRowid, iParm, r2);
@@ -741,12 +797,12 @@ static void selectInnerLoop(
assert( nResultCol==1 );
pDest->affSdst =
sqlite3CompareAffinity(pEList->a[0].pExpr, pDest->affSdst);
if( pOrderBy ){
if( pSort ){
/* At first glance you would think we could optimize out the
** ORDER BY in this case since the order of entries in the set
** does not matter. But there might be a LIMIT clause, in which
** case the order does matter */
pushOntoSorter(pParse, pOrderBy, p, regResult);
pushOntoSorter(pParse, pSort, p, regResult);
}else{
int r1 = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp4(v, OP_MakeRecord, regResult,1,r1, &pDest->affSdst, 1);
@@ -771,8 +827,8 @@ static void selectInnerLoop(
*/
case SRT_Mem: {
assert( nResultCol==1 );
if( pOrderBy ){
pushOntoSorter(pParse, pOrderBy, p, regResult);
if( pSort ){
pushOntoSorter(pParse, pSort, p, regResult);
}else{
sqlite3ExprCodeMove(pParse, regResult, iParm, 1);
/* The LIMIT clause will jump out of the loop for us */
@@ -785,10 +841,10 @@ static void selectInnerLoop(
case SRT_Output: { /* Return the results */
testcase( eDest==SRT_Coroutine );
testcase( eDest==SRT_Output );
if( pOrderBy ){
if( pSort ){
int r1 = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nResultCol, r1);
pushOntoSorter(pParse, pOrderBy, p, r1);
pushOntoSorter(pParse, pSort, p, r1);
sqlite3ReleaseTempReg(pParse, r1);
}else if( eDest==SRT_Coroutine ){
sqlite3VdbeAddOp1(v, OP_Yield, pDest->iSDParm);
@@ -865,7 +921,7 @@ static void selectInnerLoop(
** there is a sorter, in which case the sorter has already limited
** the output for us.
*/
if( pOrderBy==0 && p->iLimit ){
if( pSort==0 && p->iLimit ){
sqlite3VdbeAddOp3(v, OP_IfZero, p->iLimit, iBreak, -1); VdbeCoverage(v);
}
}
@@ -936,7 +992,12 @@ int sqlite3KeyInfoIsWriteable(KeyInfo *p){ return p->nRef==1; }
** function is responsible for seeing that this structure is eventually
** freed.
*/
static KeyInfo *keyInfoFromExprList(Parse *pParse, ExprList *pList, int nExtra){
static KeyInfo *keyInfoFromExprList(
Parse *pParse, /* Parsing context */
ExprList *pList, /* Form the KeyInfo object from this ExprList */
int iStart, /* Begin with this column of pList */
int nExtra /* Add this many extra columns to the end */
){
int nExpr;
KeyInfo *pInfo;
struct ExprList_item *pItem;
@@ -944,15 +1005,15 @@ static KeyInfo *keyInfoFromExprList(Parse *pParse, ExprList *pList, int nExtra){
int i;
nExpr = pList->nExpr;
pInfo = sqlite3KeyInfoAlloc(db, nExpr+nExtra, 1);
pInfo = sqlite3KeyInfoAlloc(db, nExpr+nExtra-iStart, 1);
if( pInfo ){
assert( sqlite3KeyInfoIsWriteable(pInfo) );
for(i=0, pItem=pList->a; i<nExpr; i++, pItem++){
for(i=iStart, pItem=pList->a+iStart; i<nExpr; i++, pItem++){
CollSeq *pColl;
pColl = sqlite3ExprCollSeq(pParse, pItem->pExpr);
if( !pColl ) pColl = db->pDfltColl;
pInfo->aColl[i] = pColl;
pInfo->aSortOrder[i] = pItem->sortOrder;
pInfo->aColl[i-iStart] = pColl;
pInfo->aSortOrder[i-iStart] = pItem->sortOrder;
}
}
return pInfo;
@@ -1054,24 +1115,31 @@ static void explainComposite(
static void generateSortTail(
Parse *pParse, /* Parsing context */
Select *p, /* The SELECT statement */
Vdbe *v, /* Generate code into this VDBE */
SortCtx *pSort, /* Information on the ORDER BY clause */
int nColumn, /* Number of columns of data */
SelectDest *pDest /* Write the sorted results here */
){
Vdbe *v = pParse->pVdbe; /* The prepared statement */
int addrBreak = sqlite3VdbeMakeLabel(v); /* Jump here to exit loop */
int addrContinue = sqlite3VdbeMakeLabel(v); /* Jump here for next cycle */
int addr;
int addrOnce = 0;
int iTab;
int pseudoTab = 0;
ExprList *pOrderBy = p->pOrderBy;
ExprList *pOrderBy = pSort->pOrderBy;
int eDest = pDest->eDest;
int iParm = pDest->iSDParm;
int regRow;
int regRowid;
int nKey;
iTab = pOrderBy->iECursor;
if( pSort->labelBkOut ){
sqlite3VdbeAddOp2(v, OP_Gosub, pSort->regReturn, pSort->labelBkOut);
sqlite3VdbeAddOp2(v, OP_Goto, 0, addrBreak);
sqlite3VdbeResolveLabel(v, pSort->labelBkOut);
addrOnce = sqlite3CodeOnce(pParse); VdbeCoverage(v);
}
iTab = pSort->iECursor;
regRow = sqlite3GetTempReg(pParse);
if( eDest==SRT_Output || eDest==SRT_Coroutine ){
pseudoTab = pParse->nTab++;
@@ -1080,20 +1148,23 @@ static void generateSortTail(
}else{
regRowid = sqlite3GetTempReg(pParse);
}
if( p->selFlags & SF_UseSorter ){
nKey = pOrderBy->nExpr - pSort->nOBSat;
if( pSort->sortFlags & SORTFLAG_UseSorter ){
int regSortOut = ++pParse->nMem;
int ptab2 = pParse->nTab++;
sqlite3VdbeAddOp3(v, OP_OpenPseudo, ptab2, regSortOut, pOrderBy->nExpr+2);
sqlite3VdbeAddOp3(v, OP_OpenPseudo, ptab2, regSortOut, nKey+2);
if( addrOnce ) sqlite3VdbeJumpHere(v, addrOnce);
addr = 1 + sqlite3VdbeAddOp2(v, OP_SorterSort, iTab, addrBreak);
VdbeCoverage(v);
codeOffset(v, p->iOffset, addrContinue);
sqlite3VdbeAddOp2(v, OP_SorterData, iTab, regSortOut);
sqlite3VdbeAddOp3(v, OP_Column, ptab2, pOrderBy->nExpr+1, regRow);
sqlite3VdbeAddOp3(v, OP_Column, ptab2, nKey+1, regRow);
sqlite3VdbeChangeP5(v, OPFLAG_CLEARCACHE);
}else{
if( addrOnce ) sqlite3VdbeJumpHere(v, addrOnce);
addr = 1 + sqlite3VdbeAddOp2(v, OP_Sort, iTab, addrBreak); VdbeCoverage(v);
codeOffset(v, p->iOffset, addrContinue);
sqlite3VdbeAddOp3(v, OP_Column, iTab, pOrderBy->nExpr+1, regRow);
sqlite3VdbeAddOp3(v, OP_Column, iTab, nKey+1, regRow);
}
switch( eDest ){
case SRT_Table:
@@ -1148,11 +1219,12 @@ static void generateSortTail(
/* The bottom of the loop
*/
sqlite3VdbeResolveLabel(v, addrContinue);
if( p->selFlags & SF_UseSorter ){
if( pSort->sortFlags & SORTFLAG_UseSorter ){
sqlite3VdbeAddOp2(v, OP_SorterNext, iTab, addr); VdbeCoverage(v);
}else{
sqlite3VdbeAddOp2(v, OP_Next, iTab, addr); VdbeCoverage(v);
}
if( pSort->regReturn ) sqlite3VdbeAddOp1(v, OP_Return, pSort->regReturn);
sqlite3VdbeResolveLabel(v, addrBreak);
if( eDest==SRT_Output || eDest==SRT_Coroutine ){
sqlite3VdbeAddOp2(v, OP_Close, pseudoTab, 0);
@@ -1522,7 +1594,7 @@ static int selectColumnsFromExprList(
char *zNewName;
int k;
for(k=nName-1; k>1 && sqlite3Isdigit(zName[k]); k--){}
if( zName[k]==':' ) nName = k;
if( k>=0 && zName[k]==':' ) nName = k;
zName[nName] = 0;
zNewName = sqlite3MPrintf(db, "%s:%d", zName, ++cnt);
sqlite3DbFree(db, zName);
@@ -1616,7 +1688,7 @@ Table *sqlite3ResultSetOfSelect(Parse *pParse, Select *pSelect){
assert( db->lookaside.bEnabled==0 );
pTab->nRef = 1;
pTab->zName = 0;
pTab->nRowEst = 1048576;
pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) );
selectColumnsFromExprList(pParse, pSelect->pEList, &pTab->nCol, &pTab->aCol);
selectAddColumnTypeAndCollation(pParse, pTab, pSelect);
pTab->iPKey = -1;
@@ -1834,7 +1906,7 @@ static void generateWithRecursiveQuery(
int regCurrent; /* Register holding Current table */
int iQueue; /* The Queue table */
int iDistinct = 0; /* To ensure unique results if UNION */
int eDest = SRT_Table; /* How to write to Queue */
int eDest = SRT_Fifo; /* How to write to Queue */
SelectDest destQueue; /* SelectDest targetting the Queue table */
int i; /* Loop counter */
int rc; /* Result code */
@@ -1866,13 +1938,13 @@ static void generateWithRecursiveQuery(
/* Allocate cursors numbers for Queue and Distinct. The cursor number for
** the Distinct table must be exactly one greater than Queue in order
** for the SRT_DistTable and SRT_DistQueue destinations to work. */
** for the SRT_DistFifo and SRT_DistQueue destinations to work. */
iQueue = pParse->nTab++;
if( p->op==TK_UNION ){
eDest = pOrderBy ? SRT_DistQueue : SRT_DistTable;
eDest = pOrderBy ? SRT_DistQueue : SRT_DistFifo;
iDistinct = pParse->nTab++;
}else{
eDest = pOrderBy ? SRT_Queue : SRT_Table;
eDest = pOrderBy ? SRT_Queue : SRT_Fifo;
}
sqlite3SelectDestInit(&destQueue, eDest, iQueue);
@@ -1938,6 +2010,7 @@ static void generateWithRecursiveQuery(
sqlite3VdbeResolveLabel(v, addrBreak);
end_of_recursive_query:
sqlite3ExprListDelete(pParse->db, p->pOrderBy);
p->pOrderBy = pOrderBy;
p->pLimit = pLimit;
p->pOffset = pOffset;
@@ -3754,7 +3827,7 @@ static int withExpand(
pTab->nRef = 1;
pTab->zName = sqlite3DbStrDup(db, pCte->zName);
pTab->iPKey = -1;
pTab->nRowEst = 1048576;
pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) );
pTab->tabFlags |= TF_Ephemeral;
pFrom->pSelect = sqlite3SelectDup(db, pCte->pSelect, 0);
if( db->mallocFailed ) return SQLITE_NOMEM;
@@ -3930,7 +4003,7 @@ static int selectExpander(Walker *pWalker, Select *p){
while( pSel->pPrior ){ pSel = pSel->pPrior; }
selectColumnsFromExprList(pParse, pSel->pEList, &pTab->nCol, &pTab->aCol);
pTab->iPKey = -1;
pTab->nRowEst = 1048576;
pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) );
pTab->tabFlags |= TF_Ephemeral;
#endif
}else{
@@ -4309,7 +4382,7 @@ static void resetAccumulator(Parse *pParse, AggInfo *pAggInfo){
"argument");
pFunc->iDistinct = -1;
}else{
KeyInfo *pKeyInfo = keyInfoFromExprList(pParse, pE->x.pList, 0);
KeyInfo *pKeyInfo = keyInfoFromExprList(pParse, pE->x.pList, 0, 0);
sqlite3VdbeAddOp4(v, OP_OpenEphemeral, pFunc->iDistinct, 0, 0,
(char*)pKeyInfo, P4_KEYINFO);
}
@@ -4464,12 +4537,11 @@ int sqlite3Select(
ExprList *pEList; /* List of columns to extract. */
SrcList *pTabList; /* List of tables to select from */
Expr *pWhere; /* The WHERE clause. May be NULL */
ExprList *pOrderBy; /* The ORDER BY clause. May be NULL */
ExprList *pGroupBy; /* The GROUP BY clause. May be NULL */
Expr *pHaving; /* The HAVING clause. May be NULL */
int rc = 1; /* Value to return from this function */
int addrSortIndex; /* Address of an OP_OpenEphemeral instruction */
DistinctCtx sDistinct; /* Info on how to code the DISTINCT keyword */
SortCtx sSort; /* Info on how to code the ORDER BY clause */
AggInfo sAggInfo; /* Information used by aggregate queries */
int iEnd; /* Address of the end of the query */
sqlite3 *db; /* The database connection */
@@ -4486,9 +4558,15 @@ int sqlite3Select(
if( sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0) ) return 1;
memset(&sAggInfo, 0, sizeof(sAggInfo));
assert( p->pOrderBy==0 || pDest->eDest!=SRT_DistFifo );
assert( p->pOrderBy==0 || pDest->eDest!=SRT_Fifo );
assert( p->pOrderBy==0 || pDest->eDest!=SRT_DistQueue );
assert( p->pOrderBy==0 || pDest->eDest!=SRT_Queue );
if( IgnorableOrderby(pDest) ){
assert(pDest->eDest==SRT_Exists || pDest->eDest==SRT_Union ||
pDest->eDest==SRT_Except || pDest->eDest==SRT_Discard);
pDest->eDest==SRT_Except || pDest->eDest==SRT_Discard ||
pDest->eDest==SRT_Queue || pDest->eDest==SRT_DistFifo ||
pDest->eDest==SRT_DistQueue || pDest->eDest==SRT_Fifo);
/* If ORDER BY makes no difference in the output then neither does
** DISTINCT so it can be removed too. */
sqlite3ExprListDelete(db, p->pOrderBy);
@@ -4496,7 +4574,8 @@ int sqlite3Select(
p->selFlags &= ~SF_Distinct;
}
sqlite3SelectPrep(pParse, p, 0);
pOrderBy = p->pOrderBy;
memset(&sSort, 0, sizeof(sSort));
sSort.pOrderBy = p->pOrderBy;
pTabList = p->pSrc;
pEList = p->pEList;
if( pParse->nErr || db->mallocFailed ){
@@ -4574,7 +4653,7 @@ int sqlite3Select(
sqlite3SelectDestInit(&dest, SRT_Coroutine, pItem->regReturn);
explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId);
sqlite3Select(pParse, pSub, &dest);
pItem->pTab->nRowEst = (unsigned)pSub->nSelectRow;
pItem->pTab->nRowLogEst = sqlite3LogEst(pSub->nSelectRow);
pItem->viaCoroutine = 1;
pItem->regResult = dest.iSdst;
sqlite3VdbeAddOp1(v, OP_EndCoroutine, pItem->regReturn);
@@ -4605,7 +4684,7 @@ int sqlite3Select(
sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor);
explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId);
sqlite3Select(pParse, pSub, &dest);
pItem->pTab->nRowEst = (unsigned)pSub->nSelectRow;
pItem->pTab->nRowLogEst = sqlite3LogEst(pSub->nSelectRow);
if( onceAddr ) sqlite3VdbeJumpHere(v, onceAddr);
retAddr = sqlite3VdbeAddOp1(v, OP_Return, pItem->regReturn);
VdbeComment((v, "end %s", pItem->pTab->zName));
@@ -4618,7 +4697,7 @@ int sqlite3Select(
pParse->nHeight -= sqlite3SelectExprHeight(p);
pTabList = p->pSrc;
if( !IgnorableOrderby(pDest) ){
pOrderBy = p->pOrderBy;
sSort.pOrderBy = p->pOrderBy;
}
}
pEList = p->pEList;
@@ -4638,18 +4717,6 @@ int sqlite3Select(
}
#endif
/* If there is both a GROUP BY and an ORDER BY clause and they are
** identical, then disable the ORDER BY clause since the GROUP BY
** will cause elements to come out in the correct order. This is
** an optimization - the correct answer should result regardless.
** Use the SQLITE_GroupByOrder flag with SQLITE_TESTCTRL_OPTIMIZER
** to disable this optimization for testing purposes.
*/
if( sqlite3ExprListCompare(p->pGroupBy, pOrderBy, -1)==0
&& OptimizationEnabled(db, SQLITE_GroupByOrder) ){
pOrderBy = 0;
}
/* If the query is DISTINCT with an ORDER BY but is not an aggregate, and
** if the select-list is the same as the ORDER BY list, then this query
** can be rewritten as a GROUP BY. In other words, this:
@@ -4666,12 +4733,12 @@ int sqlite3Select(
** BY and DISTINCT, and an index or separate temp-table for the other.
*/
if( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct
&& sqlite3ExprListCompare(pOrderBy, p->pEList, -1)==0
&& sqlite3ExprListCompare(sSort.pOrderBy, p->pEList, -1)==0
){
p->selFlags &= ~SF_Distinct;
p->pGroupBy = sqlite3ExprListDup(db, p->pEList, 0);
pGroupBy = p->pGroupBy;
pOrderBy = 0;
sSort.pOrderBy = 0;
/* Notice that even thought SF_Distinct has been cleared from p->selFlags,
** the sDistinct.isTnct is still set. Hence, isTnct represents the
** original setting of the SF_Distinct flag, not the current setting */
@@ -4685,16 +4752,16 @@ int sqlite3Select(
** we figure out that the sorting index is not needed. The addrSortIndex
** variable is used to facilitate that change.
*/
if( pOrderBy ){
if( sSort.pOrderBy ){
KeyInfo *pKeyInfo;
pKeyInfo = keyInfoFromExprList(pParse, pOrderBy, 0);
pOrderBy->iECursor = pParse->nTab++;
p->addrOpenEphm[2] = addrSortIndex =
pKeyInfo = keyInfoFromExprList(pParse, sSort.pOrderBy, 0, 0);
sSort.iECursor = pParse->nTab++;
sSort.addrSortIndex =
sqlite3VdbeAddOp4(v, OP_OpenEphemeral,
pOrderBy->iECursor, pOrderBy->nExpr+2, 0,
sSort.iECursor, sSort.pOrderBy->nExpr+2, 0,
(char*)pKeyInfo, P4_KEYINFO);
}else{
addrSortIndex = -1;
sSort.addrSortIndex = -1;
}
/* If the output is destined for a temporary table, open that table.
@@ -4708,9 +4775,9 @@ int sqlite3Select(
iEnd = sqlite3VdbeMakeLabel(v);
p->nSelectRow = LARGEST_INT64;
computeLimitRegisters(pParse, p, iEnd);
if( p->iLimit==0 && addrSortIndex>=0 ){
sqlite3VdbeGetOp(v, addrSortIndex)->opcode = OP_SorterOpen;
p->selFlags |= SF_UseSorter;
if( p->iLimit==0 && sSort.addrSortIndex>=0 ){
sqlite3VdbeGetOp(v, sSort.addrSortIndex)->opcode = OP_SorterOpen;
sSort.sortFlags |= SORTFLAG_UseSorter;
}
/* Open a virtual index to use for the distinct set.
@@ -4719,7 +4786,7 @@ int sqlite3Select(
sDistinct.tabTnct = pParse->nTab++;
sDistinct.addrTnct = sqlite3VdbeAddOp4(v, OP_OpenEphemeral,
sDistinct.tabTnct, 0, 0,
(char*)keyInfoFromExprList(pParse, p->pEList, 0),
(char*)keyInfoFromExprList(pParse, p->pEList,0,0),
P4_KEYINFO);
sqlite3VdbeChangeP5(v, BTREE_UNORDERED);
sDistinct.eTnctType = WHERE_DISTINCT_UNORDERED;
@@ -4732,8 +4799,8 @@ int sqlite3Select(
u16 wctrlFlags = (sDistinct.isTnct ? WHERE_WANT_DISTINCT : 0);
/* Begin the database scan. */
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pOrderBy, p->pEList,
wctrlFlags, 0);
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, sSort.pOrderBy,
p->pEList, wctrlFlags, 0);
if( pWInfo==0 ) goto select_end;
if( sqlite3WhereOutputRowCount(pWInfo) < p->nSelectRow ){
p->nSelectRow = sqlite3WhereOutputRowCount(pWInfo);
@@ -4741,19 +4808,23 @@ int sqlite3Select(
if( sDistinct.isTnct && sqlite3WhereIsDistinct(pWInfo) ){
sDistinct.eTnctType = sqlite3WhereIsDistinct(pWInfo);
}
if( pOrderBy && sqlite3WhereIsOrdered(pWInfo) ) pOrderBy = 0;
if( sSort.pOrderBy ){
sSort.nOBSat = sqlite3WhereIsOrdered(pWInfo);
if( sSort.nOBSat==sSort.pOrderBy->nExpr ){
sSort.pOrderBy = 0;
}
}
/* If sorting index that was created by a prior OP_OpenEphemeral
** instruction ended up not being needed, then change the OP_OpenEphemeral
** into an OP_Noop.
*/
if( addrSortIndex>=0 && pOrderBy==0 ){
sqlite3VdbeChangeToNoop(v, addrSortIndex);
p->addrOpenEphm[2] = -1;
if( sSort.addrSortIndex>=0 && sSort.pOrderBy==0 ){
sqlite3VdbeChangeToNoop(v, sSort.addrSortIndex);
}
/* Use the standard inner loop. */
selectInnerLoop(pParse, p, pEList, -1, pOrderBy, &sDistinct, pDest,
selectInnerLoop(pParse, p, pEList, -1, &sSort, &sDistinct, pDest,
sqlite3WhereContinueLabel(pWInfo),
sqlite3WhereBreakLabel(pWInfo));
@@ -4774,6 +4845,7 @@ int sqlite3Select(
int addrEnd; /* End of processing for this SELECT */
int sortPTab = 0; /* Pseudotable used to decode sorting results */
int sortOut = 0; /* Output register from the sorter */
int orderByGrp = 0; /* True if the GROUP BY and ORDER BY are the same */
/* Remove any and all aliases between the result set and the
** GROUP BY clause.
@@ -4793,6 +4865,18 @@ int sqlite3Select(
p->nSelectRow = 1;
}
/* If there is both a GROUP BY and an ORDER BY clause and they are
** identical, then it may be possible to disable the ORDER BY clause
** on the grounds that the GROUP BY will cause elements to come out
** in the correct order. It also may not - the GROUP BY may use a
** database index that causes rows to be grouped together as required
** but not actually sorted. Either way, record the fact that the
** ORDER BY and GROUP BY clauses are the same by setting the orderByGrp
** variable. */
if( sqlite3ExprListCompare(pGroupBy, sSort.pOrderBy, -1)==0 ){
orderByGrp = 1;
}
/* Create a label to jump to when we want to abort the query */
addrEnd = sqlite3VdbeMakeLabel(v);
@@ -4809,7 +4893,7 @@ int sqlite3Select(
sAggInfo.nSortingColumn = pGroupBy ? pGroupBy->nExpr+1 : 0;
sAggInfo.pGroupBy = pGroupBy;
sqlite3ExprAnalyzeAggList(&sNC, pEList);
sqlite3ExprAnalyzeAggList(&sNC, pOrderBy);
sqlite3ExprAnalyzeAggList(&sNC, sSort.pOrderBy);
if( pHaving ){
sqlite3ExprAnalyzeAggregates(&sNC, pHaving);
}
@@ -4843,7 +4927,7 @@ int sqlite3Select(
** will be converted into a Noop.
*/
sAggInfo.sortingIdx = pParse->nTab++;
pKeyInfo = keyInfoFromExprList(pParse, pGroupBy, 0);
pKeyInfo = keyInfoFromExprList(pParse, pGroupBy, 0, 0);
addrSortingIdx = sqlite3VdbeAddOp4(v, OP_SorterOpen,
sAggInfo.sortingIdx, sAggInfo.nSortingColumn,
0, (char*)pKeyInfo, P4_KEYINFO);
@@ -4872,10 +4956,11 @@ int sqlite3Select(
** in the right order to begin with.
*/
sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset);
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pGroupBy, 0,
WHERE_GROUPBY, 0);
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pGroupBy, 0,
WHERE_GROUPBY | (orderByGrp ? WHERE_SORTBYGROUP : 0), 0
);
if( pWInfo==0 ) goto select_end;
if( sqlite3WhereIsOrdered(pWInfo) ){
if( sqlite3WhereIsOrdered(pWInfo)==pGroupBy->nExpr ){
/* The optimizer is able to deliver rows in group by order so
** we do not have to sort. The OP_OpenEphemeral table will be
** cancelled later because we still need to use the pKeyInfo
@@ -4938,6 +5023,21 @@ int sqlite3Select(
VdbeComment((v, "GROUP BY sort")); VdbeCoverage(v);
sAggInfo.useSortingIdx = 1;
sqlite3ExprCacheClear(pParse);
}
/* If the index or temporary table used by the GROUP BY sort
** will naturally deliver rows in the order required by the ORDER BY
** clause, cancel the ephemeral table open coded earlier.
**
** This is an optimization - the correct answer should result regardless.
** Use the SQLITE_GroupByOrder flag with SQLITE_TESTCTRL_OPTIMIZER to
** disable this optimization for testing purposes. */
if( orderByGrp && OptimizationEnabled(db, SQLITE_GroupByOrder)
&& (groupBySort || sqlite3WhereIsSorted(pWInfo))
){
sSort.pOrderBy = 0;
sqlite3VdbeChangeToNoop(v, sSort.addrSortIndex);
}
/* Evaluate the current GROUP BY terms and store in b0, b1, b2...
@@ -5026,7 +5126,7 @@ int sqlite3Select(
sqlite3VdbeAddOp1(v, OP_Return, regOutputRow);
finalizeAggFunctions(pParse, &sAggInfo);
sqlite3ExprIfFalse(pParse, pHaving, addrOutputRow+1, SQLITE_JUMPIFNULL);
selectInnerLoop(pParse, p, p->pEList, -1, pOrderBy,
selectInnerLoop(pParse, p, p->pEList, -1, &sSort,
&sDistinct, pDest,
addrOutputRow+1, addrSetAbort);
sqlite3VdbeAddOp1(v, OP_Return, regOutputRow);
@@ -5158,7 +5258,7 @@ int sqlite3Select(
}
updateAccumulator(pParse, &sAggInfo);
assert( pMinMax==0 || pMinMax->nExpr==1 );
if( sqlite3WhereIsOrdered(pWInfo) ){
if( sqlite3WhereIsOrdered(pWInfo)>0 ){
sqlite3VdbeAddOp2(v, OP_Goto, 0, sqlite3WhereBreakLabel(pWInfo));
VdbeComment((v, "%s() by index",
(flag==WHERE_ORDERBY_MIN?"min":"max")));
@@ -5167,7 +5267,7 @@ int sqlite3Select(
finalizeAggFunctions(pParse, &sAggInfo);
}
pOrderBy = 0;
sSort.pOrderBy = 0;
sqlite3ExprIfFalse(pParse, pHaving, addrEnd, SQLITE_JUMPIFNULL);
selectInnerLoop(pParse, p, p->pEList, -1, 0, 0,
pDest, addrEnd, addrEnd);
@@ -5184,9 +5284,9 @@ int sqlite3Select(
/* If there is an ORDER BY clause, then we need to sort the results
** and send them to the callback one by one.
*/
if( pOrderBy ){
explainTempTable(pParse, "ORDER BY");
generateSortTail(pParse, p, v, pEList->nExpr, pDest);
if( sSort.pOrderBy ){
explainTempTable(pParse, sSort.nOBSat>0 ? "RIGHT PART OF ORDER BY":"ORDER BY");
generateSortTail(pParse, p, &sSort, pEList->nExpr, pDest);
}
/* Jump here to skip this query
+14 -6
View File
@@ -1184,6 +1184,7 @@ static int str_in_array(const char *zStr, const char **azArray){
** * For each "Goto", if the jump destination is earlier in the program
** and ends on one of:
** Yield SeekGt SeekLt RowSetRead Rewind
** or if the P1 parameter is one instead of zero,
** then indent all opcodes between the earlier instruction
** and "Goto" by 2 spaces.
*/
@@ -1194,7 +1195,8 @@ static void explain_data_prepare(struct callback_data *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", 0 };
const char *azNext[] = { "Next", "Prev", "VPrev", "VNext", "SorterNext",
"NextIfOpen", "PrevIfOpen", 0 };
const char *azYield[] = { "Yield", "SeekLt", "SeekGt", "RowSetRead", "Rewind", 0 };
const char *azGoto[] = { "Goto", 0 };
@@ -1231,7 +1233,9 @@ static void explain_data_prepare(struct callback_data *p, sqlite3_stmt *pSql){
if( str_in_array(zOp, azNext) ){
for(i=p2op; i<iOp; i++) p->aiIndent[i] += 2;
}
if( str_in_array(zOp, azGoto) && p2op<p->nIndent && abYield[p2op] ){
if( str_in_array(zOp, azGoto) && p2op<p->nIndent
&& (abYield[p2op] || sqlite3_column_int(pSql, 2))
){
for(i=p2op+1; i<iOp; i++) p->aiIndent[i] += 2;
}
}
@@ -2126,10 +2130,12 @@ static void tryToClone(struct callback_data *p, const char *zNewDb){
fprintf(stderr, "Cannot create output database: %s\n",
sqlite3_errmsg(newDb));
}else{
sqlite3_exec(p->db, "PRAGMA writable_schema=ON;", 0, 0, 0);
sqlite3_exec(newDb, "BEGIN EXCLUSIVE;", 0, 0, 0);
tryToCloneSchema(p, newDb, "type='table'", tryToCloneData);
tryToCloneSchema(p, newDb, "type!='table'", 0);
sqlite3_exec(newDb, "COMMIT;", 0, 0, 0);
sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0);
}
sqlite3_close(newDb);
}
@@ -3021,6 +3027,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){
{ "optimizations", SQLITE_TESTCTRL_OPTIMIZATIONS },
{ "iskeyword", SQLITE_TESTCTRL_ISKEYWORD },
{ "scratchmalloc", SQLITE_TESTCTRL_SCRATCHMALLOC },
{ "byteorder", SQLITE_TESTCTRL_BYTEORDER },
};
int testctrl = -1;
int rc = 0;
@@ -3061,9 +3068,10 @@ static int do_meta_command(char *zLine, struct callback_data *p){
break;
/* sqlite3_test_control(int) */
case SQLITE_TESTCTRL_PRNG_SAVE:
case SQLITE_TESTCTRL_PRNG_RESTORE:
case SQLITE_TESTCTRL_PRNG_SAVE:
case SQLITE_TESTCTRL_PRNG_RESTORE:
case SQLITE_TESTCTRL_PRNG_RESET:
case SQLITE_TESTCTRL_BYTEORDER:
if( nArg==2 ){
rc = sqlite3_test_control(testctrl);
fprintf(p->out, "%d (0x%08x)\n", rc, rc);
@@ -3817,8 +3825,8 @@ int main(int argc, char **argv){
);
if( warnInmemoryDb ){
printf("Connected to a ");
printBold("transient in-memory database.");
printf("\nUse \".open FILENAME\" to reopen on a "
printBold("transient in-memory database");
printf(".\nUse \".open FILENAME\" to reopen on a "
"persistent database.\n");
}
zHome = find_home_dir();
+2 -1
View File
@@ -6118,7 +6118,8 @@ int sqlite3_test_control(int op, ...);
#define SQLITE_TESTCTRL_EXPLAIN_STMT 19
#define SQLITE_TESTCTRL_NEVER_CORRUPT 20
#define SQLITE_TESTCTRL_VDBE_COVERAGE 21
#define SQLITE_TESTCTRL_LAST 21
#define SQLITE_TESTCTRL_BYTEORDER 22
#define SQLITE_TESTCTRL_LAST 22
/*
** CAPI3REF: SQLite Runtime Status
+91 -37
View File
@@ -47,8 +47,41 @@
# define _LARGEFILE_SOURCE 1
#endif
/*
** For MinGW, check to see if we can include the header file containing its
** version information, among other things. Normally, this internal MinGW
** header file would [only] be included automatically by other MinGW header
** files; however, the contained version information is now required by this
** header file to work around binary compatibility issues (see below) and
** this is the only known way to reliably obtain it. This entire #if block
** would be completely unnecessary if there was any other way of detecting
** MinGW via their preprocessor (e.g. if they customized their GCC to define
** some MinGW-specific macros). When compiling for MinGW, either the
** _HAVE_MINGW_H or _HAVE__MINGW_H (note the extra underscore) macro must be
** defined; otherwise, detection of conditions specific to MinGW will be
** disabled.
*/
#if defined(_HAVE_MINGW_H)
# include "mingw.h"
#elif defined(_HAVE__MINGW_H)
# include "_mingw.h"
#endif
/*
** For MinGW version 4.x (and higher), check to see if the _USE_32BIT_TIME_T
** define is required to maintain binary compatibility with the MSVC runtime
** library in use (e.g. for Windows XP).
*/
#if !defined(_USE_32BIT_TIME_T) && !defined(_USE_64BIT_TIME_T) && \
defined(_WIN32) && !defined(_WIN64) && \
defined(__MINGW_MAJOR_VERSION) && __MINGW_MAJOR_VERSION >= 4 && \
defined(__MSVCRT__)
# define _USE_32BIT_TIME_T
#endif
/* The public SQLite interface. The _FILE_OFFSET_BITS macro must appear
** first in QNX.
** first in QNX. Also, the _USE_32BIT_TIME_T macro must appear first for
** MinGW.
*/
#include "sqlite3.h"
@@ -492,10 +525,10 @@ typedef INT8_TYPE i8; /* 1-byte signed integer */
** gives a possible range of values of approximately 1.0e986 to 1e-986.
** But the allowed values are "grainy". Not every value is representable.
** For example, quantities 16 and 17 are both represented by a LogEst
** of 40. However, since LogEst quantatites are suppose to be estimates,
** of 40. However, since LogEst quantaties are suppose to be estimates,
** not exact values, this imprecision is not a problem.
**
** "LogEst" is short for "Logarithimic Estimate".
** "LogEst" is short for "Logarithmic Estimate".
**
** Examples:
** 1 -> 0 20 -> 43 10000 -> 132
@@ -513,22 +546,39 @@ typedef INT16_TYPE LogEst;
/*
** Macros to determine whether the machine is big or little endian,
** evaluated at runtime.
** and whether or not that determination is run-time or compile-time.
**
** For best performance, an attempt is made to guess at the byte-order
** using C-preprocessor macros. If that is unsuccessful, or if
** -DSQLITE_RUNTIME_BYTEORDER=1 is set, then byte-order is determined
** at run-time.
*/
#ifdef SQLITE_AMALGAMATION
const int sqlite3one = 1;
#else
extern const int sqlite3one;
#endif
#if defined(i386) || defined(__i386__) || defined(_M_IX86)\
|| defined(__x86_64) || defined(__x86_64__)
#if (defined(i386) || defined(__i386__) || defined(_M_IX86) || \
defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || \
defined(_M_AMD64) || defined(_M_ARM) || defined(__x86) || \
defined(__arm__)) && !defined(SQLITE_RUNTIME_BYTEORDER)
# define SQLITE_BYTEORDER 1234
# define SQLITE_BIGENDIAN 0
# define SQLITE_LITTLEENDIAN 1
# define SQLITE_UTF16NATIVE SQLITE_UTF16LE
#else
#endif
#if (defined(sparc) || defined(__ppc__)) \
&& !defined(SQLITE_RUNTIME_BYTEORDER)
# define SQLITE_BYTEORDER 4321
# define SQLITE_BIGENDIAN 1
# define SQLITE_LITTLEENDIAN 0
# define SQLITE_UTF16NATIVE SQLITE_UTF16BE
#endif
#if !defined(SQLITE_BYTEORDER)
# define SQLITE_BYTEORDER 0 /* 0 means "unknown at compile-time" */
# define SQLITE_BIGENDIAN (*(char *)(&sqlite3one)==0)
# define SQLITE_LITTLEENDIAN (*(char *)(&sqlite3one)==1)
# define SQLITE_UTF16NATIVE (SQLITE_BIGENDIAN?SQLITE_UTF16BE:SQLITE_UTF16LE)
# define SQLITE_UTF16NATIVE (SQLITE_BIGENDIAN?SQLITE_UTF16BE:SQLITE_UTF16LE)
#endif
/*
@@ -1421,7 +1471,7 @@ struct Table {
#ifndef SQLITE_OMIT_CHECK
ExprList *pCheck; /* All CHECK constraints */
#endif
tRowcnt nRowEst; /* Estimated rows in table - from sqlite_stat1 table */
LogEst nRowLogEst; /* Estimated rows in table - from sqlite_stat1 table */
int tnum; /* Root BTree node for this table (see note above) */
i16 iPKey; /* If not negative, use aCol[iPKey] as the primary key */
i16 nCol; /* Number of columns in this table */
@@ -1594,6 +1644,7 @@ struct UnpackedRecord {
KeyInfo *pKeyInfo; /* Collation and sort-order information */
u16 nField; /* Number of entries in apMem[] */
i8 default_rc; /* Comparison result if keys are equal */
u8 isCorrupt; /* Corruption detected by xRecordCompare() */
Mem *aMem; /* Values */
int r1; /* Value to return if (lhs > rhs) */
int r2; /* Value to return if (rhs < lhs) */
@@ -1629,7 +1680,7 @@ struct UnpackedRecord {
struct Index {
char *zName; /* Name of this index */
i16 *aiColumn; /* Which columns are used by this index. 1st is 0 */
tRowcnt *aiRowEst; /* From ANALYZE: Est. rows selected by each column */
LogEst *aiRowLogEst; /* From ANALYZE: Est. rows selected by each column */
Table *pTable; /* The SQL table being indexed */
char *zColAff; /* String defining the affinity of each column */
Index *pNext; /* The next index associated with the same table */
@@ -1860,8 +1911,8 @@ struct Expr {
#define EP_VarSelect 0x000020 /* pSelect is correlated, not constant */
#define EP_DblQuoted 0x000040 /* token.z was originally in "..." */
#define EP_InfixFunc 0x000080 /* True for an infix function: LIKE, GLOB, etc */
#define EP_Collate 0x000100 /* Tree contains a TK_COLLATE opeartor */
/* unused 0x000200 */
#define EP_Collate 0x000100 /* Tree contains a TK_COLLATE operator */
#define EP_Generic 0x000200 /* Ignore COLLATE or affinity on this tree */
#define EP_IntValue 0x000400 /* Integer value contained in u.iValue */
#define EP_xIsSelect 0x000800 /* x.pSelect is valid (otherwise x.pList is) */
#define EP_Skip 0x001000 /* COLLATE, AS, or UNLIKELY */
@@ -1925,7 +1976,6 @@ struct Expr {
*/
struct ExprList {
int nExpr; /* Number of expressions on the list */
int iECursor; /* VDBE Cursor associated with this ExprList */
struct ExprList_item { /* For each expression in the list */
Expr *pExpr; /* The list of expressions */
char *zName; /* Token associated with this expression */
@@ -2018,8 +2068,8 @@ typedef u64 Bitmask;
** contains more than 63 columns and the 64-th or later column is used.
*/
struct SrcList {
u8 nSrc; /* Number of tables or subqueries in the FROM clause */
u8 nAlloc; /* Number of entries allocated in a[] below */
int nSrc; /* Number of tables or subqueries in the FROM clause */
u32 nAlloc; /* Number of entries allocated in a[] below */
struct SrcList_item {
Schema *pSchema; /* Schema to which this item is fixed */
char *zDatabase; /* Name of database holding this table */
@@ -2075,6 +2125,7 @@ struct SrcList {
#define WHERE_GROUPBY 0x0100 /* pOrderBy is really a GROUP BY */
#define WHERE_DISTINCTBY 0x0200 /* pOrderby is really a DISTINCT clause */
#define WHERE_WANT_DISTINCT 0x0400 /* All output needs to be distinct */
#define WHERE_SORTBYGROUP 0x0800 /* Support sqlite3WhereIsSorted() */
/* Allowed return values from sqlite3WhereIsDistinct()
*/
@@ -2149,7 +2200,7 @@ struct Select {
u8 op; /* One of: TK_UNION TK_ALL TK_INTERSECT TK_EXCEPT */
u16 selFlags; /* Various SF_* values */
int iLimit, iOffset; /* Memory registers holding LIMIT & OFFSET counters */
int addrOpenEphm[3]; /* OP_OpenEphem opcodes related to this select */
int addrOpenEphm[2]; /* OP_OpenEphem opcodes related to this select */
u64 nSelectRow; /* Estimated number of result rows */
SrcList *pSrc; /* The FROM clause */
Expr *pWhere; /* The WHERE clause */
@@ -2173,9 +2224,9 @@ struct Select {
#define SF_UsesEphemeral 0x0008 /* Uses the OpenEphemeral opcode */
#define SF_Expanded 0x0010 /* sqlite3SelectExpand() called on this */
#define SF_HasTypeInfo 0x0020 /* FROM subqueries have Table metadata */
#define SF_UseSorter 0x0040 /* Sort using a sorter */
/* 0x0040 NOT USED */
#define SF_Values 0x0080 /* Synthesized from VALUES clause */
#define SF_Materialize 0x0100 /* NOT USED */
/* 0x0100 NOT USED */
#define SF_NestedFrom 0x0200 /* Part of a parenthesized FROM clause */
#define SF_MaybeConvert 0x0400 /* Need convertCompoundSelectToSubquery() */
#define SF_Recursive 0x0800 /* The recursive part of a recursive CTE */
@@ -2228,13 +2279,15 @@ struct Select {
** starting with pDest->iSdst.
**
** SRT_Table Store results in temporary table pDest->iSDParm.
** This is like SRT_EphemTab except that the table
** is assumed to already be open.
** SRT_Fifo This is like SRT_EphemTab except that the table
** is assumed to already be open. SRT_Fifo has
** the additional property of being able to ignore
** the ORDER BY clause.
**
** SRT_DistTable Store results in a temporary table pDest->iSDParm.
** SRT_DistFifo Store results in a temporary table pDest->iSDParm.
** But also use temporary table pDest->iSDParm+1 as
** a record of all prior results and ignore any duplicate
** rows. Name means: "Distinct Table".
** rows. Name means: "Distinct Fifo".
**
** SRT_Queue Store results in priority queue pDest->iSDParm (really
** an index). Append a sequence number so that all entries
@@ -2248,19 +2301,20 @@ struct Select {
#define SRT_Except 2 /* Remove result from a UNION index */
#define SRT_Exists 3 /* Store 1 if the result is not empty */
#define SRT_Discard 4 /* Do not save the results anywhere */
#define SRT_Fifo 5 /* Store result as data with an automatic rowid */
#define SRT_DistFifo 6 /* Like SRT_Fifo, but unique results only */
#define SRT_Queue 7 /* Store result in an queue */
#define SRT_DistQueue 8 /* Like SRT_Queue, but unique results only */
/* The ORDER BY clause is ignored for all of the above */
#define IgnorableOrderby(X) ((X->eDest)<=SRT_Discard)
#define IgnorableOrderby(X) ((X->eDest)<=SRT_DistQueue)
#define SRT_Output 5 /* Output each row of result */
#define SRT_Mem 6 /* Store result in a memory cell */
#define SRT_Set 7 /* Store results as keys in an index */
#define SRT_EphemTab 8 /* Create transient tab and store like SRT_Table */
#define SRT_Coroutine 9 /* Generate a single row of result */
#define SRT_Table 10 /* Store result as data with an automatic rowid */
#define SRT_DistTable 11 /* Like SRT_Table, but unique results only */
#define SRT_Queue 12 /* Store result in an queue */
#define SRT_DistQueue 13 /* Like SRT_Queue, but unique results only */
#define SRT_Output 9 /* Output each row of result */
#define SRT_Mem 10 /* Store result in a memory cell */
#define SRT_Set 11 /* Store results as keys in an index */
#define SRT_EphemTab 12 /* Create transient tab and store like SRT_Table */
#define SRT_Coroutine 13 /* Generate a single row of result */
#define SRT_Table 14 /* Store result as data with an automatic rowid */
/*
** An instance of this object describes where to put of the results of
@@ -2358,8 +2412,6 @@ struct Parse {
u8 checkSchema; /* Causes schema cookie check after an error */
u8 nested; /* Number of nested calls to the parser/code generator */
u8 nTempReg; /* Number of temporary registers in aTempReg[] */
u8 nColCache; /* Number of entries in aColCache[] */
u8 iColCache; /* Next entry in aColCache[] to replace */
u8 isMultiWrite; /* True if statement may modify/insert multiple rows */
u8 mayAbort; /* True if statement may throw an ABORT exception */
u8 hasCompound; /* Need to invoke convertCompoundSelectToSubquery() */
@@ -2985,7 +3037,7 @@ int sqlite3BitvecBuiltinTest(int,int*);
RowSet *sqlite3RowSetInit(sqlite3*, void*, unsigned int);
void sqlite3RowSetClear(RowSet*);
void sqlite3RowSetInsert(RowSet*, i64);
int sqlite3RowSetTest(RowSet*, u8 iBatch, i64);
int sqlite3RowSetTest(RowSet*, int iBatch, i64);
int sqlite3RowSetNext(RowSet*, i64*);
void sqlite3CreateView(Parse*,Token*,Token*,Token*,Select*,int,int);
@@ -3041,6 +3093,7 @@ void sqlite3WhereEnd(WhereInfo*);
u64 sqlite3WhereOutputRowCount(WhereInfo*);
int sqlite3WhereIsDistinct(WhereInfo*);
int sqlite3WhereIsOrdered(WhereInfo*);
int sqlite3WhereIsSorted(WhereInfo*);
int sqlite3WhereContinueLabel(WhereInfo*);
int sqlite3WhereBreakLabel(WhereInfo*);
int sqlite3WhereOkOnePass(WhereInfo*, int*);
@@ -3049,7 +3102,7 @@ void sqlite3ExprCodeGetColumnOfTable(Vdbe*, Table*, int, int, int);
void sqlite3ExprCodeMove(Parse*, int, int, int);
void sqlite3ExprCacheStore(Parse*, int, int, int);
void sqlite3ExprCachePush(Parse*);
void sqlite3ExprCachePop(Parse*, int);
void sqlite3ExprCachePop(Parse*);
void sqlite3ExprCacheRemove(Parse*, int, int);
void sqlite3ExprCacheClear(Parse*);
void sqlite3ExprCacheAffinityChange(Parse*, int, int);
@@ -3101,6 +3154,7 @@ int sqlite3IsRowid(const char*);
void sqlite3GenerateRowDelete(Parse*,Table*,Trigger*,int,int,int,i16,u8,u8,u8);
void sqlite3GenerateRowIndexDelete(Parse*, Table*, int, int, int*);
int sqlite3GenerateIndexKey(Parse*, Index*, int, int, int, int*,Index*,int);
void sqlite3ResolvePartIdxLabel(Parse*,int);
void sqlite3GenerateConstraintChecks(Parse*,Table*,int*,int,int,int,int,
u8,u8,int,int*);
void sqlite3CompleteInsertion(Parse*,Table*,int,int,int,int*,int,int,int);
@@ -3258,7 +3312,7 @@ int sqlite3ReadSchema(Parse *pParse);
CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char*,int);
CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char*zName);
CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr);
Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr*, Token*);
Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr*, const Token*);
Expr *sqlite3ExprAddCollateString(Parse*,Expr*,const char*);
Expr *sqlite3ExprSkipCollate(Expr*);
int sqlite3CheckCollSeq(Parse *, CollSeq *);
+4
View File
@@ -14,6 +14,10 @@
** testing of the SQLite library.
*/
#include "sqliteInt.h"
#if SQLITE_OS_WIN
# include "os_win.h"
#endif
#include "vdbeInt.h"
#include "tcl.h"
#include <stdlib.h>
-1
View File
@@ -76,7 +76,6 @@ static int test_value_overhead(
val.flags = MEM_Str|MEM_Term|MEM_Static;
val.z = "hello world";
val.memType = MEM_Str;
val.enc = SQLITE_UTF8;
for(i=0; i<repeat_count; i++){
+1 -1
View File
@@ -51,7 +51,7 @@ void sqlite3BtreeCursorList(Btree *p){
BtShared *pBt = p->pBt;
for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){
MemPage *pPage = pCur->apPage[pCur->iPage];
char *zMode = pCur->wrFlag ? "rw" : "ro";
char *zMode = (pCur->curFlags & BTCF_WriteFlag) ? "rw" : "ro";
sqlite3DebugPrintf("CURSOR %p rooted at %4d(%s) currently at %d.%d%s\n",
pCur, pCur->pgnoRoot, zMode,
pPage ? pPage->pgno : 0, pCur->aiIdx[pCur->iPage],
+4
View File
@@ -20,6 +20,10 @@
#include "sqliteLimit.h"
#include "sqliteInt.h"
#if SQLITE_OS_WIN
# include "os_win.h"
#endif
#include "tcl.h"
#include <stdlib.h>
#include <string.h>
-2
View File
@@ -499,7 +499,6 @@ static void test_extract(
mem.enc = ENC(db);
pHdr += sqlite3GetVarint(pHdr, &iSerialType);
pBody += sqlite3VdbeSerialGet(pBody, (u32)iSerialType, &mem);
sqlite3VdbeMemStoreType(&mem);
if( iCurrent==iIdx ){
sqlite3_result_value(context, &mem);
@@ -549,7 +548,6 @@ static void test_decode(
pHdr += sqlite3GetVarint(pHdr, &iSerialType);
pBody += sqlite3VdbeSerialGet(pBody, (u32)iSerialType, &mem);
sqlite3VdbeMemStoreType(&mem);
switch( sqlite3_value_type(&mem) ){
case SQLITE_TEXT:
pVal = Tcl_NewStringObj((const char*)sqlite3_value_text(&mem), -1);
+6 -1
View File
@@ -70,6 +70,12 @@
*/
#include "sqlite3.h"
#include "os_setup.h"
#if SQLITE_OS_WIN
# include "os_win.h"
#endif
#include <string.h>
#include <assert.h>
@@ -221,7 +227,6 @@ static sqlite3_uint64 vfslog_time(){
return sTime.tv_usec + (sqlite3_uint64)sTime.tv_sec * 1000000;
}
#elif SQLITE_OS_WIN
#include <windows.h>
#include <time.h>
static sqlite3_uint64 vfslog_time(){
FILETIME ft;
+2 -38
View File
@@ -44,49 +44,13 @@
#define sqlite3_mutex_notheld(X) ((void)(X),1)
#endif /* SQLITE_THREADSAFE==0 */
/*
** Figure out if we are dealing with Unix, Windows, or some other
** operating system. After the following block of preprocess macros,
** all of SQLITE_OS_UNIX, SQLITE_OS_WIN, and SQLITE_OS_OTHER
** will defined to either 1 or 0. One of the four will be 1. The other
** three will be 0.
*/
#if defined(SQLITE_OS_OTHER)
# if SQLITE_OS_OTHER==1
# undef SQLITE_OS_UNIX
# define SQLITE_OS_UNIX 0
# undef SQLITE_OS_WIN
# define SQLITE_OS_WIN 0
# else
# undef SQLITE_OS_OTHER
# endif
#endif
#if !defined(SQLITE_OS_UNIX) && !defined(SQLITE_OS_OTHER)
# define SQLITE_OS_OTHER 0
# ifndef SQLITE_OS_WIN
# if defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) \
|| defined(__MINGW32__) || defined(__BORLANDC__)
# define SQLITE_OS_WIN 1
# define SQLITE_OS_UNIX 0
# else
# define SQLITE_OS_WIN 0
# define SQLITE_OS_UNIX 1
# endif
# else
# define SQLITE_OS_UNIX 0
# endif
#else
# ifndef SQLITE_OS_WIN
# define SQLITE_OS_WIN 0
# endif
#endif
#include "os_setup.h"
#if SQLITE_OS_UNIX
# include <unistd.h>
#endif
#if SQLITE_OS_WIN
# include <windows.h>
# include "os_win.h"
# include <io.h>
#endif
-6
View File
@@ -31,12 +31,6 @@
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#if SQLITE_OS_UNIX
# include <unistd.h>
#endif
#if SQLITE_OS_WIN
# include <windows.h>
#endif
/* Make this callable from C++ */
#ifdef __cplusplus
+183 -17
View File
@@ -35,6 +35,8 @@ struct Circle {
double centerx;
double centery;
double radius;
double mxArea;
int eScoreType;
};
/*
@@ -50,11 +52,7 @@ static void circle_del(void *p){
static int circle_geom(
sqlite3_rtree_geometry *p,
int nCoord,
#ifdef SQLITE_RTREE_INT_ONLY
sqlite3_int64 *aCoord,
#else
double *aCoord,
#endif
sqlite3_rtree_dbl *aCoord,
int *pRes
){
int i; /* Iterator variable */
@@ -62,7 +60,12 @@ static int circle_geom(
double xmin, xmax; /* X dimensions of box being tested */
double ymin, ymax; /* X dimensions of box being tested */
if( p->pUser==0 ){
xmin = aCoord[0];
xmax = aCoord[1];
ymin = aCoord[2];
ymax = aCoord[3];
pCircle = (Circle *)p->pUser;
if( pCircle==0 ){
/* If pUser is still 0, then the parameter values have not been tested
** for correctness or stored into a Circle structure yet. Do this now. */
@@ -108,14 +111,9 @@ static int circle_geom(
pCircle->aBox[1].xmax = pCircle->centerx - pCircle->radius;
pCircle->aBox[1].ymin = pCircle->centery;
pCircle->aBox[1].ymax = pCircle->centery;
pCircle->mxArea = (xmax - xmin)*(ymax - ymin) + 1.0;
}
pCircle = (Circle *)p->pUser;
xmin = aCoord[0];
xmax = aCoord[1];
ymin = aCoord[2];
ymax = aCoord[3];
/* Check if any of the 4 corners of the bounding-box being tested lie
** inside the circular region. If they do, then the bounding-box does
** intersect the region of interest. Set the output variable to true and
@@ -154,6 +152,170 @@ static int circle_geom(
return SQLITE_OK;
}
/*
** Implementation of "circle" r-tree geometry callback using the
** 2nd-generation interface that allows scoring.
*/
static int circle_query_func(sqlite3_rtree_query_info *p){
int i; /* Iterator variable */
Circle *pCircle; /* Structure defining circular region */
double xmin, xmax; /* X dimensions of box being tested */
double ymin, ymax; /* X dimensions of box being tested */
int nWithin = 0; /* Number of corners inside the circle */
xmin = p->aCoord[0];
xmax = p->aCoord[1];
ymin = p->aCoord[2];
ymax = p->aCoord[3];
pCircle = (Circle *)p->pUser;
if( pCircle==0 ){
/* If pUser is still 0, then the parameter values have not been tested
** for correctness or stored into a Circle structure yet. Do this now. */
/* This geometry callback is for use with a 2-dimensional r-tree table.
** Return an error if the table does not have exactly 2 dimensions. */
if( p->nCoord!=4 ) return SQLITE_ERROR;
/* Test that the correct number of parameters (4) have been supplied,
** and that the parameters are in range (that the radius of the circle
** radius is greater than zero). */
if( p->nParam!=4 || p->aParam[2]<0.0 ) return SQLITE_ERROR;
/* Allocate a structure to cache parameter data in. Return SQLITE_NOMEM
** if the allocation fails. */
pCircle = (Circle *)(p->pUser = sqlite3_malloc(sizeof(Circle)));
if( !pCircle ) return SQLITE_NOMEM;
p->xDelUser = circle_del;
/* Record the center and radius of the circular region. One way that
** tested bounding boxes that intersect the circular region are detected
** is by testing if each corner of the bounding box lies within radius
** units of the center of the circle. */
pCircle->centerx = p->aParam[0];
pCircle->centery = p->aParam[1];
pCircle->radius = p->aParam[2];
pCircle->eScoreType = (int)p->aParam[3];
/* Define two bounding box regions. The first, aBox[0], extends to
** infinity in the X dimension. It covers the same range of the Y dimension
** as the circular region. The second, aBox[1], extends to infinity in
** the Y dimension and is constrained to the range of the circle in the
** X dimension.
**
** Then imagine each box is split in half along its short axis by a line
** that intersects the center of the circular region. A bounding box
** being tested can be said to intersect the circular region if it contains
** points from each half of either of the two infinite bounding boxes.
*/
pCircle->aBox[0].xmin = pCircle->centerx;
pCircle->aBox[0].xmax = pCircle->centerx;
pCircle->aBox[0].ymin = pCircle->centery + pCircle->radius;
pCircle->aBox[0].ymax = pCircle->centery - pCircle->radius;
pCircle->aBox[1].xmin = pCircle->centerx + pCircle->radius;
pCircle->aBox[1].xmax = pCircle->centerx - pCircle->radius;
pCircle->aBox[1].ymin = pCircle->centery;
pCircle->aBox[1].ymax = pCircle->centery;
pCircle->mxArea = 200.0*200.0;
}
/* Check if any of the 4 corners of the bounding-box being tested lie
** inside the circular region. If they do, then the bounding-box does
** intersect the region of interest. Set the output variable to true and
** return SQLITE_OK in this case. */
for(i=0; i<4; i++){
double x = (i&0x01) ? xmax : xmin;
double y = (i&0x02) ? ymax : ymin;
double d2;
d2 = (x-pCircle->centerx)*(x-pCircle->centerx);
d2 += (y-pCircle->centery)*(y-pCircle->centery);
if( d2<(pCircle->radius*pCircle->radius) ) nWithin++;
}
/* Check if the bounding box covers any other part of the circular region.
** See comments above for a description of how this test works. If it does
** cover part of the circular region, set the output variable to true
** and return SQLITE_OK. */
if( nWithin==0 ){
for(i=0; i<2; i++){
if( xmin<=pCircle->aBox[i].xmin
&& xmax>=pCircle->aBox[i].xmax
&& ymin<=pCircle->aBox[i].ymin
&& ymax>=pCircle->aBox[i].ymax
){
nWithin = 1;
break;
}
}
}
if( pCircle->eScoreType==1 ){
/* Depth first search */
p->rScore = p->iLevel;
}else if( pCircle->eScoreType==2 ){
/* Breadth first search */
p->rScore = 100 - p->iLevel;
}else if( pCircle->eScoreType==3 ){
/* Depth-first search, except sort the leaf nodes by area with
** the largest area first */
if( p->iLevel==1 ){
p->rScore = 1.0 - (xmax-xmin)*(ymax-ymin)/pCircle->mxArea;
if( p->rScore<0.01 ) p->rScore = 0.01;
}else{
p->rScore = 0.0;
}
}else if( pCircle->eScoreType==4 ){
/* Depth-first search, except exclude odd rowids */
p->rScore = p->iLevel;
if( p->iRowid&1 ) nWithin = 0;
}else{
/* Breadth-first search, except exclude odd rowids */
p->rScore = 100 - p->iLevel;
if( p->iRowid&1 ) nWithin = 0;
}
if( nWithin==0 ){
p->eWithin = NOT_WITHIN;
}else if( nWithin>=4 ){
p->eWithin = FULLY_WITHIN;
}else{
p->eWithin = PARTLY_WITHIN;
}
return SQLITE_OK;
}
/*
** Implementation of "breadthfirstsearch" r-tree geometry callback using the
** 2nd-generation interface that allows scoring.
**
** ... WHERE id MATCH breadthfirstsearch($x0,$x1,$y0,$y1) ...
**
** It returns all entries whose bounding boxes overlap with $x0,$x1,$y0,$y1.
*/
static int bfs_query_func(sqlite3_rtree_query_info *p){
double x0,x1,y0,y1; /* Dimensions of box being tested */
double bx0,bx1,by0,by1; /* Boundary of the query function */
if( p->nParam!=4 ) return SQLITE_ERROR;
x0 = p->aCoord[0];
x1 = p->aCoord[1];
y0 = p->aCoord[2];
y1 = p->aCoord[3];
bx0 = p->aParam[0];
bx1 = p->aParam[1];
by0 = p->aParam[2];
by1 = p->aParam[3];
p->rScore = 100 - p->iLevel;
if( p->eParentWithin==FULLY_WITHIN ){
p->eWithin = FULLY_WITHIN;
}else if( x0>=bx0 && x1<=bx1 && y0>=by0 && y1<=by1 ){
p->eWithin = FULLY_WITHIN;
}else if( x1>=bx0 && x0<=bx1 && y1>=by0 && y0<=by1 ){
p->eWithin = PARTLY_WITHIN;
}else{
p->eWithin = NOT_WITHIN;
}
return SQLITE_OK;
}
/* END of implementation of "circle" geometry callback.
**************************************************************************
*************************************************************************/
@@ -194,11 +356,7 @@ static int gHere = 42;
static int cube_geom(
sqlite3_rtree_geometry *p,
int nCoord,
#ifdef SQLITE_RTREE_INT_ONLY
sqlite3_int64 *aCoord,
#else
double *aCoord,
#endif
sqlite3_rtree_dbl *aCoord,
int *piRes
){
Cube *pCube = (Cube *)p->pUser;
@@ -293,6 +451,14 @@ static int register_circle_geom(
}
if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
rc = sqlite3_rtree_geometry_callback(db, "circle", circle_geom, 0);
if( rc==SQLITE_OK ){
rc = sqlite3_rtree_query_callback(db, "Qcircle",
circle_query_func, 0, 0);
}
if( rc==SQLITE_OK ){
rc = sqlite3_rtree_query_callback(db, "breadthfirstsearch",
bfs_query_func, 0, 0);
}
Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_STATIC);
#endif
return TCL_OK;
+48 -1
View File
@@ -67,6 +67,11 @@
** test_syscall list
** Return a list of all system calls. The list is constructed using
** the xNextSystemCall() VFS method.
**
** test_syscall pagesize PGSZ
** If PGSZ is a power of two greater than 256, install a wrapper around
** OS function getpagesize() that reports the system page size as PGSZ.
** Or, if PGSZ is less than zero, remove any wrapper already installed.
*/
#include "sqliteInt.h"
@@ -89,7 +94,9 @@ static struct TestSyscallGlobal {
int bPersist; /* 1 for persistent errors, 0 for transient */
int nCount; /* Fail after this many more calls */
int nFail; /* Number of failures that have occurred */
} gSyscall = { 0, 0 };
int pgsz;
sqlite3_syscall_ptr orig_getpagesize;
} gSyscall = { 0, 0, 0, 0, 0 };
static int ts_open(const char *, int, int);
static int ts_close(int fd);
@@ -650,6 +657,45 @@ static int test_syscall_defaultvfs(
return TCL_OK;
}
static int ts_getpagesize(void){
return gSyscall.pgsz;
}
static int test_syscall_pagesize(
void * clientData,
Tcl_Interp *interp,
int objc,
Tcl_Obj *CONST objv[]
){
sqlite3_vfs *pVfs = sqlite3_vfs_find(0);
int pgsz;
if( objc!=3 ){
Tcl_WrongNumArgs(interp, 2, objv, "PGSZ");
return TCL_ERROR;
}
if( Tcl_GetIntFromObj(interp, objv[2], &pgsz) ){
return TCL_ERROR;
}
if( pgsz<0 ){
if( gSyscall.orig_getpagesize ){
pVfs->xSetSystemCall(pVfs, "getpagesize", gSyscall.orig_getpagesize);
}
}else{
if( pgsz<512 || (pgsz & (pgsz-1)) ){
Tcl_AppendResult(interp, "pgsz out of range", 0);
return TCL_ERROR;
}
gSyscall.orig_getpagesize = pVfs->xGetSystemCall(pVfs, "getpagesize");
gSyscall.pgsz = pgsz;
pVfs->xSetSystemCall(
pVfs, "getpagesize", (sqlite3_syscall_ptr)ts_getpagesize
);
}
return TCL_OK;
}
static int test_syscall(
void * clientData,
Tcl_Interp *interp,
@@ -668,6 +714,7 @@ static int test_syscall(
{ "exists", test_syscall_exists },
{ "list", test_syscall_list },
{ "defaultvfs", test_syscall_defaultvfs },
{ "pagesize", test_syscall_pagesize },
{ 0, 0 }
};
int iCmd;
+1 -1
View File
@@ -678,7 +678,7 @@ static int vfstraceAccess(
vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
sqlite3_vfs *pRoot = pInfo->pRootVfs;
int rc;
vfstrace_printf(pInfo, "%s.xDelete(\"%s\",%d)",
vfstrace_printf(pInfo, "%s.xAccess(\"%s\",%d)",
pInfo->zVfsName, zPath, flags);
rc = pRoot->xAccess(pRoot, zPath, flags, pResOut);
vfstrace_print_errcode(pInfo, " -> %s", rc);
+1 -1
View File
@@ -566,7 +566,7 @@ void sqlite3DropTriggerPtr(Parse *pParse, Trigger *pTrigger){
assert( pTable!=0 );
if( (v = sqlite3GetVdbe(pParse))!=0 ){
int base;
static const int iLn = __LINE__+2;
static const int iLn = VDBE_OFFSET_LINENO(2);
static const VdbeOpList dropTrigger[] = {
{ OP_Rewind, 0, ADDR(9), 0},
{ OP_String8, 0, 1, 0}, /* 1 */
+2 -2
View File
@@ -1246,8 +1246,8 @@ LogEst sqlite3LogEstAdd(LogEst a, LogEst b){
}
/*
** Convert an integer into a LogEst. In other words, compute a
** good approximatation for 10*log2(x).
** Convert an integer into a LogEst. In other words, compute an
** approximation for 10*log2(x).
*/
LogEst sqlite3LogEst(u64 x){
static LogEst a[] = { 0, 2, 3, 5, 6, 7, 8, 9 };
+76 -26
View File
@@ -28,7 +28,7 @@
** pointer to the string or blob, not the content. If the original
** is changed while the copy is still in use, the string or blob might
** be changed out from under the copy. This macro verifies that nothing
** like that every happens.
** like that ever happens.
*/
#ifdef SQLITE_DEBUG
# define memAboutToChange(P,M) sqlite3VdbeMemAboutToChange(P,M)
@@ -293,7 +293,6 @@ int sqlite3_value_numeric_type(sqlite3_value *pVal){
if( eType==SQLITE_TEXT ){
Mem *pMem = (Mem*)pVal;
applyNumericAffinity(pMem);
sqlite3VdbeMemStoreType(pMem);
eType = sqlite3_value_type(pVal);
}
return eType;
@@ -311,6 +310,29 @@ void sqlite3ValueApplyAffinity(
applyAffinity((Mem *)pVal, affinity, enc);
}
/*
** Return the numeric type for pMem, either MEM_Int or MEM_Real or both or
** none.
**
** Unlike applyNumericAffinity(), this routine does not modify pMem->flags.
** But it does set pMem->r and pMem->u.i appropriately.
*/
static u16 numericType(Mem *pMem){
if( pMem->flags & (MEM_Int|MEM_Real) ){
return pMem->flags & (MEM_Int|MEM_Real);
}
if( pMem->flags & (MEM_Str|MEM_Blob) ){
if( sqlite3AtoF(pMem->z, &pMem->r, pMem->n, pMem->enc)==0 ){
return 0;
}
if( sqlite3Atoi64(pMem->z, &pMem->u.i, pMem->n, pMem->enc)==SQLITE_OK ){
return MEM_Int;
}
return MEM_Real;
}
return 0;
}
#ifdef SQLITE_DEBUG
/*
** Write a nice string representation of the contents of cell pMem
@@ -672,6 +694,11 @@ int sqlite3VdbeExec(
** The next instruction executed will be
** the one at index P2 from the beginning of
** the program.
**
** The P1 parameter is not actually used by this opcode. However, it
** is sometimes set to 1 instead of 0 as a hint to the command-line shell
** that this Goto is the bottom of a loop and that the lines from P2 down
** to the current line should be indented for EXPLAIN output.
*/
case OP_Goto: { /* jump */
pc = pOp->p2 - 1;
@@ -1076,10 +1103,11 @@ case OP_Variable: { /* out2-prerelease */
/* Opcode: Move P1 P2 P3 * *
** Synopsis: r[P2@P3]=r[P1@P3]
**
** Move the values in register P1..P1+P3 over into
** registers P2..P2+P3. Registers P1..P1+P3 are
** Move the P3 values in register P1..P1+P3-1 over into
** registers P2..P2+P3-1. Registers P1..P1+P3-1 are
** left holding a NULL. It is an error for register ranges
** P1..P1+P3 and P2..P2+P3 to overlap.
** P1..P1+P3-1 and P2..P2+P3-1 to overlap. It is an error
** for P3 to be less than 1.
*/
case OP_Move: {
char *zMalloc; /* Holding variable for allocated memory */
@@ -1090,7 +1118,7 @@ case OP_Move: {
n = pOp->p3;
p1 = pOp->p1;
p2 = pOp->p2;
assert( n>=0 && p1>0 && p2>0 );
assert( n>0 && p1>0 && p2>0 );
assert( p1+n<=p2 || p2+n<=p1 );
pIn1 = &aMem[p1];
@@ -1114,7 +1142,7 @@ case OP_Move: {
REGISTER_TRACE(p2++, pOut);
pIn1++;
pOut++;
}while( n-- );
}while( --n );
break;
}
@@ -1243,7 +1271,6 @@ case OP_ResultRow: {
assert( (pMem[i].flags & MEM_Ephem)==0
|| (pMem[i].flags & (MEM_Str|MEM_Blob))==0 );
sqlite3VdbeMemNulTerminate(&pMem[i]);
sqlite3VdbeMemStoreType(&pMem[i]);
REGISTER_TRACE(pOp->p1+i, &pMem[i]);
}
if( db->mallocFailed ) goto no_mem;
@@ -1347,20 +1374,22 @@ case OP_Multiply: /* same as TK_STAR, in1, in2, out3 */
case OP_Divide: /* same as TK_SLASH, in1, in2, out3 */
case OP_Remainder: { /* same as TK_REM, in1, in2, out3 */
char bIntint; /* Started out as two integer operands */
int flags; /* Combined MEM_* flags from both inputs */
u16 flags; /* Combined MEM_* flags from both inputs */
u16 type1; /* Numeric type of left operand */
u16 type2; /* Numeric type of right operand */
i64 iA; /* Integer value of left operand */
i64 iB; /* Integer value of right operand */
double rA; /* Real value of left operand */
double rB; /* Real value of right operand */
pIn1 = &aMem[pOp->p1];
applyNumericAffinity(pIn1);
type1 = numericType(pIn1);
pIn2 = &aMem[pOp->p2];
applyNumericAffinity(pIn2);
type2 = numericType(pIn2);
pOut = &aMem[pOp->p3];
flags = pIn1->flags | pIn2->flags;
if( (flags & MEM_Null)!=0 ) goto arithmetic_result_is_null;
if( (pIn1->flags & pIn2->flags & MEM_Int)==MEM_Int ){
if( (type1 & type2 & MEM_Int)!=0 ){
iA = pIn1->u.i;
iB = pIn2->u.i;
bIntint = 1;
@@ -1416,7 +1445,7 @@ fp_math:
}
pOut->r = rB;
MemSetTypeFlag(pOut, MEM_Real);
if( (flags & MEM_Real)==0 && !bIntint ){
if( ((type1|type2)&MEM_Real)==0 && !bIntint ){
sqlite3VdbeIntegerAffinity(pOut);
}
#endif
@@ -1489,7 +1518,6 @@ case OP_Function: {
assert( memIsValid(pArg) );
apVal[i] = pArg;
Deephemeralize(pArg);
sqlite3VdbeMemStoreType(pArg);
REGISTER_TRACE(pOp->p2+i, pArg);
}
@@ -1993,6 +2021,7 @@ case OP_Permutation: {
}
/* Opcode: Compare P1 P2 P3 P4 P5
** Synopsis: r[P1@P3] <-> r[P2@P3]
**
** Compare two vectors of registers in reg(P1)..reg(P1+P3-1) (call this
** vector "A") and in reg(P2)..reg(P2+P3-1) ("B"). Save the result of
@@ -2169,8 +2198,8 @@ case OP_BitNot: { /* same as TK_BITNOT, in1, out2 */
**
** Check if OP_Once flag P1 is set. If so, jump to instruction P2. Otherwise,
** set the flag and fall through to the next instruction. In other words,
** this opcode causes all following up codes up through P2 (but not including
** P2) to run just once and skipped on subsequent times through the loop.
** this opcode causes all following opcodes up through P2 (but not including
** P2) to run just once and to be skipped on subsequent times through the loop.
*/
case OP_Once: { /* jump */
assert( pOp->p1<p->nOnceFlag );
@@ -3328,6 +3357,7 @@ case OP_OpenEphemeral: {
pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, 1);
if( pCx==0 ) goto no_mem;
pCx->nullRow = 1;
pCx->isEphemeral = 1;
rc = sqlite3BtreeOpen(db->pVfs, 0, db, &pCx->pBt,
BTREE_OMIT_JOURNAL | BTREE_SINGLE | pOp->p5, vfsFlags);
if( rc==SQLITE_OK ){
@@ -3818,7 +3848,7 @@ case OP_NotExists: { /* jump, in3 */
}
/* Opcode: Sequence P1 P2 * * *
** Synopsis: r[P2]=rowid
** Synopsis: r[P2]=cursor[P1].ctr++
**
** Find the next available sequence number for cursor P1.
** Write the sequence number into register P2.
@@ -4202,6 +4232,7 @@ case OP_SorterData: {
pC = p->apCsr[pOp->p1];
assert( isSorter(pC) );
rc = sqlite3VdbeSorterRowkey(pC, pOut);
assert( rc!=SQLITE_OK || (pOut->flags & MEM_Blob) );
break;
}
@@ -4509,6 +4540,7 @@ case OP_SorterNext: { /* jump */
pC = p->apCsr[pOp->p1];
assert( isSorter(pC) );
res = 0;
rc = sqlite3VdbeSorterNext(db, pC, &res);
goto next_tail;
case OP_PrevIfOpen: /* jump */
@@ -4867,6 +4899,29 @@ case OP_Clear: {
break;
}
/* Opcode: ResetSorter P1 * * * *
**
** Delete all contents from the ephemeral table or sorter
** that is open on cursor P1.
**
** This opcode only works for cursors used for sorting and
** opened with OP_OpenEphemeral or OP_SorterOpen.
*/
case OP_ResetSorter: {
VdbeCursor *pC;
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
if( pC->pSorter ){
sqlite3VdbeSorterReset(db, pC->pSorter);
}else{
assert( pC->isEphemeral );
rc = sqlite3BtreeClearTableOfCursor(pC->pCursor);
}
break;
}
/* Opcode: CreateTable P1 P2 * * *
** Synopsis: r[P2]=root iDb=P1
**
@@ -5173,9 +5228,7 @@ case OP_RowSetTest: { /* jump, in1, in3 */
assert( pOp->p4type==P4_INT32 );
assert( iSet==-1 || iSet>=0 );
if( iSet ){
exists = sqlite3RowSetTest(pIn1->u.pRowSet,
(u8)(iSet>=0 ? iSet & 0xf : 0xff),
pIn3->u.i);
exists = sqlite3RowSetTest(pIn1->u.pRowSet, iSet, pIn3->u.i);
VdbeBranchTaken(exists!=0,2);
if( exists ){
pc = pOp->p2 - 1;
@@ -5494,7 +5547,6 @@ case OP_AggStep: {
assert( memIsValid(pRec) );
apVal[i] = pRec;
memAboutToChange(p, pRec);
sqlite3VdbeMemStoreType(pRec);
}
ctx.pFunc = pOp->p4.pFunc;
assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) );
@@ -5876,7 +5928,7 @@ case OP_VOpen: {
#ifndef SQLITE_OMIT_VIRTUALTABLE
/* Opcode: VFilter P1 P2 P3 P4 *
** Synopsis: iPlan=r[P3] zPlan='P4'
** Synopsis: iplan=r[P3] zplan='P4'
**
** P1 is a cursor opened using VOpen. P2 is an address to jump to if
** the filtered result set is empty.
@@ -5928,7 +5980,6 @@ case OP_VFilter: { /* jump */
apArg = p->apArg;
for(i = 0; i<nArg; i++){
apArg[i] = &pArgc[i+1];
sqlite3VdbeMemStoreType(apArg[i]);
}
p->inVtabMethod = 1;
@@ -6135,7 +6186,6 @@ case OP_VUpdate: {
for(i=0; i<nArg; i++){
assert( memIsValid(pX) );
memAboutToChange(p, pX);
sqlite3VdbeMemStoreType(pX);
apArg[i] = pX;
pX++;
}
@@ -6274,8 +6324,8 @@ default: { /* This is really OP_Noop and OP_Explain */
#ifdef VDBE_PROFILE
{
u64 elapsed = sqlite3Hwtime() - start;
pOp->cycles += elapsed;
u64 endTime = sqlite3Hwtime();
if( endTime>start ) pOp->cycles += endTime - start;
pOp->cnt++;
}
#endif
+4 -2
View File
@@ -211,10 +211,10 @@ void sqlite3VdbeSetVarmask(Vdbe*, int);
#endif
void sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,UnpackedRecord*);
int sqlite3VdbeRecordCompare(int,const void*,const UnpackedRecord*,int);
int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*,int);
UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(KeyInfo *, char *, int, char **);
typedef int (*RecordCompare)(int,const void*,const UnpackedRecord*,int);
typedef int (*RecordCompare)(int,const void*,UnpackedRecord*,int);
RecordCompare sqlite3VdbeFindCompare(UnpackedRecord*);
#ifndef SQLITE_OMIT_TRIGGER
@@ -272,11 +272,13 @@ void sqlite3VdbeLinkSubProgram(Vdbe *, SubProgram *);
# define VdbeCoverageIf(v,x) if(x)sqlite3VdbeSetLineNumber(v,__LINE__)
# define VdbeCoverageAlwaysTaken(v) sqlite3VdbeSetLineNumber(v,2);
# define VdbeCoverageNeverTaken(v) sqlite3VdbeSetLineNumber(v,1);
# define VDBE_OFFSET_LINENO(x) (__LINE__+x)
#else
# define VdbeCoverage(v)
# define VdbeCoverageIf(v,x)
# define VdbeCoverageAlwaysTaken(v)
# define VdbeCoverageNeverTaken(v)
# define VDBE_OFFSET_LINENO(x) 0
#endif
#endif
+4 -4
View File
@@ -72,6 +72,7 @@ struct VdbeCursor {
u8 nullRow; /* True if pointing to a row with no data */
u8 rowidIsValid; /* True if lastRowid is valid */
u8 deferredMoveto; /* A call to sqlite3BtreeMoveto() is needed */
Bool isEphemeral:1; /* True for an ephemeral table */
Bool useRandomRowid:1;/* Generate new record numbers semi-randomly */
Bool isTable:1; /* True if a table requiring integer keys */
Bool isOrdered:1; /* True if the underlying table is BTREE_UNORDERED */
@@ -168,7 +169,6 @@ struct Mem {
} u;
int n; /* Number of characters in string value, excluding '\0' */
u16 flags; /* Some combination of MEM_Null, MEM_Str, MEM_Dyn, etc. */
u8 memType; /* Lower 5 bits of flags */
u8 enc; /* SQLITE_UTF8, SQLITE_UTF16BE, SQLITE_UTF16LE */
#ifdef SQLITE_DEBUG
Mem *pScopyFrom; /* This Mem is a shallow copy of pScopyFrom */
@@ -195,6 +195,7 @@ struct Mem {
#define MEM_Int 0x0004 /* Value is an integer */
#define MEM_Real 0x0008 /* Value is a real number */
#define MEM_Blob 0x0010 /* Value is a BLOB */
#define MEM_AffMask 0x001f /* Mask of affinity bits */
#define MEM_RowSet 0x0020 /* Value is a RowSet object */
#define MEM_Frame 0x0040 /* Value is a VdbeFrame object */
#define MEM_Undefined 0x0080 /* Value is undefined */
@@ -391,7 +392,7 @@ u32 sqlite3VdbeSerialGet(const unsigned char*, u32, Mem*);
void sqlite3VdbeDeleteAuxData(Vdbe*, int, int);
int sqlite2BtreeKeyCompare(BtCursor *, const void *, int, int, int *);
int sqlite3VdbeIdxKeyCompare(VdbeCursor*,const UnpackedRecord*,int*);
int sqlite3VdbeIdxKeyCompare(VdbeCursor*,UnpackedRecord*,int*);
int sqlite3VdbeIdxRowid(sqlite3*, BtCursor *, i64 *);
int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*);
int sqlite3VdbeExec(Vdbe*);
@@ -434,11 +435,10 @@ int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve);
int sqlite3VdbeCloseStatement(Vdbe *, int);
void sqlite3VdbeFrameDelete(VdbeFrame*);
int sqlite3VdbeFrameRestore(VdbeFrame *);
#define sqlite3VdbeMemStoreType(X) (X)->memType = (u8)((X)->flags&0x1f)
/* void sqlite3VdbeMemStoreType(Mem *pMem); */
int sqlite3VdbeTransferError(Vdbe *p);
int sqlite3VdbeSorterInit(sqlite3 *, VdbeCursor *);
void sqlite3VdbeSorterReset(sqlite3 *, VdbeSorter *);
void sqlite3VdbeSorterClose(sqlite3 *, VdbeCursor *);
int sqlite3VdbeSorterRowkey(const VdbeCursor *, Mem *);
int sqlite3VdbeSorterNext(sqlite3 *, const VdbeCursor *, int *);
+26 -24
View File
@@ -135,7 +135,6 @@ const void *sqlite3_value_blob(sqlite3_value *pVal){
Mem *p = (Mem*)pVal;
if( p->flags & (MEM_Blob|MEM_Str) ){
sqlite3VdbeMemExpandBlob(p);
p->flags &= ~MEM_Str;
p->flags |= MEM_Blob;
return p->n ? p->z : 0;
}else{
@@ -206,7 +205,7 @@ int sqlite3_value_type(sqlite3_value* pVal){
SQLITE_INTEGER, /* 0x1e */
SQLITE_NULL, /* 0x1f */
};
return aType[pVal->memType&0x1f];
return aType[pVal->flags&MEM_AffMask];
}
/**************************** sqlite3_result_ *******************************
@@ -727,6 +726,30 @@ int sqlite3_data_count(sqlite3_stmt *pStmt){
return pVm->nResColumn;
}
/*
** Return a pointer to static memory containing an SQL NULL value.
*/
static const Mem *columnNullValue(void){
/* Even though the Mem structure contains an element
** of type i64, on certain architectures (x86) with certain compiler
** switches (-Os), gcc may align this Mem object on a 4-byte boundary
** instead of an 8-byte one. This all works fine, except that when
** running with SQLITE_DEBUG defined the SQLite code sometimes assert()s
** that a Mem structure is located on an 8-byte boundary. To prevent
** these assert()s from failing, when building with SQLITE_DEBUG defined
** using gcc, we force nullMem to be 8-byte aligned using the magical
** __attribute__((aligned(8))) macro. */
static const Mem nullMem
#if defined(SQLITE_DEBUG) && defined(__GNUC__)
__attribute__((aligned(8)))
#endif
= {0, "", (double)0, {0}, 0, MEM_Null, 0,
#ifdef SQLITE_DEBUG
0, 0, /* pScopyFrom, pFiller */
#endif
0, 0 };
return &nullMem;
}
/*
** Check to see if column iCol of the given statement is valid. If
@@ -743,32 +766,11 @@ static Mem *columnMem(sqlite3_stmt *pStmt, int i){
sqlite3_mutex_enter(pVm->db->mutex);
pOut = &pVm->pResultSet[i];
}else{
/* If the value passed as the second argument is out of range, return
** a pointer to the following static Mem object which contains the
** value SQL NULL. Even though the Mem structure contains an element
** of type i64, on certain architectures (x86) with certain compiler
** switches (-Os), gcc may align this Mem object on a 4-byte boundary
** instead of an 8-byte one. This all works fine, except that when
** running with SQLITE_DEBUG defined the SQLite code sometimes assert()s
** that a Mem structure is located on an 8-byte boundary. To prevent
** these assert()s from failing, when building with SQLITE_DEBUG defined
** using gcc, we force nullMem to be 8-byte aligned using the magical
** __attribute__((aligned(8))) macro. */
static const Mem nullMem
#if defined(SQLITE_DEBUG) && defined(__GNUC__)
__attribute__((aligned(8)))
#endif
= {0, "", (double)0, {0}, 0, MEM_Null, SQLITE_NULL, 0,
#ifdef SQLITE_DEBUG
0, 0, /* pScopyFrom, pFiller */
#endif
0, 0 };
if( pVm && ALWAYS(pVm->db) ){
sqlite3_mutex_enter(pVm->db->mutex);
sqlite3Error(pVm->db, SQLITE_RANGE, 0);
}
pOut = (Mem*)&nullMem;
pOut = (Mem*)columnNullValue();
}
return pOut;
}
+65 -25
View File
@@ -276,7 +276,7 @@ void sqlite3VdbeResolveLabel(Vdbe *v, int x){
int j = -1-x;
assert( v->magic==VDBE_MAGIC_INIT );
assert( j<p->nLabel );
if( j>=0 && p->aLabel ){
if( ALWAYS(j>=0) && p->aLabel ){
p->aLabel[j] = v->nOp;
}
p->iFixedOp = v->nOp - 1;
@@ -783,7 +783,9 @@ void sqlite3VdbeChangeP4(Vdbe *p, int addr, const char *zP4, int n){
addr = p->nOp - 1;
}
pOp = &p->aOp[addr];
assert( pOp->p4type==P4_NOTUSED || pOp->p4type==P4_INT32 );
assert( pOp->p4type==P4_NOTUSED
|| pOp->p4type==P4_INT32
|| pOp->p4type==P4_KEYINFO );
freeP4(db, pOp->p4type, pOp->p4.p);
pOp->p4.p = 0;
if( n==P4_INT32 ){
@@ -1234,6 +1236,10 @@ static void releaseMemArray(Mem *p, int N){
** with no indexes using a single prepared INSERT statement, bind()
** and reset(). Inserts are grouped into a transaction.
*/
testcase( p->flags & MEM_Agg );
testcase( p->flags & MEM_Dyn );
testcase( p->flags & MEM_Frame );
testcase( p->flags & MEM_RowSet );
if( p->flags&(MEM_Agg|MEM_Dyn|MEM_Frame|MEM_RowSet) ){
sqlite3VdbeMemRelease(p);
}else if( p->zMalloc ){
@@ -1363,7 +1369,6 @@ int sqlite3VdbeList(
}
if( p->explain==1 ){
pMem->flags = MEM_Int;
pMem->memType = MEM_Int;
pMem->u.i = i; /* Program counter */
pMem++;
@@ -1371,7 +1376,6 @@ int sqlite3VdbeList(
pMem->z = (char*)sqlite3OpcodeName(pOp->opcode); /* Opcode */
assert( pMem->z!=0 );
pMem->n = sqlite3Strlen30(pMem->z);
pMem->memType = MEM_Str;
pMem->enc = SQLITE_UTF8;
pMem++;
@@ -1397,17 +1401,14 @@ int sqlite3VdbeList(
pMem->flags = MEM_Int;
pMem->u.i = pOp->p1; /* P1 */
pMem->memType = MEM_Int;
pMem++;
pMem->flags = MEM_Int;
pMem->u.i = pOp->p2; /* P2 */
pMem->memType = MEM_Int;
pMem++;
pMem->flags = MEM_Int;
pMem->u.i = pOp->p3; /* P3 */
pMem->memType = MEM_Int;
pMem++;
if( sqlite3VdbeMemGrow(pMem, 32, 0) ){ /* P4 */
@@ -1423,7 +1424,6 @@ int sqlite3VdbeList(
pMem->n = sqlite3Strlen30(pMem->z);
pMem->enc = SQLITE_UTF8;
}
pMem->memType = MEM_Str;
pMem++;
if( p->explain==1 ){
@@ -1434,7 +1434,6 @@ int sqlite3VdbeList(
pMem->flags = MEM_Str|MEM_Term;
pMem->n = 2;
sqlite3_snprintf(3, pMem->z, "%.2x", pOp->p5); /* P5 */
pMem->memType = MEM_Str;
pMem->enc = SQLITE_UTF8;
pMem++;
@@ -1445,11 +1444,9 @@ int sqlite3VdbeList(
}
pMem->flags = MEM_Str|MEM_Term;
pMem->n = displayComment(pOp, zP4, pMem->z, 500);
pMem->memType = MEM_Str;
pMem->enc = SQLITE_UTF8;
#else
pMem->flags = MEM_Null; /* Comment */
pMem->memType = MEM_Null;
#endif
}
@@ -2738,7 +2735,7 @@ int sqlite3VdbeCursorMoveto(VdbeCursor *p){
if( rc ) return rc;
if( hasMoved ){
p->cacheStatus = CACHE_STALE;
p->nullRow = 1;
if( hasMoved==2 ) p->nullRow = 1;
}
}
return SQLITE_OK;
@@ -2971,27 +2968,32 @@ u32 sqlite3VdbeSerialGet(
case 1: { /* 1-byte signed integer */
pMem->u.i = ONE_BYTE_INT(buf);
pMem->flags = MEM_Int;
testcase( pMem->u.i<0 );
return 1;
}
case 2: { /* 2-byte signed integer */
pMem->u.i = TWO_BYTE_INT(buf);
pMem->flags = MEM_Int;
testcase( pMem->u.i<0 );
return 2;
}
case 3: { /* 3-byte signed integer */
pMem->u.i = THREE_BYTE_INT(buf);
pMem->flags = MEM_Int;
testcase( pMem->u.i<0 );
return 3;
}
case 4: { /* 4-byte signed integer */
y = FOUR_BYTE_UINT(buf);
pMem->u.i = (i64)*(int*)&y;
pMem->flags = MEM_Int;
testcase( pMem->u.i<0 );
return 4;
}
case 5: { /* 6-byte signed integer */
pMem->u.i = FOUR_BYTE_UINT(buf+2) + (((i64)1)<<32)*TWO_BYTE_INT(buf);
pMem->flags = MEM_Int;
testcase( pMem->u.i<0 );
return 6;
}
case 6: /* 8-byte signed integer */
@@ -3014,6 +3016,7 @@ u32 sqlite3VdbeSerialGet(
if( serial_type==6 ){
pMem->u.i = *(i64*)&x;
pMem->flags = MEM_Int;
testcase( pMem->u.i<0 );
}else{
assert( sizeof(x)==8 && sizeof(pMem->r)==8 );
swapMixedEndianFloat(x);
@@ -3359,20 +3362,26 @@ static i64 vdbeRecordDecodeInt(u32 serial_type, const u8 *aKey){
switch( serial_type ){
case 0:
case 1:
testcase( aKey[0]&0x80 );
return ONE_BYTE_INT(aKey);
case 2:
testcase( aKey[0]&0x80 );
return TWO_BYTE_INT(aKey);
case 3:
testcase( aKey[0]&0x80 );
return THREE_BYTE_INT(aKey);
case 4: {
testcase( aKey[0]&0x80 );
y = FOUR_BYTE_UINT(aKey);
return (i64)*(int*)&y;
}
case 5: {
testcase( aKey[0]&0x80 );
return FOUR_BYTE_UINT(aKey+2) + (((i64)1)<<32)*TWO_BYTE_INT(aKey);
}
case 6: {
u64 x = FOUR_BYTE_UINT(aKey);
testcase( aKey[0]&0x80 );
x = (x<<32) | FOUR_BYTE_UINT(aKey+4);
return (i64)*(i64*)&x;
}
@@ -3396,15 +3405,18 @@ static i64 vdbeRecordDecodeInt(u32 serial_type, const u8 *aKey){
** Key1 and Key2 do not have to contain the same number of fields. If all
** fields that appear in both keys are equal, then pPKey2->default_rc is
** returned.
**
** If database corruption is discovered, set pPKey2->isCorrupt to non-zero
** and return 0.
*/
int sqlite3VdbeRecordCompare(
int nKey1, const void *pKey1, /* Left key */
const UnpackedRecord *pPKey2, /* Right key */
UnpackedRecord *pPKey2, /* Right key */
int bSkip /* If true, skip the first field */
){
u32 d1; /* Offset into aKey[] of next data element */
int i; /* Index of next field to compare */
int szHdr1; /* Size of record header in bytes */
u32 szHdr1; /* Size of record header in bytes */
u32 idx1; /* Offset of first type in header */
int rc = 0; /* Return value */
Mem *pRhs = pPKey2->aMem; /* Next field of pPKey2 to compare */
@@ -3425,6 +3437,10 @@ int sqlite3VdbeRecordCompare(
}else{
idx1 = getVarint32(aKey1, szHdr1);
d1 = szHdr1;
if( d1>(unsigned)nKey1 ){
pPKey2->isCorrupt = (u8)SQLITE_CORRUPT_BKPT;
return 0; /* Corruption */
}
i = 0;
}
@@ -3440,6 +3456,7 @@ int sqlite3VdbeRecordCompare(
/* RHS is an integer */
if( pRhs->flags & MEM_Int ){
serial_type = aKey1[idx1];
testcase( serial_type==12 );
if( serial_type>=12 ){
rc = +1;
}else if( serial_type==0 ){
@@ -3490,14 +3507,18 @@ int sqlite3VdbeRecordCompare(
/* RHS is a string */
else if( pRhs->flags & MEM_Str ){
getVarint32(&aKey1[idx1], serial_type);
testcase( serial_type==12 );
if( serial_type<12 ){
rc = -1;
}else if( !(serial_type & 0x01) ){
rc = +1;
}else{
mem1.n = (serial_type - 12) / 2;
testcase( (d1+mem1.n)==(unsigned)nKey1 );
testcase( (d1+mem1.n+1)==(unsigned)nKey1 );
if( (d1+mem1.n) > (unsigned)nKey1 ){
rc = 1; /* Corruption */
pPKey2->isCorrupt = (u8)SQLITE_CORRUPT_BKPT;
return 0; /* Corruption */
}else if( pKeyInfo->aColl[i] ){
mem1.enc = pKeyInfo->enc;
mem1.db = pKeyInfo->db;
@@ -3515,12 +3536,16 @@ int sqlite3VdbeRecordCompare(
/* RHS is a blob */
else if( pRhs->flags & MEM_Blob ){
getVarint32(&aKey1[idx1], serial_type);
testcase( serial_type==12 );
if( serial_type<12 || (serial_type & 0x01) ){
rc = -1;
}else{
int nStr = (serial_type - 12) / 2;
testcase( (d1+nStr)==(unsigned)nKey1 );
testcase( (d1+nStr+1)==(unsigned)nKey1 );
if( (d1+nStr) > (unsigned)nKey1 ){
rc = 1; /* Corruption */
pPKey2->isCorrupt = (u8)SQLITE_CORRUPT_BKPT;
return 0; /* Corruption */
}else{
int nCmp = MIN(nStr, pRhs->n);
rc = memcmp(&aKey1[d1], pRhs->z, nCmp);
@@ -3539,9 +3564,10 @@ int sqlite3VdbeRecordCompare(
if( pKeyInfo->aSortOrder[i] ){
rc = -rc;
}
assert( CORRUPT_DB
assert( CORRUPT_DB
|| (rc<0 && vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)<0)
|| (rc>0 && vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)>0)
|| pKeyInfo->db->mallocFailed
);
assert( mem1.zMalloc==0 ); /* See comment below */
return rc;
@@ -3572,10 +3598,13 @@ int sqlite3VdbeRecordCompare(
** that (a) the first field of pPKey2 is an integer, and (b) the
** size-of-header varint at the start of (pKey1/nKey1) fits in a single
** byte (i.e. is less than 128).
**
** To avoid concerns about buffer overreads, this routine is only used
** on schemas where the maximum valid header size is 63 bytes or less.
*/
static int vdbeRecordCompareInt(
int nKey1, const void *pKey1, /* Left key */
const UnpackedRecord *pPKey2, /* Right key */
UnpackedRecord *pPKey2, /* Right key */
int bSkip /* Ignored */
){
const u8 *aKey = &((const u8*)pKey1)[*(const u8*)pKey1 & 0x3F];
@@ -3588,32 +3617,39 @@ static int vdbeRecordCompareInt(
UNUSED_PARAMETER(bSkip);
assert( bSkip==0 );
assert( (*(u8*)pKey1)<=0x3F || CORRUPT_DB );
switch( serial_type ){
case 1: { /* 1-byte signed integer */
lhs = ONE_BYTE_INT(aKey);
testcase( lhs<0 );
break;
}
case 2: { /* 2-byte signed integer */
lhs = TWO_BYTE_INT(aKey);
testcase( lhs<0 );
break;
}
case 3: { /* 3-byte signed integer */
lhs = THREE_BYTE_INT(aKey);
testcase( lhs<0 );
break;
}
case 4: { /* 4-byte signed integer */
y = FOUR_BYTE_UINT(aKey);
lhs = (i64)*(int*)&y;
testcase( lhs<0 );
break;
}
case 5: { /* 6-byte signed integer */
lhs = FOUR_BYTE_UINT(aKey+2) + (((i64)1)<<32)*TWO_BYTE_INT(aKey);
testcase( lhs<0 );
break;
}
case 6: { /* 8-byte signed integer */
x = FOUR_BYTE_UINT(aKey);
x = (x<<32) | FOUR_BYTE_UINT(aKey+4);
lhs = *(i64*)&x;
testcase( lhs<0 );
break;
}
case 8:
@@ -3666,7 +3702,7 @@ static int vdbeRecordCompareInt(
*/
static int vdbeRecordCompareString(
int nKey1, const void *pKey1, /* Left key */
const UnpackedRecord *pPKey2, /* Right key */
UnpackedRecord *pPKey2, /* Right key */
int bSkip
){
const u8 *aKey1 = (const u8*)pKey1;
@@ -3687,7 +3723,10 @@ static int vdbeRecordCompareString(
int szHdr = aKey1[0];
nStr = (serial_type-12) / 2;
if( (szHdr + nStr) > nKey1 ) return 0; /* Corruption */
if( (szHdr + nStr) > nKey1 ){
pPKey2->isCorrupt = (u8)SQLITE_CORRUPT_BKPT;
return 0; /* Corruption */
}
nCmp = MIN( pPKey2->aMem[0].n, nStr );
res = memcmp(&aKey1[szHdr], pPKey2->aMem[0].z, nCmp);
@@ -3750,9 +3789,11 @@ RecordCompare sqlite3VdbeFindCompare(UnpackedRecord *p){
if( (flags & MEM_Int) ){
return vdbeRecordCompareInt;
}
if( (flags & (MEM_Int|MEM_Real|MEM_Null|MEM_Blob))==0
&& p->pKeyInfo->aColl[0]==0
){
testcase( flags & MEM_Real );
testcase( flags & MEM_Null );
testcase( flags & MEM_Blob );
if( (flags & (MEM_Real|MEM_Null|MEM_Blob))==0 && p->pKeyInfo->aColl[0]==0 ){
assert( flags & MEM_Str );
return vdbeRecordCompareString;
}
}
@@ -3850,7 +3891,7 @@ idx_rowid_corruption:
*/
int sqlite3VdbeIdxKeyCompare(
VdbeCursor *pC, /* The cursor to compare against */
const UnpackedRecord *pUnpacked, /* Unpacked version of key */
UnpackedRecord *pUnpacked, /* Unpacked version of key */
int *res /* Write the comparison result here */
){
i64 nCellKey = 0;
@@ -3936,7 +3977,6 @@ sqlite3_value *sqlite3VdbeGetBoundValue(Vdbe *v, int iVar, u8 aff){
if( pRet ){
sqlite3VdbeMemCopy((Mem *)pRet, pMem);
sqlite3ValueApplyAffinity(pRet, aff, SQLITE_UTF8);
sqlite3VdbeMemStoreType((Mem *)pRet);
}
return pRet;
}
+2 -4
View File
@@ -77,9 +77,7 @@ static int blobSeekToRow(Incrblob *p, sqlite3_int64 iRow, char **pzErr){
p->iOffset = pC->aType[p->iCol + pC->nField];
p->nByte = sqlite3VdbeSerialTypeLen(type);
p->pCsr = pC->pCursor;
sqlite3BtreeEnterCursor(p->pCsr);
sqlite3BtreeCacheOverflow(p->pCsr);
sqlite3BtreeLeaveCursor(p->pCsr);
sqlite3BtreeIncrblobCursor(p->pCsr);
}
}
@@ -133,7 +131,7 @@ int sqlite3_blob_open(
** which closes the b-tree cursor and (possibly) commits the
** transaction.
*/
static const int iLn = __LINE__+4;
static const int iLn = VDBE_OFFSET_LINENO(4);
static const VdbeOpList openBlob[] = {
/* {OP_Transaction, 0, 0, 0}, // 0: Inserted separately */
{OP_TableLock, 0, 0, 0}, /* 1: Acquire a read or write lock */
+11 -22
View File
@@ -122,6 +122,7 @@ int sqlite3VdbeMemGrow(Mem *pMem, int n, int bPreserve){
}
if( pMem->zMalloc==0 ){
VdbeMemRelease(pMem);
pMem->z = 0;
pMem->flags = MEM_Null;
return SQLITE_NOMEM;
}
@@ -320,7 +321,7 @@ void sqlite3VdbeMemReleaseExternal(Mem *p){
/*
** Release any memory held by the Mem. This may leave the Mem in an
** inconsistent state, for example with (Mem.z==0) and
** (Mem.memType==MEM_Str).
** (Mem.flags==MEM_Str).
*/
void sqlite3VdbeMemRelease(Mem *p){
assert( sqlite3VdbeCheckMemInvariants(p) );
@@ -512,7 +513,6 @@ void sqlite3VdbeMemSetNull(Mem *pMem){
sqlite3RowSetClear(pMem->u.pRowSet);
}
MemSetTypeFlag(pMem, MEM_Null);
pMem->memType = MEM_Null;
}
void sqlite3ValueSetNull(sqlite3_value *p){
sqlite3VdbeMemSetNull((Mem*)p);
@@ -525,7 +525,6 @@ void sqlite3ValueSetNull(sqlite3_value *p){
void sqlite3VdbeMemSetZeroBlob(Mem *pMem, int n){
sqlite3VdbeMemRelease(pMem);
pMem->flags = MEM_Blob|MEM_Zero;
pMem->memType = MEM_Blob;
pMem->n = 0;
if( n<0 ) n = 0;
pMem->u.nZero = n;
@@ -548,7 +547,6 @@ void sqlite3VdbeMemSetInt64(Mem *pMem, i64 val){
sqlite3VdbeMemRelease(pMem);
pMem->u.i = val;
pMem->flags = MEM_Int;
pMem->memType = MEM_Int;
}
#ifndef SQLITE_OMIT_FLOATING_POINT
@@ -563,7 +561,6 @@ void sqlite3VdbeMemSetDouble(Mem *pMem, double val){
sqlite3VdbeMemRelease(pMem);
pMem->r = val;
pMem->flags = MEM_Real;
pMem->memType = MEM_Real;
}
}
#endif
@@ -772,7 +769,6 @@ int sqlite3VdbeMemSetStr(
pMem->n = nByte;
pMem->flags = flags;
pMem->enc = (enc==0 ? SQLITE_UTF8 : enc);
pMem->memType = flags&0x1f;
#ifndef SQLITE_OMIT_UTF16
if( pMem->enc!=SQLITE_UTF8 && sqlite3VdbeMemHandleBom(pMem) ){
@@ -827,22 +823,22 @@ int sqlite3VdbeMemFromBtree(
sqlite3VdbeMemRelease(pMem);
pMem->z = &zData[offset];
pMem->flags = MEM_Blob|MEM_Ephem;
pMem->n = (int)amt;
}else if( SQLITE_OK==(rc = sqlite3VdbeMemGrow(pMem, amt+2, 0)) ){
pMem->flags = MEM_Blob|MEM_Term;
pMem->enc = 0;
pMem->memType = MEM_Blob;
if( key ){
rc = sqlite3BtreeKey(pCur, offset, amt, pMem->z);
}else{
rc = sqlite3BtreeData(pCur, offset, amt, pMem->z);
}
pMem->z[amt] = 0;
pMem->z[amt+1] = 0;
if( rc!=SQLITE_OK ){
if( rc==SQLITE_OK ){
pMem->z[amt] = 0;
pMem->z[amt+1] = 0;
pMem->flags = MEM_Blob|MEM_Term;
pMem->n = (int)amt;
}else{
sqlite3VdbeMemRelease(pMem);
}
}
pMem->n = (int)amt;
return rc;
}
@@ -900,7 +896,6 @@ sqlite3_value *sqlite3ValueNew(sqlite3 *db){
Mem *p = sqlite3DbMallocZero(db, sizeof(*p));
if( p ){
p->flags = MEM_Null;
p->memType = MEM_Null;
p->db = db;
}
return p;
@@ -949,7 +944,6 @@ static sqlite3_value *valueNew(sqlite3 *db, struct ValueNewStat4Ctx *p){
pRec->aMem = (Mem *)((u8*)pRec + ROUND8(sizeof(UnpackedRecord)));
for(i=0; i<nCol; i++){
pRec->aMem[i].flags = MEM_Null;
pRec->aMem[i].memType = MEM_Null;
pRec->aMem[i].db = db;
}
}else{
@@ -1022,7 +1016,6 @@ static int valueFromExpr(
zVal = sqlite3MPrintf(db, "%s%s", zNeg, pExpr->u.zToken);
if( zVal==0 ) goto no_mem;
sqlite3ValueSetStr(pVal, -1, zVal, SQLITE_UTF8, SQLITE_DYNAMIC);
if( op==TK_FLOAT ) pVal->memType = MEM_Real;
}
if( (op==TK_INTEGER || op==TK_FLOAT ) && affinity==SQLITE_AFF_NONE ){
sqlite3ValueApplyAffinity(pVal, SQLITE_AFF_NUMERIC, SQLITE_UTF8);
@@ -1040,9 +1033,9 @@ static int valueFromExpr(
){
sqlite3VdbeMemNumerify(pVal);
if( pVal->u.i==SMALLEST_INT64 ){
pVal->flags &= MEM_Int;
pVal->flags &= ~MEM_Int;
pVal->flags |= MEM_Real;
pVal->r = (double)LARGEST_INT64;
pVal->r = (double)SMALLEST_INT64;
}else{
pVal->u.i = -pVal->u.i;
}
@@ -1068,9 +1061,6 @@ static int valueFromExpr(
}
#endif
if( pVal ){
sqlite3VdbeMemStoreType(pVal);
}
*ppVal = pVal;
return rc;
@@ -1234,7 +1224,6 @@ int sqlite3Stat4ProbeSetValue(
sqlite3ValueApplyAffinity(pVal, affinity, ENC(db));
}
pVal->db = pParse->db;
sqlite3VdbeMemStoreType((Mem*)pVal);
}
}
}else{
+75 -17
View File
@@ -504,23 +504,40 @@ static void vdbeSorterRecordFree(sqlite3 *db, SorterRecord *pRecord){
}
}
/*
** Reset a sorting cursor back to its original empty state.
*/
void sqlite3VdbeSorterReset(sqlite3 *db, VdbeSorter *pSorter){
if( pSorter->aIter ){
int i;
for(i=0; i<pSorter->nTree; i++){
vdbeSorterIterZero(db, &pSorter->aIter[i]);
}
sqlite3DbFree(db, pSorter->aIter);
pSorter->aIter = 0;
}
if( pSorter->pTemp1 ){
sqlite3OsCloseFree(pSorter->pTemp1);
pSorter->pTemp1 = 0;
}
vdbeSorterRecordFree(db, pSorter->pRecord);
pSorter->pRecord = 0;
pSorter->iWriteOff = 0;
pSorter->iReadOff = 0;
pSorter->nInMemory = 0;
pSorter->nTree = 0;
pSorter->nPMA = 0;
pSorter->aTree = 0;
}
/*
** Free any cursor components allocated by sqlite3VdbeSorterXXX routines.
*/
void sqlite3VdbeSorterClose(sqlite3 *db, VdbeCursor *pCsr){
VdbeSorter *pSorter = pCsr->pSorter;
if( pSorter ){
if( pSorter->aIter ){
int i;
for(i=0; i<pSorter->nTree; i++){
vdbeSorterIterZero(db, &pSorter->aIter[i]);
}
sqlite3DbFree(db, pSorter->aIter);
}
if( pSorter->pTemp1 ){
sqlite3OsCloseFree(pSorter->pTemp1);
}
vdbeSorterRecordFree(db, pSorter->pRecord);
sqlite3VdbeSorterReset(db, pSorter);
sqlite3DbFree(db, pSorter->pUnpacked);
sqlite3DbFree(db, pSorter);
pCsr->pSorter = 0;
@@ -956,14 +973,55 @@ int sqlite3VdbeSorterNext(sqlite3 *db, const VdbeCursor *pCsr, int *pbEof){
if( pSorter->aTree ){
int iPrev = pSorter->aTree[1];/* Index of iterator to advance */
int i; /* Index of aTree[] to recalculate */
rc = vdbeSorterIterNext(db, &pSorter->aIter[iPrev]);
for(i=(pSorter->nTree+iPrev)/2; rc==SQLITE_OK && i>0; i=i/2){
rc = vdbeSorterDoCompare(pCsr, i);
}
if( rc==SQLITE_OK ){
int i; /* Index of aTree[] to recalculate */
VdbeSorterIter *pIter1; /* First iterator to compare */
VdbeSorterIter *pIter2; /* Second iterator to compare */
u8 *pKey2; /* To pIter2->aKey, or 0 if record cached */
*pbEof = (pSorter->aIter[pSorter->aTree[1]].pFile==0);
/* Find the first two iterators to compare. The one that was just
** advanced (iPrev) and the one next to it in the array. */
pIter1 = &pSorter->aIter[(iPrev & 0xFFFE)];
pIter2 = &pSorter->aIter[(iPrev | 0x0001)];
pKey2 = pIter2->aKey;
for(i=(pSorter->nTree+iPrev)/2; i>0; i=i/2){
/* Compare pIter1 and pIter2. Store the result in variable iRes. */
int iRes;
if( pIter1->pFile==0 ){
iRes = +1;
}else if( pIter2->pFile==0 ){
iRes = -1;
}else{
vdbeSorterCompare(pCsr, 0,
pIter1->aKey, pIter1->nKey, pKey2, pIter2->nKey, &iRes
);
}
/* If pIter1 contained the smaller value, set aTree[i] to its index.
** Then set pIter2 to the next iterator to compare to pIter1. In this
** case there is no cache of pIter2 in pSorter->pUnpacked, so set
** pKey2 to point to the record belonging to pIter2.
**
** Alternatively, if pIter2 contains the smaller of the two values,
** set aTree[i] to its index and update pIter1. If vdbeSorterCompare()
** was actually called above, then pSorter->pUnpacked now contains
** a value equivalent to pIter2. So set pKey2 to NULL to prevent
** vdbeSorterCompare() from decoding pIter2 again. */
if( iRes<=0 ){
pSorter->aTree[i] = (int)(pIter1 - pSorter->aIter);
pIter2 = &pSorter->aIter[ pSorter->aTree[i ^ 0x0001] ];
pKey2 = pIter2->aKey;
}else{
if( pIter1->pFile ) pKey2 = 0;
pSorter->aTree[i] = (int)(pIter2 - pSorter->aIter);
pIter1 = &pSorter->aIter[ pSorter->aTree[i ^ 0x0001] ];
}
}
*pbEof = (pSorter->aIter[pSorter->aTree[1]].pFile==0);
}
}else{
SorterRecord *pFree = pSorter->pRecord;
pSorter->pRecord = pFree->pNext;
+563 -273
View File
File diff suppressed because it is too large Load Diff
+5 -4
View File
@@ -121,7 +121,7 @@ struct WhereLoop {
struct { /* Information for virtual tables */
int idxNum; /* Index number */
u8 needFree; /* True if sqlite3_free(idxStr) is needed */
u8 isOrdered; /* True if satisfies ORDER BY */
i8 isOrdered; /* True if satisfies ORDER BY */
u16 omitMask; /* Terms that may be omitted */
char *idxStr; /* Index identifier string */
} vtab;
@@ -183,8 +183,7 @@ struct WherePath {
Bitmask revLoop; /* aLoop[]s that should be reversed for ORDER BY */
LogEst nRow; /* Estimated number of rows generated by this path */
LogEst rCost; /* Total cost of this path */
u8 isOrdered; /* True if this path satisfies ORDER BY */
u8 isOrderedValid; /* True if the isOrdered field is valid */
i8 isOrdered; /* No. of ORDER BY terms satisfied. -1 for unknown */
WhereLoop **aLoop; /* Array of WhereLoop objects implementing this path */
};
@@ -398,7 +397,8 @@ struct WhereInfo {
Bitmask revMask; /* Mask of ORDER BY terms that need reversing */
LogEst nRowOut; /* Estimated number of output rows */
u16 wctrlFlags; /* Flags originally passed to sqlite3WhereBegin() */
u8 bOBSat; /* ORDER BY satisfied by indices */
i8 nOBSat; /* Number of ORDER BY terms satisfied by indices */
u8 sorted; /* True if really sorted (not just grouped) */
u8 okOnePass; /* Ok to use one-pass algorithm for UPDATE/DELETE */
u8 untestedTerms; /* Not all WHERE terms resolved by outer loop */
u8 eDistinct; /* One of the WHERE_DISTINCT_* values below */
@@ -458,3 +458,4 @@ struct WhereInfo {
#define WHERE_AUTO_INDEX 0x00004000 /* Uses an ephemeral index */
#define WHERE_SKIPSCAN 0x00008000 /* Uses the skip-scan algorithm */
#define WHERE_UNQ_WANTED 0x00010000 /* WHERE_ONEROW would have been helpful*/
#define WHERE_LIKELIHOOD 0x00020000 /* A likelihood() is affecting nOut */
+38
View File
@@ -875,4 +875,42 @@ do_execsql_test alter-16.2 {
SELECT * FROM t16a_rn ORDER BY a;
} {abc 1.25 99 xyzzy cba 5.5 98 fizzle}
#-------------------------------------------------------------------------
# Verify that NULL values into the internal-use-only sqlite_rename_*()
# functions do not cause problems.
#
do_execsql_test alter-17.1 {
SELECT sqlite_rename_table('CREATE TABLE xyz(a,b,c)','abc');
} {{CREATE TABLE "abc"(a,b,c)}}
do_execsql_test alter-17.2 {
SELECT sqlite_rename_table('CREATE TABLE xyz(a,b,c)',NULL);
} {{CREATE TABLE "(NULL)"(a,b,c)}}
do_execsql_test alter-17.3 {
SELECT sqlite_rename_table(NULL,'abc');
} {{}}
do_execsql_test alter-17.4 {
SELECT sqlite_rename_trigger('CREATE TRIGGER r1 ON xyz WHEN','abc');
} {{CREATE TRIGGER r1 ON "abc" WHEN}}
do_execsql_test alter-17.5 {
SELECT sqlite_rename_trigger('CREATE TRIGGER r1 ON xyz WHEN',NULL);
} {{CREATE TRIGGER r1 ON "(NULL)" WHEN}}
do_execsql_test alter-17.6 {
SELECT sqlite_rename_trigger(NULL,'abc');
} {{}}
do_execsql_test alter-17.7 {
SELECT sqlite_rename_parent('CREATE TABLE t1(a REFERENCES "xyzzy")',
'xyzzy','lmnop');
} {{CREATE TABLE t1(a REFERENCES "lmnop")}}
do_execsql_test alter-17.8 {
SELECT sqlite_rename_parent('CREATE TABLE t1(a REFERENCES "xyzzy")',
'xyzzy',NULL);
} {{CREATE TABLE t1(a REFERENCES "(NULL)")}}
do_execsql_test alter-17.9 {
SELECT sqlite_rename_parent('CREATE TABLE t1(a REFERENCES "xyzzy")',
NULL, 'lmnop');
} {{}}
do_execsql_test alter-17.10 {
SELECT sqlite_rename_parent(NULL,'abc','xyz');
} {{}}
finish_test
+21
View File
@@ -334,4 +334,25 @@ do_test alter4-8.2 {
}
} [list $::sql]
# Test that a default value equal to -1 multipied by the smallest possible
# 64-bit integer is correctly converted to a real.
do_execsql_test alter4-9.1 {
CREATE TABLE t5(
a INTEGER DEFAULT -9223372036854775808,
b INTEGER DEFAULT (-(-9223372036854775808))
);
INSERT INTO t5 DEFAULT VALUES;
}
do_execsql_test alter4-9.2 { SELECT typeof(a), a, typeof(b), b FROM t5; } {
integer -9223372036854775808
real 9.22337203685478e+18
}
do_execsql_test alter4-9.3 {
ALTER TABLE t5 ADD COLUMN c INTEGER DEFAULT (-(-9223372036854775808));
SELECT typeof(c), c FROM t5;
} {real 9.22337203685478e+18}
finish_test
+30 -12
View File
@@ -103,12 +103,21 @@ do_test analyze3-1.1.1 {
}
} {1}
do_execsql_test analyze3-1.1.x {
SELECT count(*) FROM t1 WHERE x>200 AND x<300;
SELECT count(*) FROM t1 WHERE x>0 AND x<1100;
} {99 1000}
# The first of the following two SELECT statements visits 99 rows. So
# it is better to use the index. But the second visits every row in
# the table (1000 in total) so it is better to do a full-table scan.
#
do_eqp_test analyze3-1.1.2 {
SELECT sum(y) FROM t1 WHERE x>200 AND x<300
} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (x>? AND x<?)}}
do_eqp_test analyze3-1.1.3 {
SELECT sum(y) FROM t1 WHERE x>0 AND x<1100
} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (x>? AND x<?)}}
} {0 0 0 {SCAN TABLE t1}}
do_test analyze3-1.1.4 {
sf_execsql { SELECT sum(y) FROM t1 WHERE x>200 AND x<300 }
@@ -125,17 +134,17 @@ do_test analyze3-1.1.6 {
} {199 0 14850}
do_test analyze3-1.1.7 {
sf_execsql { SELECT sum(y) FROM t1 WHERE x>0 AND x<1100 }
} {2000 0 499500}
} {999 999 499500}
do_test analyze3-1.1.8 {
set l [string range "0" 0 end]
set u [string range "1100" 0 end]
sf_execsql { SELECT sum(y) FROM t1 WHERE x>$l AND x<$u }
} {2000 0 499500}
} {999 999 499500}
do_test analyze3-1.1.9 {
set l [expr int(0)]
set u [expr int(1100)]
sf_execsql { SELECT sum(y) FROM t1 WHERE x>$l AND x<$u }
} {2000 0 499500}
} {999 999 499500}
# The following tests are similar to the block above. The difference is
@@ -152,12 +161,17 @@ do_test analyze3-1.2.1 {
ANALYZE;
}
} {}
do_execsql_test analyze3-2.1.x {
SELECT count(*) FROM t2 WHERE x>1 AND x<2;
SELECT count(*) FROM t2 WHERE x>0 AND x<99;
} {200 990}
do_eqp_test analyze3-1.2.2 {
SELECT sum(y) FROM t2 WHERE x>1 AND x<2
} {0 0 0 {SEARCH TABLE t2 USING INDEX i2 (x>? AND x<?)}}
do_eqp_test analyze3-1.2.3 {
SELECT sum(y) FROM t2 WHERE x>0 AND x<99
} {0 0 0 {SEARCH TABLE t2 USING INDEX i2 (x>? AND x<?)}}
} {0 0 0 {SCAN TABLE t2}}
do_test analyze3-1.2.4 {
sf_execsql { SELECT sum(y) FROM t2 WHERE x>12 AND x<20 }
} {161 0 4760}
@@ -173,17 +187,17 @@ do_test analyze3-1.2.6 {
} {161 0 integer integer 4760}
do_test analyze3-1.2.7 {
sf_execsql { SELECT sum(y) FROM t2 WHERE x>0 AND x<99 }
} {1981 0 490555}
} {999 999 490555}
do_test analyze3-1.2.8 {
set l [string range "0" 0 end]
set u [string range "99" 0 end]
sf_execsql {SELECT typeof($l), typeof($u), sum(y) FROM t2 WHERE x>$l AND x<$u}
} {1981 0 text text 490555}
} {999 999 text text 490555}
do_test analyze3-1.2.9 {
set l [expr int(0)]
set u [expr int(99)]
sf_execsql {SELECT typeof($l), typeof($u), sum(y) FROM t2 WHERE x>$l AND x<$u}
} {1981 0 integer integer 490555}
} {999 999 integer integer 490555}
# Same tests a third time. This time, column x has INTEGER affinity and
# is not the leftmost column of the table. This triggered a bug causing
@@ -199,12 +213,16 @@ do_test analyze3-1.3.1 {
ANALYZE;
}
} {}
do_execsql_test analyze3-1.3.x {
SELECT count(*) FROM t3 WHERE x>200 AND x<300;
SELECT count(*) FROM t3 WHERE x>0 AND x<1100
} {99 1000}
do_eqp_test analyze3-1.3.2 {
SELECT sum(y) FROM t3 WHERE x>200 AND x<300
} {0 0 0 {SEARCH TABLE t3 USING INDEX i3 (x>? AND x<?)}}
do_eqp_test analyze3-1.3.3 {
SELECT sum(y) FROM t3 WHERE x>0 AND x<1100
} {0 0 0 {SEARCH TABLE t3 USING INDEX i3 (x>? AND x<?)}}
} {0 0 0 {SCAN TABLE t3}}
do_test analyze3-1.3.4 {
sf_execsql { SELECT sum(y) FROM t3 WHERE x>200 AND x<300 }
@@ -221,17 +239,17 @@ do_test analyze3-1.3.6 {
} {199 0 14850}
do_test analyze3-1.3.7 {
sf_execsql { SELECT sum(y) FROM t3 WHERE x>0 AND x<1100 }
} {2000 0 499500}
} {999 999 499500}
do_test analyze3-1.3.8 {
set l [string range "0" 0 end]
set u [string range "1100" 0 end]
sf_execsql { SELECT sum(y) FROM t3 WHERE x>$l AND x<$u }
} {2000 0 499500}
} {999 999 499500}
do_test analyze3-1.3.9 {
set l [expr int(0)]
set u [expr int(1100)]
sf_execsql { SELECT sum(y) FROM t3 WHERE x>$l AND x<$u }
} {2000 0 499500}
} {999 999 499500}
#-------------------------------------------------------------------------
# Test that the values of bound SQL variables may be used for the LIKE
+5 -5
View File
@@ -566,7 +566,7 @@ foreach {tn schema} {
drop_all_tables
do_test 13.1 {
execsql {
CREATE TABLE t1(a, b, c);
CREATE TABLE t1(a, b, c, d);
CREATE INDEX i1 ON t1(a);
CREATE INDEX i2 ON t1(b, c);
}
@@ -577,16 +577,16 @@ do_test 13.1 {
execsql ANALYZE
} {}
do_eqp_test 13.2.1 {
SELECT * FROM t1 WHERE a='abc' AND rowid<15 AND b<20
SELECT * FROM t1 WHERE a='abc' AND rowid<15 AND b<12
} {/SEARCH TABLE t1 USING INDEX i1/}
do_eqp_test 13.2.2 {
SELECT * FROM t1 WHERE a='abc' AND rowid<'15' AND b<20
SELECT * FROM t1 WHERE a='abc' AND rowid<'15' AND b<12
} {/SEARCH TABLE t1 USING INDEX i1/}
do_eqp_test 13.3.1 {
SELECT * FROM t1 WHERE a='abc' AND rowid<100 AND b<20
SELECT * FROM t1 WHERE a='abc' AND rowid<100 AND b<12
} {/SEARCH TABLE t1 USING INDEX i2/}
do_eqp_test 13.3.2 {
SELECT * FROM t1 WHERE a='abc' AND rowid<'100' AND b<20
SELECT * FROM t1 WHERE a='abc' AND rowid<'100' AND b<12
} {/SEARCH TABLE t1 USING INDEX i2/}
#-------------------------------------------------------------------------
+2
View File
@@ -97,6 +97,8 @@ do_test autoindex1-210 {
PRAGMA automatic_index=ON;
ANALYZE;
UPDATE sqlite_stat1 SET stat='10000' WHERE tbl='t1';
-- Table t2 actually contains 8 rows.
UPDATE sqlite_stat1 SET stat='16' WHERE tbl='t2';
ANALYZE sqlite_master;
SELECT b, (SELECT d FROM t2 WHERE c=a) FROM t1;
}
+18
View File
@@ -16,6 +16,7 @@
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set ::testprefix capi3
# Do not use a codec for tests in this file, as the database file is
# manipulated directly using tcl scripts (using the [hexio_write] command).
@@ -1221,6 +1222,23 @@ do_test capi3-19.1 {
sqlite3_prepare_tkt3134 db
} {}
# Test that calling sqlite3_column_blob() on a TEXT value does not change
# the return type of subsequent calls to sqlite3_column_type().
#
do_execsql_test 20.1 {
CREATE TABLE t4(x);
INSERT INTO t4 VALUES('abcdefghij');
}
do_test 20.2 {
set stmt [sqlite3_prepare db "SELECT * FROM t4" -1 dummy]
sqlite3_step $stmt
} {SQLITE_ROW}
do_test 20.3 { sqlite3_column_type $stmt 0 } {TEXT}
do_test 20.4 { sqlite3_column_blob $stmt 0 } {abcdefghij}
do_test 20.5 { sqlite3_column_type $stmt 0 } {TEXT}
do_test 20.6 { sqlite3_finalize $stmt } SQLITE_OK
# Tests of the interface when no VFS is registered.
#
if {![info exists tester_do_binarylog]} {
+3 -8
View File
@@ -47,12 +47,12 @@ do_test 1.2 {
catchsql {
SELECT c FROM t1 WHERE a>'abc';
}
} {0 {}}
} {1 {database disk image is malformed}}
do_test 1.3 {
catchsql {
PRAGMA integrity_check
}
} {0 ok}
} {1 {database disk image is malformed}}
do_test 1.4 {
catchsql {
SELECT c FROM t1 ORDER BY a;
@@ -71,11 +71,6 @@ do_test 2.1 {
catchsql {
SELECT rowid FROM t1 WHERE a='abc' and b='xyz123456789XYZ';
}
# The following test result is brittle. The point above is to try to
# force a buffer overread by a corrupt database file. If we get an
# incorrect answer from a corrupt database file, that is OK. If the
# result below changes, that just means that "undefined behavior" has
# changed.
} {/0 .*/}
} {1 {database disk image is malformed}}
finish_test
+13 -11
View File
@@ -20,6 +20,18 @@ set testprefix corruptH
do_not_use_codec
database_may_be_corrupt
# The corruption migrations tested by the code in this file are not detected
# mmap mode.
#
# The reason is that in mmap mode, the different queries may use different
# PgHdr objects for the same page (same data, but different PgHdr container
# objects). And so the corruption is not detected.
#
if {[permutation]=="mmap"} {
finish_test
return
}
# Initialize the database.
#
do_execsql_test 1.1 {
@@ -52,6 +64,7 @@ do_test 1.2 {
} {}
do_test 1.3 {
breakpoint
db eval { PRAGMA secure_delete=1 }
list [catch {
db eval { SELECT * FROM t1 WHERE a IN (1, 2) } {
@@ -97,9 +110,6 @@ do_test 2.2 {
} {}
# The corruption migration caused by the test case below does not
# cause corruption to be detected in mmap mode.
#
# The trick here is that the root page of the tree scanned by the outer
# query is also currently on the free-list. So while the first seek on
# the table (for a==1) works, by the time the second is attempted The
@@ -109,15 +119,7 @@ do_test 2.2 {
# the cursor (as it is now marked with PgHdr.intKey==0) and returns
# SQLITE_CORRUPT.
#
# However, in mmap mode, the outer query and the inner queries use
# different PgHdr objects (same data, but different PgHdr container
# objects). And so the corruption is not detected. Instead, the second
# seek fails to find anything and only a single row is returned.
#
set res23 {1 {database disk image is malformed}}
if {[permutation]=="mmap"} {
set res23 {0 one}
}
do_test 2.3 {
list [catch {
set res [list]
+37 -5
View File
@@ -14,6 +14,11 @@ set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix corruptI
if {[permutation]=="mmap"} {
finish_test
return
}
# Do not use a codec for tests in this file, as the database file is
# manipulated directly using tcl scripts (using the [hexio_write] command).
#
@@ -27,21 +32,48 @@ do_execsql_test 1.1 {
PRAGMA auto_vacuum=0;
CREATE TABLE t1(a);
CREATE INDEX i1 ON t1(a);
INSERT INTO t1 VALUES('a');
INSERT INTO t1 VALUES('abcdefghijklmnop');
} {}
db close
do_test 1.2 {
set offset [hexio_get_int [hexio_read test.db [expr 2*1024 + 8] 2]]
set off [expr 2*1024 + $offset + 1]
hexio_write test.db $off FF06
breakpoint
hexio_write test.db $off 7f06
sqlite3 db test.db
catchsql { SELECT * FROM t1 WHERE a = 10 }
} {0 {}}
do_test 1.3 {
db close
set offset [hexio_get_int [hexio_read test.db [expr 2*1024 + 8] 2]]
set off [expr 2*1024 + $offset + 1]
hexio_write test.db $off FFFF7f02
sqlite3 db test.db
catchsql { SELECT * FROM t1 WHERE a = 10 }
} {1 {database disk image is malformed}}
do_test 2.0 {
execsql {
CREATE TABLE r(x);
INSERT INTO r VALUES('ABCDEFGHIJK');
CREATE INDEX r1 ON r(x);
}
set pg [db one {SELECT rootpage FROM sqlite_master WHERE name = 'r1'}]
} {5}
do_test 2.1 {
db close
set offset [hexio_get_int [hexio_read test.db [expr (5-1)*1024 + 8] 2]]
set off [expr (5-1)*1024 + $offset + 1]
hexio_write test.db $off FFFF0004
sqlite3 db test.db
catchsql { SELECT * FROM r WHERE x >= 10.0 }
} {1 {database disk image is malformed}}
do_test 2.2 {
catchsql { SELECT * FROM r WHERE x >= 10 }
} {1 {database disk image is malformed}}
finish_test
+251
View File
@@ -0,0 +1,251 @@
# 2014-04-26
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix cost
do_execsql_test 1.1 {
CREATE TABLE t3(id INTEGER PRIMARY KEY, b NOT NULL);
CREATE TABLE t4(c, d, e);
CREATE UNIQUE INDEX i3 ON t3(b);
CREATE UNIQUE INDEX i4 ON t4(c, d);
}
do_eqp_test 1.2 {
SELECT e FROM t3, t4 WHERE b=c ORDER BY b, d;
} {
0 0 0 {SCAN TABLE t3 USING COVERING INDEX i3}
0 1 1 {SEARCH TABLE t4 USING INDEX i4 (c=?)}
}
do_execsql_test 2.1 {
CREATE TABLE t1(a, b);
CREATE INDEX i1 ON t1(a);
}
# It is better to use an index for ORDER BY than sort externally, even
# if the index is a non-covering index.
do_eqp_test 2.2 {
SELECT * FROM t1 ORDER BY a;
} {
0 0 0 {SCAN TABLE t1 USING INDEX i1}
}
do_execsql_test 3.1 {
CREATE TABLE t5(a INTEGER PRIMARY KEY,b,c,d,e,f,g);
CREATE INDEX t5b ON t5(b);
CREATE INDEX t5c ON t5(c);
CREATE INDEX t5d ON t5(d);
CREATE INDEX t5e ON t5(e);
CREATE INDEX t5f ON t5(f);
CREATE INDEX t5g ON t5(g);
}
do_eqp_test 3.2 {
SELECT a FROM t5
WHERE b IS NULL OR c IS NULL OR d IS NULL
ORDER BY a;
} {
0 0 0 {SEARCH TABLE t5 USING INDEX t5b (b=?)}
0 0 0 {SEARCH TABLE t5 USING INDEX t5c (c=?)}
0 0 0 {SEARCH TABLE t5 USING INDEX t5d (d=?)}
0 0 0 {USE TEMP B-TREE FOR ORDER BY}
}
#-------------------------------------------------------------------------
# If there is no likelihood() or stat3 data, SQLite assumes that a closed
# range scan (e.g. one constrained by "col BETWEEN ? AND ?" constraint)
# visits 1/64 of the rows in a table.
#
# Note: 1/63 =~ 0.016
# Note: 1/65 =~ 0.015
#
reset_db
do_execsql_test 4.1 {
CREATE TABLE t1(a, b);
CREATE INDEX i1 ON t1(a);
CREATE INDEX i2 ON t1(b);
}
do_eqp_test 4.2 {
SELECT * FROM t1 WHERE likelihood(a=?, 0.014) AND b BETWEEN ? AND ?;
} {
0 0 0 {SEARCH TABLE t1 USING INDEX i1 (a=?)}
}
do_eqp_test 4.3 {
SELECT * FROM t1 WHERE likelihood(a=?, 0.016) AND b BETWEEN ? AND ?;
} {
0 0 0 {SEARCH TABLE t1 USING INDEX i2 (b>? AND b<?)}
}
#-------------------------------------------------------------------------
#
reset_db
do_execsql_test 5.1 {
CREATE TABLE t2(x, y);
CREATE INDEX t2i1 ON t2(x);
}
do_eqp_test 5.2 {
SELECT * FROM t2 ORDER BY x, y;
} {
0 0 0 {SCAN TABLE t2 USING INDEX t2i1}
0 0 0 {USE TEMP B-TREE FOR RIGHT PART OF ORDER BY}
}
do_eqp_test 5.3 {
SELECT * FROM t2 WHERE x BETWEEN ? AND ? ORDER BY rowid;
} {
0 0 0 {SEARCH TABLE t2 USING INDEX t2i1 (x>? AND x<?)}
0 0 0 {USE TEMP B-TREE FOR ORDER BY}
}
# where7.test, where8.test:
#
do_execsql_test 6.1 {
CREATE TABLE t3(a INTEGER PRIMARY KEY, b, c);
CREATE INDEX t3i1 ON t3(b);
CREATE INDEX t3i2 ON t3(c);
}
do_eqp_test 6.2 {
SELECT a FROM t3 WHERE (b BETWEEN 2 AND 4) OR c=100 ORDER BY a
} {
0 0 0 {SEARCH TABLE t3 USING INDEX t3i1 (b>? AND b<?)}
0 0 0 {SEARCH TABLE t3 USING INDEX t3i2 (c=?)}
0 0 0 {USE TEMP B-TREE FOR ORDER BY}
}
#-------------------------------------------------------------------------
#
reset_db
do_execsql_test 7.1 {
CREATE TABLE t1(a INTEGER PRIMARY KEY,b,c,d,e,f,g);
CREATE INDEX t1b ON t1(b);
CREATE INDEX t1c ON t1(c);
CREATE INDEX t1d ON t1(d);
CREATE INDEX t1e ON t1(e);
CREATE INDEX t1f ON t1(f);
CREATE INDEX t1g ON t1(g);
}
do_eqp_test 7.2 {
SELECT a FROM t1
WHERE (b>=950 AND b<=1010) OR (b IS NULL AND c NOT NULL)
ORDER BY a
} {
0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b>? AND b<?)}
0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b=?)}
0 0 0 {USE TEMP B-TREE FOR ORDER BY}
}
do_eqp_test 7.3 {
SELECT rowid FROM t1
WHERE (+b IS NULL AND c NOT NULL AND d NOT NULL)
OR (b NOT NULL AND c IS NULL AND d NOT NULL)
OR (b NOT NULL AND c NOT NULL AND d IS NULL)
} {
0 0 0 {SCAN TABLE t1}
}
do_eqp_test 7.4 {
SELECT rowid FROM t1 WHERE (+b IS NULL AND c NOT NULL) OR c IS NULL
} {
0 0 0 {SCAN TABLE t1}
}
#-------------------------------------------------------------------------
#
reset_db
do_execsql_test 8.1 {
CREATE TABLE composer(
cid INTEGER PRIMARY KEY,
cname TEXT
);
CREATE TABLE album(
aid INTEGER PRIMARY KEY,
aname TEXT
);
CREATE TABLE track(
tid INTEGER PRIMARY KEY,
cid INTEGER REFERENCES composer,
aid INTEGER REFERENCES album,
title TEXT
);
CREATE INDEX track_i1 ON track(cid);
CREATE INDEX track_i2 ON track(aid);
}
do_eqp_test 8.2 {
SELECT DISTINCT aname
FROM album, composer, track
WHERE cname LIKE '%bach%'
AND unlikely(composer.cid=track.cid)
AND unlikely(album.aid=track.aid);
} {
0 0 2 {SCAN TABLE track}
0 1 0 {SEARCH TABLE album USING INTEGER PRIMARY KEY (rowid=?)}
0 2 1 {SEARCH TABLE composer USING INTEGER PRIMARY KEY (rowid=?)}
0 0 0 {USE TEMP B-TREE FOR DISTINCT}
}
#-------------------------------------------------------------------------
#
do_execsql_test 9.1 {
CREATE TABLE t1(
a,b,c,d,e, f,g,h,i,j,
k,l,m,n,o, p,q,r,s,t
);
CREATE INDEX i1 ON t1(k,l,m,n,o,p,q,r,s,t);
}
do_test 9.2 {
for {set i 0} {$i < 100} {incr i} {
execsql { INSERT INTO t1 DEFAULT VALUES }
}
execsql {
ANALYZE;
CREATE INDEX i2 ON t1(a,b,c,d,e,f,g,h,i,j);
}
} {}
set L [list a=? b=? c=? d=? e=? f=? g=? h=? i=? j=?]
foreach {tn nTerm nRow} {
1 1 10
2 2 9
3 3 8
4 4 7
5 5 6
6 6 5
7 7 5
8 8 5
9 9 5
10 10 5
} {
set w [join [lrange $L 0 [expr $nTerm-1]] " AND "]
set p1 [expr ($nRow-1) / 100.0]
set p2 [expr ($nRow+1) / 100.0]
set sql1 "SELECT * FROM t1 WHERE likelihood(k=?, $p1) AND $w"
set sql2 "SELECT * FROM t1 WHERE likelihood(k=?, $p2) AND $w"
do_eqp_test 9.3.$tn.1 $sql1 {/INDEX i1/}
do_eqp_test 9.3.$tn.2 $sql2 {/INDEX i2/}
}
finish_test
+1 -1
View File
@@ -162,7 +162,7 @@ do_execsql_test 2.0 {
foreach {tn sql temptables res} {
1 "a, b FROM t1" {} {A B a b}
2 "b, a FROM t1" {} {B A b a}
3 "a, b, c FROM t1" {hash} {a b c A B C}
3 "a, b, c FROM t1" {hash} {A B C a b c}
4 "a, b, c FROM t1 ORDER BY a, b, c" {btree} {A B C a b c}
5 "b FROM t1 WHERE a = 'a'" {} {b}
6 "b FROM t1 ORDER BY +b COLLATE binary" {btree hash} {B b}
+3 -2
View File
@@ -884,9 +884,10 @@ do_execsql_test e_createtable-3.3.1 {
);
} {}
# EVIDENCE-OF: R-10288-43169 For the purposes of the DEFAULT clause, an
# EVIDENCE-OF: R-36381-62919 For the purposes of the DEFAULT clause, an
# expression is considered constant provided that it does not contain
# any sub-queries or string constants enclosed in double quotes.
# any sub-queries, column or table references, or string literals
# enclosed in double-quotes instead of single-quotes.
#
do_createtable_tests 3.4.1 -error {
default value of column [x] is not constant
+6 -5
View File
@@ -135,9 +135,9 @@ reset_db
#
# This also tests that foreign key constraints are disabled by default.
#
# EVIDENCE-OF: R-59578-04990 Foreign key constraints are disabled by
# EVIDENCE-OF: R-44261-39702 Foreign key constraints are disabled by
# default (for backwards compatibility), so must be enabled separately
# for each database connection separately.
# for each database connection.
#
drop_all_tables
do_test e_fkey-4.1 {
@@ -163,9 +163,10 @@ do_test e_fkey-4.2 {
} {world}
#-------------------------------------------------------------------------
# EVIDENCE-OF: R-15278-54456 The application can can also use a PRAGMA
# EVIDENCE-OF: R-08013-37737 The application can also use a PRAGMA
# foreign_keys statement to determine if foreign keys are currently
# enabled.
#
# This also tests the example code in section 2 of foreignkeys.in.
#
@@ -2990,8 +2991,8 @@ if {[clang_sanitize_address]==0} {
# The setting of the recursive_triggers pragma does not affect foreign
# key actions.
#
# EVIDENCE-OF: R-51769-32730 The PRAGMA recursive_triggers setting does
# not not affect the operation of foreign key actions.
# EVIDENCE-OF: R-44355-00270 The PRAGMA recursive_triggers setting does
# not affect the operation of foreign key actions.
#
foreach recursive_triggers_setting [list 0 1 ON OFF] {
drop_all_tables
+6 -6
View File
@@ -312,8 +312,8 @@ do_eqp_test 4.2.3 {
} {
1 0 0 {SCAN TABLE t1}
1 0 0 {USE TEMP B-TREE FOR ORDER BY}
2 0 0 {SCAN TABLE t2}
2 0 0 {USE TEMP B-TREE FOR ORDER BY}
2 0 0 {SCAN TABLE t2 USING INDEX t2i1}
2 0 0 {USE TEMP B-TREE FOR RIGHT PART OF ORDER BY}
0 0 0 {COMPOUND SUBQUERIES 1 AND 2 (UNION)}
}
do_eqp_test 4.2.4 {
@@ -321,8 +321,8 @@ do_eqp_test 4.2.4 {
} {
1 0 0 {SCAN TABLE t1}
1 0 0 {USE TEMP B-TREE FOR ORDER BY}
2 0 0 {SCAN TABLE t2}
2 0 0 {USE TEMP B-TREE FOR ORDER BY}
2 0 0 {SCAN TABLE t2 USING INDEX t2i1}
2 0 0 {USE TEMP B-TREE FOR RIGHT PART OF ORDER BY}
0 0 0 {COMPOUND SUBQUERIES 1 AND 2 (INTERSECT)}
}
do_eqp_test 4.2.5 {
@@ -330,8 +330,8 @@ do_eqp_test 4.2.5 {
} {
1 0 0 {SCAN TABLE t1}
1 0 0 {USE TEMP B-TREE FOR ORDER BY}
2 0 0 {SCAN TABLE t2}
2 0 0 {USE TEMP B-TREE FOR ORDER BY}
2 0 0 {SCAN TABLE t2 USING INDEX t2i1}
2 0 0 {USE TEMP B-TREE FOR RIGHT PART OF ORDER BY}
0 0 0 {COMPOUND SUBQUERIES 1 AND 2 (EXCEPT)}
}
+28
View File
@@ -219,4 +219,32 @@ do_execsql_test 5.2 {
SELECT count(*) FROM sqlite_master WHERE name LIKE 't8%';
} {0 6}
# At one point this was causing a memory leak.
#
foreach {tn sql} {
1 {}
2 { INSERT INTO ft(ft) VALUES('merge=2,2'); }
} {
reset_db
do_execsql_test 6.$tn.1 "
CREATE TABLE t1(x);
CREATE VIRTUAL TABLE ft USING fts3;
INSERT INTO ft VALUES('hello world');
$sql
"
db close
sqlite3 db test.db
do_execsql_test 6.$tn.2 { SELECT * FROM t1 } {}
do_test 6.$tn.3 {
sqlite3 db2 test.db
db2 eval { DROP TABLE t1 }
db2 close
set stmt [sqlite3_prepare db { SELECT * FROM ft } -1 dummy]
sqlite3_finalize $stmt
} {SQLITE_OK}
db close
}
finish_test
+11
View File
@@ -354,6 +354,17 @@ do_test fts3d-6.5 {
SELECT name FROM sqlite_master WHERE name GLOB '???_*' ORDER BY 1;
}
} {xyz_content xyz_segdir xyz_segments}
# ALTER TABLE RENAME on an FTS3 table following an incr-merge op.
#
do_test fts3d-6.6 {
execsql { INSERT INTO xyz(xyz) VALUES('merge=2,2') }
sqlite3 db test.db
execsql {
ALTER TABLE xyz RENAME TO ott;
SELECT name FROM sqlite_master WHERE name GLOB '???_*' ORDER BY 1;
}
} {ott_content ott_segdir ott_segments ott_stat}
finish_test
+12 -5
View File
@@ -1301,11 +1301,13 @@ do_test func-29.3 {
db eval {SELECT typeof(+x) FROM t29 ORDER BY id}
} {integer null real blob text}
if {[permutation] != "mmap"} {
do_test func-29.4 {
set x [lindex [sqlite3_db_status db CACHE_MISS 1] 1]
if {$x>100} {set x many}
set x
} {many}
ifcapable !direct_read {
do_test func-29.4 {
set x [lindex [sqlite3_db_status db CACHE_MISS 1] 1]
if {$x>100} {set x many}
set x
} {many}
}
}
do_test func-29.5 {
db close
@@ -1361,4 +1363,9 @@ for {set i 65536} {$i<=0x10ffff} {incr i 139} {
do_execsql_test func-30.5.$i {SELECT unicode(char($i))} $i
}
# Test char().
#
do_execsql_test func-31.1 {
SELECT char(), length(char()), typeof(char())
} {{} 0 text}
finish_test
+1 -1
View File
@@ -285,7 +285,7 @@ do_test fuzz-1.18 {
)
))
}
} {0 -4294967298}
} {0 {{}}}
# At one point the following INSERT statement caused an assert() to fail.
#
+177
View File
@@ -159,4 +159,181 @@ do_test in4-3.12 {
execsql { SELECT * FROM t3 WHERE x IN (1, 2) AND y IN ()}
} {}
# Tests for "... IN (?)" and "... NOT IN (?)". In other words, tests
# for when the RHS of IN is a single expression. This should work the
# same as the == and <> operators.
#
do_execsql_test in4-3.21 {
SELECT * FROM t3 WHERE x=10 AND y IN (10);
} {10 10 10}
do_execsql_test in4-3.22 {
SELECT * FROM t3 WHERE x IN (10) AND y=10;
} {10 10 10}
do_execsql_test in4-3.23 {
SELECT * FROM t3 WHERE x IN (10) AND y IN (10);
} {10 10 10}
do_execsql_test in4-3.24 {
SELECT * FROM t3 WHERE x=1 AND y NOT IN (10);
} {1 1 1}
do_execsql_test in4-3.25 {
SELECT * FROM t3 WHERE x NOT IN (10) AND y=1;
} {1 1 1}
do_execsql_test in4-3.26 {
SELECT * FROM t3 WHERE x NOT IN (10) AND y NOT IN (10);
} {1 1 1}
# The query planner recognizes that "x IN (?)" only generates a
# single match and can use this information to optimize-out ORDER BY
# clauses.
#
do_execsql_test in4-3.31 {
DROP INDEX t3i1;
CREATE UNIQUE INDEX t3xy ON t3(x,y);
SELECT *, '|' FROM t3 A, t3 B
WHERE A.x=10 AND A.y IN (10)
AND B.x=1 AND B.y IN (1);
} {10 10 10 1 1 1 |}
do_execsql_test in4-3.32 {
EXPLAIN QUERY PLAN
SELECT *, '|' FROM t3 A, t3 B
WHERE A.x=10 AND A.y IN (10)
AND B.x=1 AND B.y IN (1);
} {~/B-TREE/} ;# No separate sorting pass
do_execsql_test in4-3.33 {
SELECT *, '|' FROM t3 A, t3 B
WHERE A.x IN (10) AND A.y=10
AND B.x IN (1) AND B.y=1;
} {10 10 10 1 1 1 |}
do_execsql_test in4-3.34 {
EXPLAIN QUERY PLAN
SELECT *, '|' FROM t3 A, t3 B
WHERE A.x IN (10) AND A.y=10
AND B.x IN (1) AND B.y=1;
} {~/B-TREE/} ;# No separate sorting pass
# An expression of the form "x IN (?,?)" creates an ephemeral table to
# hold the list of values on the RHS. But "x IN (?)" does not create
# an ephemeral table.
#
do_execsql_test in4-3.41 {
SELECT * FROM t3 WHERE x IN (10,11);
} {10 10 10}
do_execsql_test in4-3.42 {
EXPLAIN
SELECT * FROM t3 WHERE x IN (10,11);
} {/OpenEphemeral/}
do_execsql_test in4-3.43 {
SELECT * FROM t3 WHERE x IN (10);
} {10 10 10}
do_execsql_test in4-3.44 {
EXPLAIN
SELECT * FROM t3 WHERE x IN (10);
} {~/OpenEphemeral/}
do_execsql_test in4-3.45 {
SELECT * FROM t3 WHERE x NOT IN (10,11);
} {1 1 1}
do_execsql_test in4-3.46 {
EXPLAIN
SELECT * FROM t3 WHERE x NOT IN (10,11);
} {/OpenEphemeral/}
do_execsql_test in4-3.47 {
SELECT * FROM t3 WHERE x NOT IN (10);
} {1 1 1}
do_execsql_test in4-3.48 {
EXPLAIN
SELECT * FROM t3 WHERE x NOT IN (10);
} {~/OpenEphemeral/}
# Make sure that when "x IN (?)" is converted into "x==?" that collating
# sequence and affinity computations do not get messed up.
#
do_execsql_test in4-4.1 {
CREATE TABLE t4a(a TEXT, b TEXT COLLATE nocase, c);
INSERT INTO t4a VALUES('ABC','abc',1);
INSERT INTO t4a VALUES('def','xyz',2);
INSERT INTO t4a VALUES('ghi','ghi',3);
SELECT c FROM t4a WHERE a=b ORDER BY c;
} {3}
do_execsql_test in4-4.2 {
SELECT c FROM t4a WHERE b=a ORDER BY c;
} {1 3}
do_execsql_test in4-4.3 {
SELECT c FROM t4a WHERE (a||'')=b ORDER BY c;
} {1 3}
do_execsql_test in4-4.4 {
SELECT c FROM t4a WHERE (a||'')=(b||'') ORDER BY c;
} {3}
do_execsql_test in4-4.5 {
SELECT c FROM t4a WHERE a IN (b) ORDER BY c;
} {3}
do_execsql_test in4-4.6 {
SELECT c FROM t4a WHERE (a||'') IN (b) ORDER BY c;
} {3}
do_execsql_test in4-4.11 {
CREATE TABLE t4b(a TEXT, b NUMERIC, c);
INSERT INTO t4b VALUES('1.0',1,4);
SELECT c FROM t4b WHERE a=b;
} {4}
do_execsql_test in4-4.12 {
SELECT c FROM t4b WHERE b=a;
} {4}
do_execsql_test in4-4.13 {
SELECT c FROM t4b WHERE +a=b;
} {4}
do_execsql_test in4-4.14 {
SELECT c FROM t4b WHERE a=+b;
} {}
do_execsql_test in4-4.15 {
SELECT c FROM t4b WHERE +b=a;
} {}
do_execsql_test in4-4.16 {
SELECT c FROM t4b WHERE b=+a;
} {4}
do_execsql_test in4-4.17 {
SELECT c FROM t4b WHERE a IN (b);
} {}
do_execsql_test in4-4.18 {
SELECT c FROM t4b WHERE b IN (a);
} {4}
do_execsql_test in4-4.19 {
SELECT c FROM t4b WHERE +b IN (a);
} {}
do_execsql_test in4-5.1 {
CREATE TABLE t5(c INTEGER PRIMARY KEY, d TEXT COLLATE nocase);
INSERT INTO t5 VALUES(17, 'fuzz');
SELECT 1 FROM t5 WHERE 'fuzz' IN (d); -- match
SELECT 2 FROM t5 WHERE 'FUZZ' IN (d); -- no match
SELECT 3 FROM t5 WHERE d IN ('fuzz'); -- match
SELECT 4 FROM t5 WHERE d IN ('FUZZ'); -- match
} {1 3 4}
# An expression of the form "x IN (y)" can be used as "x=y" by the
# query planner when computing transitive constraints or to run the
# query using an index on y.
#
do_execsql_test in4-6.1 {
CREATE TABLE t6a(a INTEGER PRIMARY KEY, b);
INSERT INTO t6a VALUES(1,2),(3,4),(5,6);
CREATE TABLE t6b(c INTEGER PRIMARY KEY, d);
INSERT INTO t6b VALUES(4,44),(5,55),(6,66);
SELECT * FROM t6a, t6b WHERE a=3 AND b IN (c);
} {3 4 4 44}
do_execsql_test in4-6.1-eqp {
EXPLAIN QUERY PLAN
SELECT * FROM t6a, t6b WHERE a=3 AND b IN (c);
} {~/SCAN/}
do_execsql_test in4-6.2 {
SELECT * FROM t6a, t6b WHERE a=3 AND c IN (b);
} {3 4 4 44}
do_execsql_test in4-6.2-eqp {
EXPLAIN QUERY PLAN
SELECT * FROM t6a, t6b WHERE a=3 AND c IN (b);
} {~/SCAN/}
finish_test
+22 -2
View File
@@ -145,11 +145,11 @@ do_test index6-2.1 {
execsql {
CREATE TABLE t2(a,b);
INSERT INTO t2(a,b) SELECT value, value FROM nums WHERE value<1000;
UPDATE t2 SET a=NULL WHERE b%5==0;
UPDATE t2 SET a=NULL WHERE b%2==0;
CREATE INDEX t2a1 ON t2(a) WHERE a IS NOT NULL;
SELECT count(*) FROM t2 WHERE a IS NOT NULL;
}
} {800}
} {500}
do_test index6-2.2 {
execsql {
EXPLAIN QUERY PLAN
@@ -157,6 +157,7 @@ do_test index6-2.2 {
}
} {/.* TABLE t2 USING INDEX t2a1 .*/}
ifcapable stat4||stat3 {
execsql ANALYZE
do_test index6-2.3stat4 {
execsql {
EXPLAIN QUERY PLAN
@@ -248,4 +249,23 @@ do_execsql_test index6-5.0 {
SELECT stat+0 FROM sqlite_stat1 WHERE idx='t3b';
} {6 6}
# Test case for ticket [2ea3e9fe6379fc3f6ce7e090ce483c1a3a80d6c9] from
# 2014-04-13: Partial index causes assertion fault on UPDATE OR REPLACE.
#
do_execsql_test index6-6.0 {
CREATE TABLE t6(a,b);
CREATE UNIQUE INDEX t6ab ON t1(a,b);
CREATE INDEX t6b ON t6(b) WHERE b=1;
INSERT INTO t6(a,b) VALUES(123,456);
SELECT * FROM t6;
} {123 456}
do_execsql_test index6-6.1 {
UPDATE OR REPLACE t6 SET b=789;
SELECT * FROM t6;
} {123 789}
do_execsql_test index6-6.2 {
PRAGMA integrity_check;
} {ok}
finish_test
+35
View File
@@ -641,4 +641,39 @@ do_test join-11.10 {
execsql { SELECT * FROM t2 NATURAL JOIN t1 }
} {1 one 2 two}
#-------------------------------------------------------------------------
# Test that at most 64 tables are allowed in a join.
#
do_execsql_test join-12.1 {
CREATE TABLE t14(x);
INSERT INTO t14 VALUES('abcdefghij');
}
proc jointest {tn nTbl res} {
set sql "SELECT 1 FROM [string repeat t14, [expr $nTbl-1]] t14;"
uplevel [list do_catchsql_test $tn $sql $res]
}
jointest join-12.2 30 {0 1}
jointest join-12.3 63 {0 1}
jointest join-12.4 64 {0 1}
jointest join-12.5 65 {1 {at most 64 tables in a join}}
jointest join-12.6 66 {1 {at most 64 tables in a join}}
jointest join-12.7 127 {1 {at most 64 tables in a join}}
jointest join-12.8 128 {1 {at most 64 tables in a join}}
jointest join-12.9 1000 {1 {at most 64 tables in a join}}
# If SQLite is built with SQLITE_MEMDEBUG, then the huge number of realloc()
# calls made by the following test cases are too time consuming to run.
# Without SQLITE_MEMDEBUG, realloc() is fast enough that these are not
# a problem.
ifcapable pragma&&compileoption_diags {
if {[lsearch [db eval {PRAGMA compile_options}] MEMDEBUG]<0} {
jointest join-12.10 65534 {1 {at most 64 tables in a join}}
jointest join-12.11 65535 {1 {too many references to "t14": max 65535}}
jointest join-12.12 65536 {1 {too many references to "t14": max 65535}}
jointest join-12.13 65537 {1 {too many references to "t14": max 65535}}
}
}
finish_test
+20
View File
@@ -616,4 +616,24 @@ do_test limit-13.81 {
db eval {SELECT z FROM v13c LIMIT 1 OFFSET 8}
} {}
do_execsql_test limit-14.1 {
SELECT 123 LIMIT 1 OFFSET 0
} {123}
do_execsql_test limit-14.2 {
SELECT 123 LIMIT 1 OFFSET 1
} {}
do_execsql_test limit-14.3 {
SELECT 123 LIMIT 0 OFFSET 0
} {}
do_execsql_test limit-14.4 {
SELECT 123 LIMIT 0 OFFSET 1
} {}
do_execsql_test limit-14.6 {
SELECT 123 LIMIT -1 OFFSET 0
} {123}
do_execsql_test limit-14.7 {
SELECT 123 LIMIT -1 OFFSET 1
} {}
finish_test
+20 -2
View File
@@ -64,10 +64,28 @@ do_execsql_test 1.7 {
EXPLAIN QUERY PLAN
SELECT DISTINCT c, b, a FROM t1 WHERE +a=0;
} {/B-TREE/}
do_execsql_test 2.1 {
# In some cases, it is faster to do repeated index lookups than it is to
# sort. But in other cases, it is faster to sort than to do repeated index
# lookups.
#
do_execsql_test 2.1a {
CREATE TABLE t2(a,b,c);
CREATE INDEX t2bc ON t2(b,c);
ANALYZE;
INSERT INTO sqlite_stat1 VALUES('t1','t1bc','1000000 10 9');
INSERT INTO sqlite_stat1 VALUES('t2','t2bc','100 10 5');
ANALYZE sqlite_master;
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE a=0 ORDER BY a, b, c;
SELECT * FROM t2 WHERE a=0 ORDER BY a, b, c;
} {~/B-TREE/}
do_execsql_test 2.1b {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE likelihood(a=0, 0.05) ORDER BY a, b, c;
} {/B-TREE/}
do_execsql_test 2.2 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE +a=0 ORDER BY a, b, c;
+183
View File
@@ -0,0 +1,183 @@
# 2014-03-21
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library. The
# focus of this file is testing that the block-sort optimization.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set ::testprefix orderby6
# Run all tests twice. Once with a normal table and a second time
# with a WITHOUT ROWID table
#
foreach {tn rowidclause} {1 {} 2 {WITHOUT ROWID}} {
# Construct a table with 1000 rows and a split primary key
#
reset_db
do_test $tn.1 {
db eval "CREATE TABLE t1(a,b,c,PRIMARY KEY(b,c)) $rowidclause;"
db eval {
WITH RECURSIVE
cnt(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM cnt WHERE x<1000)
INSERT INTO t1 SELECT x, x%40, x/40 FROM cnt;
}
} {}
# Run various ORDER BY queries that can benefit from block-sort.
# Compare the output to the same output using a full-sort enforced
# by adding + to each term of the ORDER BY clause.
#
do_execsql_test $tn.2 {
SELECT b,a,c FROM t1 ORDER BY b,a,c;
} [db eval {SELECT b,a,c FROM t1 ORDER BY +b,+a,+c}]
do_execsql_test $tn.3 {
SELECT b,a,c FROM t1 ORDER BY b,c DESC,a;
} [db eval {SELECT b,a,c FROM t1 ORDER BY +b,+c DESC,+a}]
do_execsql_test $tn.4 {
SELECT b,a,c FROM t1 ORDER BY b DESC,c,a;
} [db eval {SELECT b,a,c FROM t1 ORDER BY +b DESC,+c,+a}]
do_execsql_test $tn.5 {
SELECT b,a,c FROM t1 ORDER BY b DESC,a,c;
} [db eval {SELECT b,a,c FROM t1 ORDER BY +b DESC,+a,+c}]
# LIMIT and OFFSET clauses on block-sort queries.
#
do_execsql_test $tn.11 {
SELECT a FROM t1 ORDER BY b, a LIMIT 10 OFFSET 20;
} {840 880 920 960 1000 1 41 81 121 161}
do_execsql_test $tn.11x {
SELECT a FROM t1 ORDER BY +b, a LIMIT 10 OFFSET 20;
} {840 880 920 960 1000 1 41 81 121 161}
do_execsql_test $tn.12 {
SELECT a FROM t1 ORDER BY b DESC, a LIMIT 10 OFFSET 20;
} {839 879 919 959 999 38 78 118 158 198}
do_execsql_test $tn.12 {
SELECT a FROM t1 ORDER BY +b DESC, a LIMIT 10 OFFSET 20;
} {839 879 919 959 999 38 78 118 158 198}
do_execsql_test $tn.13 {
SELECT a FROM t1 ORDER BY b, a DESC LIMIT 10 OFFSET 45;
} {161 121 81 41 1 962 922 882 842 802}
do_execsql_test $tn.13x {
SELECT a FROM t1 ORDER BY +b, a DESC LIMIT 10 OFFSET 45;
} {161 121 81 41 1 962 922 882 842 802}
do_execsql_test $tn.14 {
SELECT a FROM t1 ORDER BY b DESC, a LIMIT 10 OFFSET 45;
} {838 878 918 958 998 37 77 117 157 197}
do_execsql_test $tn.14x {
SELECT a FROM t1 ORDER BY +b DESC, a LIMIT 10 OFFSET 45;
} {838 878 918 958 998 37 77 117 157 197}
# Many test cases where the LIMIT+OFFSET window is in various
# alignments with block-sort boundaries.
#
foreach {tx limit offset orderby} {
1 10 24 {+b,+a}
2 10 25 {+b,+a}
3 10 26 {+b,+a}
4 10 39 {+b,+a}
5 10 40 {+b,+a}
6 10 41 {+b,+a}
7 27 24 {+b,+a}
8 27 49 {+b,+a}
11 10 24 {+b DESC,+a}
12 10 25 {+b DESC,+a}
13 10 26 {+b DESC,+a}
14 10 39 {+b DESC,+a}
15 10 40 {+b DESC,+a}
16 10 41 {+b DESC,+a}
17 27 24 {+b DESC,+a}
18 27 49 {+b DESC,+a}
21 10 24 {+b,+a DESC}
22 10 25 {+b,+a DESC}
23 10 26 {+b,+a DESC}
24 10 39 {+b,+a DESC}
25 10 40 {+b,+a DESC}
26 10 41 {+b,+a DESC}
27 27 24 {+b,+a DESC}
28 27 49 {+b,+a DESC}
31 10 24 {+b DESC,+a DESC}
32 10 25 {+b DESC,+a DESC}
33 10 26 {+b DESC,+a DESC}
34 10 39 {+b DESC,+a DESC}
35 10 40 {+b DESC,+a DESC}
36 10 41 {+b DESC,+a DESC}
37 27 24 {+b DESC,+a DESC}
38 27 49 {+b DESC,+a DESC}
} {
set sql1 "SELECT a FROM t1 ORDER BY $orderby LIMIT $limit OFFSET $offset;"
set sql2 [string map {+ {}} $sql1]
# puts $sql2\n$sql1\n[db eval $sql2]
do_test $tn.21.$tx {db eval $::sql2} [db eval $sql1]
}
########################################################################
# A second test table, t2, has many columns open to sorting.
do_test $tn.31 {
db eval "CREATE TABLE t2(a,b,c,d,e,f,PRIMARY KEY(b,c,d,e,f)) $rowidclause;"
db eval {
WITH RECURSIVE
cnt(x) AS (VALUES(0) UNION ALL SELECT x+1 FROM cnt WHERE x<242)
INSERT INTO t2 SELECT x, x%3, (x/3)%3, (x/9)%3, (x/27)%3, (x/81)%3
FROM cnt;
}
} {}
do_execsql_test $tn.32 {
SELECT a FROM t2 ORDER BY b,c,d,e,f;
} [db eval {SELECT a FROM t2 ORDER BY +b,+c,+d,+e,+f;}]
do_execsql_test $tn.33 {
SELECT a FROM t2 ORDER BY b,c,d,e,+f;
} [db eval {SELECT a FROM t2 ORDER BY +b,+c,+d,+e,+f;}]
do_execsql_test $tn.34 {
SELECT a FROM t2 ORDER BY b,c,d,+e,+f;
} [db eval {SELECT a FROM t2 ORDER BY +b,+c,+d,+e,+f;}]
do_execsql_test $tn.35 {
SELECT a FROM t2 ORDER BY b,c,+d,+e,+f;
} [db eval {SELECT a FROM t2 ORDER BY +b,+c,+d,+e,+f;}]
do_execsql_test $tn.36 {
SELECT a FROM t2 ORDER BY b,+c,+d,+e,+f;
} [db eval {SELECT a FROM t2 ORDER BY +b,+c,+d,+e,+f;}]
do_execsql_test $tn.37 {
SELECT a FROM t2 ORDER BY b,c,d,e,f DESC;
} [db eval {SELECT a FROM t2 ORDER BY +b,+c,+d,+e,+f DESC;}]
do_execsql_test $tn.38 {
SELECT a FROM t2 ORDER BY b,c,d,e DESC,f;
} [db eval {SELECT a FROM t2 ORDER BY +b,+c,+d,+e DESC,+f;}]
do_execsql_test $tn.39 {
SELECT a FROM t2 ORDER BY b,c,d DESC,e,f;
} [db eval {SELECT a FROM t2 ORDER BY +b,+c,+d DESC,+e,+f;}]
do_execsql_test $tn.40 {
SELECT a FROM t2 ORDER BY b,c DESC,d,e,f;
} [db eval {SELECT a FROM t2 ORDER BY +b,+c DESC,+d,+e,+f;}]
do_execsql_test $tn.41 {
SELECT a FROM t2 ORDER BY b DESC,c,d,e,f;
} [db eval {SELECT a FROM t2 ORDER BY +b DESC,+c,+d,+e,+f;}]
do_execsql_test $tn.42 {
SELECT a FROM t2 ORDER BY b DESC,c DESC,d,e,f LIMIT 31;
} [db eval {SELECT a FROM t2 ORDER BY +b DESC,+c DESC,+d,+e,+f LIMIT 31}]
do_execsql_test $tn.43 {
SELECT a FROM t2 ORDER BY b,c,d,e,f DESC LIMIT 8 OFFSET 7;
} [db eval {SELECT a FROM t2 ORDER BY +b,+c,+d,+e,+f DESC LIMIT 8 OFFSET 7}]
}
finish_test
+106
View File
@@ -0,0 +1,106 @@
# 2014-04-25
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library. The
# focus of this file is testing ORDER BY optimizations on joins
# that involve virtual tables.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set ::testprefix orderby7
ifcapable !fts3 {
finish_test
return
}
do_execsql_test 1.0 {
CREATE VIRTUAL TABLE fts USING fts3(content TEXT);
INSERT INTO fts(rowid,content)
VALUES(1,'this is a test of the fts3 virtual'),
(2,'table used as part of a join together'),
(3,'with the DISTINCT keyword. There was'),
(4,'a bug at one time (2013-06 through 2014-04)'),
(5,'that prevented this from working correctly.'),
(11,'a row that occurs twice'),
(12,'a row that occurs twice');
CREATE TABLE t1(x TEXT PRIMARY KEY, y);
INSERT OR IGNORE INTO t1 SELECT content, rowid+100 FROM fts;
} {}
do_execsql_test 1.1 {
SELECT DISTINCT fts.rowid, t1.y
FROM fts, t1
WHERE fts MATCH 'that twice'
AND content=x
ORDER BY y;
} {11 111 12 111}
do_execsql_test 1.2 {
SELECT DISTINCT fts.rowid, t1.x
FROM fts, t1
WHERE fts MATCH 'that twice'
AND content=x
ORDER BY 1;
} {11 {a row that occurs twice} 12 {a row that occurs twice}}
do_execsql_test 1.3 {
SELECT DISTINCT t1.x
FROM fts, t1
WHERE fts MATCH 'that twice'
AND content=x
ORDER BY 1;
} {{a row that occurs twice}}
do_execsql_test 1.4 {
SELECT t1.x
FROM fts, t1
WHERE fts MATCH 'that twice'
AND content=x
ORDER BY 1;
} {{a row that occurs twice} {a row that occurs twice}}
do_execsql_test 1.5 {
SELECT DISTINCT t1.x
FROM fts, t1
WHERE fts MATCH 'that twice'
AND content=x;
} {{a row that occurs twice}}
do_execsql_test 1.6 {
SELECT t1.x
FROM fts, t1
WHERE fts MATCH 'that twice'
AND content=x;
} {{a row that occurs twice} {a row that occurs twice}}
do_execsql_test 2.1 {
SELECT DISTINCT t1.x
FROM fts, t1
WHERE fts.rowid=11
AND content=x
ORDER BY fts.rowid;
} {{a row that occurs twice}}
do_execsql_test 2.2 {
SELECT DISTINCT t1.*
FROM fts, t1
WHERE fts.rowid=11
AND content=x
ORDER BY fts.rowid;
} {{a row that occurs twice} 111}
do_execsql_test 2.3 {
SELECT DISTINCT t1.*
FROM fts, t1
WHERE fts.rowid=11
AND content=x
ORDER BY t1.y
} {{a row that occurs twice} 111}
finish_test
+65
View File
@@ -21,6 +21,7 @@
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix selectA
ifcapable !compound {
finish_test
@@ -1310,4 +1311,68 @@ do_execsql_test selectA-3.98 {
SELECT n FROM xyz ORDER BY +n;
} {MAD MAD+ MAD++}
#-------------------------------------------------------------------------
# At one point the following code exposed a temp register reuse problem.
#
proc f {args} { return 1 }
db func f f
do_execsql_test 4.1.1 {
CREATE TABLE t4(a, b);
CREATE TABLE t5(c, d);
INSERT INTO t5 VALUES(1, 'x');
INSERT INTO t5 VALUES(2, 'x');
INSERT INTO t4 VALUES(3, 'x');
INSERT INTO t4 VALUES(4, 'x');
CREATE INDEX i1 ON t4(a);
CREATE INDEX i2 ON t5(c);
}
do_eqp_test 4.1.2 {
SELECT c, d FROM t5
UNION ALL
SELECT a, b FROM t4 WHERE f()==f()
ORDER BY 1,2
} {
1 0 0 {SCAN TABLE t5 USING INDEX i2}
1 0 0 {USE TEMP B-TREE FOR RIGHT PART OF ORDER BY}
2 0 0 {SCAN TABLE t4 USING INDEX i1}
2 0 0 {USE TEMP B-TREE FOR RIGHT PART OF ORDER BY}
0 0 0 {COMPOUND SUBQUERIES 1 AND 2 (UNION ALL)}
}
do_execsql_test 4.1.3 {
SELECT c, d FROM t5
UNION ALL
SELECT a, b FROM t4 WHERE f()==f()
ORDER BY 1,2
} {
1 x 2 x 3 x 4 x
}
do_execsql_test 4.2.1 {
CREATE TABLE t6(a, b);
CREATE TABLE t7(c, d);
INSERT INTO t7 VALUES(2, 9);
INSERT INTO t6 VALUES(3, 0);
INSERT INTO t6 VALUES(4, 1);
INSERT INTO t7 VALUES(5, 6);
INSERT INTO t6 VALUES(6, 0);
INSERT INTO t7 VALUES(7, 6);
CREATE INDEX i6 ON t6(a);
CREATE INDEX i7 ON t7(c);
}
do_execsql_test 4.2.2 {
SELECT c, f(d,c,d,c,d) FROM t7
UNION ALL
SELECT a, b FROM t6
ORDER BY 1,2
} {/2 . 3 . 4 . 5 . 6 . 7 ./}
finish_test
+57
View File
@@ -0,0 +1,57 @@
#!/usr/bin/tclsh
#
# This script displays the field of rectangles used by --testset rtree
# of speedtest1. Run this script as follows:
#
# rm test.db
# ./speedtest1 --testset rtree --size 25 test.db
# sqlite3 --separator ' ' test.db 'SELECT * FROM rt1' >data.txt
# wish show_speedtest1_rtree.tcl
#
# The filename "data.txt" is hard coded into this script and so that name
# must be used on lines 3 and 4 above. Elsewhere, different filenames can
# be used. The --size N parameter can be adjusted as desired.
#
package require Tk
set f [open data.txt rb]
set data [read $f]
close $f
canvas .c
frame .b
button .b.b1 -text X-Y -command refill-xy
button .b.b2 -text X-Z -command refill-xz
button .b.b3 -text Y-Z -command refill-yz
pack .b.b1 .b.b2 .b.b3 -side left
pack .c -side top -fill both -expand 1
pack .b -side top
proc resize_canvas_to_fit {} {
foreach {x0 y0 x1 y1} [.c bbox all] break
set w [expr {$x1-$x0}]
set h [expr {$y1-$y0}]
.c config -width $w -height $h
}
proc refill-xy {} {
.c delete all
foreach {id x0 x1 y0 y1 z0 z1} $::data {
.c create rectangle $x0 $y0 $x1 $y1
}
.c scale all 0 0 0.05 0.05
resize_canvas_to_fit
}
proc refill-xz {} {
.c delete all
foreach {id x0 x1 y0 y1 z0 z1} $::data {
.c create rectangle $x0 $z0 $x1 $z1
}
.c scale all 0 0 0.05 0.05
resize_canvas_to_fit
}
proc refill-yz {} {
.c delete all
foreach {id x0 x1 y0 y1 z0 z1} $::data {
.c create rectangle $y0 $z0 $y1 $z1
}
.c scale all 0 0 0.05 0.05
resize_canvas_to_fit
}
refill-xy
+38
View File
@@ -209,4 +209,42 @@ do_execsql_test skipscan1-4.1 {
SELECT i FROM t4 WHERE h=8;
} {9 9 9 9 9 9 9 9}
# Make sure skip-scan cost computation in the query planner takes into
# account the fact that the seek must occur multiple times.
#
# Prior to 2014-03-10, the costs were computed incorrectly which would
# cause index t5i2 to be used instead of t5i1 on the skipscan1-5.3.
#
do_execsql_test skipscan1-5.1 {
CREATE TABLE t5(
id INTEGER PRIMARY KEY,
loc TEXT,
lang INTEGER,
utype INTEGER,
xa INTEGER,
xd INTEGER,
xh INTEGER
);
CREATE INDEX t5i1 on t5(loc, xh, xa, utype, lang);
CREATE INDEX t5i2 ON t5(xd,loc,utype,lang);
EXPLAIN QUERY PLAN
SELECT xh, loc FROM t5 WHERE loc >= 'M' AND loc < 'N';
} {/.*COVERING INDEX t5i1 .*/}
do_execsql_test skipscan1-5.2 {
ANALYZE;
DELETE FROM sqlite_stat1;
DROP TABLE IF EXISTS sqlite_stat4;
DROP TABLE IF EXISTS sqlite_stat3;
INSERT INTO sqlite_stat1 VALUES('t5','t5i1','2702931 3 2 2 2 2');
INSERT INTO sqlite_stat1 VALUES('t5','t5i2','2702931 686 2 2 2');
ANALYZE sqlite_master;
} {}
db cache flush
do_execsql_test skipscan1-5.3 {
EXPLAIN QUERY PLAN
SELECT xh, loc FROM t5 WHERE loc >= 'M' AND loc < 'N';
} {/.*COVERING INDEX t5i1 .*/}
finish_test

Some files were not shown because too many files have changed in this diff Show More