Compare commits

...

511 Commits

Author SHA1 Message Date
dan 781b7ac3f6 Fix a problem with a window function in a correlated sub-query where at least one reference to the outer SELECT appears in a FROM clause sub-select.
FossilOrigin-Name: 9aca86f98388ff66b2bccb3fbfc486a3931398d2a8da139f905826ae2cdbb205
2019-03-22 13:56:49 +00:00
dan c7694a6d1d Remove assert() statements based on the counter-factual proposition that 0 is not a valid cursor number.
FossilOrigin-Name: c7b336181aac6785a515f275c0f50ad4bf2dee20abde959b56d968a7fdce3e5b
2019-03-21 13:51:09 +00:00
dan 78694ea307 Add further tests to window8.test.
FossilOrigin-Name: ec7e224f50271a69a28074270b01328ec0ee38751fcb93b2c598d8be2b77a95d
2019-03-19 19:39:42 +00:00
dan 6603342f12 Fix a problem with EXCLUDE clauses on window frames with no ORDER BY.
FossilOrigin-Name: e0255063799a2a8531f0eaa8790334509591a5ababc5b915035b46d2faa80363
2019-03-19 19:19:53 +00:00
dan 8eff0cc326 Add tests to ensure that the window functions implementation is not generating code for unnecessary sorts.
FossilOrigin-Name: e195948a6876efe01b5cf2ed67bc9015a781fda39dca668099cb7edc1d331818
2019-03-19 17:45:31 +00:00
dan 1d4b25fa50 Add missing VdbeCoverage() macros to new code in window.c.
FossilOrigin-Name: 4f9b93e6cfa0b3b6ab8a126299c2b2a242f840453dc450e84d3df87576cf6cf8
2019-03-19 16:49:15 +00:00
dan e5166e070a Revert the OP_MustBeInt opcode implementation on this branch so that it again matches trunk. The extra functionality is no longer required.
FossilOrigin-Name: c02f77b1b4d025d4243f883d6f3a2b3abcaf4944e0209f641b62c576415343dc
2019-03-19 11:56:39 +00:00
dan d430c2eb46 Update this branch with latest trunk changes.
FossilOrigin-Name: 98cc26598718e5557ee00aa77336024c91e483ec6de650e172ad1b44a6f0a77b
2019-03-19 11:17:28 +00:00
drh 713836f913 Add a LICENSE.md, containing the text of the blessing.
FossilOrigin-Name: cbb7e60272cda518fa1bd8d3e3cd02e031b657fef92a9d4d7ed8c2bfb97be7c8
2019-03-19 09:57:52 +00:00
dan ced89124d8 Ensure that all the new window-function keywords can still be used as SQL identifiers.
FossilOrigin-Name: a6d61dfd4780eccfce5f7a5ead6c04e3b78bc4a461551fd7dd602550e0d51084
2019-03-19 06:40:29 +00:00
dan 0525b6f47f Add further tests for new window function functionality.
FossilOrigin-Name: 1fbddf01b1c3fff95b05e2f2f709754e2b514296060b4846518791e7161d9ddb
2019-03-18 21:19:40 +00:00
dan 108e6b2c87 Always evaluate window functions using the alternative path usually only used by EXCLUDE frames if the SQLITE_QueryFlattener test flag is set.
FossilOrigin-Name: 2879a691aca9304aea5acb46bab8e82bb2e08eb54201f3679d60bfc0e8383845
2019-03-18 18:55:35 +00:00
dan bdabe742da Fixes for RANGE windows and NULL values.
FossilOrigin-Name: 723c84be3ec5ae941b7abd2442cdb76ca3bd76a5ce2d830b0e648c6e1424885a
2019-03-18 16:51:24 +00:00
dan d406d07262 Fix a buffer overread that could occur when running fts5 prefix queries inside a transaction.
FossilOrigin-Name: b3fa58dd7403dbd4d2e9f3ae23d7d1337830d6fef2aa2f137ac5174de0d5828e
2019-03-18 15:49:07 +00:00
dan b15f19c75e Fix an fts5 problem with interleaving reads and writes in a single transaction.
FossilOrigin-Name: 45c73deb440496e848cb24d4c1326d4105dacfee8bbafb115e567051855e6518
2019-03-18 15:23:20 +00:00
drh 610f11de25 Fix a typo in a comment. No changes to code.
FossilOrigin-Name: c2f50aa4e7bad8821e91a7490283dd53e44047d10a8cfebc3e2da26c770a5218
2019-03-18 10:30:00 +00:00
drh faeeddf0f0 New hyperlink on the README.md file.
FossilOrigin-Name: cc5ab96715ebb1089b4e9aa647badd2510aaa056f26004718f921f4ac07e2f93
2019-03-17 23:59:02 +00:00
drh 3756d59bc3 Update the README.md file at the top level to talk about how to deal with
version names and how to verify the code in Git mirrors.

FossilOrigin-Name: e8c87a0ac1bf434c12a8ab602e7913a89a51898e818f30fa541a9b5708864212
2019-03-17 23:44:16 +00:00
dan 1e7cb19be3 Fix problems with RANGE windows and string, blob and NULL values.
FossilOrigin-Name: cebe09e11cc91d9776f259dd9b87e9c760a460f53ba6fa36481dfe58f77ad417
2019-03-16 20:29:54 +00:00
dan bf84515a2b In order to identify the first row of each partition, check if the rowid in the ephemeral table is 1 instead of using a dedicated flag register.
FossilOrigin-Name: f2d5f7a24c7aa483c579706c5bd7268a74da6d53025d78fa8642908c2aed1707
2019-03-16 10:15:24 +00:00
dan c782a81aa5 Implement the EXCLUDE clause for window frames.
FossilOrigin-Name: 9b43c3ee2e054b05715573f4f3893b84aabc5100832333c9a0f2a1628552a978
2019-03-15 20:46:19 +00:00
drh aadf8327be Back out the change to support Fuchsia, since it turns out fuchsia does not
like dot-file locks.

FossilOrigin-Name: 1d801a3b2c48dc8a918d6da047bc877acf033d5f5c4e1d4b412ba7678ed6f8b3
2019-03-15 19:08:23 +00:00
dan 25f5383cb8 Remove a debugging printf() left in test/sessionfuzz.c.
FossilOrigin-Name: 73c4abc90264355f3ea6e8c34e5aad6ed665b70fb136c4d416e2a98e46562bbd
2019-03-15 18:57:49 +00:00
dan 1f3b284b11 Ensure that ALTER TABLE commands open statement transactions. Fix for [596d059a].
FossilOrigin-Name: 0f2129f59f7df929106e2af876c2976dea6528c1dc1850d64cddb256f20e121a
2019-03-15 16:17:32 +00:00
dan d35300f9b6 Parse EXCLUDE clauses in window frames. They do not yet work.
FossilOrigin-Name: d03c7533a1e993f1b12392a5193b2127484307b27072236a1255e7a30849a381
2019-03-14 20:53:21 +00:00
dan a0f6b83300 Add things to this branch that will be required to support the EXCLUDE clause.
FossilOrigin-Name: 7d66cd2013206ebad50c7cdb7dab9211fa8b47f5cb7067dcb314b3e0180875f8
2019-03-14 16:36:20 +00:00
drh a49774f478 Technical improvements to the documentation for sqlite3_bind_blob() and
sqlite3_bind_text().  No changes to code.

FossilOrigin-Name: fb60150aeedc3898cb249c75c98a7cb48fcec090f94ded7896b634e436c7daa5
2019-03-14 00:01:23 +00:00
drh 2e41b99ea9 Improvements to the sqlite3_db_filename() API documentation. No code changes.
FossilOrigin-Name: 711f5ec4dc2635e3102a607510cbbe0b468d9f0af935e09d3454e6e925c8dcb2
2019-03-13 23:51:05 +00:00
dan db7d895e9d Merge latest trunk changes into this branch.
FossilOrigin-Name: 0b904517bd6c4c59082381577246d3d2351b4265fc9151438ee4c33cf16f2eb1
2019-03-13 17:31:20 +00:00
dan b6f2deac3c Avoid allocating excessive registers for the PARTITION BY expressions when processing window functions.
FossilOrigin-Name: 180be266238e18c01f8bd52c75dd9aa3e26e553620258141cd95189a0ae59ddb
2019-03-13 17:20:27 +00:00
dan b560a7194d Remove rows from the ephemeral table used by window functions once they are no longer required.
FossilOrigin-Name: 6ad553192051eaa0c6d929baacde2de07b93c6d09de861028bbce55a2c9bfdd3
2019-03-13 15:29:14 +00:00
drh b65e801e5f New test cases added to test/fuzzdata8.db
FossilOrigin-Name: 049e9926202317f58c54b6351ff120fb69bf821f409909b1a1c5e335c0396707
2019-03-13 13:19:05 +00:00
dan fcb02429ec When deserializing a database (sqlite3_deserialize()), do not attempt to parse the schema before the data is loaded.
FossilOrigin-Name: 4e1b005e8b397a22161a6b89cbd3f17bda70a6e0a86d8abdc61856edf2a74da4
2019-03-13 11:40:30 +00:00
drh 2a934d75d9 Detect zero-length free slots on btree pages and report that as corruption.
FossilOrigin-Name: c4f0568fde1d4070e7522ec36c0958be7426076002a7fa2da12a46411ab2e92d
2019-03-13 10:29:16 +00:00
dan d446165f7d Minor optimization in sqlite3WindowCodeStep().
FossilOrigin-Name: b1322ffb6e63a110998068bf4f0a903028bd4fc0464ae1e517d745fb46423f39
2019-03-13 08:28:51 +00:00
dan bb40727857 Allow real values to be used in PRECEDING and FOLLOWING expressions for RANGE window frames.
FossilOrigin-Name: 25ff7091cb12c63b1864ce68a9151f8432af5804b5ae905a2175761ab4b9fdd8
2019-03-12 18:28:51 +00:00
dan 935d9d8260 Expand on header comment for sqlite3WindowCodeStep(). Further simplify the implementation of the same.
FossilOrigin-Name: 5129bcc996b3c9f78ab6b674a4364787e7b353b90f15f027cad4431012022c30
2019-03-12 15:21:51 +00:00
dan 9e24439c2f Fix a crash that could occur if the RHS of an IN expression is a correlated sub-query that refers to the outer query from within a window frame definition only.
FossilOrigin-Name: 0524aaaf45681437c2dca3d31ff26a65bee7bd2074730277c29136635ee0be0f
2019-03-12 09:49:10 +00:00
dan cc7a850f2e Remove "cache mode" from the window frame code generator. Handle the same cases by editing the window frame specification itself.
FossilOrigin-Name: 081263538332bb9c07e62630629007ccbba31bef5dc890f60b4ba58a355f70ac
2019-03-11 19:50:54 +00:00
dan a786e453a4 Simplify the windows frame code some. Add a comment explaining some of the VM code generated by sqlite3WindowCodeStep().
FossilOrigin-Name: 6bd1a07949ff3d394056bfcc813444401ef00806e3f0e0423ff6962541e84bdb
2019-03-11 18:17:04 +00:00
dan 71fddaf195 Fix problems with "RANGE ... ORDER BY <expr> DESC" window frames.
FossilOrigin-Name: e7bced731aa071c95bc398cdecd53c939841bf0c52fbcd06e47ba68f8c5cc35a
2019-03-11 11:12:34 +00:00
dan 72b9fdcf20 Add support for RANGE window frames. Some cases still do not work.
FossilOrigin-Name: ffc32b246d92d53c66094afe11950b53ffab6a1c230c602eebbfedafb2eb57f4
2019-03-09 20:49:17 +00:00
dan f7b846e4ed Merge latest trunk changes into this branch.
FossilOrigin-Name: 53ea550ce759ae4683bcf0ae3af655bfe04f85db70f74edee6bcab56d83bb041
2019-03-09 07:38:16 +00:00
dan 0d86a9bd54 Add simple tests for GROUPS window frames.
FossilOrigin-Name: 2872702dacadad11f4fd7c437b77ef82763e840c9c92eefe87eac2491c38f963
2019-03-08 20:57:05 +00:00
drh 37f6ffb887 Fix a harmless bug in the Makefile.
FossilOrigin-Name: 62ac9cb07f5f2d14e716cd0f99f3f2fd34f6c9b4303619be8dfbca2eecf5b727
2019-03-08 20:26:12 +00:00
dan 6c75b39614 Finish consolidation of window frame code. Add untested support for GROUPS frames.
FossilOrigin-Name: 954bf369935083c188c3b14e77ed89fc5ec4323cc5b0c67e4a2e48fcc278df45
2019-03-08 20:02:52 +00:00
drh bcf1f41a62 Add new test cases in test/fuzzdata8.db
FossilOrigin-Name: 97bdc090f30610cc5dd29101452d1647550387f9c6f742e50f1e07c3cf68a147
2019-03-08 14:07:15 +00:00
drh 4b986b2a47 Patch makes balance_nonroot() slightly smaller and faster and more robust
against corrupt databases.

FossilOrigin-Name: 174da3c32c9caebd642c31cb594597ccd5bb2a7fc501b1f49aef0b7b4765bfca
2019-03-08 14:02:11 +00:00
dan 66b8457c7c Fix another segfault in fts3 that could occur with corrupt records.
FossilOrigin-Name: fcc24edde471c2214add2dbc3a27da8890a7148105c5ffa024faf72457964a5f
2019-03-08 13:27:27 +00:00
drh 9a518843f5 Detect an attempt to drop a btree that is not within the bounds of the
database file and abort early with an SQLITE_CORRUPT error, to avoid
problems later on in the process.

FossilOrigin-Name: 235a9698f5e9b3c21dc51c9c5042becfb82fc1762a7519a46b9f9fdafe9b0f13
2019-03-08 01:52:30 +00:00
dan 54975cdff9 Fix other "ROWS BETWEEN" cases on this branch.
FossilOrigin-Name: a5f68f66472610b5beb4fe28669fbbfe83a32742be73cecad9b2ae28f8a17b30
2019-03-07 20:47:46 +00:00
dan c813750b7b Modify new window functions function so that cursors are stepped immediately after each operation, instead of immediately before.
FossilOrigin-Name: 093d2b25f1b656bba57d665aac68109436861b157a5769432b612176dae3f6eb
2019-03-07 19:26:17 +00:00
dan 00267b8a7b Simplify the window function code generator some more.
FossilOrigin-Name: 45cbd3b4498cea8856f189e9d0a192556d4f15212055b8328a1beca6083fc47a
2019-03-06 21:04:11 +00:00
dan b33487b0b6 Improvements to the way built-in window functions are handled.
FossilOrigin-Name: e8eee566dfca6f4c8af074731dfe91f7fbcd9ca72f0303235b52e4e2e80d5b71
2019-03-06 17:12:32 +00:00
drh 39c5c4ae06 Add the sqlite3_stmt_isexplain() interface.
FossilOrigin-Name: ee642d3e2775ba4c73627ac71d0abf7a0f7a4ab3151d88e0076e9992f4814983
2019-03-06 14:53:27 +00:00
drh aff0fd483c Add an "|| CORRUPT_DB" term to an assert() that might be false if the database
is corrupt.  Also add a branch to have sqlite3PagerMovepage() return
SQLITE_CORRUPT in that case.

FossilOrigin-Name: b0d5cf40bba34e459caa7480bc84a1d75496c2ab52029f4bb0a31f2d9369a8ee
2019-03-06 14:08:41 +00:00
drh aaad696141 Fix a potential 32-bit integer overflow in the "showdb" utility program when
it is trying to interpret a corrupt database file.

FossilOrigin-Name: 3803e750384ec37091b0a6c350f8ef67720e316fd6f74c95e3c5f231c4a01ceb
2019-03-05 23:49:17 +00:00
dan b25a214dec Extend windowCodeStep() to handle any ROWS PRECEDING/FOLLOWING frame specification.
FossilOrigin-Name: af0ea1363548461b2aad8fd54ee3f2f616111dcae2d6480f5294da44c87a0a5d
2019-03-05 19:29:36 +00:00
drh 91ed9ce0dd Add a script to tool/ that will extract the sqlite3.h header file from an
sqlite3.c amalgamation.

FossilOrigin-Name: 38d2e510cdedf38153466b161c0842b1604aef7b5589c51f628ae7cbb6a8722a
2019-03-05 16:53:16 +00:00
drh 7bf3133fef New dbfuzz2 test cases added to test/fuzzdata7.db
FossilOrigin-Name: 25975e1fb2be0c011542c0a6b001385cec8113662df93dc618f725f2a4692bc2
2019-03-05 14:47:53 +00:00
drh 0a31dc201e If the initial byte of a record is a large value, then always used the
generalized record comparison routine sqlite3VdbeRecordCompare() rather than
one of the specialized versions that are optimized for shorter records.

FossilOrigin-Name: c1ac00706bae45fe9735061ada025880606cdfb8ecfdaa36b4e2d04275820861
2019-03-05 14:39:00 +00:00
dan 4e72e62f3b Merge trunk changes into this branch.
FossilOrigin-Name: 9b4d561f68febdab6624d8c567fb4357bf67dda500664cf708d16a76f37b8ec1
2019-03-04 21:08:53 +00:00
dan 680f6e8e2e Support some "ROWS BETWEEN N PRECEDING AND M FOLLOWING" window functions without caching entire partitions.
FossilOrigin-Name: e7a91f12282afb5d5d7d78397a11d18e0268ee0c931d85e21fce00d13929494e
2019-03-04 21:07:11 +00:00
dan 4474e869fe Fix a problem preventing compilation with SQLITE_OMIT_UTF16.
FossilOrigin-Name: 906d1fd8650874236e0bf5734d5347dcc45ec036164a56570fec37da4ffeaf8f
2019-03-04 07:15:57 +00:00
drh 75db74fdae Improved comments on the fossildelta.c extension.
FossilOrigin-Name: d7d23f0450d659b2c7df34e4df8623ca7b6fe3bd19422e3e9234515214ae8510
2019-03-02 20:09:35 +00:00
drh e22976c535 Fix the SQLITE_DIRECT_OVERFLOW_READ compile-time option so that it works
with SQLITE_HAS_CODEC.

FossilOrigin-Name: fd085e9260bec18f968704abb2dd324d954baa121d13b67c3f5b801e9e3834aa
2019-03-02 15:25:24 +00:00
drh 8f46f34e2d Remove a redundant parameter extraction call from the percentile.c extension.
FossilOrigin-Name: d49c32e6e7cc341b5961d2c7b7c68d1649c6542eeec201660e3f82a55aea9e3b
2019-03-02 12:17:35 +00:00
drh f10c535fa5 The fts3_tokenizer() function returns NULL if the
SQLITE_DBCONFIG_ENABLE_FTS_TOKENIZER setting is disabled, which is is
by default.

FossilOrigin-Name: f5732f4caf7a37a6445c61ae0d0ac14cc9deb897376e73aa36a1ead025b92c69
2019-03-01 21:33:29 +00:00
drh 10cc16c954 Fix a minor comment typo. No code changes.
FossilOrigin-Name: 9a0a93c89d3fdd0f9000a9226388e2e53f299165e043913f40b83bf597bfea04
2019-03-01 21:12:40 +00:00
drh b531aa8fd9 In a query that uses a partial index, the expression that is the WHERE clause
of the partial index must always be true.  Use this fact to avoid evaluating
identical terms in the WHERE clause of the query.

FossilOrigin-Name: 9b2879629c34fc0a8e99d94648903eb93aabbc7a3682c80cb7382f9a9ca5ffb7
2019-03-01 18:07:05 +00:00
drh 9cb0264041 Add the ".parameter" command to the CLI.
FossilOrigin-Name: 1f9fa58541dc974989eee9c9a5d453956f7dbcf42965ece2db2cb5dee3f3f5e2
2019-02-28 20:10:52 +00:00
drh c06ede105d Add the new "bind_fallback" method to the "sqlite3" object in the TCL
interface.

FossilOrigin-Name: c7f70b6d96338dba201e005104e7f7148c1a8cd767ab05e35b44617c4c797bc5
2019-02-28 17:29:19 +00:00
drh 4ddf7f4211 New test case loaded into test/fuzzdata8.db.
FossilOrigin-Name: 00ae0c6c4815366bd2f36bc054b13bc7b568dd0a3caceddf0eba4db33f010ee4
2019-02-28 14:09:14 +00:00
dan 95fdb63b7f Avoid an assert() failure and an undefined left-shift operation in the fts3 snippet() function that could occur if the database was corrupt.
FossilOrigin-Name: d5250db6322103326f0d5782ba049996d9ce8784f9e53a3112fb6f09f888f1c3
2019-02-28 13:41:35 +00:00
drh 45616c7f75 Add an "|| CORRUPT_DB" term to an assert() statement in the btree defragmenter.
FossilOrigin-Name: 6bfd8655f006e031c0d4c988356c4b9206efa6bfdb034fde8ffa3361521a4844
2019-02-28 13:21:36 +00:00
drh 8e0f794d17 Enable the LIKE optimization when the ESCAPE keyword is present and the
PRAGMA case_sensitive_like pragma is ON.

FossilOrigin-Name: 6ae4b8c525f446ddb0e0bdd5e4e01e06e2ab975e3effa42fce6a1102b3a39830
2019-02-27 23:05:14 +00:00
drh 0319934322 Fix the readfile() UDF so that it returns an empty BLOB, not an OOM error,
when reading an empty file.

FossilOrigin-Name: 0edad5339e36d69aed9289bb3e60d35f9930386d76a62bb0194c4fdf420d16fb
2019-02-27 19:59:56 +00:00
dan 89d249364e Add the "-returntype" option to the "db function" Tcl method.
FossilOrigin-Name: 789a492b68c353e2b763d67d399722b7ab61bfe09b472466df2821f65cab1be9
2019-02-27 16:38:19 +00:00
dan f26b145385 Verify that fts5 auxiliary functions cannot be used in aggregate queries.
FossilOrigin-Name: 122330dba3eb2492875bd02a46442306f73e251408447af5e5914ee0c8d6a110
2019-02-27 15:26:03 +00:00
dan 69e224f88a Reformat the white-space in a few test cases so that the tests work with Tcl 8.6.9.
FossilOrigin-Name: 29d02bf2fa9ecacbcc3e862ca70382f5875da8c1dc7fd27366190045fcc42b15
2019-02-26 19:16:49 +00:00
drh ddc28c23d5 Minor change to dbfuzz2 that allows it to be compiled against older versions
of SQLite.

FossilOrigin-Name: 6d39d6a68bf09e0b4f6706218373e74fc03148fd8bdba5031c3de2f750d87cf2
2019-02-26 18:21:08 +00:00
drh bfa70de117 New test cases added to test/fuzzdata8.db.
FossilOrigin-Name: 61fdfc57b9539cb6da5fc24653da2c8fb7c041a7409df911df11b987ed479a3a
2019-02-26 17:52:44 +00:00
drh 5cb1ffc1bd Allocate a few extra bytes for the pager temp page as an overrun buffer while
processing corrupt database files.

FossilOrigin-Name: e7aca0714bc475e04b16e9db78722ce025d2a1382f80cfc0a49cff2af904eae5
2019-02-26 17:49:07 +00:00
drh eaac9996ed Use unsigned integers to count the number of pages in a freelist during
an integrity_check, to avoid any possibility of a signed integer overflow.

FossilOrigin-Name: 05b87e0755638d31f6d8918f8758362f8c3981661449b5171180a8498f66bd9d
2019-02-26 16:17:06 +00:00
drh 2b454e0335 Fix a harmless compiler warning that only comes up during debug builds.
FossilOrigin-Name: 848869ced988ca4d0ac76d43f984360fd11997a580719cccf8d55becea4e8fb1
2019-02-26 16:11:46 +00:00
drh 9ebe59d6ff Update the configure-generated makekfile to generate a portable pkgIndex.tcl.
FossilOrigin-Name: 35cbee7fe4a0b7ca06206ca2f69fc35abe3de4929070d6585ab765af82027438
2019-02-26 12:29:25 +00:00
drh 8b738d0865 Enhance the command-line shell to accept bound parameters, using the
TEMP table named "$Parameters" to look up the values for bound parameters.

FossilOrigin-Name: 7c941ce5bcc872ec92cbe0e409fd773f44a5ab1f814e689ad57f756b911e2b96
2019-02-25 18:43:54 +00:00
drh c3017e7b4a Update comments on the fossildelta extension. No changes to code.
FossilOrigin-Name: 9da4fb59b28686630d63a79988b458726332cf06cc0e6e84d7c0a7600f5fcab0
2019-02-25 14:52:43 +00:00
drh 7edcb11ca7 Fix a typo in the documentation for sqlite3_total_changes().
FossilOrigin-Name: 8474c1560e0c3a28c6a7ed360202a8e7caae3c8259f60bbfa6d2948ab7876f51
2019-02-25 14:16:19 +00:00
dan f2e5c98613 Fix a couple of assert() statements in fts3 that can be false if the database is corrupt.
FossilOrigin-Name: 84162af521f29df8a186163fbdef9856e1aa8aba78e74d7df0ba2cc83bb86240
2019-02-23 20:48:41 +00:00
drh 7f414c0c0c Check-in [fa792714ae62fa98] is incorrect. Add a test case to refute it and
also a fix to make it right. 
Then add an alternative fix to ticket [df46dfb631f75694] in which
all ephemeral tables used as the RHS of an IN operator be index btrees
and never table btrees so that they can always be reused.

FossilOrigin-Name: d3915230e3ee5878fe2e65a0afb7e91ee124aaf46b4e28c6e00053d6df13d445
2019-02-23 00:21:00 +00:00
drh 4bdd26dfab Remove a testcase() macro which is now unreachable due to the contraction of
the use of IN_INDEX_ROWID.

FossilOrigin-Name: 90c5a17cd526b256753f876e575f3e731d5e8b9dd6e196cf8d8f7306e099b91c
2019-02-23 00:08:09 +00:00
drh 50ef6716d2 Make all ephemeral tables built to hold the RHS of an IN operator be
index-btrees, never table-btrees, regardless of whether or not they are
used as IN_INDEX_LOOP or IN_INDEX_MEMBERSHIP.  That way, the same ephmerial
table can be reused for both cases.

FossilOrigin-Name: c2d50df8fd1a1fdae6226a3e77296ded09b53a74540caedd4868e686a93cbc10
2019-02-22 23:29:56 +00:00
drh bc0a55cf0b Check-in [fa792714ae62fa980] is not a valid fix for ticket
[df46dfb631f75694], as the new test case in this check-in demonstrates.
The fix here causes test cases for the [df46dfb631f75694] bug to fail
again, so this check-in is on a branch.  A new fix is needed for
[df46dfb631f75694].

FossilOrigin-Name: 0d456456da6e25b20d9d27ca95f1013082bca52ee74ee9bf91732a9fa843ea45
2019-02-22 21:33:56 +00:00
dan f030b37682 Internally, remove all references to a Window object that belongs to an expression in an ORDER BY clause if that expression is converted to an alias of a result-set expression. Fix for [4feb3159c6].
FossilOrigin-Name: 579b66eaa0816561c6e47ea116b46f229188f0fc84c1173bfe0d21df2dff9a9a
2019-02-22 19:24:16 +00:00
drh 480c572f2d In sqlite3NestedParse() be sure to detect all SQLITE_NOMEM and SQLITE_TOOBIG
errors and to distinguish between them.

FossilOrigin-Name: 73056b314bd63288c662752e9bd469b70264c38031c1c857460e64fdb1ed4e2e
2019-02-22 16:18:12 +00:00
drh 255a81f10a Modify sqlite3_str_finish() and sqlite3VMPrintf() so that they always
return NULL on any OOM or SQLITE_LIMIT_LENGTH error.

FossilOrigin-Name: e7144ffd21294d7aebbfa6aa5a262797a6d16de11193f1bf6b75f5f27b04c940
2019-02-22 15:42:10 +00:00
drh dbdddc99d8 Detect oversized strings in the OP_String opcode even if the P4 argument
is originally UTF8 and has to be converted to UTF16 to match the database
file and that conversion causes the string to become shorter and cross
below SQLITE_LIMIT_LENGTH threshold.  This might fix an OSSFuzz problem
that we have been so far unable to reproduce.

FossilOrigin-Name: c13d563925db12bc2c91ff9432050261e5bd39d960e2739777a66bf804df2e31
2019-02-21 16:41:34 +00:00
drh 6a1bfc9a6d Changes to the unix VFS that allegedly enable it to build of Fuchsia.
We have no way of testing this.

FossilOrigin-Name: be21a6416d47ff7db995006a0422b745044d9b8bb5bad3c53342aa6e2e524771
2019-02-20 19:20:16 +00:00
drh 7e85e9033f Disable unix-specific features of dbfuzz2 when compiling on windows.
FossilOrigin-Name: af84774d1eebcfe6a61b564b4edf280ad3c3a93f39b7f70b6fcc56f7bbdfb9eb
2019-02-20 19:06:16 +00:00
drh 8cf92890f2 Avoid the use of function pointers in columnName(), as function pointers
appear to be a source of consternation to LLVM.

FossilOrigin-Name: c48f6f39c5f89a338fed7153553a27a5d882d4d8db8221e911b96e0dd57c53d9
2019-02-20 18:13:57 +00:00
drh b1af9c603c Progress handler improvements:
(1) Invoke the callback after OP_Program opcodes
(2) Invoke the callback multiple times in a row to catch up after a
long run of no progress checks.

FossilOrigin-Name: 0c5db18d79366d9c23925ce3ed835500311f32a10aa7dbfdd09148b1e8a2507b
2019-02-20 13:55:45 +00:00
drh 042666e4fa When an IN operator drives a query loop, mark it as "CODED" so that it
will not be used afterwards for a (pointless) membership test.  This is
a better fix for ticket [df46dfb631f75694] than the previous fix that is
now on a branch as it preserves the full optimization of
check-in [e130319317e76119].

FossilOrigin-Name: fa792714ae62fa980f1767acc6d622a6727ceb677870243c88548423795dcb5b
2019-02-20 12:52:47 +00:00
drh 2a98b586c8 Enhance the xBestIndex method on delta_parse() to return SQLITE_CONSTRAINT if
no delta argument is supplied.

FossilOrigin-Name: f16d127c3b4a735afae1fc236bcf90f31adff079c7d3a896f901d908ff8b8532
2019-02-19 20:29:05 +00:00
drh 2d441ce3f3 Add the delta_parse(DELTA) table-valued function to the fossildelta
extension.

FossilOrigin-Name: d91fcc267bf1be795dfdb1fbfb40c2aea79ddff247a51d26462136c325b7a6d3
2019-02-19 20:19:51 +00:00
drh 4bec44bdfa Add the fossildelta.c extension in ext/misc with implementations of the Fossil
delta functions.

FossilOrigin-Name: b80cafa6f8a5c6ff1dc9efd2f670777ab131ace2df1eb431cedc8cfa901baf18
2019-02-19 18:39:16 +00:00
drh 6d7f18d60c Fix a potential memory leak in RBU if the rbu_fossil_delta() SQL function is
misused.  Misuse never happens in a working RBU system, so this is not a 
particularly important fix.

FossilOrigin-Name: 12517d1b15da46bc90bd95bb9c161d7f2ecdd7f28b1b3a5ed4397939ef986061
2019-02-19 17:45:31 +00:00
drh 12fe9a0d25 Fix an assert() that might not be true if the database file is corrupt.
FossilOrigin-Name: f2d400db4dbfb05e2540178ed3662f97f8c57a95f8129886c7081c35e53adf0d
2019-02-19 16:42:54 +00:00
drh 3cbd2b7245 New assert() to verify the TF_HasprimaryKey flag.
FossilOrigin-Name: 0abace8a7aecca01c8677d07f3ec1bafb289ceffe5bcd60284701a7bf813f415
2019-02-19 13:51:58 +00:00
drh 9df385ec3d Always use the symbolic name SQLITE_IDXTYPE_PRIMARYKEY rather than a hard-coded
magic number 2.

FossilOrigin-Name: 55d43adc894a6b1e0f77bf481dad6dd604a0dc0022e72bbf2e3037f97351971e
2019-02-19 13:08:35 +00:00
drh b43ac0021f Fix an assert() that might not be true if the %_segdir table of FTS3 contains
corrupt entries.

FossilOrigin-Name: a6509ca3dc2602c7d0376230ee63c1bb4c4066f007e77e9ac20d8eee966e5e13
2019-02-18 12:16:03 +00:00
drh 56785a0a80 Fix an assert() that might be false for a corrupt database.
FossilOrigin-Name: 0cfb888723fb8ff0763bbc23acb7d21a53f6d1c40661d8468248644281b29d85
2019-02-16 22:45:55 +00:00
dan e7c9ca41b2 Add support for chaining of WINDOW definitions.
FossilOrigin-Name: c155125fd5dddb438c09d40f5137c47d88defb7a6ede4261f09d7bdaad250d37
2019-02-16 17:27:51 +00:00
drh 9c7e44cddd Improved oversized cell detection when updating ptrmap pages in
balance_nonroot().

FossilOrigin-Name: aa61435a4c3800f023788081c1342ad6a05a41449a424fa6c039d5ca46072256
2019-02-14 15:27:12 +00:00
drh 82642f815b Ensure that the nProgressLimit variable is always initialized in
sqlite3VdbeExec(), even if the routine jumps to its exit processing early.

FossilOrigin-Name: 167b91df77fff1a84791f6ab5f72239b90475475be690a838248119b6dd312f0
2019-02-12 22:58:32 +00:00
drh c332e04310 Enhancement the progress callback mechanism so that the progress callback
is always invoked at least once at the end of a prepared statement if the 
opcode count has been exceeded.  This makes the progress callback more
effective at limiting run times.  This check-in also includes and unrelated
performance enhancement to OP_Column.

FossilOrigin-Name: 68cce272e7f7cbc0c319ee8b7ff674d652cb1e95e903d99d848c41dff2b5d304
2019-02-12 21:04:33 +00:00
drh 5860a61d59 Further performance improvements to btreeInitPage().
FossilOrigin-Name: 93ae382e97c23c90312739481e47ef7f9bc475a8382c063a2de2986c950c0aec
2019-02-12 16:58:26 +00:00
drh 83acc14ad4 Increase the version number to 3.28.0 for the next release cycle.
FossilOrigin-Name: 6eb38c59a81d27b7c1f3edad84b27a1114df6f1607282b2be1b5de9c7decc512
2019-02-12 15:51:36 +00:00
drh f9101623a3 Register the "vfsstat" virtual table immediately when loading the vfsstat.c
extension.

FossilOrigin-Name: 9bd92afd0cb0a958441e861c7006b77027125b1ceea0868958ec948b6b3c7bc9
2019-02-12 12:25:34 +00:00
drh 62e009f3d8 New test cases in test/fuzzdata8.db.
FossilOrigin-Name: ab2356f580384e4b40d128fc04fd6bc4dfcf50109df77d05d59adcc20f339066
2019-02-12 01:28:24 +00:00
drh 3e7800a9db Defer computing the number of bytes of free space on a btree page until that
value is actually needed.

FossilOrigin-Name: 177f5f40eabfcfd229ac7f291dfed9e9ee35762e86923a0f356915f389da177d
2019-02-12 01:04:49 +00:00
drh a941ff712d Change an assert() into a NEVER(), since the condition is difficult to prove
with certainty.  Improved comment on the MemPage.nFree field.

FossilOrigin-Name: fec071b89df2cbafda365077bb54bc9999e12086f36d6cea8d125662b36638dc
2019-02-12 00:58:10 +00:00
drh 8357c662b3 Do not invoke btreeComputeFreeSpace() when not necessary.
FossilOrigin-Name: f11b0ed47402034378ded2c60b82841b81cd1319cdb72d1ef052faef29a5294d
2019-02-11 22:50:01 +00:00
drh d4a6744b50 Improvements to comments. No changes to code.
FossilOrigin-Name: 16eb0fc8f8cce51eaa5305ebc9f3bd8c8d935dd3ebebab6820e5629f9292eec2
2019-02-11 19:27:36 +00:00
drh 6813350966 Fix test cases. Avoid unnecessary tests for MemPage.nFree less than zero.
FossilOrigin-Name: 480a5090befdc29eaeb6f0b22831c980d6ee92438d9b2e766de68b037ded38b8
2019-02-11 17:22:30 +00:00
dan 43a6e4d3df Fix another segfault that could occur in fts5 with a corrupted database.
FossilOrigin-Name: 09e337386beb2008eba969f79601d1b8ed953951ce6e43782586e168140d78d2
2019-02-11 16:12:09 +00:00
dan 47a30159e5 Fix typos in comments in fts5.h. No changes to code.
FossilOrigin-Name: c19e97bc927074915a3ac8307bf89d30580cf90edd75f4001bcf589b2dfefe58
2019-02-11 13:25:33 +00:00
drh c01f41cfa6 Updates to a comment to keep it in alignment to the changes on this branch.
FossilOrigin-Name: 7499f74351415e601eb48eff6b6fccd3a78d137f5ea9cd7cac46b904772966de
2019-02-11 12:51:39 +00:00
dan 8cd2e4ae03 Build and test fixes for SQLITE_OMIT_WINDOWFUNC builds.
FossilOrigin-Name: 8824115a9776e876a3677f0cb479e311ee65584d43872b37766a146afec72d8f
2019-02-11 11:34:01 +00:00
dan 3fd7eaf3f2 Avoid using non-ANSI return statement in void function sqlite3WalSnapshotUnlock().
FossilOrigin-Name: 4a4952d38e8177ed8d59aaa575410bebf76787dd6d801fdbdb809d4f8c670da0
2019-02-11 11:04:17 +00:00
drh f0c48b1cd8 Add an assert() in an attempt to repro an ASAN warning from OSSFuzz.
FossilOrigin-Name: 7b41222428dcebaae2e9a0e8192e091b6fdee5b1163a5fa14ca1cd4f06354983
2019-02-11 01:58:34 +00:00
drh 85a379b74b Fix a page-cache reference leak in the btree balancer when there is a corrupt
database.

FossilOrigin-Name: 9285899120dec24ff2944431ad455d7ae217ef408ae2f1a3e7bdfb897099028c
2019-02-09 22:33:44 +00:00
drh b0ea9432a1 Defer computing the MemPage.nFree value of an in-memory btree page
until it is actually needed, since for many pages it is never needed.
This checkin works sufficiently to prove the concept, but still has issues
with exception handling.

FossilOrigin-Name: 1d43ee4000b71f5c6d49244dee96358c567f09ba3451b9d22895a796d3f61ad6
2019-02-09 21:06:40 +00:00
dan 2fa619a3a8 Change a few assert() statements in fts3 that might fail if the database is corrupt.
FossilOrigin-Name: db74a56af73d92b7a9d43ceda7e4540915c580c68a0266b4ddefb9e0d5cbcbeb
2019-02-09 19:23:54 +00:00
drh 298f45c641 Small performance improvement and size reduction for pageFindSlot() - the
routine in btree.c that locates a free slot for a cell on a btree page.

FossilOrigin-Name: 1969372ac72d25cc642a0268f4bb0ae4b59f2dca568c119ef61b67183b3a8bd9
2019-02-08 22:34:59 +00:00
drh 16d7e87caa Further simplifications to sqlite3VdbeMemSetStr().
FossilOrigin-Name: 1d212957079a2caa30f3c9d80f43464781bc9634c2b5181a5814efbddae31711
2019-02-08 17:28:20 +00:00
drh 6ff7427733 Change the sqlite3VdbeMemGrow() routine so that it no longer guarantees a
minimum size of 32 bytes.  That minimum is no longer required, and without
the extra check for the minimum size, the routine runs faster.

FossilOrigin-Name: 5c499da8a4d0babc56883aa362ae124772fd9214a51169a88a5dee523d051658
2019-02-08 15:59:20 +00:00
drh 1cf197583d Give the sqlite3 object a pointer to the current Parse so that if an OOM
occurs, it can automatically set the Parse.rc value to SQLITE_NOMEM.  This
avoids a frequent extra test of db.mallocFailed in the innermost parser loop.

FossilOrigin-Name: 5c6638040b3017c6be016441422d965a3ca00dd6ae1f78cadc0b54562978f64e
2019-02-08 14:55:30 +00:00
drh 8851e10017 Do not do the optimization that attempts to pull expression values from
an index on that expression when processing a multi-index OR
(see check-in [a47efb7c8520a0111]) because the expression transformations
that are applied become invalid when the processing moves off of the current
index and on to the next index.  Fix for ticket [4e8e4857d32d401f].

FossilOrigin-Name: 440a7cda000164d3b46109caf2e1dde80681ba9b0d94ba9be6847d2b917445cf
2019-02-08 04:15:19 +00:00
drh 1e30c7f369 Change VACUUM so that it preserves ROWID values.
FossilOrigin-Name: 49e5d11d463de078c2b8a963f5ed436210937e6dfddf06942132db9ec685bfd8
2019-02-07 19:07:11 +00:00
drh c9912d1706 Version 3.27.0
FossilOrigin-Name: 97744701c3bd414e6c9d7182639d8c2ce7cf124c4fce625071ae65658ac61713
2019-02-07 17:02:52 +00:00
drh 24bfecab3c Experimental change to VACUUM so that it preserves existing ROWID values.
FossilOrigin-Name: f264015f84de51d74f681ba62a5f26bd859480d93e1eaf9e1018b3e9b4e0bea3
2019-02-07 15:09:44 +00:00
drh af63892337 In the fuzzcheck test program, make sure the isspace() and related routines
are not given values outside the range of -1 to 255.

FossilOrigin-Name: f298328771d5aaba798d05f50c77ac239c7c72422ff35953463d6876a9659f74
2019-02-07 00:17:36 +00:00
dan e385d33a29 Ensure all bytes of the PgHdr1 structure are initialized. This avoids a valgrind error when running corruptI.test.
FossilOrigin-Name: a505e34d4ec31159a4508ec827fcffed0cf3bd5ea5ef0ac293016da02367a53a
2019-02-06 20:49:49 +00:00
dan 922b35801d Update an assert() in test_journal.c to take the new "VACUUM INTO" functionality into account.
FossilOrigin-Name: 0e6249cb958a40ead0edf6e75a2c46e8657db3d358c5fe78a9dc0fa5ed7ad929
2019-02-06 20:12:00 +00:00
dan 9c5f734339 Avoid attempting to delete a file while it is still open in walfault2.test.
FossilOrigin-Name: 9d54a63d6e3cd47b483cf0ee868a5e7f638bcb0e3cbdeaecc667f293b87a3e99
2019-02-06 19:42:02 +00:00
dan 6e08c4a5e6 Update test file dbfuzz001.test so that it works with SQLITE_ENABLE_OVERSIZE_CELL_CHECK builds.
FossilOrigin-Name: 4371a0c46ee7bfbc0a1507796bd9eefd3371adad81b8dda214d018854316727b
2019-02-06 18:08:42 +00:00
dan 531230d006 Add -DSQLITE_ENABLE_DESERIALIZE to the default testing configuration in test/releasetest.tcl.
FossilOrigin-Name: 433d6ef637a10ee017b5d8cadd125a162cfedc9895ae862b8dde6dddb7eda59b
2019-02-06 15:23:43 +00:00
dan fbf6136c78 Do not attempt to test the shell ".trace" command in SQLITE_OMIT_TRACE builds.
FossilOrigin-Name: 3839e9098107604e1526c2b1e813c019607077dfe39d7eeb92f3466518dec3b1
2019-02-06 13:48:04 +00:00
dan 871b13492d Fix a problem preventing testfixture from being built with SQLITE_OMIT_VIRTUALTABLE.
FossilOrigin-Name: d2cca36adc69d2c8e7707d70cbd75c497eae6a1a3f8a9dd18249ca6804c9db5f
2019-02-06 13:41:19 +00:00
drh d0ee3a1e6d When extending the size of SrcList objects, do not attempt to use
extra space on the end of the allocation, as that provides scarcely any
performance benefit but does greatly complicate cross-platform testing.

FossilOrigin-Name: 3087a0c31e9fbfaedb7cf10a2fda59bc22318ff178614aefcc00ac83d9a7bb14
2019-02-06 01:18:36 +00:00
drh 4acd754c79 If the query flattener detects an error, cause the SELECT code generator
to abort immediately.

FossilOrigin-Name: 3d3b142f1045080beb775a9cfe88ec143aa460750132e20059fd510291449850
2019-02-06 00:55:47 +00:00
drh 01996dae49 Back out check-in [008112bcef561a8], reenabling deprecated PRAGMAs when the
SQLITE_OMIT_DEPRECATED compile-time option is used, because way too many
TH3 tests depend on those deprecated PRAGMAs.

FossilOrigin-Name: 9dbf512d1c4627a28d60f4e7238cb100d7a4e11f976139b07ad1c59e9b584c7d
2019-02-06 00:11:13 +00:00
drh 569b1d9119 Omit the ".progress" command from the shell if it is compiled with the
SQLITE_OMIT_PROGRESS_CALLBACK option.

FossilOrigin-Name: 4d0a949fd92e19fbf243a2e3a1a7c2cdb111f9a6943949d2420dd846bc7d9285
2019-02-05 20:51:41 +00:00
drh d46b6f57c9 Fix a harmless compiler warning in the memtrace.c extension.
FossilOrigin-Name: 2f468da4e9fb3edb5e902fa5d3c528726d1fb64d749d29e558ba3243c76bcb95
2019-02-05 19:52:39 +00:00
drh fc4eeef9e7 Fix compiler warnings on Windows.
FossilOrigin-Name: 4978ee8b5405f958723b4ebbd4288bd08bff2b453da2d1c032d1ae904c2a3821
2019-02-05 19:48:46 +00:00
dan dee9be9b3b Update the tester.tcl --malloctrace option so that it uses eu-addr2line instead of addr2line.
FossilOrigin-Name: 79c073878d56fc638b751b0e61295df182f7ee6f8ebd7319c1eeac1608abbac8
2019-02-05 16:53:26 +00:00
drh d57936721b The IS NOT NULL operator does not imply that the operand is never NULL.
Fix for ticket [5948e09b8c415bc45da5cf]

FossilOrigin-Name: d840e9bb023a1e84a7739d764a0f6cf608fc3183ff8c366fcdb486ebd932f0c1
2019-02-05 14:36:33 +00:00
drh 24545d2300 Keep the temp_store_directory and data_store_directory pragmas even when
compiling with SQLITE_OMIT_DEPRECATED.

FossilOrigin-Name: 93386a7c97f27df69f79052ef4d80143bb6832a806885249c315d226b2a256b2
2019-02-05 12:16:53 +00:00
dan 41e0717bcb Update test file "resetdb.test" so that it works with the "prepare" permutation.
FossilOrigin-Name: 95d338124be2e0e18f17354b28f4320336202f1a4ec1177df753b2800e954bfb
2019-02-05 08:55:43 +00:00
drh 53d30dd371 Early detection of implausibly sized records to avoid unnecessary
large memory allocations.

FossilOrigin-Name: 2c8769c69f301307db6663adb8b7c0b89f5959516bf6110cb8ff4b21bd903f70
2019-02-04 21:10:24 +00:00
drh af48257bc9 Mention the new -memtrace command-line option in the -help output of the CLI.
FossilOrigin-Name: ada91aefe37efe3c009691b5599e4d6acf182e5ec3cf28dda0871d09858498b3
2019-02-04 19:52:39 +00:00
drh a790882d63 Add the -memtrace option to dbfuzz2.
FossilOrigin-Name: 67fecbc79d3e927a7e22f3589be3184114322635874e4b3170666e352d0bfe9d
2019-02-04 19:50:44 +00:00
drh 88862d49a6 Enhance dbfuzz2 so that with the -v option it shows the return code and
error message for any failing SQL statements.

FossilOrigin-Name: 3a127ef9f7feafe6ba8c75e4eb29e28aa61a30249082cc8767ada1ec0cc0b7f1
2019-02-04 19:45:26 +00:00
drh f2305414cd Ensure that the sqlite3_exec() callback gets the correct number of columns
for a query, even if the schema changes out from under it.

FossilOrigin-Name: a16ffb5a4b30f1ac4a8384fccde0a0f69e49545b6f9be9267928609328c4a151
2019-02-04 19:12:54 +00:00
dan 4fc4ba771c Do not run shmlock.test as part of the inmemory_journal permutation.
FossilOrigin-Name: d3fea69cbb071867a90ad56ca05123ebf8e44689a92577a525a883c176c791bd
2019-02-04 16:42:57 +00:00
drh e2d2ad6ece Update the test/fuzzdata8.db database with new interesting cases from
dbsqlfuzz.

FossilOrigin-Name: e467e4c8fa256ddd6c26c1f21bc26289a21f18b781737eaf706bc813ed8234fa
2019-02-04 16:36:24 +00:00
dan 83a635a267 Fix problems with SAVEPOINT and related commands within transactions on a corrupt database that include fts5 or some other virtual tables.
FossilOrigin-Name: b0da6e0dd1f9a9ba7646ee6bb3c14945e570303c9a42d20fa8a653570e12c3f9
2019-02-04 16:25:40 +00:00
drh 3f83f59154 Add the ".progress" command to the CLI.
FossilOrigin-Name: ad84ca24ff760f7a2b128f2eeb4d799a97f84b8b8a8bb8d9657c4c555f6ccf47
2019-02-04 14:53:18 +00:00
dan 0062ddd4c9 Fix another potential buffer overread in fts5.
FossilOrigin-Name: 14fba4cc5db2bc206f024bfa5dd82fffdbc7577162da2c3b15a91cc1c91f3846
2019-02-04 14:00:20 +00:00
dan 81f44cdbfb Fix another corruption case in fts5.
FossilOrigin-Name: e608085d3f7e3cc0015fde626e205ee9842ef3cd06dc879fbbc7f2067c592965
2019-02-04 11:54:22 +00:00
dan 41fc545147 Fix an assertion failure in fts3 triggered by a corrupt database.
FossilOrigin-Name: 560ebd4269fad07b8e988d070454017123593eb6762597d08e8c32d7b4fb92ac
2019-02-03 07:46:07 +00:00
drh 150edadf58 New testcase added to test/fuzzdata8.db.
FossilOrigin-Name: 2f5c1925b94d85489533549c58191feb1d803ad9d58b43f47fef42b72c531a38
2019-02-02 18:24:28 +00:00
drh e5989723ba Honor key query parameters for SEE on the URI filename for ATTACH
and VACUUM INTO.

FossilOrigin-Name: 2e01096b8933a2315e3dffcd7d0de84c744c1b4be1d909388c61f0fd636ddb99
2019-02-02 15:59:49 +00:00
drh 9b2bd91d9a Give a link to the URI Filename document in the documentation to the
various sqlite3_uri_parameter() interfaces.

FossilOrigin-Name: 69b0b2ee536fda8975f60643f7f1891db4649958aca476822ea2a632ce731992
2019-02-02 15:05:25 +00:00
dan 8f5b14a5c2 Fix a buffer overread in fts5 debugging scalar function fts5_decode().
FossilOrigin-Name: 54f2399fb2a626602d405c857297f2da833f9f048cbc478f9110bed2e9bda299
2019-02-02 13:47:25 +00:00
mistachkin 844b900491 Fix harmless compiler warning.
FossilOrigin-Name: dddda685f3443d8a38901f758543fcde73d7b8cfe72b0ad5f419cd7459343bf5
2019-02-02 01:27:45 +00:00
drh 7ba03ea15a Slight adjustment to the printf formatter large memory allocation detector
so that it does not overestimate the amount of space needed for
oversize %d conversions.

FossilOrigin-Name: 1aee70d6de8a9b17ebb74a7cb1dad65139cde1b615dcce4d15d3a476fda8676b
2019-02-01 21:08:27 +00:00
drh 2964225247 Prevent the printf formatter from doing large memory allocations - larger
than either the size of the static buffer for interfaces like
sqlite3_snprintf(), or larger than SQLITE_LIMIT_LENGTH for interfaces that
are associated with a database connection.  This helps to prevent DOS
attacks on products that let hostile sources inject arbitrary SQL.  It also
helps fuzzers run faster and more effectively.

FossilOrigin-Name: 179e5d46054e5c86f53a79b7a0823d9a383da8391ad1d3c3b22645927a1e052b
2019-02-01 20:29:04 +00:00
drh 9a6d01bff5 Performance improvement in the parsing of options to %-formats in the
printf implementation.

FossilOrigin-Name: 40d8f8ae87abf928542c4e558a4c3a3eab18776a3e8db7ca1c5e5f744ca0bce3
2019-02-01 18:46:41 +00:00
drh 9c46c66c46 Ensure that the Walker.pParse structure is initialized when walking the
source tree to gather the WINDOW clauses on a query with window functions.

FossilOrigin-Name: 4ca9d5d53d41d08fbce29f9da8cc0948df9c4c3136210af88b499cf889b5ccb8
2019-02-01 15:06:27 +00:00
drh 38a28a7434 New test cases added to test/fuzzdata8.db.
FossilOrigin-Name: e5924939c9c8f39367900360fa294cdb1220e9f68d183e32882e0926f775869d
2019-02-01 14:54:18 +00:00
drh 26b7ec8b24 Improve the strict enforcement of cell sizes in balancing from
check-in [12713f320b2c1def] so that it also works with table-btrees
in addition to index-btrees.

FossilOrigin-Name: ef27e7a08728aa7447ae19812803ac5c4a9d80c97541014bd292485792005a3e
2019-02-01 14:50:43 +00:00
dan 1c7d389a23 Fix an assert() in fts5 that could fail if the database is corrupt.
FossilOrigin-Name: 55f06aa3f890dc1dc5c2ed0e6777e46d609a6f9d223d1d4b5813097ce4f4e797
2019-02-01 14:40:44 +00:00
dan abd7449478 Fix another corrupt-database-handling problem in fts5.
FossilOrigin-Name: 9876ae1b802a449aacbbdd42778653edc19e29315dc627c23ab7493d6492c800
2019-02-01 13:34:00 +00:00
drh 3bf0d7a881 Remove an incorrect assert() from the deserialize in-memory database VFS.
FossilOrigin-Name: 80151d7e3b9fd84086874a1cebed024b9e14005ea2d0108cf6efcd07373fcf51
2019-01-31 16:09:48 +00:00
drh 23a885956e Add the SQLITE_CONFIG_MEMDB_MAXSIZE configuration option for configuring
the default maximum size of an in-memory database created using
sqlite3_deserialize().  This is necessary to make the interface reasonably
testable.

FossilOrigin-Name: cb72ee0478ce98c48aae059fd5de4e36caf2b8c953e08fcb799bfd119ad46b73
2019-01-31 15:38:53 +00:00
dan b92b019fe3 Fix another buffer overrun that could occur when quering a corrupt database using an fts5vocab table.
FossilOrigin-Name: b80119bd6044c0993210115732b6ae7b4b0b29c1471b0723bef24f2052c8e671
2019-01-31 14:37:18 +00:00
drh 6a0db87a2f If the amalgamation file "sqlite3.c" is generated using the
SQLITE_ENABLE_UPDATE_DELETE_LIMIT option, but then subsequently (mis-)compiled
without that option, and then a particular syntax error could cause
a memory leak, but for this fix.

FossilOrigin-Name: 1bb17c863a269ab8b28df94b9fdaac3ee70777ccd0a30300131bf67df6722052
2019-01-31 02:42:47 +00:00
drh 9b747068ba Improvements to "PRAGMA parser_trace=ON": Make it a flag pragma, and then
use the flag to show the complete SQL text at the beginning of the parse.

FossilOrigin-Name: 507c43537f00d089efb3c3020fb6e826e8f89f3efa2caaa12c5309d35dd0c22e
2019-01-31 01:39:01 +00:00
drh 8bf4126c84 Change the error message slightly for when two or more indexes have the
same rootpage.

FossilOrigin-Name: 916c52dad414b224695d455a42af36f85dff216504c2aa67d1d2c5818cdca8d6
2019-01-30 19:50:07 +00:00
dan da7a4c0f7a When parsing the schema, check for duplicate index root page numbers before adding the index to the schema hash table.
FossilOrigin-Name: 6b360bc0b9ad18ccda9d58d43a8388d19999432bfdf294abcf5beb44ef990cb4
2019-01-30 19:12:13 +00:00
dan 56b99ebc32 Add test case for the previous commit.
FossilOrigin-Name: 197edb235b785c68fda7be788efbc61137d9452886599415a927b959ade93c65
2019-01-30 18:47:35 +00:00
drh 8d40673c84 Detect if two indexes of the same table share a common rootpage while
parsing the schema, and throw an error immediately.

FossilOrigin-Name: f21c6f1343edc4ba68f9f8e68caac34da0d1c651526ecaf61c0e2d66593a555e
2019-01-30 18:33:33 +00:00
drh ba7bd02002 Fix an off-by-one error when parsing the names of indexes that do not have
arguments in the index_usage utility.

FossilOrigin-Name: dc794d8f518ed46536928a77a560d46e4f9365c30a00cd108f000d8556a66c00
2019-01-30 16:58:04 +00:00
drh a8614259c1 Add the --progress, --using, and -q options to the index_usage utility program.
FossilOrigin-Name: a5e6be7cbc5d931308ddcc073c9cd6275c9711cae055d72a7c4aa71c1d15914c
2019-01-30 15:47:38 +00:00
drh 5a9c6bcc15 Enhancements to the index_usage utility program.
FossilOrigin-Name: 19c739b4a8a43d894e37a99fa34838f3e3fa1fe0d019aefbc33f1d38d76af1a4
2019-01-30 14:01:43 +00:00
dan dd579233e8 Fix another buffer overread in fts5 that may occur when accessing a corrupt database.
FossilOrigin-Name: 760d14374d40bcd9ce3a89771c18dc236c9728553c4747c9b7452ee7b24f4140
2019-01-30 12:15:27 +00:00
drh 3f4f6823ac Fix harmless compiler warnings.
FossilOrigin-Name: 9a93c68a7673bda2e6c308d3b2798d0fb12fde399996cae24b1f0d5864adf355
2019-01-29 16:54:31 +00:00
drh 4551005332 Load all the latest dbsqlfuzz finds into test/fuzzdata8.db.
FossilOrigin-Name: e744d2dd93a78235e6c1d938b08232183b5ce7e355d1b7daf2199e585b03c106
2019-01-29 16:47:46 +00:00
drh a046643820 More robust handling of corrupt database file in the rebalance operation of
the btree logic.

FossilOrigin-Name: 97704cb7d29fa7cc4ea9a6761a7844c1946d637ea2b22d287fc787ae0f63c407
2019-01-29 16:41:13 +00:00
dan e25646d64c Avoid an integer overflow in the fts5 snippet() function triggered by a corrupt database record.
FossilOrigin-Name: 7c862c4655841e1263cf548d01f5b4331685ab7d396494891cad0a5f50c63e16
2019-01-29 16:34:45 +00:00
dan eb2ed10ec0 Avoid a crash when the fts5 snippet() function (or similar) is used with a special query pattern, like '*id' or '*reads'.
FossilOrigin-Name: 9d58a15737f7379fed724749cfd5b4de5b44231870e99fc664683ad483c3e6ba
2019-01-29 15:30:03 +00:00
dan 3993397e6c Fix a buffer overrun triggered by a merge operation on a corrupt fts5 database.
FossilOrigin-Name: 7ee3cd5b2cdf8db35f70400b3df58f7c421c78ae77c50f22b0ee22d5a3039429
2019-01-29 11:42:43 +00:00
drh 4a7e9a25b6 Set a low limit on the length of strings and blobs in the OSSFuzz module,
in an effort to avoid timeouts when the fuzzer does things like
"randomblob(1e12)".

FossilOrigin-Name: 119d1609fa415894fdd0aa19440ca1c658bd01910838a4cfadbe0e304b033bfd
2019-01-29 02:37:22 +00:00
drh 3967d946c7 Fix the query planner so that it is able to use an index on a CAST expression.
FossilOrigin-Name: 2c886f3d49c9569e9f6ee28b89b57e2d4004c8972d11da0c23f7b2d2e0c9900a
2019-01-28 19:06:17 +00:00
drh e86974c619 Fix a performance regression caused by the previous commit.
FossilOrigin-Name: c4db0ad12d4f3d2800d36404f391b325cdc4aa7f8dcea93b2d63a489d9095ad4
2019-01-28 18:58:54 +00:00
dan 95d5a88058 Make indexes on CAST(...) expressions work.
FossilOrigin-Name: 3ef711d98fb239cf24472f124e7b36b0dde33355de5a2c9a3a978bbdd042a735
2019-01-28 18:08:59 +00:00
dan c7def600bd Fix a buffer overread in fts3 that could occur when accessing a corrupt database.
FossilOrigin-Name: a9faf9033910927c74553e66c474d84ed3386f263cef3eec299e25d8306f410d
2019-01-28 16:50:42 +00:00
dan 6c43dbad98 Do not assume that text parameters passed to fts4aux queries do not contain embedded nul characters.
FossilOrigin-Name: df04859a995571cd6faf1abe088725708f35e81195760274df9e2ec9bd47f69f
2019-01-28 13:27:25 +00:00
drh 9e35a61e59 Add a new test case to fuzzdata8.db.
FossilOrigin-Name: ce8e279a7d37594e865c2d9197a5efe5d647e11f074dbaf4a4ee31c74c71dbc9
2019-01-28 11:54:13 +00:00
drh 0c873bf28a Change the definition of the BtCursor.skipNext field so that it is undefined
for states CURSOR_VALID and CURSOR_INVALID.

FossilOrigin-Name: 6089d5dba73437d787259033e94a38cf1b0c87cac4a89c27e69d8239c22f496e
2019-01-28 00:42:06 +00:00
drh c07eee7a50 Improvements to the ".eqp trace" command in the CLI so that it ensures that
the schema has been read prior to activing the tracing feature, to avoid
cluttering the output with a trace of the schema parse.

FossilOrigin-Name: 42687d45aa1a2b2a32ddfc5711b4ae9cf76b8cfbeb20b57d6705ecaf5824fcb6
2019-01-27 19:50:56 +00:00
drh 05d49d1442 New test cases form dbsqlfuzz
FossilOrigin-Name: 9cf8ebd141aa2eb661d457624c76433bd9e4abfdef04aa52e28bc169172c2c8f
2019-01-27 02:45:32 +00:00
drh 211a0857b9 Window functions that can abort should indicate this, so that if they are
used in DML statement, a statement journal will be used.

FossilOrigin-Name: 0ea05a0eb96acb860d8af2e788e29a5ae3b161e7892ab62f1ff2f3e722c0dcb6
2019-01-27 02:41:34 +00:00
drh e5da9356e0 Update fuzzcheck so that with the --load-dbsql options it screens its
inputs to ensure that they are valid dbsqlfuzz cases.  Add new dbsqlfuzz
finds to the test/fuzzdata8.db database.

FossilOrigin-Name: 004f7d9bbeee049c22a7e1c82c6cc0ea79a237967de3ff57686acea3060d5f45
2019-01-27 01:11:40 +00:00
drh e6a9efb976 Ensure that the btree cursor is correctly set up prior to backing it up
as part of a delete operation on a divider cell in an index.

FossilOrigin-Name: a3ea1a822d3a110f4f186f2fc8550f435c8c98635d058096b7be9d4df7066b8b
2019-01-26 23:34:50 +00:00
dan 32bb700a95 Fix a broken assert() in fts3. Also some test script issues causing failures with builds that do not support fts3.
FossilOrigin-Name: d59567dda231e7ffec437d5e055676cf42d791196406cdc696cafa2583eb483b
2019-01-26 21:05:54 +00:00
drh b4e5039316 Add the ".eqp trace" command to the CLI when using SQLITE_DEBUG, as a
convenient shorthand for "PRAGMA vdbe_debug=ON" but with automatic indentation
feature for program listings provided by the CLI.

FossilOrigin-Name: 626502faa17b5b7a0fa36cabfd12e463eb09aec048d01c587a18d3977cf04662
2019-01-26 15:40:04 +00:00
drh 0814acd981 Do not accidently truncate zeroblob values when doing an arithmetic
operation.  Fix for ticket [bb4bdb9f7f654b0bb9f34cfba].

FossilOrigin-Name: 13f6942eb0da2d92a0830f18640ce64208bd0cd6ff6d0c97e4a4c57ac3d65ba6
2019-01-25 20:09:04 +00:00
drh b2e61bc66b Reinitialize debugging information on registers of a trigger prior to each
invocation of the trigger.  This prevents false-positives from the
sqlite3VdbeMemAboutToChange() test logic.

FossilOrigin-Name: 98b3b97573ccb3d986d1552f97f96e15088a598945923adcac77010c1e8b7fe4
2019-01-25 19:29:01 +00:00
drh f69af053dc Fix harmless compiler warnings.
FossilOrigin-Name: 3ff220ad378d547538b4501e6b2201e835a2c66891e5e40856db377c101a50e5
2019-01-25 18:17:37 +00:00
drh 0578084507 Fix the assert_fts3_nc() macro so that it works for test builds that omit
SQLITE_DEBUG.

FossilOrigin-Name: b10df2b569e356551cf51ca179f307e4f8827413ee9feb886db1f1e0650e6c5f
2019-01-25 18:17:03 +00:00
drh ed457037c4 Fix harmless compiler warnings in fuzzcheck
FossilOrigin-Name: a82539665718c8183d9d0bb7bcb3adcb1a23294b8c30f364829a982dab89a332
2019-01-25 17:51:06 +00:00
dan c2ea77e5b2 Fix a segfault that could follow an OOM when querying a table that has one or more columns with default values "true" or "false".
FossilOrigin-Name: 202f9919c222ee933924c63c15ad36ec4481457b1e4d9179af14c9f284117c0c
2019-01-25 17:26:59 +00:00
dan e88609f23e Fix asan warnings in fts5 triggered by corrupt databases - passing NULL to memcmp, out-of-range left-shift values and signed integer overflow.
FossilOrigin-Name: 93f8ec146d63af13f04e337ada4fa75e9254f72b1394df09701ae12e185f27e2
2019-01-25 16:54:06 +00:00
dan c1f6618217 Add an assert_fts3_nc() macro to fts3 - for assert() conditions that are only true when it is guaranteed that the fts3 database is not corrupt.
FossilOrigin-Name: 3498908cd7f3d0e35b70796537124e3da0bd99d48750ba51bcb9eba87e28ed4d
2019-01-25 14:48:18 +00:00
drh 31ab7d8e5c Extend fuzzcheck so that it can process dbsqlfuzz cases. Add a collection
of interesting dbsqlfuzz cases to the standard test suite.

FossilOrigin-Name: e2991a7ecf5dd241c4bab7c7cadc4901043fb0c3ea1fac70b684f6d8332677f1
2019-01-25 14:23:36 +00:00
drh 94f0a83421 Fix the xFetch method of the "memdb" VFS (used by deserialize) so that it
is robust against corrupt database file.

FossilOrigin-Name: 2c1ef40e787a6bc355b50168527a47eb09acd30d0d88cff8336a434ad554115d
2019-01-25 14:16:01 +00:00
dan ba14c69b4f Fix a couple of assert() statments in btree.c that could fail with corrupt databases.
FossilOrigin-Name: 5eb5e8289fa71e5e29e081d33d4a59c64b463bf6b06d7070c05c46d77d808ad4
2019-01-25 13:42:12 +00:00
drh 725a9c7f6c In fuzzcheck, activate vdbe_debug for dbsqlfuzz cases when using the -vvvvv
verbosity level or above.

FossilOrigin-Name: 2e6f7c2aced49824a38b3494b796a8ec73aa7a90b51159f670596df15ed1c5ab
2019-01-25 13:03:38 +00:00
drh df21659a40 Improved automatic detection of dbsqlfuzz cases in fuzzcheck.
FossilOrigin-Name: 1ef24e89c9630fd383ba32f5aefcf9c27907f27f5072f3537a1cfd75a093a8d7
2019-01-25 04:43:26 +00:00
drh a47e709e89 Add the ability to process dbsqlfuzz cases in fuzzcheck and add an initial
set of interesting dbsqlfuzz cases.

FossilOrigin-Name: fb9074ff450a67feaa62ca61d19154de26d5c8a8d147409ee6d1fbd667b2914f
2019-01-25 04:00:14 +00:00
dan 813ed78054 Fix a buffer overread in fts3 that could occur in a prefix query on a corrupted database.
FossilOrigin-Name: d0d5689371577b2861d4a9464443d055f3256f3f51d89e0388233a4cbe2601ee
2019-01-24 17:41:12 +00:00
dan f467744d5f Fix a problem with running ALTER TABLE on a schema that contains expressions of the type "col IN ()" (empty set on RHS of IN operator).
FossilOrigin-Name: 2d9cd06715092c312c8c0ec392696a0e90ed090b074e2082e0b830f1399aa941
2019-01-24 16:27:10 +00:00
drh 3cc9af2140 Omit deprecated PRAGMAs when compiling with the -DSQLITE_OMIT_DEPRECATED option.
FossilOrigin-Name: 008112bcef561a8a3ebfb007cbef36cbc0071f547e6ebdba3d3bbb39e2c48c7a
2019-01-24 16:07:18 +00:00
drh 491b6d897d Make sure the column name flags are restored correctly after an error
inside of sqlite3ResultSetOfSelect().

FossilOrigin-Name: b1601db7adba2dccd4f90fbbe5099c801a2b0d97af087fbe82ed98d05496b38c
2019-01-24 15:51:03 +00:00
dan b0c4c94996 Fix a potential problem with "INSERT INTO ... SELECT * FROM" (or VACUUM) statements on a corrupted database.
FossilOrigin-Name: db4b4c2c1e9f1adacfb1b2fedb717a4d8bb0a299c3b11835404a99fcd67bf24b
2019-01-24 15:16:17 +00:00
drh 936ade4dba Change a integer variable in sqlite3VdbeRecordUnpack() to unsigned in order
to avoid any possibility of an integer overflow.

FossilOrigin-Name: 1b536f6fd8d58800042f130842f0586aaa357841ee0d1b690a9815c865d50826
2019-01-24 14:16:20 +00:00
drh 55469bbafb Use memmove() instead of memcpy() in a place where buffers might overlap
if the database file is badly corrupted, to prevent warnings
from ASAN and valgrind.

FossilOrigin-Name: 65ad6c55f1ba9bc2f75afffa3adaf19f145fad7ac9a00ccce6372e9a2cc4341b
2019-01-24 13:36:47 +00:00
drh 6a02f237e3 Remove an unreachable branch.
FossilOrigin-Name: 4c976f171342ba2d39779279c28f3bc088572c440922e3e4421a3bf541263360
2019-01-24 04:44:54 +00:00
dan b4738ddb20 Fix an assert() in vdbemem.c that could fire if the database was corrupt.
FossilOrigin-Name: a70958cd7d5cf750c293537856918e5789013b70f6a827f724d83559b38629c8
2019-01-23 20:31:56 +00:00
dan a5f9f42a0e Fix a problem with renaming a table within a schema that contains a composite query that uses a column alias as an ORDER BY term.
FossilOrigin-Name: 2ca6b8f84ec07e313aa4e1c0894827401b418dcc4221e9c54c384f1c3893952a
2019-01-23 19:50:46 +00:00
drh e3dadac591 Stricter enforcement of cell sizes when doing balancing operations on the
btree, in order to catch file corruption sooner.

FossilOrigin-Name: 12713f320b2c1def273dd8b7833dddaaad5331aba779d4b1ec9aa949814f38fe
2019-01-23 19:25:59 +00:00
dan f8f47dd8c5 Fix another fts5 crash that can occur if the database is corrupted.
FossilOrigin-Name: 44ce8baa47192be03c8f11777904c3c07fa5cc5c97b6d8e81572d380995ac688
2019-01-23 19:17:05 +00:00
dan d99950310f Fix problems with sub-selects in WINDOW definitions. Also rename-column operations when the column being renamed appears in a WINDOW definition that is part of a VIEW or TRIGGER.
FossilOrigin-Name: 0387cb3add992b2028efe4f2100188d8f9fdfdcb233329857aa4b46a293cfc97
2019-01-23 16:59:24 +00:00
dan 4c7bdd1597 Fix a buffer overwrite triggered by a prefix query on a corrupt fts5 table.
FossilOrigin-Name: 1d8172a94bce2d067027685e5aa1dc8f5d5d55b5da0832ad2836f6939de68c8f
2019-01-23 12:19:22 +00:00
dan ccfa550922 Fix a buffer overrun that could occur in fts5 if a prefix query is made on a corrupt database.
FossilOrigin-Name: 1abc4415648e69362061e9f9a4f2c1d419ba33801999b377650d8b9a4d2d3a7c
2019-01-22 21:17:40 +00:00
dan 8e4fe01dda Do not run shmlock.test as part of the journaltest permutation.
FossilOrigin-Name: 5b7d0c784e6467154d9549af0163d788b69d5e5a6478a735834cdea945e7dbb7
2019-01-22 20:18:29 +00:00
drh c5ea2d474d Use _strdup() instead of strdup() on Windows builds of the CLI, to avoid
a compiler warning reported on the mailing list.

FossilOrigin-Name: a7126a4f4fb4e3e25be95d673323f835252bb2b427469616046a90b2acf64071
2019-01-22 16:44:59 +00:00
drh f186f0b058 Fix the SQLITE_DESERIALIZE_READONLY feature so that it does not cause
an assertion fault in the pager.

FossilOrigin-Name: b9eccef7825c61980678599358b62bc394283124653061ce163ead0c653f481d
2019-01-22 16:43:47 +00:00
drh 178edcd774 Update dbfuzz2 to set a maximum database size of 100MiB by default, but
with the new --max-db-size N option to change that limit.

FossilOrigin-Name: 21d6bb78ef2979d011b917d2d6519d7cd0009fcad83ed23ab2e9a5e02d8e51ab
2019-01-22 16:11:31 +00:00
drh 6ca644818b Enhancements to deserialize: (1) Add the SQLITE_FCNTL_SIZE_LIMIT file control
to set a maximum size for an in-memory database, defaulting to 
SQLITE_MEMDB_DEFAULT_MAXSIZE or 1GiB.  (2) Honor the SQLITE_DESERIALIZE_READONLY
flag. (3) Enhance the TCL interface to support -maxsize N and -readonly BOOLEAN.
(4) Add the --maxsize option to the ".open" command and on the command-line for
the CLI.

FossilOrigin-Name: 30f08d58882819a69e353bcc1b6b349664bbfbe00aa1c115ba44a9fd899fcc5b
2019-01-22 16:06:20 +00:00
drh 247c1b4a0b Make sure cursors are opened on all indexes for an UPDATE OR REPLACE
regardless of whether or not the indexes are partial or contain columns
that might need to be updated.

FossilOrigin-Name: e148cdad35520e6684cfeba23b003f60b55f83a6bf621aff16be8aa5612cdcee
2019-01-22 13:45:48 +00:00
dan 2c7a73eaea Fix another segfault caused by a corrupt fts3 database.
FossilOrigin-Name: ba3b8412726548a0716c1a2d67260c3b7e31956474f4cd4ce607cf2cebc667dd
2019-01-22 12:21:28 +00:00
drh 9b13365bba Ensure that a key comparison does not read a collating sequence past the
end of the KeyInfo, even if the key field of an index is corrupted by having
a string in the last column instead of the ROWID.

FossilOrigin-Name: 058a8006dceda78a894ea9446f057aa60b6d38e96506d4d91bda0ee2f9314ba3
2019-01-22 02:34:35 +00:00
drh 87c3ad4537 Enhance the btree search routine so that it does early detection of
impossibly large keys and thereby avoids a large malloc() call.

FossilOrigin-Name: 3ecaaee69f49e43d38047b7d53b82689eba7f7d33541fcac3c32b6dc8a568458
2019-01-21 23:18:22 +00:00
dan 129371553c Avoid deferencing a freed pointer following an OOM or SQLITE_CORRUPT error in
the fts3 xDestroy method.

FossilOrigin-Name: 505ed9a47825240979338a24044559613fbbd2a7850bdff70c7164da054ec63d
2019-01-21 17:57:31 +00:00
dan ac30553f76 Remove a faulty assert() from fts3.
FossilOrigin-Name: 6c33a303ebbb0f5193ead535280ba63118e14fb4f9977ce80dc716a0b082ec99
2019-01-21 16:12:20 +00:00
drh e6c628e98c Make sure the extra bytes allocated for the saved cursor position by
check-in [160b1e31c0f27257] are initialized to zero.

FossilOrigin-Name: 2737564929e86ead84a3ff6512369268198d38b46e3e02866f8ce34babc76cb9
2019-01-21 16:01:17 +00:00
drh 50b910a8b5 Add the --memtrace option to the CLI.
FossilOrigin-Name: a1e12fa2a8eb5648a96cc2d8d39899d6f87c5e2269cec7de486964c8b915e724
2019-01-21 14:55:03 +00:00
drh 7c04c69204 Minor fix the fallocate.test module change from [7cd56cad5efead5]
FossilOrigin-Name: 94fb7a47003c3c1a52e833e98d27399cfec5382afde2b3990e8223c8bff7cfa0
2019-01-21 14:49:14 +00:00
drh 5976552a72 Add the --max-data and --max-as options to dbfuzz2. Also cause dbfuzz2 to
show its maximum RSS size upon exit in standalone mode with the -v option.

FossilOrigin-Name: 7ce93e824a954d1e0cf8d7343e59a2660175f42bd4dac02aed8ad77644e7eb2f
2019-01-21 13:47:55 +00:00
drh 8ed07d1274 Add the --max-stack option to dbfuzz2.
FossilOrigin-Name: c11ae4fed89484f0a0061002861b5d599bbda8e40a1f0c33fdbe8cb072134d5c
2019-01-20 00:03:59 +00:00
dan 27a037354c Avoid a division-by-zero error in fts5 caused by a corrupt database.
FossilOrigin-Name: 928e622178bd004be52b2271ac554176aebe9d6e115ecac4e7072eccbb4262b5
2019-01-19 15:55:27 +00:00
dan b8852ae083 Remove a broken assert() triggered by a "PRAGMA max_page_count = N"
invocation, where N is larger than the number of pages in the database image,
but smaller than the number of pages in the database file.

FossilOrigin-Name: 7cd56cad5efead5097e9918c87313bb46e583fe62bae0df1be60e10117e2c3cb
2019-01-19 15:27:09 +00:00
dan 93b6c1666d Fix a problem with using ALTER TABLE to rename a table or column when the
database schema contains a trigger or view that itself contains an expression
 "<column> AND 0".

FossilOrigin-Name: 908ff7fffa302255a74e2334ca3a1779ed43acb0268fce5a83a56fd16794dc88
2019-01-19 14:07:37 +00:00
dan 225b05795f Fix a memory leak introduced by [55c5d72a].
FossilOrigin-Name: fbd681dce2905d8b8ad7948ba684b0b62d6c04be0f7a2992ee7d6836a99010de
2019-01-18 21:17:08 +00:00
dan 6e0a75a2b8 Fix a crash in the fts5vocab module caused by including a "term < NULL" term
in a WHERE clause.

FossilOrigin-Name: 9e717c4377c0116a5d36815fbc30f8b8803f14770d30be361feb27cc5b5b537b
2019-01-18 21:12:32 +00:00
dan a86b20820d Fix an infinite loop caused by a corrupt database in fts3. Also an undefined
left-shift in fts5.

FossilOrigin-Name: 55c5d72af9510e2f27c33544d804a58d4282b0efb384ead38484129ce91b574f
2019-01-18 21:03:15 +00:00
dan 4c1c79035f Avoid passing a NULL pointer to memcpy in fts5, even if the database is corrupt.
FossilOrigin-Name: acccc9808f52009b2c7794770c8b7efe2ce861fa184d32e287e7114c74e2b522
2019-01-18 20:15:02 +00:00
drh d00ad9a656 Typecasts added to the GeoPoly extension to avoid harmless UBSAN warnings.
FossilOrigin-Name: a1f6a093ac4a2de8c5b02c30fe57e09770460fd5bdddfe9c7a9a24fb83a6b491
2019-01-18 19:33:56 +00:00
dan 451297752c Fix problems causing undefined left-shift operations in the fts3 snippet()
function.

FossilOrigin-Name: b90dbaed3092236e97f9796fa63989a3648060e16189e1267c430f4a7e799fac
2019-01-18 19:26:48 +00:00
drh ed968fa4cb Avoid integer overflow when computing the array of a bounding box with
the rtree_i32 virtual table.

FossilOrigin-Name: b352f1590d20a574b0681e011ececcf4f41fa5b157503d330e03939404aca0e9
2019-01-18 18:52:17 +00:00
drh e3b89d2c5f Handle oversize floating point values carefully when converting to integers
for the '%' binary operator.

FossilOrigin-Name: 048add13fc10e69ae504a49c4663612381d928b2cf1f9cdab4ff34bd40f601a3
2019-01-18 17:53:50 +00:00
dan 0e14e98706 Fix a fairly obscure problem allowing an "ALTER TABLE RENAME col TO ..." statement to modify the schema in such a way as to break a reference within a trigger program.
FossilOrigin-Name: 64bec9e6214c6932fab5a3fb8c569ae14cd2d603bd0f8b26104815c3bb9d396a
2019-01-18 16:06:18 +00:00
drh 3cb79202f8 Use the full 64-bit integer value in the argument to randomblob().
FossilOrigin-Name: 05df5f7aeaf2132810452e8871132d1e66650a841991cb2a9ce32f2d03e20bf4
2019-01-18 14:53:15 +00:00
drh 21908b2166 Disable the xfer-optimization if the two tables have the same root page
due to schema corruption.

FossilOrigin-Name: f31b3bd2a6a8aa35a6454f37f3a4b4595e2ad74256cd180439019ab4c6c2059e
2019-01-17 20:19:35 +00:00
dan 934d4f7bac Fix another corruption related crash in fts5.
FossilOrigin-Name: 4538d9afe4e6360e20c7b474e77314e5ad293453e1edbe356bf6ea84c05857ee
2019-01-17 20:06:56 +00:00
drh aa0f2d0efa Add the SQLITE_ENABLE_EARLY_CURSOR_CLOSE compile-time option which causes
read cursors to be closed after their usefulness ends during a two-pass
UPDATE.

FossilOrigin-Name: 7def6c8edd85f19ee09038e01541f75b1f71ca39b9fb782b8f0fcac89207c353
2019-01-17 19:33:16 +00:00
dan f66da6ce8e Fix a buffer overwrite that could occur when running an fts5 prefix query
against a corrupt database.

FossilOrigin-Name: 3910b5639d5c96d1840d4feeea64d3a55073531b7365a4e75d9cda6f119f3cfc
2019-01-17 19:11:10 +00:00
dan 25fb50674f Fix problems with joining two or more fts5_vocab tables that access the same
underlying fts5 table.

FossilOrigin-Name: 49956395e14b61f6bf839e59ae7dd95eb32ebf32f3d16388844de6621b9c2d98
2019-01-17 17:39:15 +00:00
drh 29c992cb04 Revamp the SrcList allocator routines to be methods of Parse instead of
being methods of the "sqlite3" object, so that they can leave better error
messages when the SrcList object grows too large.

FossilOrigin-Name: df08d472b090b212fb77ce2aae0e1ffe79ae5db4b1accf55e6fdb18e8b0a7098
2019-01-17 15:40:41 +00:00
drh 0ad7aa8182 Limit the size of SrcList objects to 200 entries (compile-time configurable
using -DSQLITE_MAX_SRCLIST=n).  The maximum number of tables in a join has
always been 64, so this is not a real constraint on capability.  Limiting the
size of a SrcList prevents DOS attacks (discovered by OSSFuzz) using crazy
nexted CTE joins.

FossilOrigin-Name: 7cac614d5df55eb092b863163483b6782b942b21bd15fd787576fef5619fa849
2019-01-17 14:34:46 +00:00
drh 04fcef00ee Fix a corner-case for the logic that cause an insert of a NULL into an
INTEGER PRIMARY KEY column to be converted into a valid integer key,
when the NULL results from a CASE expression that lacks an ELSE clause.

FossilOrigin-Name: 9a425051e7ba59e797636f5cf32b5f6efafdb21c8d5300e099b8008b829c1439
2019-01-17 04:40:04 +00:00
drh 30fdb45da0 Ensure that the variable-length integer decoder in FTS3 never tries to
left-shift a negative number.

FossilOrigin-Name: 10ffc1fe006a1766ff2f1ffc6129786afb86b6b1f8d3a17334e8ecb838d37b9c
2019-01-17 03:43:38 +00:00
drh f20bbc5f69 Fix a failure in sqlite3ExprCompare()
FossilOrigin-Name: 835e2cc55feea2f2426c99816c27f9c35d2fd4cdd9bf1c7f46f889ecfd222778
2019-01-17 01:06:00 +00:00
dan 8b20e4a3eb Fix a problem with fix [b4b57413].
FossilOrigin-Name: ca7b7aaed010ec67bec5355a9ac1d7f229d6d5f2ba2d796b76f5e908b1267688
2019-01-16 20:48:13 +00:00
dan e011ee2830 Fix a problem in the fts3 matchinfo() function with corrupt database handling.
FossilOrigin-Name: 24ed5fb6aea30b098d2faf3cf9d638933e518657217e903239ffaa1e25d34f66
2019-01-16 19:44:09 +00:00
drh 375afb8bda Fix a problem in the code generator for sorting results with SRT_EphemTab
and a LIMIT clause.

FossilOrigin-Name: 49fcde2f1f981ac0c75728bed3444e7c1d3167311db282d3375c96ce090b2210
2019-01-16 19:26:31 +00:00
dan 5e970a8f40 Fix a problem with renaming a column that is used as part of an ORDER BY on a
compound SELECT within a database view or trigger.

FossilOrigin-Name: b4b5741366578b25ec6e4c415ab8239215e53b1c900be613575f40a826cfccc9
2019-01-16 14:58:37 +00:00
dan fb8ac325d7 Avoid a dangling pointer comparison when renaming a table that has a trigger
that itself contains a window function with an (illegal) column reference in a
FOLLOWING expression.

FossilOrigin-Name: d45bee36f2c1091a2d32c16ca8921bf4e7c9e40c46d0a36fbcb179ecfafcfbf0
2019-01-16 12:05:22 +00:00
dan 4ccb41fc99 Fix a memory leak that could occur in fts3 when handling a corrupt database.
FossilOrigin-Name: 65cebb06a0afcbcb4157c3d518a62ed188b1e90d9e9b69d88fece484bcb6e380
2019-01-16 11:38:06 +00:00
dan dfb5c963a0 Fix a problem with ALTER TABLE and vector assignments in UPDATE statements
within triggers.

FossilOrigin-Name: cc6cd7531fee39b4c2a9f522f1089c1d79254a9e25acae59468322031f94c25a
2019-01-15 20:51:35 +00:00
dan 1a39d2bb5c Handle SQL NULL values without crashing in the fts5 snippet() and highlight()
functions.

FossilOrigin-Name: a5e9cc794f17566160c4b2b5791601a744a21ace987b19ff8a5816fd78dce56a
2019-01-15 18:14:27 +00:00
dan a783931794 Fix a buffer overread in fts3 caused by a corrupt record.
FossilOrigin-Name: e54efd60c20bbfc5d70ddb9e1dd6ffb68cbbcfa57b4f07cb104767ef08c1a559
2019-01-15 16:14:31 +00:00
dan 2d4e720579 Have fts5 reject attempts to insert a non-integer, non-null value into a rowid
column with SQLITE_MISMATCH.

FossilOrigin-Name: 4a9483f81e9ca1aa41d6ca33cb3171370418ccc71fdee9741bbf6f694bf4fbaa
2019-01-15 15:18:58 +00:00
drh e2dcc42e1f Fix a harmless memory leak in the Lemon parser generator utility program.
FossilOrigin-Name: 1caff0fb0b2051e205e7a8cfd5dadf92680c52a88a441ded95b1ea6542db5f83
2019-01-15 14:44:23 +00:00
dan 58ed374370 Fix a problem triggered by DELETE statements with WHERE clauses that use the
OR-optimization on some virtual tables.

FossilOrigin-Name: ecf5caa7e9825a8b03d15ee525ec68be78c55926ddfaca27a040a7614caf0e85
2019-01-15 14:31:01 +00:00
dan 9c039d9f2e Add scalar function "prefix_length()" to ext/misc/prefixes.c.
FossilOrigin-Name: 0bf1550507d9d3c8a41f8a50db3a59bf808f0a4e24637dc0905d35579305eca7
2019-01-14 20:44:00 +00:00
dan 9274ad898f Fix a problem causing some Tcl test cases to fail with errors like "expected: [<multiline-whitespace>], got: []".
FossilOrigin-Name: 11b8a4cba747ca214fe3506caa3b711c87be4d55412754e673cc0603afefb086
2019-01-14 19:13:30 +00:00
drh 4ead96348e Add the "prefixes" table-valued function in the ext/misc folder.
FossilOrigin-Name: f0fd2163fc23a555ef03af43294a14fcabae6921f52e64c979286c745b4f6218
2019-01-14 16:16:30 +00:00
dan f8a488bb6b Fix a problem causing a crash if an fts5vocab table was created to query an
fts3/4 FTS index.

FossilOrigin-Name: 9cd64ce453e4435d80117b8610c22a0a4b53cd6e84b39815e70e684f6b0295c8
2019-01-14 15:35:15 +00:00
dan 94ec92a1f7 Fix a problem with querying a corrupt fts3 database.
FossilOrigin-Name: 65e50706a017751d72d0f9c7f575955194977decd0acf13aaca90c3cb925f20e
2019-01-14 15:09:00 +00:00
drh 4067ce7d54 When parsing a corrupt record using sqlite3VdbeRecordUnpack(), make sure
that the resulting UnpackedRecord object is completely initialized, to avoid
(harmless) MSAN warnings.

FossilOrigin-Name: ddc3697efd61830fad55c6bf7f9115f4a7f53e08838eba5a82e1406c7a721665
2019-01-14 13:32:15 +00:00
dan 68c1f9ce9a Have fts3 ignore empty sets of parenthesis if built with
SQLITE_ENABLE_FTS3_PARENTHESIS.

FossilOrigin-Name: c93c6b45a317c40eb5c0abb6620d21f5821a601632c791e11e5ce62e039eccda
2019-01-14 11:56:13 +00:00
drh d12db3dabb Avoid reading off the front of a page buffer when balancing a corrupt
btree page.

FossilOrigin-Name: cb50509020d952fa9efed8df7fa08b07b71ae9bdbdefea216b6e660863291039
2019-01-14 05:48:10 +00:00
drh b10a50e7f8 In dbfuzz2, avoid using a malloc in the LLVMFuzzerInitialize() initializer
routine, so that no memory leaks are reported.  Also, show the version of
SQLite being used when the -v option is on.

FossilOrigin-Name: 824f93246988ffa213bbd41a7de08886999b1a8ae00fdf6b9767acb6e3ec6a1f
2019-01-13 20:23:34 +00:00
drh f202c6cdcf Relax the minimum size database file constraint on the dbtotxt utility program.
FossilOrigin-Name: 97e723d746eeb2159f5bf1701532271ac6a4620879c82d496f4499c178b64479
2019-01-13 20:17:52 +00:00
drh 0f1bf4c1ac Improved detection of database corruption while balancing pages from an
auto_vacuum database with overflow pages.  Test cases in TH3.

FossilOrigin-Name: 35f04235c477501390acea126d07a730d81d03cdf7abcd82d861e397b3f75b0f
2019-01-13 20:17:21 +00:00
drh a1bd5c6aae Move a local variable declaration into the outermost scope in which it
is used. This fixes an ASAN warning.

FossilOrigin-Name: ac3b6021d9437ab1c027850d321f0a3e575b008763d8d515e2347f7d4e7c294b
2019-01-13 00:58:57 +00:00
drh a79bcf358b Prevent unsigned 32-bit integer overflow from leading to a buffer overread
inside of an assert().  The problem fixed here is no reachable in production
code.

FossilOrigin-Name: 0f850a25d67a752fe1e9059c0c3f78e00c222113e556a7605fd3c50817b573cb
2019-01-12 21:30:26 +00:00
dan 951d165125 Fix another problem with handling corrupt records in fts5_decode().
FossilOrigin-Name: 726e398b9ddc15ea1b67c40e2a12ddf5d04428a866699588c5fa1af75af846e1
2019-01-12 20:55:36 +00:00
drh 6214d93993 Fix an off-by-one error on a Goto in the code generator, that only
causes problems for a REPLACE on an INTEGER PRIMARY KEY in non-debug
builds.  Test case in TH3.

FossilOrigin-Name: e35eb8776ed539afe1d5db099470ab1124d8dd2db73ee5db7c811f8df9a9576e
2019-01-12 16:19:23 +00:00
dan b4439eef10 Fix a problem with corrupt database handling in the fts3 matchinfo() function.
FossilOrigin-Name: 703646b1b5c84d550fe0d74e399c0eeb729da1d263e4693320f69e6509678985
2019-01-12 14:58:35 +00:00
drh 5d4589014a Improved detection of shadow table corruption in the fts5_decode() SQL function.
FossilOrigin-Name: b74e5f3f3057ee7a98ebcb14ca0751048eacbec8fca3e11e241883029a57ecdf
2019-01-12 00:45:20 +00:00
drh 3e534eac19 Improved shadow table corruption detection in the matchinfo() function of FTS3.
FossilOrigin-Name: 567be3bb1e8b6477f3bf1c7b4cd6ec066fba69d0dcf8785632e244ce25db639f
2019-01-12 00:12:33 +00:00
drh a2dc7494ef Indicate that the database may be corrupt in the fts3corrupt4.test test script.
FossilOrigin-Name: 473626d5579dd19023abccaf7c1822ac0c883a0b98904837ea096fa16e4f41c4
2019-01-12 00:07:48 +00:00
drh 73bce66701 Use 64-bit APIs in the fileio.c extension.
FossilOrigin-Name: b49d56a0faf012978c50fb8662125ea21bdf5054fddf5975644cbc941c153e70
2019-01-11 23:08:56 +00:00
dan 90294961da Fix a segfault in fts3 prompted by a corrupted database.
FossilOrigin-Name: 2d7b1d1d41ff69d5465fcb861420816ecb066c25a9015eefdab5fae15a2e1c9f
2019-01-11 21:34:25 +00:00
dan 0ad63e5e0c Fix another problem with corrupt databases in fts5.
FossilOrigin-Name: 9bf811ea89a133d481a86407683a7518e909eccb7aa3aa02f7932bdb33387572
2019-01-11 19:27:55 +00:00
dan e6370e9c29 Fix a problem handling a negative value in the "number-of-pages" database
header field. Also a problem with running "REINDEX tbl" against a virtual
table for which the SQL passed to sqlite3_declare_vtab() contains PRIMARY KEY
or UNIQUE constraints.

FossilOrigin-Name: 556dd8922f65af93084ee725c638b8dc696b611dd508c212a3b507d6ca474031
2019-01-11 17:41:23 +00:00
drh 1735f91df4 Improved detection and reporting of errors in the readfile() extension SQL
function.

FossilOrigin-Name: d2f0b5a483869d39f5c5814c9d6df3d3b8a46d582b4dcf0cf11e23b707c4213e
2019-01-11 17:20:25 +00:00
drh 2bd207ff6d Omit errors about missing SAVEPOINTs when aborting the .archive command
in the CLI.

FossilOrigin-Name: 2a47387ba6aa3c294607b7641aa1c4cf70a7b27a861e1098c2f79a38e5b7036a
2019-01-11 17:19:59 +00:00
drh 2a58dbde30 Improved detection of cell corruption in sqlite3VdbeRecordCompareWithSkip().
FossilOrigin-Name: fa47f4c6589c431cf678560ac33dea6b695052012bea2096b2c92869ed51c688
2019-01-11 16:44:16 +00:00
drh f10ce63651 Fix PRAGMA integrity_check so that it does not cancel the PRAGMA vdbe_debug
setting.

FossilOrigin-Name: aaa3a19f8cf5ba7003634e4610abc7832354af91d7c7f65469218678f66bcd46
2019-01-11 14:46:44 +00:00
drh 1972c8cf07 Add the --vdbe-debug command-line option to dbfuzz2.
FossilOrigin-Name: 599b4df43c64ce295517c804b6bb4c3ab77d77e0ba585dc0657274f55489a3b1
2019-01-11 14:38:47 +00:00
drh 26391eeefe Add the "dbfuzz2" target to main.mk. Remove an unused local variable
from dbfuzz2.c.

FossilOrigin-Name: 05c7609cfd02f49114876267d7090f4e0ea2467f3aa7c65019c5986ec8f60a87
2019-01-11 14:22:33 +00:00
drh 51d35b0fa9 The keywords TRUE and FALSE should only act as boolean literal values if
unquoted.

FossilOrigin-Name: 5547f39de993c708f72301ef25df190a2f007e0c4253799bdd9e86bb1ae41777
2019-01-11 13:32:23 +00:00
drh e65b9c6a5e Separate makefile targets for "dbfuzz2", "dbfuzz2-asan", and "dbfuzz2-msan".
FossilOrigin-Name: ea119641a7edcd0e1ec14371d93e35f860971888bd98cb0019253358a2ef123b
2019-01-11 13:03:06 +00:00
dan 6ca98ad6b1 Fix a memory leak in fts5 that could occur if scalar function fts5_decode()
was passed a corrupt record.

FossilOrigin-Name: 240f1c0c92cad8a1c19438b38489aedb831f62a4603c53f22367e876d8f644ff
2019-01-10 19:26:52 +00:00
dan f7d687c9d3 Fix a memory leak in fts5.
FossilOrigin-Name: ff3b011f17f4f02e486f3c8de607f62eddf3b86562e2df82dba57ea166994b65
2019-01-10 18:35:09 +00:00
dan 25e3073741 Avoid use-after-free and double-free errors that could occur if an fts5 table
is modified in certain ways while there are active cursors.

FossilOrigin-Name: 3291b2a6fe6f38ae91b933e5cd2bf7d97432374b4fb1fccd92b4bd759b02ee06
2019-01-10 17:08:20 +00:00
dan c80864d77a Fix further problems with fts5 handling corrupt databases.
FossilOrigin-Name: 83c467d7af63bd2e7800aff4fe9b09dbd75557460b75a9e07205dfae7e28312c
2019-01-10 15:17:32 +00:00
drh 69ab18d213 More aggressive early detection of orphaned and malformed autoindexes when
parsing the schema.

FossilOrigin-Name: 10f9e39d6ed2413fa9abc6c82da3ed48f32a42b6190b6219fca7faf850d05113
2019-01-10 14:33:15 +00:00
drh 5f913ecb62 Use the new SQLITE_IDXTYPE_IPK values (3) on Index.idxType to indicate the
fake INTEGER PRIMARY KEY index used during query planning.

FossilOrigin-Name: e22d2f905fe840bea51b536ebedc9b637190ea0a37f16559668d99a61e971411
2019-01-10 13:56:08 +00:00
drh c49d43a787 Fix the fts3DecodeIntArray() function so that it will not read off the end
of the buffer it is handed.  Any unread integers are set to zero.

FossilOrigin-Name: 666cf8f6b39ae1f72e82b45e9cacba23caf61370ca0c695b3b14452accbb1a0d
2019-01-10 01:12:43 +00:00
dan a47e45f734 Fix an out-of-bounds read in SQL function fts5_decode() that could occur if it
was passed a corrupt record.

FossilOrigin-Name: 931278b257b12ac14fc8fbc82c6dc88ce4ac4b8e0d668543e68f0289d825daa1
2019-01-09 21:12:23 +00:00
drh 1757fed87f Adjustments to the page cache to try to avoid harmless TSAN warnings.
FossilOrigin-Name: 383437be276719ac1c72688ae81017c63907ac561f2ffb8e42c43b012248f294
2019-01-09 14:49:58 +00:00
drh 8eaf565feb Improved database corruption detection in the dbstat virtual table.
FossilOrigin-Name: fc5ecc88f8a0855ba90039177ee284721b2035e4de56a1024e323216f011f0af
2019-01-09 11:19:41 +00:00
drh 3e08ba4521 Small simplification to the dbstat virtual table.
FossilOrigin-Name: 9d4c156fa26f80bb8f88b6ad8f24520a15af296de9c110604f6bd42c257455a0
2019-01-09 11:06:03 +00:00
drh 885eeb676b Enhance the ALTER TABLE RENAME COLUMN feature so that it works on tables
that have redundant UNIQUE and/or PRIMARY KEY constraints.
Fix for ticket [bc8d94f0fbd633fd9a051e3]

FossilOrigin-Name: f09aa3248e2b4a32ff5b5d37084cb2a27445322cb06a3354cef723f4f0b2cd34
2019-01-09 02:02:24 +00:00
drh 2d77d80a65 Use 64-bit math to compute the sizes of memory allocations in extensions.
FossilOrigin-Name: ca67f2ec0e294384c397db438605df1b47aae5f348a8de94f97286997625d169
2019-01-08 20:02:48 +00:00
drh c930b405f0 Performance improvement on the instr() function, especially for large
haystacks.

FossilOrigin-Name: ce51f1a2b6a1789a5876e01cf829e45d84f3851d135a2fa5c44a56f948673a60
2019-01-08 15:18:24 +00:00
drh c0f162020e Fix a possible memory leak when trying to UPDATE a corrupt RTREE index.
FossilOrigin-Name: 63eb803dbc27077007dbee8def659d1523724eb73f1def1cdb68027e5c20843a
2019-01-08 14:28:02 +00:00
dan 174c21ff06 Fix further problems with fts5 and corrupt databases causing integer overflow.
FossilOrigin-Name: 673a7dd698eca05bb2909fa01f962a0667361732a6d0e61cf7780ead4a07c967
2019-01-08 08:02:12 +00:00
dan d9d7d253fc Fix another potential buffer overread in fts5.
FossilOrigin-Name: d0e943d9574c7cab1af4a0fe753a0b5f91ea0e884b91a85b13239144b71f067c
2019-01-07 16:52:00 +00:00
dan 418454c63f For SQLITE_ENABLE_PREUPDATE_HOOK builds, disable the optimization for a
REPLACE command on a WITHOUT ROWID table with no indexes, triggers or foreign
key constraints that causes SQLite to clobber any existing row without
separately checking for it. This optimization causes SQLite to omit the
expected pre-update-hook callbacks.

FossilOrigin-Name: 6281ef974c0ac7a7133c9e1e04c09fdbd627c019c6ff3227293548caf8283864
2019-01-07 15:57:35 +00:00
drh dcc2700d7e The page size becomes fixed as soon as page1 from a non-empty database file
is read.

FossilOrigin-Name: 6064584d578f0ac7aba3f67912a5d9eb1a3c6001469f6b9becbe68871131f887
2019-01-06 02:06:31 +00:00
drh a8e057618a Add the exprNodeCopy() routine that will safely memcpy() an Expr node that
might be a size-reduced node.

FossilOrigin-Name: a874c649960ba2e2b2fd380d08c02a45884a1060d3922be8847729008ca6766e
2019-01-05 21:56:12 +00:00
drh 6b86e51eea If the OP_ParseSchema opcode with a non-NULL P4 operand does not parse any
rows out of the sqlite_master table, that indicates that the sqlite_master
table is corrupt, so raise an SQLITE_CORRUPT error.

FossilOrigin-Name: 598d7358e7329f0de6e3defc217665909e46874258ac29592ee2fd53e6411cda
2019-01-05 21:09:37 +00:00
dan c210c08891 Fix two more problems with corrupt database handling in fts5.
FossilOrigin-Name: 444c7c99beb9f8b82963e9784aa2be54124c7011f4771122b4f608c02aa26408
2019-01-05 07:17:56 +00:00
drh b042d92128 Give a meaningful error on an attempt to use UPSERT on a virtual table,
rather than simply not working.

FossilOrigin-Name: fa98748f956cff95fcfda3a513cea4df27aa573ae795a6855c40bfeca661d0b2
2019-01-04 23:39:37 +00:00
drh f25cc4f3c5 If the ".open" command fails in the CLI, reopen to :memory: so that at least
some database is available for subsequent commands.

FossilOrigin-Name: d7f55c62c3fa053b9b930a044b60076a8278cbf679d8e5116b95f2ff19247f6b
2019-01-04 14:29:21 +00:00
drh 48cd0f28c5 Remove debugging pragmas accidently left in by a prior change.
FossilOrigin-Name: 26275fc7e89eb2542a65d01fd271cef016a4a1815bc3845c599cf2f4fbf7513d
2019-01-04 12:46:01 +00:00
drh dfe3b58315 Fix a typo in a comment used to generate documentation. No functional changes.
FossilOrigin-Name: ccc4f7424bc8f37c168333091dd9e3d6f80ccff9e2b06f182df65be59a7e3349
2019-01-04 12:35:50 +00:00
dan 2f36262dbf Fix another fts5 assert() that may fail if the database is corrupt.
FossilOrigin-Name: 0888fc2e881d56ccd5222383d1a08cdf16fbd15c40da7ebfc14346be69ffb26a
2019-01-04 11:20:14 +00:00
dan e9ad07c0a3 Fix some problems with sqlite3_interrupt() handling in fts5.
FossilOrigin-Name: c0eb839a3c23612b93002d2e1fbc41bf5db140775267989f85db52146144750b
2019-01-03 19:12:21 +00:00
drh 1baae57a72 Fix the csv01.test module so that it works on systems with \r\n line endings.
FossilOrigin-Name: 36eaf5a5e51b20699328aae67c2bfd325f81bea342e2b167fddd859a50a26e28
2019-01-03 16:03:48 +00:00
drh 94e02d9c2c Fix the shmlock.test script so that it works with the Windows restriction
that UnlockFile must exactly correspond to a prior LockFile.

FossilOrigin-Name: df939c89fa90b7f9ccf961027ca4eca4f987c49eabf530b5719a83e5ab0d346d
2019-01-03 16:00:23 +00:00
drh 20c0082371 Fix a harmless compiler warning in the CSV extension.
FossilOrigin-Name: fbcd72565f4425016cebbbf5dfd6aa510234cfb31c785cf364f04fff444aacae
2019-01-03 15:22:33 +00:00
dan 0d756cc83a Fix a problem with the second and subsequent sqlite3rbu_savestate() calls made
on an RBU vacuum handle.

FossilOrigin-Name: bef216dfa1456a787e3d9c74936ee1c6600827d4e252bd13e7a93046ce07469f
2019-01-03 15:17:01 +00:00
drh 232f278084 Fix the geopoly_svg() function so that it returns NULL when given zero
arguments.

FossilOrigin-Name: 120cb1768338eb86412fb69d4c7677247775bb37875ab3a98766cffd535f04cf
2019-01-03 00:44:03 +00:00
drh 8fc4a11c94 Fix harmless compiler warnings in the unicode2 logic of FTS3 and FTS5.
FossilOrigin-Name: 703029ac6d24860230a8c30fcbf5e7e1da619e84f1cc9b9e65ebc74879a184d2
2019-01-02 23:49:47 +00:00
dan ca076bf26e Add another test case to vacuum-into.test.
FossilOrigin-Name: 0465d2fc0d3f8beaa1b6b0bd7bd51d69a524f30d889c9402e7d02cc06164a310
2019-01-02 16:01:59 +00:00
dan 992e927281 Add test cases for commit [6c6fb1c6].
FossilOrigin-Name: 3961995cb56b43f1753c53fc869edf336f1c17ec994d67dc74e44e8e02493894
2019-01-02 15:27:27 +00:00
drh ee751fab4c Raise an error if the argument to VACUUM INTO is an identifier.
FossilOrigin-Name: 6c6fb1c6ea452c70b56fd4ac796affebee21512adba0455ae81c291b715f544f
2019-01-02 14:34:46 +00:00
dan 9b0da8319c Fix another fts5 problem caused by a corrupt database.
FossilOrigin-Name: 911342f7512145a8a189bb0ec59e70e4c9ddc9f20f3e84816ab25139ead5dc45
2019-01-01 19:17:42 +00:00
dan 97c8cb3ed8 Ensure that when a new cursor is opened by OP_OpenDup, any existing cursor
with the same id opened by a previous OP_OpenDup is closed first.

FossilOrigin-Name: 5c188361a91407805c0feb4bf6d3214522ce3e55013efcf63a4613ecd416bcbc
2019-01-01 18:00:17 +00:00
dan fff1dc8e05 Fix another case in fts5 where a corrupt database could cause a buffer
overread.

FossilOrigin-Name: f7e6cdc5625664f449d0edbe39af2d45910c4137bfd856ae1f770dd826c138ff
2019-01-01 13:59:34 +00:00
drh f9231c34eb Fix harmless compiler warnings.
FossilOrigin-Name: b57c545a384ab5d62becf3164945b32b1e108b2fb4c8dbd939a1706c2079e18b
2018-12-31 21:43:55 +00:00
drh f01dae1f32 Additional steps to help ensure that scalar subqueries are only evaluated
once even if they are used in multiple places within the query.  This fixes
a performance regression reported on the mailing list and caused by
check-in [531eca6104e41e43] which was a fix for ticket
[787fa716be3a7f650c]. Think of this check-in as an improved fix for
that ticket.

FossilOrigin-Name: e130319317e761193890ef75787a3c114b61166f518df019697be8e2c820ec54
2018-12-31 20:39:37 +00:00
drh d471bcb396 Remove an optimization that can no longer occur, being superceded by the
subquery-reuse optimization.  Put an assert in place of the optimization
to detect if the need for this optimization ever returns.

FossilOrigin-Name: 4fcdc7a2939457e51aab37cab168677cd7f464a9a0aff4f8981e864a30828b3b
2018-12-31 20:13:12 +00:00
drh 0de6efe59e Merge enhancements and bug fixes from trunk.
FossilOrigin-Name: 9fb646f29c05bca5f677a2c7c4f45c36bfe0a0c6a88cb7968b4a0459bdd63bb2
2018-12-31 18:30:41 +00:00
drh d0fb7960ce Small changes to the OP_OpenEphemeral opcode to improve testability.
FossilOrigin-Name: f856676c8438dbf52d299e78f6dd6148d929755dc05cdcabafd17d9a86439435
2018-12-31 17:58:05 +00:00
drh 4afdfa195b Fix the OP_OpenEphemeral opcode in the bytecode engine so that if it is called
a second or subsequent time, it merely clears the existing table rather than
creating a new one.  Proposed fix for ticket [d0866b26f83e9c55e30de0821f5d].

FossilOrigin-Name: 4678cb1044f0b4dc813e48f3bd0f85240a66e2ecf8763280d66726cc031c93a7
2018-12-31 16:36:42 +00:00
drh d1d158bf5a Additional small performance increase and size reduction to the
sqlite3VdbeMakeLabel() mechanism.

FossilOrigin-Name: 1bdee199a71e0a6c247b85e72de9e3a3099b7179c33288735721facef3b96459
2018-12-29 14:23:22 +00:00
drh ec4ccdbcb1 A new implementation of sqlite3VdbeMakeLabel() is faster and makes fewer
memory allocations by deferring memory allocation until 
sqlite3VdbeResolveLabel() is called, at which point the code generator has
a better idea of how big the relocation table needs to be.
The sqlite3VdbeMakeLabel() routine now takes a Parse* parameter instead of
Vdbe*.

FossilOrigin-Name: 4a0929ac76d8aa5dd65eac3b83d6bbf41e505e01d175ca0fb2b19ba02d439415
2018-12-29 02:26:59 +00:00
drh 01e92df41e Merge performance enhancements from trunk.
FossilOrigin-Name: 0f1b9ff9e1e6f13e03045fcb7d0907227085054f9eb0b0b8471fb26b0094b13a
2018-12-28 21:32:35 +00:00
drh 81f9159b5e Faster allocation of new sqlite3_stmt objects.
FossilOrigin-Name: 891f1f72187f0f9ec0d24fda98cc08be3ae3c3ff8b27c4e409ee7135c3106398
2018-12-28 20:48:07 +00:00
drh b6991796b4 Move the nOpAlloc field from Parse into Vdbe to avoid an extra pointer
deference on the fast path in sqlite3VdbeAddOp3().

FossilOrigin-Name: 8f10efc29dea7b816b1ba401726c268950d6671d890f686911269082a241d8d9
2018-12-28 20:14:03 +00:00
drh 64919e9b00 Merge patches and enhancements from trunk.
FossilOrigin-Name: da53f3d3ff26cc32d3a5ac788b6785baa3d1688e50d9354025a3130dc7e71a38
2018-12-28 19:23:20 +00:00
dan 4177c8a2b7 Fix another problem with loading the structure record from a corrupt fts5
database.

FossilOrigin-Name: c4d44542d259bbec11aea60ae94fcb4acd53e97e125723cae078cf0f8873f8ef
2018-12-28 18:09:45 +00:00
dan 1d4b16405b Fix a problem causing the sqlite_master entry corresponding to a virtual table
to be removed by a DROP TABLE even if the call to the vtabs xDestroy() method
failed.

FossilOrigin-Name: 0140f6dbfbea93eadcd7f727d84064a0c0d1f0806dbe3e5ef1017da603157e3b
2018-12-28 17:45:08 +00:00
dan eefc72d12f Avoid an undefined left-shift operation in fts5 caused by malformed utf-8
text.

FossilOrigin-Name: c3a3a11194586bef80a9d7ca54caae8af30d4e7b464b8bb3d257ba2d2ec4791f
2018-12-28 14:33:55 +00:00
dan 666636b6de Fix a buffer overwrite in fts5 triggered by a corrupt database.
FossilOrigin-Name: a385298df264dbfa6765f63ad8708f74bc8e8a1404239c1049890b39a1bda888
2018-12-28 13:57:30 +00:00
dan b163b57212 Fix problems in fts5 found by ASAN.
FossilOrigin-Name: c564bf870106faef297594a51995619c80311d06bd5f8a0c7644f666f22ba576
2018-12-28 07:37:22 +00:00
dan 593c716781 Fix another problem with corrupt database handling in fts5.
FossilOrigin-Name: fb0d7fba07865ff557bfcdacfda7b625d099ac8b4dcbe0c08cd2d4b84a068bb9
2018-12-27 20:12:02 +00:00
drh aa243aa7cd Modify the btree02.test module so that it does not depend on whether TCL
interprets a value as a string or as an integer.

FossilOrigin-Name: d9e4f9574659c6285deba3dca68eca9989e615971cea3a901ffcda12fb4ee36f
2018-12-27 16:55:01 +00:00
dan e80834f6ff Fix another problem in fts5 caused by a corrupt schema record.
FossilOrigin-Name: ff45f9dd69fe1e1c7875e5bb73ac3dde2a31746475d3765cda9233f8e06e26ca
2018-12-27 15:36:16 +00:00
drh 57e141bc28 Fix the filename normalization in the dbtotxt utility program.
FossilOrigin-Name: 29a00a05dd40ff59be340969e1aca4fee41e092f2faa1cea85a3448265a83c2c
2018-12-27 13:52:45 +00:00
dan cd80dc3667 Fix a null-pointer dereference that could occur in fts5 with a corrupt
database.

FossilOrigin-Name: b0a49d5e6df116bb5eacb60a0bb0f482760aec38bd417d4250d9e57d43bdbb13
2018-12-27 07:46:37 +00:00
drh bdefaf08ee Fix a problem in which nested CTEs with the same table name trick the
code generator into thinking they are the same CTE, which then tries to
use the manifest them both into the same transient table.

FossilOrigin-Name: 202dd033019dd27428e3cc5f6e164c95b37efe39e2753515112b201ddefca67b
2018-12-27 02:16:01 +00:00
drh 7eb2c9176a In the treeview debugging output,
provide additional details for the Table object
associated with each FROM clause term.

FossilOrigin-Name: 11d4682d2eec133ccca99ca9cf2620cd249b4afe55918f3ebf93b454431f9c55
2018-12-27 00:30:42 +00:00
dan f6febee0e2 Update the coverage-wal permutation to cover branches enabled by
SQLITE_ENABLE_SNAPSHOT.

FossilOrigin-Name: 6821c61f1d71be2be7f867e59fd94582a1eaf45a4d1fb88be995807a77cc22ea
2018-12-26 18:34:56 +00:00
dan 89dec01e48 Add a few more test cases to walvfs.test.
FossilOrigin-Name: 14a64df36efe0dc36795311d58385f9c65dc465b214059e07c2ee6b95ea99c87
2018-12-26 17:49:57 +00:00
dan 0f55a571fc Avoid an "unitialized value read" problem in fts5 that can occur with a
corrupt database.

FossilOrigin-Name: 6cae81cd1ffb0180e0260d5ba921502c7dee2f54637bff3558a4d1cb5dfd3f32
2018-12-26 16:57:47 +00:00
dan c2909bf8ac Fix a problem with handling corrupt databases in the fts5 integrity-check
function.

FossilOrigin-Name: 9bad745d373f4686a2726c3f77a2ccad60e7181645d7ed483a2e43075a4ef30c
2018-12-26 16:04:54 +00:00
dan d8f3b4c320 Fix a problem with corrupt fts3 database detection introduced by [95a9a39f].
FossilOrigin-Name: c80bb15b44e9b6a3c0c5a49d5e93e66376c3520ecefc1db7425c8a7e09d3eade
2018-12-26 14:15:09 +00:00
drh 8625221444 Fix a problem with the CSV extension when it uses the "header" option on
a real file.

FossilOrigin-Name: 7acaed08f946633fca3ab8434dd6349ea6f1bac4fd9ec21f476db013ee06de30
2018-12-26 12:50:47 +00:00
drh e4c26c41b4 Fix a typo in a comment that is used to generate session documentation.
FossilOrigin-Name: a1f50d57ce76f6c08a0ddbdd3c3fe2732d0e57dda14cb9aa3da00a14ceb4bc44
2018-12-25 11:17:50 +00:00
drh 47df8a2c40 Increase the number of parameters to sqlite3WhereCodeOneLoopStart() to
encourage the compiler to inline that routine within sqlite3WhereBegin().
This gives a performance improvement.

FossilOrigin-Name: 3c2ad0e915e835b1cb2962879beff50b2745d0cefe1cfc89ef90b7879c139ce6
2018-12-25 00:15:37 +00:00
drh bd462bcc10 Improvements to EXPLAIN QUERY PLAN formatting. The MULTI-INDEX OR now shows
a separate "INDEX" subtree for each index.  SCALAR SUBQUERY entries provide
a subquery number that is related back to the .selecttrace output.

FossilOrigin-Name: 7153552bac51295c56a1c42ca79d57195851e232509f9e9610375692f48c7e86
2018-12-24 20:21:06 +00:00
dan 92107a38dc Add a few more test cases to walfault2.test and walvfs.test.
FossilOrigin-Name: 3873941c4fb9aa2d0de1129722c5fcdf2be1ea261677d4841ed99f896c778459
2018-12-24 20:00:27 +00:00
dan 1ab76166e3 Change another fts5 assert() that may fail with a corrupt database to an
assert_nc().

FossilOrigin-Name: d9653380c455b4bf6c371540d677cbde6d17664c58662b5cc9a12929f46192dd
2018-12-24 19:59:37 +00:00
dan 76e4990b25 Add test cases to test file walvfs.test.
FossilOrigin-Name: d697f6f3ca47350dad30feb529914fc5254fa662ece783408eea963d912918c1
2018-12-24 18:51:13 +00:00
drh c310c53e01 Always include OP_Explain opcodes in the bytecode when SQLITE_DEBUG is enabled.
FossilOrigin-Name: d8c1235c02b745138ac2b12e8bbb00dda4cac321176be92a2fa9547be029b3d0
2018-12-24 18:10:39 +00:00
dan 94e95ea46e Copy some extra test infrastructure from the mutexfree-shmlock branch to trunk.
FossilOrigin-Name: 883337ffdb434b6856ceaada121c0be67e2fdec7b447675f45e85568ef28d7d9
2018-12-24 15:22:47 +00:00
drh a599e150ca Restore a line of code that was previously commented out for debugging.
FossilOrigin-Name: e53781f5bdf5c7b7d91ffe76565ea2fe5d1b3a9b162b3a88a7017bbe785d4c72
2018-12-24 14:30:11 +00:00
dan 29e9af8848 Change the way a comparison used to detect corrupt databases in fts3 is done
to avoid potential pointer overflow in 32-bit builds.

FossilOrigin-Name: 95a9a39ff784b960b62dd6298e722a620ba3f9c8b76839a49bbef35d7bc84a8e
2018-12-24 13:34:36 +00:00
drh 5198ff5767 Do not generate subroutines for non-static SELECT and EXISTS expressions.
Fix up some test cases to account for the minor changes in EXPLAIN QUERY PLAN
output.

FossilOrigin-Name: 06de44ec9e173992ca9afb89dd2b4e40d2a7e35512c7959603cdceb606f5dfbd
2018-12-24 12:09:47 +00:00
drh efb699fc7c Prevent the use of subroutines to implement the RHS of IN operators within
CHECK constraints.

FossilOrigin-Name: 6b24d3fb94e787d25e49501714780dfb0c0c99077102056aa68445f4808cdd57
2018-12-24 11:55:44 +00:00
drh 2c04131ca7 Experimental code that tries to put the computation of subqueries inside a
subroutine, and reuse that subroutine if the same subquery is evaluated more
than once.  Current code does not work for CHECK constraints.

FossilOrigin-Name: 6c44838adbe5dc482bc010e91a6dd7a0f777c989f443dd600740d2c783208e0d
2018-12-24 02:34:49 +00:00
drh 85bcdce270 Split the code generation for the RHS of IN operators and for SELECT and
EXISTS expressions into two separate subroutines, because there is now little
commonality between those to functions. This is intended to help make the
code easier to read and maintain.

FossilOrigin-Name: 2b6494b1509f0d0189f98aa34c990eee99c775ff57826e79b2c5b0a12b4c97ad
2018-12-23 21:27:29 +00:00
dan 8d69a58119 Improve the coverage of wal.c provided by the "coverage-wal" test permutation.
FossilOrigin-Name: 6231485114eb07b258cd0e6e163ca05f7e9cf5664e071808fcb1329b33e4c4f5
2018-12-22 20:32:28 +00:00
dan 6a509d56bc Catch another case of a corrupted structure record in fts5.
FossilOrigin-Name: fb17fea4b9779fbd3adb6ff9500da83a6ca4fa7cba379aa70074e4328814a7f2
2018-12-22 19:54:17 +00:00
dan 862faf28bb Change a faulty assert() in fts5 that could fail on a corrupt db to an if() statement.
FossilOrigin-Name: 1daaba9fb46706af8ed0669a661c304df999a69cf639d29d93208f422c515d8c
2018-12-22 19:09:46 +00:00
drh 11d07ed643 Fix one more instance of excess whitespace in test result strings.
FossilOrigin-Name: c064964deb0b7220ba784f07ca9c603680f3c8bb936d56ab4eca1962beac1359
2018-12-22 16:14:45 +00:00
drh 3a07548b0d Remove unnecessary whitespace from testcase result strings.
FossilOrigin-Name: ad70f03ceda74163903d247a975666b35fae722a27c48dd3efd31c1164b5627e
2018-12-22 15:46:23 +00:00
dan b63d6070ee Fix an assert() in fts5 that could fail with a corrupt database.
FossilOrigin-Name: 83935b950619855fb3bf05486091804ac2a61fb993c6ec826c89f943264fabc3
2018-12-22 15:21:31 +00:00
dan 634ac14488 Fix a "jump or move depends on uninitialized value" valgrind error that could
occur in fts5 when dealing with a corrupt database.

FossilOrigin-Name: 3518c09b944c92974939b1de244401afd34de5d9aa75050e5ad55581a94e1e71
2018-12-22 13:34:52 +00:00
dan fb11bf8c91 Avoid a left-shift of a negative value (undefined behaviour) when dealing with a corrupt database in
fts3.

FossilOrigin-Name: b851d12474035328df8354c7da8d81bc78833c8c704153f9f573c19b47a8487e
2018-12-22 09:39:06 +00:00
dan 583521fbb0 Fix cut-and-paste error in test file fts4umlaut.test.
FossilOrigin-Name: cad5da1bf5f65ad87d97b72e9a84081fde455ba4085e79943fdf6c0144b1ef83
2018-12-22 07:16:42 +00:00
drh 9bfb079409 Do not all REPLACE to sneak a NULL value into a NOT NULL column. Detect that
situation and ABORT instead.  Fix for ticket [e6f1f2e34dceeb1ed61531c7e98].

FossilOrigin-Name: db8d1d12f5c1673404b2afb5426d5ea3afe3b69d01f8f2bc47ffdf70684fdf24
2018-12-22 01:13:25 +00:00
drh a42325e731 The OP_Eq and OP_Ne operators have a special P5 value SQLITE_NOTNULL that
asserts that the values are not null.  Except that is not always true for
a corrupt database.  Adjust the assert() and add a testcase() to make this
point clear.

FossilOrigin-Name: a3fdb2c78d23b94d68dc08126b22d03152ac6068496a42402cdfb336cd4a7e33
2018-12-22 00:34:30 +00:00
drh a86c8ce940 Update the dbtotxt utility program so that it does not output characters that
are special to TCL, thus making the output of dbtotxt easier to insert into
test scripts.

FossilOrigin-Name: 48438bb35b48955a1df83ef90f0ef6c9cfed0b16d2e938f36d74ad9d53b4b5b4
2018-12-21 22:11:37 +00:00
drh cde4bf8ba7 Improved detection of shadow table corruption in RTREE.
FossilOrigin-Name: b39bf4356e6bcf1d8442721d6cbbfe06caba01325104fb469da8fe69e1f623a2
2018-12-21 22:08:59 +00:00
dan 6ba81ef1bf Add new sqlite3_prepare_v3() flag SQLITE_PREPARE_NO_VTAB, for
preparing statements that are not allowed to use any virtual tables.
Use this to prevent circular references in triggers on virtual table
shadow tables from causing resource leaks.

FossilOrigin-Name: da587d18575ac06a6b65fec1d106f0cc65bc10f493ca6c6b99117a2162d15a52
2018-12-21 20:18:06 +00:00
dan deb201b866 Use SQLITE_PREPARE_NO_VTAB in rtree as well.
FossilOrigin-Name: 82a2ae7132964eab0dfad9a8314a399ffd3b72366b35e1767df6452125dd1d80
2018-12-21 19:55:20 +00:00
dan 38e3853240 Add tests for the use of SQLITE_PREPARE_NO_VTAB in fts5.
FossilOrigin-Name: 1999612010e310fc2430d1f00076f69fade0c66d202771dbb0f3d5597ac0a03c
2018-12-21 19:30:18 +00:00
dan 1ea0443c2d Add new sqlite3_prepare_v3() flag SQLITE_PREPARE_NO_VTAB, for preparing
statements that are not allowed to use any virtual tables. Use this to prevent
circular references in triggers on virtual table shadow tables from causing
resource leaks.

FossilOrigin-Name: 25666e3d03950caf753295cdb55df162e07dbcf6840b05875c6e0b127c469ecb
2018-12-21 19:29:11 +00:00
drh afdc9e23fc In FTS3, avoid calling memcpy() with a NULL source pointer, even if the
transfer amount is zero bytes.

FossilOrigin-Name: 1abb83d29a06308c96bea379311b390240347c5f81824749348d18ad75840c96
2018-12-21 18:51:27 +00:00
drh 8bcc686614 The fts4umlaut.test module requires FTS5, so do not try to run it without that
module.

FossilOrigin-Name: dee3ae900129d39d69aff3ec6187376be100803ee6170bbf39529f37b4253260
2018-12-21 18:50:43 +00:00
drh 687e20079c Fix the node hash function in RTREE to ensure that it always returns a
non-negative value.

FossilOrigin-Name: 0bf4c70a6849da74797e8616a4f3730492ad02882ae67a0fe0f3b3cc3f1043b4
2018-12-21 18:17:35 +00:00
drh 273e01b4c6 Fix a potential NULL-pointer deference in RTREE due to corrupt shadow tables.
FossilOrigin-Name: 1fdd3604eef880414682e9e6f74d714520fe1c63f267ec4da752d2dc1da6bf72
2018-12-21 17:51:30 +00:00
drh fb077f3c50 Prevent an infinite loop in rtree that can result from a corrupt shadow table.
FossilOrigin-Name: 085667180b230587abb82abfdd14da8859e23620994d5cf152236b64c756dd04
2018-12-21 16:53:58 +00:00
drh 1429eca9d4 Fix the RTree extension so that it correctly ignores constraints that it
does not understand, even if they are against a dimension column.

FossilOrigin-Name: ed8531e57596f0d5911a05a26d5ae61e1eccfaadee49219d7f6e212cac288238
2018-12-21 15:13:49 +00:00
drh 558ef11ad9 In RTREE, turn an assert() into an if() because the condition can
sometimes be false when dealing with a corrupt database.

FossilOrigin-Name: 99bce4358beb5dbaba47048ee2eec5c376dcd86e5b1462238a37ea4c5f3d77db
2018-12-21 13:30:34 +00:00
dan e1e28ec35c Remove an assert() that could fail on a corrupt db from fts3_write.c.
FossilOrigin-Name: 4cdcda408a4edcd2845584ddef64f0efdd2b4cc030afbc05fc2b8b555c69d3f6
2018-12-21 11:53:43 +00:00
drh 94f4f873b2 Do not set the Cursor.seekOp test variable in the OP_NotExists opcode.
This is a change to test logic only and does not affect deliverable builds.

FossilOrigin-Name: 98f343077887c4d3fc2ca3bbc7f20c80ec37b0e521d70af9c986ab80bb2c7903
2018-12-20 22:08:32 +00:00
dan e46201e264 Fix a bug in the code that detects self-referencing rows as part of foreign
key processing. Fix for [50d2a6c2].

FossilOrigin-Name: 16fff05347f42fe9fa0f3150290b98b59a9bb921e49dc07ca397aa1de7a7e17d
2018-12-20 17:32:33 +00:00
dan 16dd3985f0 Fix a segfault caused by using the RAISE function incorrectly (library now
returns an error instead of crashing).

FossilOrigin-Name: ddf06db702761d663119d508afe21d7dfebe963d576bb42fc2f2024205ab86f8
2018-12-20 15:04:38 +00:00
dan 397a78d4a1 In defensive mode, do not allow shadow tables to be renamed using ALTER TABLE.
FossilOrigin-Name: 23e200da5cfbde0798e67cd9e016e4a1cd73b67981e1af841493fcd123d8f547
2018-12-18 20:31:14 +00:00
mistachkin 99490934ae Move variable declaration to address compilation issue (C89).
FossilOrigin-Name: d64f248da3ce7762fe2c17fbc83f7bea9ffca73723bb3ad0982a85320839da90
2018-12-17 22:19:57 +00:00
dan bef06d2637 Fix errors in comments in fts5.h.
FossilOrigin-Name: 4002790d9418289f3e090c694f651a89d8f523119c8ce2f396999b0387148241
2018-12-15 07:12:34 +00:00
drh 3c2db5def6 Fix harmless compiler warnings.
FossilOrigin-Name: 27221c69901d2b4546167639c4a3c8f54b2e18820f1346870fa26b7c919027db
2018-12-14 18:11:02 +00:00
drh ae10474125 Fix possible integer overflow while running PRAGMA integrity_check on a
database file with a badly corrupted freelist.

FossilOrigin-Name: 395599116d801324f0763e59bc5e2fc8622aa5b7572e0c1c9a982efbb3cc8280
2018-12-14 17:57:01 +00:00
drh d7a5e49840 Back out the expansion of the temporary buffer size from
[32754ca6f86da816] and replace it with an explicit test for buffer
overreads.

FossilOrigin-Name: 8ba3d9f38090c4bbbcffba1930e5c26f69ff61f49b72a4a5a59253d37341380f
2018-12-14 16:20:54 +00:00
drh e7acce66b2 Avoid a buffer overread in ptrmapPutOvflPtr() that can occurs in a
corrupt database file that has large entries and uses autovacuum.

FossilOrigin-Name: f8b781cf41800e9f61a1c5376404a97e76a2bbbcaa17396d42be62f731363947
2018-12-14 16:00:38 +00:00
drh fa94d492c8 Fix a harmless compiler warning in Sessions.
FossilOrigin-Name: fc9791ea987352e3e1322fbb7f833c23b402432af8249f9d397c6f7456788637
2018-12-14 13:47:17 +00:00
drh d6401e869b Expand the size of the temporary page used during btree rebalancing by a
few bytes, to avoid problems with small buffer overreads that can occur
on corrupted database files.

FossilOrigin-Name: 32754ca6f86da8165e274f98f35fc3df3aebd273e9da08387e2d0c3c89abda0f
2018-12-14 13:35:48 +00:00
dan fffaf23013 When saving the position of a cursor at the b-tree layer, allocate a few extra
bytes at the end of the buffer used to save the key. Otherwise, if the key is
corrupt, the code that restores the cursor position may overread the buffer by a
little.

FossilOrigin-Name: 160b1e31c0f27257c06c2987af9ec3a64abfacb2150325b72e8ccd3d217b5baa
2018-12-14 13:18:35 +00:00
drh 5a1ce4369f Fix a problem with bytecode generation when a query involves two or more
indexes on expressions connected by OR.
Ticket [d96eba87698a428c1ddd0790ea04]

FossilOrigin-Name: 7e4ed8b5c2047b69bbb037497111e56e465a4d9f8afca3b337f9ac744471dc4a
2018-12-14 11:16:52 +00:00
dan 7525b87b6c Posible fix for [d96eba87].
FossilOrigin-Name: 89a25abfcd069aebdf817890e5c27f46de3000fb858ae01029e4528f9d677567
2018-12-14 08:40:11 +00:00
drh d8cc8b30b4 Fix a bug in fuzzcheck that cause it to overlook a pointer-map bug that was
trigger by the fuzzcheck test data, and also fix the pointer-map bug.

FossilOrigin-Name: cc42dd15100db28a9796254f69a4e367ea5eae29f546be055017cf3e12aa66ba
2018-12-14 03:16:17 +00:00
drh 203b1ea0f5 Detect when an attempt is made to write to a pointer map page that is also
being used as a btree page and report corruption.

FossilOrigin-Name: 3036fd71ac7063359b04a0ed54a6c63a380eb7ff75cd29ed27486d4259066aee
2018-12-14 03:14:18 +00:00
drh e45985b595 Fix a bug in the custom in-memory VFS used by fuzzcheck. This bug masks
other bugs that should have caused some existing fuzzdata7.db entries to
fail, and so this fix is initially on a branch until those other bugs can
be repaired.

FossilOrigin-Name: e0994e99955cf11f23dba029b5ed7f150f467887558848d5f03510e2fb5855f9
2018-12-14 02:29:56 +00:00
drh f354e77f3d Fix the dbtotxt decoder in the CLI so that it ignores excess bytes.
FossilOrigin-Name: 18740bd448887d618fafee0b5a7c004aa2f2632244f7d29e2428772baa36b828
2018-12-13 22:58:52 +00:00
drh 6301c43f23 dbfuzz2 found a NEVER() that is sometimes true.
FossilOrigin-Name: 1201615cbbd3070158ea5fab3d2c8c95f41b25d6da096a44cb9257a7b7405efc
2018-12-13 21:52:18 +00:00
drh 8061ad8abd Add extra tests for database corruption inside the defragmentPage() routine,
as dbfuzz2 has found ways for corruption to leak into that point.  Add test
cases in fuzzdata7.db.

FossilOrigin-Name: 997b65117f8c12dba5fb85434fde9765cdb0d2a49cc3e31979abba3e21350086
2018-12-13 21:11:22 +00:00
drh 1641f11f4c Fix a problem in sqlite3BtreeDelete() in which deleting an entry from a
corrupt database can leave a btree page with zero cells.

FossilOrigin-Name: 682053d1e603c21b8085c39db618a39b23ec8d2c4d822fd19634db0e03038ea2
2018-12-13 21:05:45 +00:00
drh f7e74904cc Add the "decode_hexdb" TCL command to testfixture. Add the dbfuzz001.test
module to demonstration how to use decode_hexdb to deserialize a dbtotxt
database description for use in a corruption test.

FossilOrigin-Name: 1f583c53f3b7318c69f6e235934d97ef9493278feeab0837217076d7d071c35b
2018-12-13 20:49:43 +00:00
drh 2c8ee026ba Fix the CLI to keep proper track of input line numbers for use in error
messages, even after processing in-line hex database inputs using
".open --hexdb".

FossilOrigin-Name: 7ffa9858162774cba03a565a7b65135d9e8bfea726af1a29de6898f66c4b1261
2018-12-13 18:59:30 +00:00
drh 60379d4243 Fix the CLI so that the ".open --hexdb" command works even if it is contained
in a subscript that is read using ".read".

FossilOrigin-Name: 67a87399b8ad8f1ce3052ee3159906f5c6df3d7b5691b3acac856bd2f1c82088
2018-12-13 18:30:01 +00:00
drh 51caa04836 Merge the dbtotxt enhancement from trunk.
FossilOrigin-Name: b386fce9a23e628dce7362dcca2904b8d0af6da58a6fe6eb7f12f058a8363e49
2018-12-13 15:52:31 +00:00
drh 3374648545 Add the "dbtotxt" utility program and the ability to read "dbtotxt" output
as a deserialized input database in the CLI, using the --hexdb option to
the ".open" command.

FossilOrigin-Name: e3bf1d3ea5f748c5142c2403813fdace5aedc1fc68f0dcd5eae40a2fe763fedb
2018-12-13 15:06:26 +00:00
drh 69a66a7be1 Include OPTS in the build of dbfuzz2.
FossilOrigin-Name: eac9c0c49650b008951318a2225b932709a0a8dffbb01ed57684c40357b2e25c
2018-12-13 12:37:13 +00:00
drh bc1be957c1 Fix the Makefile so that it honors CFLAGS when building sessionfuzz.
FossilOrigin-Name: 54231ac4ca506e6c34c31bc02bb8d3db22f14e1b01679bc70529b165d7dabb83
2018-12-13 12:28:01 +00:00
drh 5881dfea2c New database corruption test cases discovered by dbfuzz2. The new cases
have been added to test/fuzzdata7.db, but have not yet all been fixed,
so tests will not currently pass.

FossilOrigin-Name: b4210d320c6426d2838d4cc08709fdfd015c1c95fcad9a5f9e8fd390c23b9fad
2018-12-13 03:36:13 +00:00
drh cb0e04f929 Fix another problem found by Matthew Denton's new fuzzer.
FossilOrigin-Name: 2b690dbdffe144bd69ca0aa291c230faf3d9d73f7a2985d50f016fe54003f9a9
2018-12-12 21:34:17 +00:00
drh 89b6de0357 Remove an ALWAYS() from a branch that is not always taken. The test case
found by OSSFuzz has been added to TH3.

FossilOrigin-Name: 5c7dab85535ac42c021977dbd4a39cef5a72e3d9dccff1c5ca5570a1780516cd
2018-12-12 20:11:23 +00:00
drh 03c5c21328 OSSFuzz found a case where an assert() inside sqlite3ExprCompare() can be
true.  Test case added to TH3.

FossilOrigin-Name: 23b62fb160d86dc9d9073bcc714601f5b7695f96abd893eafecf4b2e565b87f2
2018-12-12 11:23:40 +00:00
drh cfc078318c Small performance improvement in sqlite3_step().
FossilOrigin-Name: d1db8d5894450b24bb0335983503d9bbf6cc48a0ae4b83291283fb2d32b6b25b
2018-12-11 12:51:46 +00:00
drh 368bfe8b00 Small performance improvement in the sqlite3_bind() family of interfaces.
FossilOrigin-Name: 1dc0c3df32572f09265fc73eeaa0748159e0e9523b9b2d6768b834a29c909968
2018-12-11 12:20:41 +00:00
drh 1a6c2b1d38 Further refinements to the sqlite3_normalized_sql() interface. TH3 now
gives 100% MC/DC on that interface.

FossilOrigin-Name: c96bf6cca220e363b099455ce35195ce7e89d374a52dc787f56e7b11e587bced
2018-12-10 20:01:40 +00:00
drh 21b9225ff5 Refactor the sqlite3_normalized_sql() implementation.
FossilOrigin-Name: 06e955e5d2b857b9ce94a73fb174b620c101bdb160842f9a0e958bdb48e8c987
2018-12-10 18:15:44 +00:00
drh 9042ff214b Fix issues with the new normalizer.
FossilOrigin-Name: 057d7d40c56b7416a59a79cb627b2b3e5837eca2d6dbcb50127baaadf1941f51
2018-12-10 16:49:33 +00:00
drh 643d855da9 Refactor the sqlite3_normalized_sql() implementation. This is a
work-in-progress. There are still issues.

FossilOrigin-Name: a4c890b0af9786295e6df05022009d8946550adb873535c610be805c2b7a4083
2018-12-10 16:00:57 +00:00
dan dc6214ee39 Fix a problem with using "<db>-vacuum" (the default) as the state database
when resuming an RBU vacuum.

FossilOrigin-Name: c878d741733a897d47a1a0b57b454bc9095ce302b48cc01089336d5d20e2a24c
2018-12-10 08:41:32 +00:00
drh fb34559eb1 Add support for the VACUUM INTO command.
FossilOrigin-Name: 77f150b8b46761f4f62f9d8926c10a95a70589a4525393fc16b321bd98c083a7
2018-12-10 01:48:29 +00:00
drh 4d342827d6 Fix the shell1.test test for the new format of the .backup command.
FossilOrigin-Name: 9748d7995bc1dd632d66d2d326048d50e29c6f5e6993d5a6294d14421d2cb72f
2018-12-10 00:41:28 +00:00
drh 2134eb5721 Merge fixes from trunk.
FossilOrigin-Name: ab1e58fac9e3f9d7d90cefb39f8f145d211d38ec0cb393208c4531cc646056c1
2018-12-10 00:40:43 +00:00
drh ce706c2cf3 New test case for ticket [1d958d90596593a77420e59].
FossilOrigin-Name: b7bf3c9832bde26b359f4d58ebcf7788c500586d311387d022192ed65a126252
2018-12-09 18:55:05 +00:00
drh d4a4a36171 Do not use a partial index as a table scan in an IN operator.
Fix for ticket [1d958d90596593a77420e59].

FossilOrigin-Name: 15bc915dd7ae25bfdfbe357c3792db3639799e4d121c6b5b24297af2d6d7129e
2018-12-08 20:30:31 +00:00
drh a50bffb85e Add the --async option to the ".backup" command in the CLI.
FossilOrigin-Name: 7b6a605b1883dfcbe237b0a58f6f0c233a109e88b521c3b3d97198526c8a0317
2018-12-08 01:09:14 +00:00
drh 2f6239ed4e Allow the INTO clause of VACUUM to be a text-valued expression.
FossilOrigin-Name: af172b53b46759f491f522356e14c5e2374d3f25ec70fbc1e100cadded8f9b22
2018-12-08 00:43:08 +00:00
drh 7464f578ed Do not allow VACUUM INTO into a file that already exists.
FossilOrigin-Name: 92f70e0fa3c9de7fde046f11cc0a7c2800511bb5ace8e68c845133931607616e
2018-12-07 23:48:41 +00:00
drh 52993b31e1 Merge the VACUUM simplification from trunk.
FossilOrigin-Name: 93d92a0a5d21a1856316c0205ecaa253691b6e5349b552d43027005676d14820
2018-12-07 20:40:12 +00:00
drh 83da91b7bd Remove a line of code from VACUUM that is no longer needed, due to the
change that allows ATTACH to run within a transaction.

FossilOrigin-Name: a92c398fc5df142ff1459c1be4a6832f2219bc7fabe5789535be3bbd41a4269b
2018-12-07 20:26:29 +00:00
drh b0b7db91b8 Prototype implementation for the VACUUM INTO command.
FossilOrigin-Name: 036e3320a4af36c1311b25b2e504b0079c8b33df8ad7b7e5fddad07150e6f87d
2018-12-07 17:28:28 +00:00
drh 893bd3751b Fix the sqlite3_normalized_sql() interface so that it renders
double-quoted string literals as "?".

FossilOrigin-Name: 0d8e150434bbd179696f1ffe71d1e06cb3d43e6468496c7e481fca8486387bad
2018-12-07 16:32:11 +00:00
drh 62a88294e8 Fix dbfuzz2.c so that it works with -DSQLITE_OMIT_INIT
FossilOrigin-Name: 9ad796a8822f1b7e1e99b73c2cc5be59dbfd85e9c27f3e795c29a2c002c611d1
2018-12-07 03:01:07 +00:00
drh b9a0e668f3 Fix the sqlite3ExprDup() function so that it correctly duplicates the
Window object list on a Select that contains window functions.  Fix
for ticket [f09fcd17810f65f717].

FossilOrigin-Name: db5ed2268eda2e6c1df15cd8df4176463d89103b8fda33ba9a0604f0d92bd4da
2018-12-07 01:56:26 +00:00
drh a37b6a5e31 Performance improvement: Avoid using sqlite3WalkerSelectExpr()
and sqlite3WalkerSelectFrom() twice, so that the compiler will in-line their
implementation.

FossilOrigin-Name: 2b9258b8b0342330ebe8c22b59ec276fd042a05547d15b24fdf29e16280868de
2018-12-06 22:12:18 +00:00
drh a838997544 Fix the sqlite3ExprDup() routine so that it makes complete duplications of
subqueries containing window functions.

FossilOrigin-Name: 940174543e87184a0278fcd02e8a096a11510174d9c1d65d21878819790ddaff
2018-12-06 22:04:19 +00:00
drh bb383df7c6 New test case that still hits an assertion fault, just to prove that the
previous checkin merely made the problem more obscure and did not completely
fix it.

FossilOrigin-Name: a9a3b532643b5f106509bb29c3e6bc9d41ec5b2da5a0cd4067898f376eb626a2
2018-12-06 19:56:20 +00:00
drh 11df7d2839 Simplify the query flattener so that it does not duplicate the WHERE clause
of subquery that is being incorporated into the outer query - copies it
directly.  This is more efficient.  And it also fixes the specific test case
show for ticket [f09fcd17810f65f71789525] but it does not resolve the more
general problem that sqlite3ExprDup() does not correctly duplicate expressions
that contain subqueries with window functions.

FossilOrigin-Name: f1b18d44ff855573542c1947a42d4025dff54cacc13dac14d044521762ea9736
2018-12-06 19:15:36 +00:00
drh d5b44d60c7 When masking bits off of sqlite3.flags, make sure the mask is 64 bits
in size so as not to accidentally mask of high-order bits.

FossilOrigin-Name: 53d3b169d8e1892163526caff2c843302c92e280fdeff6831e23a9bb15b82be3
2018-12-06 17:06:02 +00:00
drh 70d5dfba68 When saving off the value of sqlite3.flags, take care to preserve all 64
bits.

FossilOrigin-Name: 9c6dbcfab5952cf4e54de30cf9cee48f988b91a35dc3f04d64d6d994dd84a076
2018-12-06 16:50:55 +00:00
drh ec8fc62c42 Issue a warning whenever a double-quoted string literal is used.
FossilOrigin-Name: ac9ad5043026b30394812457e1535df2759aea0d4510029561e92e386672796f
2018-12-06 16:11:14 +00:00
drh 3e2d47d49f Invoking the sqlite3_trace() or sqlite3_trace_v2() interfaces cancels
any sqlite3_profile() that is running.

FossilOrigin-Name: ec63d3506bd429560077f82a4c5ed9d189780789fe1c134fff4f3b8733be1a3f
2018-12-06 03:59:25 +00:00
drh fc08a1aef8 Remove the unused pColHash field from the Table object.
FossilOrigin-Name: 3a2c047989facc3461c63a2f9eed412014c951035a80da47c52a70139fb552de
2018-12-06 02:01:17 +00:00
drh 974b24896a Fix a potential NULL pointer dereference that can occur in ALTER TABLE
following an OOM.  Test case in TH3.

FossilOrigin-Name: ea50815bf80ab0d36891518f209acbcd3d6d8d84529741bffd4e841874c78aff
2018-12-06 01:53:12 +00:00
drh 1f169fefca Fix a missing mutex in the sqlite3_normalized_sql() interface when it is
called on a prepared statement that did not previously have a computed
normalization of the input SQL.

FossilOrigin-Name: 1a1a59c6c570879c8f318bbc132103c0285088ba233dd8c32e049b86419347b0
2018-12-06 01:08:58 +00:00
drh 7b278f0c3d Get rid of the hash table used to track IN operators in the
sqlite3_normalized_sql() implementation.  Use simple integer variables
instead.

FossilOrigin-Name: 272dc74fd0304d6a28aaa8798d13e2f950c1a24d92d17519e3c32aef86714586
2018-12-05 23:56:02 +00:00
drh 253a6af532 The sqlite3_normalized_sql() interface should not be transforming quoted
identifier names into wildcards.  Fix this, and at the same time simplify
the code substantially.

FossilOrigin-Name: e8540377ec66fa5f9ae3c93bedb5c094057698199c37fc211f7ea95429e815e4
2018-12-05 23:45:46 +00:00
drh d4a4dd6ebc Fix an imbalanced lock problem in sqlite3Normalize() introduced by the
simplification in [94ea6379178e3ff6a].

FossilOrigin-Name: f69624373e33c4d370a9264a317ffdb0adbce967a950f243de2b41161a8c7ded
2018-12-05 21:55:39 +00:00
drh 8a65380de9 Increase the version number to 3.27.0 for the next development cycle.
FossilOrigin-Name: 8f8d682825d065bcaebda4cba63f8b67789b923d8b62eb7c576a5bc01536f577
2018-12-05 19:42:59 +00:00
drh 19efd0db41 Simplifications to the sqlite3_normalized_sql() implementation.
FossilOrigin-Name: 94ea6379178e3ff6a0d1d5819ca4ac558bdadb1ca8a3637c797079db7dc0cd61
2018-12-05 17:48:57 +00:00
dan ea41251eb0 Ensure that ALTER TABLE modifies table and column names embedded in WITH
clauses that are part of views and triggers.

FossilOrigin-Name: f44bc7a8b3fac82aa5598e9bdaf65ea4dd3c331cf90c1d5ba26ff1698e92c230
2018-12-05 13:49:04 +00:00
drh 707821ff72 Enhance the sqlite3_normalize_sql() interface so that it works even if the
prepared statement was not initially compiled using
SQLITE_PREPARE_NORMALIZED.  Enhance the ".trace" command in the CLI so that
it is able to access the full scope of functionality provided by 
sqlite3_trace_v2() and in particular so that it is able to show normalized
SQL output using the newly enhanced sqlite3_normalize_sql() interface.

FossilOrigin-Name: 7da617e97eb905cb009c47403786682b911e32a630f266e1c53ea72836fc88b5
2018-12-05 13:39:06 +00:00
254 changed files with 64499 additions and 5476 deletions
+6
View File
@@ -0,0 +1,6 @@
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.
+38 -10
View File
@@ -452,6 +452,7 @@ TESTSRC += \
$(TOP)/ext/misc/nextchar.c \
$(TOP)/ext/misc/normalize.c \
$(TOP)/ext/misc/percentile.c \
$(TOP)/ext/misc/prefixes.c \
$(TOP)/ext/misc/regexp.c \
$(TOP)/ext/misc/remember.c \
$(TOP)/ext/misc/series.c \
@@ -588,7 +589,8 @@ FUZZDATA = \
$(TOP)/test/fuzzdata4.db \
$(TOP)/test/fuzzdata5.db \
$(TOP)/test/fuzzdata6.db \
$(TOP)/test/fuzzdata7.db
$(TOP)/test/fuzzdata7.db \
$(TOP)/test/fuzzdata8.db
# Standard options to testfixture
#
@@ -611,6 +613,12 @@ FUZZERSHELL_OPT = -DSQLITE_ENABLE_JSON1
FUZZCHECK_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5 -DSQLITE_OSS_FUZZ
FUZZCHECK_OPT += -DSQLITE_MAX_MEMORY=50000000
FUZZCHECK_OPT += -DSQLITE_PRINTF_PRECISION_LIMIT=1000
FUZZCHECK_OPT += -DSQLITE_ENABLE_DESERIALIZE
FUZZCHECK_OPT += -DSQLITE_ENABLE_FTS4
#FUZZCHECK_OPT += -DSQLITE_ENABLE_FTS5
FUZZCHECK_OPT += -DSQLITE_ENABLE_RTREE
FUZZCHECK_OPT += -DSQLITE_ENABLE_GEOPOLY
FUZZCHECK_OPT += -DSQLITE_ENABLE_DBSTAT_VTAB
FUZZCHECK_SRC = $(TOP)/test/fuzzcheck.c $(TOP)/test/ossfuzz.c
DBFUZZ_OPT =
@@ -669,7 +677,7 @@ ossshell$(TEXE): $(TOP)/test/ossfuzz.c $(TOP)/test/ossshell.c sqlite3.c sqlite3.
$(TOP)/test/ossfuzz.c sqlite3.c $(TLIBS)
sessionfuzz$(TEXE): $(TOP)/test/sessionfuzz.c sqlite3.c sqlite3.h
$(CC) $(CFLAGS) -I. -o $@ $(TOP)/test/sessionfuzz.c $(TLIBS)
$(LTLINK) -o $@ $(TOP)/test/sessionfuzz.c $(TLIBS)
dbfuzz$(TEXE): $(TOP)/test/dbfuzz.c sqlite3.c sqlite3.h
$(LTLINK) -o $@ $(DBFUZZ_OPT) $(TOP)/test/dbfuzz.c sqlite3.c $(TLIBS)
@@ -682,11 +690,26 @@ DBFUZZ2_OPTS = \
-DSQLITE_ENABLE_DBSTAT_VTAB \
-DSQLITE_ENABLE_RTREE \
-DSQLITE_ENABLE_FTS4 \
-DSQLITE_EANBLE_FTS5
-DSQLITE_ENABLE_FTS5
dbfuzz2: $(TOP)/test/dbfuzz2.c sqlite3.c sqlite3.h
clang-6.0 -I. -g -O0 -fsanitize=fuzzer,undefined,address -o dbfuzz2 \
$(DBFUZZ2_OPTS) $(TOP)/test/dbfuzz2.c sqlite3.c
dbfuzz2$(TEXE): $(TOP)/test/dbfuzz2.c sqlite3.c sqlite3.h
$(CC) $(OPT_FEATURE_FLAGS) $(OPTS) -I. -g -O0 \
-DSTANDALONE -o dbfuzz2 \
$(DBFUZZ2_OPTS) $(TOP)/test/dbfuzz2.c sqlite3.c $(TLIBS)
mkdir -p dbfuzz2-dir
cp $(TOP)/test/dbfuzz2-seed* dbfuzz2-dir
dbfuzz2-asan: $(TOP)/test/dbfuzz2.c sqlite3.c sqlite3.h
clang-6.0 $(OPT_FEATURE_FLAGS) $(OPTS) -I. -g -O0 \
-fsanitize=fuzzer,undefined,address -o dbfuzz2-asan \
$(DBFUZZ2_OPTS) $(TOP)/test/dbfuzz2.c sqlite3.c $(TLIBS)
mkdir -p dbfuzz2-dir
cp $(TOP)/test/dbfuzz2-seed* dbfuzz2-dir
dbfuzz2-msan: $(TOP)/test/dbfuzz2.c sqlite3.c sqlite3.h
clang-6.0 $(OPT_FEATURE_FLAGS) $(OPTS) -I. -g -O0 \
-fsanitize=fuzzer,undefined,memory -o dbfuzz2-msan \
$(DBFUZZ2_OPTS) $(TOP)/test/dbfuzz2.c sqlite3.c $(TLIBS)
mkdir -p dbfuzz2-dir
cp $(TOP)/test/dbfuzz2-seed* dbfuzz2-dir
@@ -1052,6 +1075,7 @@ SHELL_SRC = \
$(TOP)/ext/expert/sqlite3expert.c \
$(TOP)/ext/expert/sqlite3expert.h \
$(TOP)/ext/misc/zipfile.c \
$(TOP)/ext/misc/memtrace.c \
$(TOP)/src/test_windirent.c
shell.c: $(SHELL_SRC) $(TOP)/tool/mkshellc.tcl
@@ -1125,10 +1149,10 @@ fts3_write.lo: $(TOP)/ext/fts3/fts3_write.c $(HDR) $(EXTHDR)
rtree.lo: $(TOP)/ext/rtree/rtree.c $(HDR) $(EXTHDR)
$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/rtree/rtree.c
sqlite3session.lo: $(TOP)/ext/userauth/userauth.c $(HDR) $(EXTHDR)
userauth.lo: $(TOP)/ext/userauth/userauth.c $(HDR) $(EXTHDR)
$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/userauth/userauth.c
userauth.lo: $(TOP)/ext/session/sqlite3session.c $(HDR) $(EXTHDR)
sqlite3session.lo: $(TOP)/ext/session/sqlite3session.c $(HDR) $(EXTHDR)
$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/session/sqlite3session.c
json1.lo: $(TOP)/ext/misc/json1.c
@@ -1189,6 +1213,7 @@ TESTFIXTURE_FLAGS += -DSQLITE_SERIES_CONSTRAINT_VERIFY=1
TESTFIXTURE_FLAGS += -DSQLITE_DEFAULT_PAGE_SIZE=1024
TESTFIXTURE_FLAGS += -DSQLITE_ENABLE_STMTVTAB
TESTFIXTURE_FLAGS += -DSQLITE_ENABLE_DBPAGE_VTAB
TESTFIXTURE_FLAGS += -DSQLITE_ENABLE_DESERIALIZE
TESTFIXTURE_SRC0 = $(TESTSRC2) libsqlite3.la
TESTFIXTURE_SRC1 = sqlite3.c
@@ -1291,6 +1316,9 @@ dbdump$(TEXE): $(TOP)/ext/misc/dbdump.c sqlite3.lo
$(LTLINK) -DDBDUMP_STANDALONE -o $@ \
$(TOP)/ext/misc/dbdump.c sqlite3.lo $(TLIBS)
dbtotxt$(TEXE): $(TOP)/tool/dbtotxt.c
$(LTLINK)-o $@ $(TOP)/tool/dbtotxt.c
showdb$(TEXE): $(TOP)/tool/showdb.c sqlite3.lo
$(LTLINK) -o $@ $(TOP)/tool/showdb.c sqlite3.lo $(TLIBS)
@@ -1307,7 +1335,7 @@ showshm$(TEXE): $(TOP)/tool/showshm.c
$(LTLINK) -o $@ $(TOP)/tool/showshm.c
index_usage$(TEXE): $(TOP)/tool/index_usage.c sqlite3.lo
$(LTLINK) -o $@ $(TOP)/tool/index_usage.c sqlite3.lo $(TLIBS)
$(LTLINK) $(SHELL_OPT) -o $@ $(TOP)/tool/index_usage.c sqlite3.lo $(TLIBS)
changeset$(TEXE): $(TOP)/ext/session/changeset.c sqlite3.lo
$(LTLINK) -o $@ $(TOP)/ext/session/changeset.c sqlite3.lo $(TLIBS)
@@ -1396,7 +1424,7 @@ install: sqlite3$(TEXE) lib_install sqlite3.h sqlite3.pc ${HAVE_TCL:1=tcl_instal
$(INSTALL) -m 0644 sqlite3.pc $(DESTDIR)$(pkgconfigdir)
pkgIndex.tcl:
echo 'package ifneeded sqlite3 $(RELEASE) [list load $(TCLLIBDIR)/libtclsqlite3$(SHLIB_SUFFIX) sqlite3]' > $@
echo 'package ifneeded sqlite3 $(RELEASE) [list load [file join $$dir libtclsqlite3[info sharedlibextension]] sqlite3]' > $@
tcl_install: lib_install libtclsqlite3.la pkgIndex.tcl
$(INSTALL) -d $(DESTDIR)$(TCLLIBDIR)
$(LTINSTALL) libtclsqlite3.la $(DESTDIR)$(TCLLIBDIR)
+17 -4
View File
@@ -1527,6 +1527,7 @@ TESTEXT = \
$(TOP)\ext\misc\nextchar.c \
$(TOP)\ext\misc\normalize.c \
$(TOP)\ext\misc\percentile.c \
$(TOP)\ext\misc\prefixes.c \
$(TOP)\ext\misc\regexp.c \
$(TOP)\ext\misc\remember.c \
$(TOP)\ext\misc\series.c \
@@ -1625,7 +1626,8 @@ FUZZDATA = \
$(TOP)\test\fuzzdata4.db \
$(TOP)\test\fuzzdata5.db \
$(TOP)\test\fuzzdata6.db \
$(TOP)\test\fuzzdata7.db
$(TOP)\test\fuzzdata7.db \
$(TOP)\test\fuzzdata8.db
# <</mark>>
# Additional compiler options for the shell. These are only effective
@@ -1643,7 +1645,13 @@ SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_DESERIALIZE=1
#
MPTESTER_COMPILE_OPTS = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5
FUZZERSHELL_COMPILE_OPTS = -DSQLITE_ENABLE_JSON1
FUZZCHECK_COMPILE_OPTS = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5 -DSQLITE_OSS_FUZZ -DSQLITE_MAX_MEMORY=50000000 -DSQLITE_PRINTF_PRECISION_LIMIT=1000
FUZZCHECK_OPTS = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5 -DSQLITE_OSS_FUZZ -DSQLITE_MAX_MEMORY=50000000 -DSQLITE_PRINTF_PRECISION_LIMIT=1000
FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_ENABLE_DESERIALIZE
FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_ENABLE_FTS4
FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_ENABLE_RTREE
FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_ENABLE_GEOPOLY
FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_ENABLE_DBSTAT_VTAB
FUZZCHECK_SRC = $(TOP)\test\fuzzcheck.c $(TOP)\test\ossfuzz.c
OSSSHELL_SRC = $(TOP)\test\ossshell.c $(TOP)\test\ossfuzz.c
DBFUZZ_COMPILE_OPTS = -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION
@@ -1730,10 +1738,10 @@ dbfuzz.exe: $(TOP)\test\dbfuzz.c $(SQLITE3C) $(SQLITE3H)
$(LTLINK) $(NO_WARN) $(DBFUZZ_COMPILE_OPTS) $(TOP)\test\dbfuzz.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
fuzzcheck.exe: $(FUZZCHECK_SRC) $(SQLITE3C) $(SQLITE3H)
$(LTLINK) $(NO_WARN) $(FUZZCHECK_COMPILE_OPTS) $(FUZZCHECK_SRC) $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
$(LTLINK) $(NO_WARN) $(FUZZCHECK_OPTS) $(FUZZCHECK_SRC) $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
ossshell.exe: $(OSSSHELL_SRC) $(SQLITE3C) $(SQLITE3H)
$(LTLINK) $(NO_WARN) $(FUZZCHECK_COMPILE_OPTS) $(OSSSHELL_SRC) $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
$(LTLINK) $(NO_WARN) $(FUZZCHECK_OPTS) $(OSSSHELL_SRC) $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
sessionfuzz.exe: zlib $(TOP)\test\sessionfuzz.c $(SQLITE3C) $(SQLITE3H)
$(LTLINK) $(NO_WARN) -I$(ZLIBINCDIR) $(TOP)\test\sessionfuzz.c /link $(LDFLAGS) $(LTLINKOPTS) /LIBPATH:$(ZLIBLIBDIR) $(ZLIBLIB)
@@ -2130,6 +2138,7 @@ SHELL_SRC = \
$(TOP)\ext\misc\completion.c \
$(TOP)\ext\expert\sqlite3expert.c \
$(TOP)\ext\expert\sqlite3expert.h \
$(TOP)\ext\misc\memtrace.c \
$(TOP)\src\test_windirent.c
# If use of zlib is enabled, add the "zipfile.c" source file.
@@ -2298,6 +2307,7 @@ TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_DEFAULT_PAGE_SIZE=1024
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_ENABLE_STMTVTAB=1
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_ENABLE_DBPAGE_VTAB=1
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_ENABLE_JSON1=1
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_ENABLE_DESERIALIZE=1
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) $(TEST_CCONV_OPTS)
TESTFIXTURE_SRC0 = $(TESTEXT) $(TESTSRC2)
@@ -2425,6 +2435,9 @@ testloadext.lo: $(TOP)\src\test_loadext.c $(SQLITE3H)
testloadext.dll: testloadext.lo
$(LD) $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) /DLL /OUT:$@ testloadext.lo
dbtotxt.exe: $(TOP)\tool\dbtotxt.c
$(LTLINK) $(NO_WARN) $(TOP)\tool\dbtotxt.c /link $(LDFLAGS) $(LTLINKOPTS)
showdb.exe: $(TOP)\tool\showdb.c $(SQLITE3C) $(SQLITE3H)
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
$(TOP)\tool\showdb.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
+46 -7
View File
@@ -5,16 +5,28 @@ This repository contains the complete source code for the
are also included. However, many other test scripts
and most of the documentation are managed separately.
SQLite [does not use Git](https://sqlite.org/whynotgit.html).
If you are reading this on GitHub, then you are looking at an
unofficial mirror. See <https://sqlite.org/src> for the official
repository.
## Obtaining The Code
## Version Control
SQLite sources are managed using the
[Fossil](https://www.fossil-scm.org/), a distributed version control system
that was specifically designed to support SQLite development.
that was specifically designed and written to support SQLite development.
The [Fossil repository](https://sqlite.org/src/timeline) contains the urtext.
If you are reading this on GitHub or some other Git repository or service,
then you are looking at a mirror. The names of check-ins and
other artifacts in a Git mirror are different from the official
names for those objects. The offical names for check-ins are
found in a footer on the check-in comment for authorized mirrors.
The official check-in name can also be seen in the `manifest.uuid` file
in the root of the tree. Always use the official name, not the
Git-name, when communicating about an SQLite check-in.
If you pulled your SQLite source code from a secondary source and want to
verify its integrity, there are hints on how to do that in the
[Verifying Code Authenticity](#vauth) section below.
## Obtaining The Code
If you do not want to use Fossil, you can download tarballs or ZIP
archives or [SQLite archives](https://sqlite.org/cli.html#sqlar) as follows:
@@ -294,6 +306,33 @@ Key files:
There are many other source files. Each has a succinct header comment that
describes its purpose and role within the larger system.
<a name="vauth"></a>
## Verifying Code Authenticity
If you obtained an SQLite source tree from a secondary source, such as a
GitHub mirror, and you want to verify that it has not been altered, there
are a couple of ways to do that.
If you have an official release version of SQLite, and you are using the
`sqlite3.c` amalgamation, then SHA3-256 hashes for the amalgamation are
available in the [change log](https://www.sqlite.org/changes.html) on
the official website. After building the `sqlite3.c` file, you can check
that is authentic by comparing the hash. This does not ensure that the
test scripts are unaltered, but it does validate the deliverable part of
the code and only involves computing and comparing a single hash.
For versions other than an official release, or if you are building the
`sqlite3.c` amalgamation using non-standard build options, the verification
process is a little more involved. The `manifest` file at the root directory
of the source tree ([example](https://sqlite.org/src/artifact/bd49a8271d650fa8))
contains either a SHA3-256 hash (for newer files) or a SHA1 hash (for
older files) for every source file in the repository. You can write a script
to extracts hashes from `manifest` and verifies the hashes against the
corresponding files in the source tree. The SHA3-256 hash of the `manifest`
file itself is the official name of the version of the source tree that you
have. The `manifest.uuid` file should contain the SHA3-256 hash of the
`manifest` file. If all of the above hash comparisons are correct, then
you can be confident that your source tree is authentic and unadulterated.
## Contacts
+1 -1
View File
@@ -1 +1 @@
3.26.0
3.28.0
Vendored
+9 -9
View File
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.69 for sqlite 3.26.0.
# Generated by GNU Autoconf 2.69 for sqlite 3.28.0.
#
#
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
@@ -726,8 +726,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='sqlite'
PACKAGE_TARNAME='sqlite'
PACKAGE_VERSION='3.26.0'
PACKAGE_STRING='sqlite 3.26.0'
PACKAGE_VERSION='3.28.0'
PACKAGE_STRING='sqlite 3.28.0'
PACKAGE_BUGREPORT=''
PACKAGE_URL=''
@@ -1466,7 +1466,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.26.0 to adapt to many kinds of systems.
\`configure' configures sqlite 3.28.0 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1531,7 +1531,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
short | recursive ) echo "Configuration of sqlite 3.26.0:";;
short | recursive ) echo "Configuration of sqlite 3.28.0:";;
esac
cat <<\_ACEOF
@@ -1657,7 +1657,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
sqlite configure 3.26.0
sqlite configure 3.28.0
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2076,7 +2076,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.26.0, which was
It was created by sqlite $as_me 3.28.0, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -12232,7 +12232,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
This file was extended by sqlite $as_me 3.26.0, which was
This file was extended by sqlite $as_me 3.28.0, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -12298,7 +12298,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
sqlite config.status 3.26.0
sqlite config.status 3.28.0
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
+4 -2
View File
@@ -243,8 +243,10 @@ do_setup_rec_test $tn.12.1 {
CREATE INDEX t7_idx_00000062 ON t7(b);
CREATE INDEX t7_idx_00000061 ON t7(a);
MULTI-INDEX OR
SEARCH TABLE t7 USING INDEX t7_idx_00000061 (a=?)
SEARCH TABLE t7 USING INDEX t7_idx_00000062 (b=?)
INDEX 1
SEARCH TABLE t7 USING INDEX t7_idx_00000061 (a=?)
INDEX 2
SEARCH TABLE t7 USING INDEX t7_idx_00000062 (b=?)
}
# rowid terms.
+4 -2
View File
@@ -52,8 +52,10 @@
SECURITY: If the fts3 extension is used in an environment where potentially
malicious users may execute arbitrary SQL (i.e. gears), they should be
prevented from invoking the fts3_tokenizer() function, possibly using the
authorisation callback.
prevented from invoking the fts3_tokenizer() function. The
fts3_tokenizer() function is disabled by default. It is only enabled
by SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER. Do not enable it in
security sensitive environments.
See "Sample code" below for an example of calling the fts3_tokenizer()
function from C code.
+79 -51
View File
@@ -320,6 +320,14 @@ int sqlite3Fts3Never(int b) { assert( !b ); return b; }
# endif
#endif
/*
** This variable is set to false when running tests for which the on disk
** structures should not be corrupt. Otherwise, true. If it is false, extra
** assert() conditions in the fts3 code are activated - conditions that are
** only true if it is guaranteed that the fts3 database is not corrupt.
*/
int sqlite3_fts3_may_be_corrupt = 1;
/*
** Write a 64-bit variable-length integer to memory starting at p[0].
** The length of data written will be between 1 and FTS3_VARINT_MAX bytes.
@@ -338,7 +346,7 @@ int sqlite3Fts3PutVarint(char *p, sqlite_int64 v){
}
#define GETVARINT_STEP(v, ptr, shift, mask1, mask2, var, ret) \
v = (v & mask1) | ( (*ptr++) << shift ); \
v = (v & mask1) | ( (*(const unsigned char*)(ptr++)) << shift ); \
if( (v & mask2)==0 ){ var = v; return ret; }
#define GETVARINT_INIT(v, ptr, shift, mask1, mask2, var, ret) \
v = (*ptr++); \
@@ -376,20 +384,21 @@ int sqlite3Fts3GetVarint(const char *pBuf, sqlite_int64 *v){
** a non-negative 32-bit integer before it is returned.
*/
int sqlite3Fts3GetVarint32(const char *p, int *pi){
const unsigned char *ptr = (const unsigned char*)p;
u32 a;
#ifndef fts3GetVarint32
GETVARINT_INIT(a, p, 0, 0x00, 0x80, *pi, 1);
GETVARINT_INIT(a, ptr, 0, 0x00, 0x80, *pi, 1);
#else
a = (*p++);
a = (*ptr++);
assert( a & 0x80 );
#endif
GETVARINT_STEP(a, p, 7, 0x7F, 0x4000, *pi, 2);
GETVARINT_STEP(a, p, 14, 0x3FFF, 0x200000, *pi, 3);
GETVARINT_STEP(a, p, 21, 0x1FFFFF, 0x10000000, *pi, 4);
GETVARINT_STEP(a, ptr, 7, 0x7F, 0x4000, *pi, 2);
GETVARINT_STEP(a, ptr, 14, 0x3FFF, 0x200000, *pi, 3);
GETVARINT_STEP(a, ptr, 21, 0x1FFFFF, 0x10000000, *pi, 4);
a = (a & 0x0FFFFFFF );
*pi = (int)(a | ((u32)(*p & 0x07) << 28));
*pi = (int)(a | ((u32)(*ptr & 0x07) << 28));
assert( 0==(a & 0x80000000) );
assert( *pi>=0 );
return 5;
@@ -560,13 +569,18 @@ static int fts3DestroyMethod(sqlite3_vtab *pVtab){
sqlite3 *db = p->db; /* Database handle */
/* Drop the shadow tables */
if( p->zContentTbl==0 ){
fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_content'", zDb, p->zName);
}
fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_segments'", zDb,p->zName);
fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_segdir'", zDb, p->zName);
fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_docsize'", zDb, p->zName);
fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_stat'", zDb, p->zName);
fts3DbExec(&rc, db,
"DROP TABLE IF EXISTS %Q.'%q_segments';"
"DROP TABLE IF EXISTS %Q.'%q_segdir';"
"DROP TABLE IF EXISTS %Q.'%q_docsize';"
"DROP TABLE IF EXISTS %Q.'%q_stat';"
"%s DROP TABLE IF EXISTS %Q.'%q_content';",
zDb, p->zName,
zDb, p->zName,
zDb, p->zName,
zDb, p->zName,
(p->zContentTbl ? "--" : ""), zDb,p->zName
);
/* If everything has worked, invoke fts3DisconnectMethod() to free the
** memory associated with the Fts3Table structure and return SQLITE_OK.
@@ -798,10 +812,10 @@ static void fts3Appendf(
** memory.
*/
static char *fts3QuoteId(char const *zInput){
int nRet;
sqlite3_int64 nRet;
char *zRet;
nRet = 2 + (int)strlen(zInput)*2 + 1;
zRet = sqlite3_malloc(nRet);
zRet = sqlite3_malloc64(nRet);
if( zRet ){
int i;
char *z = zRet;
@@ -982,7 +996,7 @@ static int fts3PrefixParameter(
}
}
aIndex = sqlite3_malloc(sizeof(struct Fts3Index) * nIndex);
aIndex = sqlite3_malloc64(sizeof(struct Fts3Index) * nIndex);
*apIndex = aIndex;
if( !aIndex ){
return SQLITE_NOMEM;
@@ -1061,7 +1075,7 @@ static int fts3ContentColumns(
if( rc==SQLITE_OK ){
const char **azCol; /* Output array */
int nStr = 0; /* Size of all column names (incl. 0x00) */
sqlite3_int64 nStr = 0; /* Size of all column names (incl. 0x00) */
int nCol; /* Number of table columns */
int i; /* Used to iterate through columns */
@@ -1071,11 +1085,11 @@ static int fts3ContentColumns(
nCol = sqlite3_column_count(pStmt);
for(i=0; i<nCol; i++){
const char *zCol = sqlite3_column_name(pStmt, i);
nStr += (int)strlen(zCol) + 1;
nStr += strlen(zCol) + 1;
}
/* Allocate and populate the array to return. */
azCol = (const char **)sqlite3_malloc(sizeof(char *) * nCol + nStr);
azCol = (const char **)sqlite3_malloc64(sizeof(char *) * nCol + nStr);
if( azCol==0 ){
rc = SQLITE_NOMEM;
}else{
@@ -1123,7 +1137,7 @@ static int fts3InitVtab(
Fts3Table *p = 0; /* Pointer to allocated vtab */
int rc = SQLITE_OK; /* Return code */
int i; /* Iterator variable */
int nByte; /* Size of allocation used for *p */
sqlite3_int64 nByte; /* Size of allocation used for *p */
int iCol; /* Column index */
int nString = 0; /* Bytes required to hold all column names */
int nCol = 0; /* Number of columns in the FTS table */
@@ -1157,10 +1171,10 @@ static int fts3InitVtab(
nName = (int)strlen(argv[2]) + 1;
nByte = sizeof(const char *) * (argc-2);
aCol = (const char **)sqlite3_malloc(nByte);
aCol = (const char **)sqlite3_malloc64(nByte);
if( aCol ){
memset((void*)aCol, 0, nByte);
azNotindexed = (char **)sqlite3_malloc(nByte);
azNotindexed = (char **)sqlite3_malloc64(nByte);
}
if( azNotindexed ){
memset(azNotindexed, 0, nByte);
@@ -1355,7 +1369,7 @@ static int fts3InitVtab(
nName + /* zName */
nDb + /* zDb */
nString; /* Space for azColumn strings */
p = (Fts3Table*)sqlite3_malloc(nByte);
p = (Fts3Table*)sqlite3_malloc64(nByte);
if( p==0 ){
rc = SQLITE_NOMEM;
goto fts3_init_out;
@@ -1859,7 +1873,7 @@ static int fts3ScanInteriorNode(
zCsr += fts3GetVarint32(zCsr, &nSuffix);
assert( nPrefix>=0 && nSuffix>=0 );
if( nPrefix>zCsr-zNode || nSuffix>zEnd-zCsr ){
if( nPrefix>zCsr-zNode || nSuffix>zEnd-zCsr || nSuffix==0 ){
rc = FTS_CORRUPT_VTAB;
goto finish_scan;
}
@@ -2134,7 +2148,7 @@ static int fts3PutColNumber(char **pp, int iCol){
** updated appropriately. The caller is responsible for insuring
** that there is enough space in *pp to hold the complete output.
*/
static void fts3PoslistMerge(
static int fts3PoslistMerge(
char **pp, /* Output buffer */
char **pp1, /* Left input list */
char **pp2 /* Right input list */
@@ -2147,11 +2161,17 @@ static void fts3PoslistMerge(
int iCol1; /* The current column index in pp1 */
int iCol2; /* The current column index in pp2 */
if( *p1==POS_COLUMN ) fts3GetVarint32(&p1[1], &iCol1);
if( *p1==POS_COLUMN ){
fts3GetVarint32(&p1[1], &iCol1);
if( iCol1==0 ) return FTS_CORRUPT_VTAB;
}
else if( *p1==POS_END ) iCol1 = POSITION_LIST_END;
else iCol1 = 0;
if( *p2==POS_COLUMN ) fts3GetVarint32(&p2[1], &iCol2);
if( *p2==POS_COLUMN ){
fts3GetVarint32(&p2[1], &iCol2);
if( iCol2==0 ) return FTS_CORRUPT_VTAB;
}
else if( *p2==POS_END ) iCol2 = POSITION_LIST_END;
else iCol2 = 0;
@@ -2199,6 +2219,7 @@ static void fts3PoslistMerge(
*pp = p;
*pp1 = p1 + 1;
*pp2 = p2 + 1;
return SQLITE_OK;
}
/*
@@ -2263,10 +2284,9 @@ static int fts3PoslistPhraseMerge(
p += sqlite3Fts3PutVarint(p, iCol1);
}
assert( *p1!=POS_END && *p1!=POS_COLUMN );
assert( *p2!=POS_END && *p2!=POS_COLUMN );
fts3GetDeltaVarint(&p1, &iPos1); iPos1 -= 2;
fts3GetDeltaVarint(&p2, &iPos2); iPos2 -= 2;
if( iPos1<0 || iPos2<0 ) break;
while( 1 ){
if( iPos2==iPos1+nToken
@@ -2492,6 +2512,7 @@ static int fts3DoclistOrMerge(
char *a2, int n2, /* Second doclist */
char **paOut, int *pnOut /* OUT: Malloc'd doclist */
){
int rc = SQLITE_OK;
sqlite3_int64 i1 = 0;
sqlite3_int64 i2 = 0;
sqlite3_int64 iPrev = 0;
@@ -2535,7 +2556,7 @@ static int fts3DoclistOrMerge(
** A symetric argument may be made if the doclists are in descending
** order.
*/
aOut = sqlite3_malloc(n1+n2+FTS3_VARINT_MAX-1);
aOut = sqlite3_malloc64((i64)n1+n2+FTS3_VARINT_MAX-1+FTS3_BUFFER_PADDING);
if( !aOut ) return SQLITE_NOMEM;
p = aOut;
@@ -2546,7 +2567,8 @@ static int fts3DoclistOrMerge(
if( p2 && p1 && iDiff==0 ){
fts3PutDeltaVarint3(&p, bDescDoclist, &iPrev, &bFirstOut, i1);
fts3PoslistMerge(&p, &p1, &p2);
rc = fts3PoslistMerge(&p, &p1, &p2);
if( rc ) break;
fts3GetDeltaVarint3(&p1, pEnd1, bDescDoclist, &i1);
fts3GetDeltaVarint3(&p2, pEnd2, bDescDoclist, &i2);
}else if( !p2 || (p1 && iDiff<0) ){
@@ -2560,10 +2582,16 @@ static int fts3DoclistOrMerge(
}
}
if( rc!=SQLITE_OK ){
sqlite3_free(aOut);
p = aOut = 0;
}else{
assert( (p-aOut)<=n1+n2+FTS3_VARINT_MAX-1 );
memset(&aOut[(p-aOut)], 0, FTS3_BUFFER_PADDING);
}
*paOut = aOut;
*pnOut = (int)(p-aOut);
assert( *pnOut<=n1+n2+FTS3_VARINT_MAX-1 );
return SQLITE_OK;
return rc;
}
/*
@@ -2598,7 +2626,7 @@ static int fts3DoclistPhraseMerge(
assert( nDist>0 );
if( bDescDoclist ){
aOut = sqlite3_malloc(*pnRight + FTS3_VARINT_MAX);
aOut = sqlite3_malloc64((sqlite3_int64)*pnRight + FTS3_VARINT_MAX);
if( aOut==0 ) return SQLITE_NOMEM;
}else{
aOut = aRight;
@@ -2782,6 +2810,7 @@ static int fts3TermSelectMerge(
pTS->anOutput[0] = nDoclist;
if( pTS->aaOutput[0] ){
memcpy(pTS->aaOutput[0], aDoclist, nDoclist);
memset(&pTS->aaOutput[0][nDoclist], 0, FTS3_VARINT_MAX);
}else{
return SQLITE_NOMEM;
}
@@ -2833,8 +2862,8 @@ static int fts3SegReaderCursorAppend(
){
if( (pCsr->nSegment%16)==0 ){
Fts3SegReader **apNew;
int nByte = (pCsr->nSegment + 16)*sizeof(Fts3SegReader*);
apNew = (Fts3SegReader **)sqlite3_realloc(pCsr->apSegment, nByte);
sqlite3_int64 nByte = (pCsr->nSegment + 16)*sizeof(Fts3SegReader*);
apNew = (Fts3SegReader **)sqlite3_realloc64(pCsr->apSegment, nByte);
if( !apNew ){
sqlite3Fts3SegReaderFree(pNew);
return SQLITE_NOMEM;
@@ -2898,7 +2927,7 @@ static int fts3SegReaderCursor(
/* If zTerm is not NULL, and this segment is not stored entirely on its
** root node, the range of leaves scanned can be reduced. Do this. */
if( iStartBlock && zTerm ){
if( iStartBlock && zTerm && zRoot ){
sqlite3_int64 *pi = (isPrefix ? &iLeavesEndBlock : 0);
rc = fts3SelectLeaf(p, zTerm, nTerm, zRoot, nRoot, &iStartBlock, pi);
if( rc!=SQLITE_OK ) goto finished;
@@ -3840,7 +3869,6 @@ static int fts3RollbackToMethod(sqlite3_vtab *pVtab, int iSavepoint){
Fts3Table *p = (Fts3Table*)pVtab;
UNUSED_PARAMETER(iSavepoint);
assert( p->inTransaction );
assert( p->mxSavepoint >= iSavepoint );
TESTONLY( p->mxSavepoint = iSavepoint );
sqlite3Fts3PendingTermsClear(p);
return SQLITE_OK;
@@ -4615,9 +4643,10 @@ static int fts3EvalIncrPhraseNext(
if( bEof==0 ){
int nList = 0;
int nByte = a[p->nToken-1].nList;
char *aDoclist = sqlite3_malloc(nByte+1);
char *aDoclist = sqlite3_malloc(nByte+FTS3_BUFFER_PADDING);
if( !aDoclist ) return SQLITE_NOMEM;
memcpy(aDoclist, a[p->nToken-1].pList, nByte+1);
memset(&aDoclist[nByte], 0, FTS3_BUFFER_PADDING);
for(i=0; i<(p->nToken-1); i++){
if( a[i].bIgnore==0 ){
@@ -5008,7 +5037,7 @@ static int fts3EvalStart(Fts3Cursor *pCsr){
if( rc==SQLITE_OK && nToken>1 && pTab->bFts4 ){
Fts3TokenAndCost *aTC;
Fts3Expr **apOr;
aTC = (Fts3TokenAndCost *)sqlite3_malloc(
aTC = (Fts3TokenAndCost *)sqlite3_malloc64(
sizeof(Fts3TokenAndCost) * nToken
+ sizeof(Fts3Expr *) * nOr * 2
);
@@ -5319,7 +5348,7 @@ static int fts3EvalNearTest(Fts3Expr *pExpr, int *pRc){
&& (pExpr->pParent==0 || pExpr->pParent->eType!=FTSQUERY_NEAR)
){
Fts3Expr *p;
int nTmp = 0; /* Bytes of temp space */
sqlite3_int64 nTmp = 0; /* Bytes of temp space */
char *aTmp; /* Temp space for PoslistNearMerge() */
/* Allocate temporary working space. */
@@ -5328,7 +5357,7 @@ static int fts3EvalNearTest(Fts3Expr *pExpr, int *pRc){
nTmp += p->pRight->pPhrase->doclist.nList;
}
nTmp += p->pPhrase->doclist.nList;
aTmp = sqlite3_malloc(nTmp*2);
aTmp = sqlite3_malloc64(nTmp*2);
if( !aTmp ){
*pRc = SQLITE_NOMEM;
res = 0;
@@ -5598,15 +5627,14 @@ static void fts3EvalRestart(
** found in Fts3Expr.pPhrase->doclist.pList for each of the phrase
** expression nodes.
*/
static void fts3EvalUpdateCounts(Fts3Expr *pExpr){
static void fts3EvalUpdateCounts(Fts3Expr *pExpr, int nCol){
if( pExpr ){
Fts3Phrase *pPhrase = pExpr->pPhrase;
if( pPhrase && pPhrase->doclist.pList ){
int iCol = 0;
char *p = pPhrase->doclist.pList;
assert( *p );
while( 1 ){
do{
u8 c = 0;
int iCnt = 0;
while( 0xFE & (*p | c) ){
@@ -5622,11 +5650,11 @@ static void fts3EvalUpdateCounts(Fts3Expr *pExpr){
if( *p==0x00 ) break;
p++;
p += fts3GetVarint32(p, &iCol);
}
}while( iCol<nCol );
}
fts3EvalUpdateCounts(pExpr->pLeft);
fts3EvalUpdateCounts(pExpr->pRight);
fts3EvalUpdateCounts(pExpr->pLeft, nCol);
fts3EvalUpdateCounts(pExpr->pRight, nCol);
}
}
@@ -5670,7 +5698,7 @@ static int fts3EvalGatherStats(
for(p=pRoot; p; p=p->pLeft){
Fts3Expr *pE = (p->eType==FTSQUERY_PHRASE?p:p->pRight);
assert( pE->aMI==0 );
pE->aMI = (u32 *)sqlite3_malloc(pTab->nColumn * 3 * sizeof(u32));
pE->aMI = (u32 *)sqlite3_malloc64(pTab->nColumn * 3 * sizeof(u32));
if( !pE->aMI ) return SQLITE_NOMEM;
memset(pE->aMI, 0, pTab->nColumn * 3 * sizeof(u32));
}
@@ -5696,7 +5724,7 @@ static int fts3EvalGatherStats(
);
if( rc==SQLITE_OK && pCsr->isEof==0 ){
fts3EvalUpdateCounts(pRoot);
fts3EvalUpdateCounts(pRoot, pTab->nColumn);
}
}
+14
View File
@@ -95,6 +95,8 @@ SQLITE_EXTENSION_INIT3
*/
#define FTS3_VARINT_MAX 10
#define FTS3_BUFFER_PADDING 8
/*
** FTS4 virtual tables may maintain multiple indexes - one index of all terms
** in the document set and zero or more prefix indexes. All indexes are stored
@@ -127,6 +129,18 @@ SQLITE_EXTENSION_INIT3
#define POS_COLUMN (1) /* Column-list terminator */
#define POS_END (0) /* Position-list terminator */
/*
** The assert_fts3_nc() macro is similar to the assert() macro, except that it
** is used for assert() conditions that are true only if it can be
** guranteed that the database is not corrupt.
*/
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
extern int sqlite3_fts3_may_be_corrupt;
# define assert_fts3_nc(x) assert(sqlite3_fts3_may_be_corrupt || (x))
#else
# define assert_fts3_nc(x) assert(x)
#endif
/*
** This section provides definitions to allow the
** FTS3 extension to be compiled outside of the
+5 -5
View File
@@ -66,7 +66,7 @@ static int fts3auxConnectMethod(
char const *zFts3; /* Name of fts3 table */
int nDb; /* Result of strlen(zDb) */
int nFts3; /* Result of strlen(zFts3) */
int nByte; /* Bytes of space to allocate here */
sqlite3_int64 nByte; /* Bytes of space to allocate here */
int rc; /* value returned by declare_vtab() */
Fts3auxTable *p; /* Virtual table object to return */
@@ -98,7 +98,7 @@ static int fts3auxConnectMethod(
if( rc!=SQLITE_OK ) return rc;
nByte = sizeof(Fts3auxTable) + sizeof(Fts3Table) + nDb + nFts3 + 2;
p = (Fts3auxTable *)sqlite3_malloc(nByte);
p = (Fts3auxTable *)sqlite3_malloc64(nByte);
if( !p ) return SQLITE_NOMEM;
memset(p, 0, nByte);
@@ -248,7 +248,7 @@ static int fts3auxCloseMethod(sqlite3_vtab_cursor *pCursor){
static int fts3auxGrowStatArray(Fts3auxCursor *pCsr, int nSize){
if( nSize>pCsr->nStat ){
struct Fts3auxColstats *aNew;
aNew = (struct Fts3auxColstats *)sqlite3_realloc(pCsr->aStat,
aNew = (struct Fts3auxColstats *)sqlite3_realloc64(pCsr->aStat,
sizeof(struct Fts3auxColstats) * nSize
);
if( aNew==0 ) return SQLITE_NOMEM;
@@ -416,15 +416,15 @@ static int fts3auxFilterMethod(
assert( (iEq==0 && iGe==-1) || (iEq==-1 && iGe==0) );
if( zStr ){
pCsr->filter.zTerm = sqlite3_mprintf("%s", zStr);
pCsr->filter.nTerm = sqlite3_value_bytes(apVal[0]);
if( pCsr->filter.zTerm==0 ) return SQLITE_NOMEM;
pCsr->filter.nTerm = (int)strlen(pCsr->filter.zTerm);
}
}
if( iLe>=0 ){
pCsr->zStop = sqlite3_mprintf("%s", sqlite3_value_text(apVal[iLe]));
pCsr->nStop = sqlite3_value_bytes(apVal[iLe]);
if( pCsr->zStop==0 ) return SQLITE_NOMEM;
pCsr->nStop = (int)strlen(pCsr->zStop);
}
if( iLangid>=0 ){
+7 -8
View File
@@ -122,8 +122,8 @@ static int fts3isspace(char c){
** zero the memory before returning a pointer to it. If unsuccessful,
** return NULL.
*/
static void *fts3MallocZero(int nByte){
void *pRet = sqlite3_malloc(nByte);
static void *fts3MallocZero(sqlite3_int64 nByte){
void *pRet = sqlite3_malloc64(nByte);
if( pRet ) memset(pRet, 0, nByte);
return pRet;
}
@@ -198,7 +198,7 @@ static int getNextToken(
if( rc==SQLITE_OK ){
const char *zToken;
int nToken = 0, iStart = 0, iEnd = 0, iPosition = 0;
int nByte; /* total space to allocate */
sqlite3_int64 nByte; /* total space to allocate */
rc = pModule->xNext(pCursor, &zToken, &nToken, &iStart, &iEnd, &iPosition);
if( rc==SQLITE_OK ){
@@ -252,8 +252,8 @@ static int getNextToken(
** Enlarge a memory allocation. If an out-of-memory allocation occurs,
** then free the old allocation.
*/
static void *fts3ReallocOrFree(void *pOrig, int nNew){
void *pRet = sqlite3_realloc(pOrig, nNew);
static void *fts3ReallocOrFree(void *pOrig, sqlite3_int64 nNew){
void *pRet = sqlite3_realloc64(pOrig, nNew);
if( !pRet ){
sqlite3_free(pOrig);
}
@@ -497,7 +497,6 @@ static int getNextNode(
int nConsumed = 0;
pParse->nNest++;
rc = fts3ExprParse(pParse, zInput+1, nInput-1, ppExpr, &nConsumed);
if( rc==SQLITE_OK && !*ppExpr ){ rc = SQLITE_DONE; }
*pnConsumed = (int)(zInput - z) + 1 + nConsumed;
return rc;
}else if( *zInput==')' ){
@@ -796,7 +795,7 @@ static int fts3ExprBalance(Fts3Expr **pp, int nMaxDepth){
if( rc==SQLITE_OK ){
if( (eType==FTSQUERY_AND || eType==FTSQUERY_OR) ){
Fts3Expr **apLeaf;
apLeaf = (Fts3Expr **)sqlite3_malloc(sizeof(Fts3Expr *) * nMaxDepth);
apLeaf = (Fts3Expr **)sqlite3_malloc64(sizeof(Fts3Expr *) * nMaxDepth);
if( 0==apLeaf ){
rc = SQLITE_NOMEM;
}else{
@@ -1216,7 +1215,7 @@ static void fts3ExprTestCommon(
zExpr = (const char *)sqlite3_value_text(argv[1]);
nExpr = sqlite3_value_bytes(argv[1]);
nCol = argc-2;
azCol = (char **)sqlite3_malloc(nCol*sizeof(char *));
azCol = (char **)sqlite3_malloc64(nCol*sizeof(char *));
if( !azCol ){
sqlite3_result_error_nomem(context);
goto exprtest_out;
+2 -2
View File
@@ -35,8 +35,8 @@
/*
** Malloc and Free functions
*/
static void *fts3HashMalloc(int n){
void *p = sqlite3_malloc(n);
static void *fts3HashMalloc(sqlite3_int64 n){
void *p = sqlite3_malloc64(n);
if( p ){
memset(p, 0, n);
}
+2 -2
View File
@@ -60,7 +60,7 @@ static int icuCreate(
if( argc>0 ){
n = strlen(argv[0])+1;
}
p = (IcuTokenizer *)sqlite3_malloc(sizeof(IcuTokenizer)+n);
p = (IcuTokenizer *)sqlite3_malloc64(sizeof(IcuTokenizer)+n);
if( !p ){
return SQLITE_NOMEM;
}
@@ -117,7 +117,7 @@ static int icuOpen(
nInput = strlen(zInput);
}
nChar = nInput+1;
pCsr = (IcuCursor *)sqlite3_malloc(
pCsr = (IcuCursor *)sqlite3_malloc64(
sizeof(IcuCursor) + /* IcuCursor */
((nChar+3)&~3) * sizeof(UChar) + /* IcuCursor.aChar[] */
(nChar+1) * sizeof(int) /* IcuCursor.aOffset[] */
+44 -26
View File
@@ -178,7 +178,7 @@ static void (*fts3MIBufferAlloc(MatchinfoBuffer *p, u32 **paOut))(void*){
aOut = &p->aMatchinfo[p->nElem+2];
xRet = fts3MIBufferFree;
}else{
aOut = (u32*)sqlite3_malloc(p->nElem * sizeof(u32));
aOut = (u32*)sqlite3_malloc64(p->nElem * sizeof(u32));
if( aOut ){
xRet = sqlite3_free;
if( p->bGlobal ) memcpy(aOut, &p->aMatchinfo[1], p->nElem*sizeof(u32));
@@ -429,11 +429,12 @@ static void fts3SnippetDetails(
char *pCsr = pPhrase->pTail;
int iCsr = pPhrase->iTail;
while( iCsr<(iStart+pIter->nSnippet) ){
while( iCsr<(iStart+pIter->nSnippet) && iCsr>=iStart ){
int j;
u64 mPhrase = (u64)1 << i;
u64 mPos = (u64)1 << (iCsr - iStart);
assert( iCsr>=iStart );
assert( iCsr>=iStart && (iCsr - iStart)<=64 );
assert( i>=0 && i<=64 );
if( (mCover|mCovered)&mPhrase ){
iScore++;
}else{
@@ -475,11 +476,14 @@ static int fts3SnippetFindPositions(Fts3Expr *pExpr, int iPhrase, void *ctx){
int iFirst = 0;
pPhrase->pList = pCsr;
fts3GetDeltaPosition(&pCsr, &iFirst);
assert( iFirst>=0 );
pPhrase->pHead = pCsr;
pPhrase->pTail = pCsr;
pPhrase->iHead = iFirst;
pPhrase->iTail = iFirst;
if( iFirst<0 ){
rc = FTS_CORRUPT_VTAB;
}else{
pPhrase->pHead = pCsr;
pPhrase->pTail = pCsr;
pPhrase->iHead = iFirst;
pPhrase->iTail = iFirst;
}
}else{
assert( rc!=SQLITE_OK || (
pPhrase->pList==0 && pPhrase->pHead==0 && pPhrase->pTail==0
@@ -516,7 +520,7 @@ static int fts3BestSnippet(
int rc; /* Return Code */
int nList; /* Number of phrases in expression */
SnippetIter sIter; /* Iterates through snippet candidates */
int nByte; /* Number of bytes of space to allocate */
sqlite3_int64 nByte; /* Number of bytes of space to allocate */
int iBestScore = -1; /* Best snippet score found so far */
int i; /* Loop counter */
@@ -534,7 +538,7 @@ static int fts3BestSnippet(
** the required space using malloc().
*/
nByte = sizeof(SnippetPhrase) * nList;
sIter.aPhrase = (SnippetPhrase *)sqlite3_malloc(nByte);
sIter.aPhrase = (SnippetPhrase *)sqlite3_malloc64(nByte);
if( !sIter.aPhrase ){
return SQLITE_NOMEM;
}
@@ -604,8 +608,8 @@ static int fts3StringAppend(
** appended data.
*/
if( pStr->n+nAppend+1>=pStr->nAlloc ){
int nAlloc = pStr->nAlloc+nAppend+100;
char *zNew = sqlite3_realloc(pStr->z, nAlloc);
sqlite3_int64 nAlloc = pStr->nAlloc+(sqlite3_int64)nAppend+100;
char *zNew = sqlite3_realloc64(pStr->z, nAlloc);
if( !zNew ){
return SQLITE_NOMEM;
}
@@ -660,6 +664,7 @@ static int fts3SnippetShift(
for(nLeft=0; !(hlmask & ((u64)1 << nLeft)); nLeft++);
for(nRight=0; !(hlmask & ((u64)1 << (nSnippet-1-nRight))); nRight++);
assert( (nSnippet-1-nRight)<=63 && (nSnippet-1-nRight)>=0 );
nDesired = (nLeft-nRight)/2;
/* Ideally, the start of the snippet should be pushed forward in the
@@ -852,7 +857,7 @@ static int fts3ColumnlistCount(char **ppCollist){
/*
** This function gathers 'y' or 'b' data for a single phrase.
*/
static void fts3ExprLHits(
static int fts3ExprLHits(
Fts3Expr *pExpr, /* Phrase expression node */
MatchInfo *p /* Matchinfo context */
){
@@ -882,25 +887,29 @@ static void fts3ExprLHits(
if( *pIter!=0x01 ) break;
pIter++;
pIter += fts3GetVarint32(pIter, &iCol);
if( iCol>=p->nCol ) return FTS_CORRUPT_VTAB;
}
return SQLITE_OK;
}
/*
** Gather the results for matchinfo directives 'y' and 'b'.
*/
static void fts3ExprLHitGather(
static int fts3ExprLHitGather(
Fts3Expr *pExpr,
MatchInfo *p
){
int rc = SQLITE_OK;
assert( (pExpr->pLeft==0)==(pExpr->pRight==0) );
if( pExpr->bEof==0 && pExpr->iDocid==p->pCursor->iPrevId ){
if( pExpr->pLeft ){
fts3ExprLHitGather(pExpr->pLeft, p);
fts3ExprLHitGather(pExpr->pRight, p);
rc = fts3ExprLHitGather(pExpr->pLeft, p);
if( rc==SQLITE_OK ) rc = fts3ExprLHitGather(pExpr->pRight, p);
}else{
fts3ExprLHits(pExpr, p);
rc = fts3ExprLHits(pExpr, p);
}
}
return rc;
}
/*
@@ -1117,11 +1126,12 @@ static int fts3MatchinfoLcs(Fts3Cursor *pCsr, MatchInfo *pInfo){
int i;
int iCol;
int nToken = 0;
int rc = SQLITE_OK;
/* Allocate and populate the array of LcsIterator objects. The array
** contains one element for each matchable phrase in the query.
**/
aIter = sqlite3_malloc(sizeof(LcsIterator) * pCsr->nPhrase);
aIter = sqlite3_malloc64(sizeof(LcsIterator) * pCsr->nPhrase);
if( !aIter ) return SQLITE_NOMEM;
memset(aIter, 0, sizeof(LcsIterator) * pCsr->nPhrase);
(void)fts3ExprIterate(pCsr->pExpr, fts3MatchinfoLcsCb, (void*)aIter);
@@ -1137,13 +1147,16 @@ static int fts3MatchinfoLcs(Fts3Cursor *pCsr, MatchInfo *pInfo){
int nLive = 0; /* Number of iterators in aIter not at EOF */
for(i=0; i<pInfo->nPhrase; i++){
int rc;
LcsIterator *pIt = &aIter[i];
rc = sqlite3Fts3EvalPhrasePoslist(pCsr, pIt->pExpr, iCol, &pIt->pRead);
if( rc!=SQLITE_OK ) return rc;
if( rc!=SQLITE_OK ) goto matchinfo_lcs_out;
if( pIt->pRead ){
pIt->iPos = pIt->iPosOffset;
fts3LcsIteratorAdvance(&aIter[i]);
fts3LcsIteratorAdvance(pIt);
if( pIt->pRead==0 ){
rc = FTS_CORRUPT_VTAB;
goto matchinfo_lcs_out;
}
nLive++;
}
}
@@ -1175,8 +1188,9 @@ static int fts3MatchinfoLcs(Fts3Cursor *pCsr, MatchInfo *pInfo){
pInfo->aMatchinfo[iCol] = nLcs;
}
matchinfo_lcs_out:
sqlite3_free(aIter);
return SQLITE_OK;
return rc;
}
/*
@@ -1272,7 +1286,7 @@ static int fts3MatchinfoValues(
case FTS3_MATCHINFO_LHITS: {
int nZero = fts3MatchinfoSize(pInfo, zArg[i]) * sizeof(u32);
memset(pInfo->aMatchinfo, 0, nZero);
fts3ExprLHitGather(pCsr->pExpr, pInfo);
rc = fts3ExprLHitGather(pCsr->pExpr, pInfo);
break;
}
@@ -1424,6 +1438,10 @@ void sqlite3Fts3Snippet(
return;
}
/* Limit the snippet length to 64 tokens. */
if( nToken<-64 ) nToken = -64;
if( nToken>+64 ) nToken = +64;
for(nSnippet=1; 1; nSnippet++){
int iSnip; /* Loop counter 0..nSnippet-1 */
@@ -1525,7 +1543,7 @@ static int fts3ExprTermOffsetInit(Fts3Expr *pExpr, int iPhrase, void *ctx){
nTerm = pExpr->pPhrase->nToken;
if( pList ){
fts3GetDeltaPosition(&pList, &iPos);
assert( iPos>=0 );
assert_fts3_nc( iPos>=0 );
}
for(iTerm=0; iTerm<nTerm; iTerm++){
@@ -1566,7 +1584,7 @@ void sqlite3Fts3Offsets(
if( rc!=SQLITE_OK ) goto offsets_out;
/* Allocate the array of TermOffset iterators. */
sCtx.aTerm = (TermOffset *)sqlite3_malloc(sizeof(TermOffset)*nToken);
sCtx.aTerm = (TermOffset *)sqlite3_malloc64(sizeof(TermOffset)*nToken);
if( 0==sCtx.aTerm ){
rc = SQLITE_NOMEM;
goto offsets_out;
@@ -1635,7 +1653,7 @@ void sqlite3Fts3Offsets(
/* All offsets for this column have been gathered. */
rc = SQLITE_DONE;
}else{
assert( iCurrent<=iMinPos );
assert_fts3_nc( iCurrent<=iMinPos );
if( 0==(0xFE&*pTerm->pList) ){
pTerm->pList = 0;
}else{
+3 -3
View File
@@ -68,9 +68,9 @@ static int fts3termConnectMethod(
char const *zFts3; /* Name of fts3 table */
int nDb; /* Result of strlen(zDb) */
int nFts3; /* Result of strlen(zFts3) */
int nByte; /* Bytes of space to allocate here */
sqlite3_int64 nByte; /* Bytes of space to allocate here */
int rc; /* value returned by declare_vtab() */
Fts3termTable *p; /* Virtual table object to return */
Fts3termTable *p; /* Virtual table object to return */
int iIndex = 0;
UNUSED_PARAMETER(pCtx);
@@ -96,7 +96,7 @@ static int fts3termConnectMethod(
if( rc!=SQLITE_OK ) return rc;
nByte = sizeof(Fts3termTable) + sizeof(Fts3Table) + nDb + nFts3 + 2;
p = (Fts3termTable *)sqlite3_malloc(nByte);
p = (Fts3termTable *)sqlite3_malloc64(nByte);
if( !p ) return SQLITE_NOMEM;
memset(p, 0, nByte);
+30 -1
View File
@@ -574,6 +574,33 @@ static int SQLITE_TCLAPI fts3_test_varint_cmd(
** End of tokenizer code.
**************************************************************************/
/*
** sqlite3_fts3_may_be_corrupt BOOLEAN
**
** Set or clear the global "may-be-corrupt" flag. Return the old value.
*/
static int SQLITE_TCLAPI fts3_may_be_corrupt(
void * clientData,
Tcl_Interp *interp,
int objc,
Tcl_Obj *CONST objv[]
){
int bOld = sqlite3_fts3_may_be_corrupt;
if( objc!=2 && objc!=1 ){
Tcl_WrongNumArgs(interp, 1, objv, "?BOOLEAN?");
return TCL_ERROR;
}
if( objc==2 ){
int bNew;
if( Tcl_GetBooleanFromObj(interp, objv[1], &bNew) ) return TCL_ERROR;
sqlite3_fts3_may_be_corrupt = bNew;
}
Tcl_SetObjResult(interp, Tcl_NewIntObj(bOld));
return TCL_OK;
}
int Sqlitetestfts3_Init(Tcl_Interp *interp){
Tcl_CreateObjCommand(interp, "fts3_near_match", fts3_near_match_cmd, 0, 0);
Tcl_CreateObjCommand(interp,
@@ -582,10 +609,12 @@ int Sqlitetestfts3_Init(Tcl_Interp *interp){
Tcl_CreateObjCommand(
interp, "fts3_test_tokenizer", fts3_test_tokenizer_cmd, 0, 0
);
Tcl_CreateObjCommand(
interp, "fts3_test_varint", fts3_test_varint_cmd, 0, 0
);
Tcl_CreateObjCommand(
interp, "sqlite3_fts3_may_be_corrupt", fts3_may_be_corrupt, 0, 0
);
return TCL_OK;
}
#endif /* SQLITE_ENABLE_FTS3 || SQLITE_ENABLE_FTS4 */
+1 -1
View File
@@ -122,7 +122,7 @@ static int fts3tokDequoteArray(
nByte += (int)(strlen(argv[i]) + 1);
}
*pazDequote = azDequote = sqlite3_malloc(sizeof(char *)*argc + nByte);
*pazDequote = azDequote = sqlite3_malloc64(sizeof(char *)*argc + nByte);
if( azDequote==0 ){
rc = SQLITE_NOMEM;
}else{
+3 -1
View File
@@ -106,7 +106,9 @@ static void fts3TokenizerFunc(
return;
}
}
sqlite3_result_blob(context, (void *)&pPtr, sizeof(pPtr), SQLITE_TRANSIENT);
if( fts3TokenizerEnabled(context) ){
sqlite3_result_blob(context, (void *)&pPtr, sizeof(pPtr), SQLITE_TRANSIENT);
}
}
int sqlite3Fts3IsIdChar(char c){
+2 -2
View File
@@ -155,7 +155,7 @@ static int unicodeAddExceptions(
int *aNew; /* New aiException[] array */
int nNew; /* Number of valid entries in array aNew[] */
aNew = sqlite3_realloc(p->aiException, (p->nException+nEntry)*sizeof(int));
aNew = sqlite3_realloc64(p->aiException,(p->nException+nEntry)*sizeof(int));
if( aNew==0 ) return SQLITE_NOMEM;
nNew = p->nException;
@@ -344,7 +344,7 @@ static int unicodeNext(
/* Grow the output buffer if required. */
if( (zOut-pCsr->zToken)>=(pCsr->nAlloc-4) ){
char *zNew = sqlite3_realloc(pCsr->zToken, pCsr->nAlloc+64);
char *zNew = sqlite3_realloc64(pCsr->zToken, pCsr->nAlloc+64);
if( !zNew ) return SQLITE_NOMEM;
zOut = &zNew[zOut - pCsr->zToken];
pCsr->zToken = zNew;
+26 -25
View File
@@ -1,5 +1,5 @@
/*
** 2012 May 25
** 2012-05-25
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
@@ -178,28 +178,29 @@ static int remove_diacritic(int c, int bComplex){
62830, 62890, 62924, 62974, 63032, 63050, 63082, 63118,
63182, 63242, 63274, 63310, 63368, 63390,
};
char aChar[] = {
'\0', 'a'|0x00, 'c'|0x00, 'e'|0x00, 'i'|0x00, 'n'|0x00,
'o'|0x00, 'u'|0x00, 'y'|0x00, 'y'|0x00, 'a'|0x00, 'c'|0x00,
'd'|0x00, 'e'|0x00, 'e'|0x00, 'g'|0x00, 'h'|0x00, 'i'|0x00,
'j'|0x00, 'k'|0x00, 'l'|0x00, 'n'|0x00, 'o'|0x00, 'r'|0x00,
's'|0x00, 't'|0x00, 'u'|0x00, 'u'|0x00, 'w'|0x00, 'y'|0x00,
'z'|0x00, 'o'|0x00, 'u'|0x00, 'a'|0x00, 'i'|0x00, 'o'|0x00,
'u'|0x00, 'u'|0x80, 'a'|0x80, 'g'|0x00, 'k'|0x00, 'o'|0x00,
'o'|0x80, 'j'|0x00, 'g'|0x00, 'n'|0x00, 'a'|0x80, 'a'|0x00,
'e'|0x00, 'i'|0x00, 'o'|0x00, 'r'|0x00, 'u'|0x00, 's'|0x00,
't'|0x00, 'h'|0x00, 'a'|0x00, 'e'|0x00, 'o'|0x80, 'o'|0x00,
'o'|0x80, 'y'|0x00, '\0', '\0', '\0', '\0',
'\0', '\0', '\0', '\0', 'a'|0x00, 'b'|0x00,
'c'|0x80, 'd'|0x00, 'd'|0x00, 'e'|0x80, 'e'|0x00, 'e'|0x80,
'f'|0x00, 'g'|0x00, 'h'|0x00, 'h'|0x00, 'i'|0x00, 'i'|0x80,
'k'|0x00, 'l'|0x00, 'l'|0x80, 'l'|0x00, 'm'|0x00, 'n'|0x00,
'o'|0x80, 'p'|0x00, 'r'|0x00, 'r'|0x80, 'r'|0x00, 's'|0x00,
's'|0x80, 't'|0x00, 'u'|0x00, 'u'|0x80, 'v'|0x00, 'w'|0x00,
'w'|0x00, 'x'|0x00, 'y'|0x00, 'z'|0x00, 'h'|0x00, 't'|0x00,
'w'|0x00, 'y'|0x00, 'a'|0x00, 'a'|0x80, 'a'|0x80, 'a'|0x80,
'e'|0x00, 'e'|0x80, 'e'|0x80, 'i'|0x00, 'o'|0x00, 'o'|0x80,
'o'|0x80, 'o'|0x80, 'u'|0x00, 'u'|0x80, 'u'|0x80, 'y'|0x00,
#define HIBIT ((unsigned char)0x80)
unsigned char aChar[] = {
'\0', 'a', 'c', 'e', 'i', 'n',
'o', 'u', 'y', 'y', 'a', 'c',
'd', 'e', 'e', 'g', 'h', 'i',
'j', 'k', 'l', 'n', 'o', 'r',
's', 't', 'u', 'u', 'w', 'y',
'z', 'o', 'u', 'a', 'i', 'o',
'u', 'u'|HIBIT, 'a'|HIBIT, 'g', 'k', 'o',
'o'|HIBIT, 'j', 'g', 'n', 'a'|HIBIT, 'a',
'e', 'i', 'o', 'r', 'u', 's',
't', 'h', 'a', 'e', 'o'|HIBIT, 'o',
'o'|HIBIT, 'y', '\0', '\0', '\0', '\0',
'\0', '\0', '\0', '\0', 'a', 'b',
'c'|HIBIT, 'd', 'd', 'e'|HIBIT, 'e', 'e'|HIBIT,
'f', 'g', 'h', 'h', 'i', 'i'|HIBIT,
'k', 'l', 'l'|HIBIT, 'l', 'm', 'n',
'o'|HIBIT, 'p', 'r', 'r'|HIBIT, 'r', 's',
's'|HIBIT, 't', 'u', 'u'|HIBIT, 'v', 'w',
'w', 'x', 'y', 'z', 'h', 't',
'w', 'y', 'a', 'a'|HIBIT, 'a'|HIBIT, 'a'|HIBIT,
'e', 'e'|HIBIT, 'e'|HIBIT, 'i', 'o', 'o'|HIBIT,
'o'|HIBIT, 'o'|HIBIT, 'u', 'u'|HIBIT, 'u'|HIBIT, 'y',
};
unsigned int key = (((unsigned int)c)<<3) | 0x00000007;
@@ -230,8 +231,8 @@ int sqlite3FtsUnicodeIsdiacritic(int c){
unsigned int mask1 = 0x000361F8;
if( c<768 || c>817 ) return 0;
return (c < 768+32) ?
(mask0 & (1 << (c-768))) :
(mask1 & (1 << (c-768-32)));
(mask0 & ((unsigned int)1 << (c-768))) :
(mask1 & ((unsigned int)1 << (c-768-32)));
}
+38 -19
View File
@@ -396,10 +396,12 @@ static int fts3SqlStmt(
pStmt = p->aStmt[eStmt];
if( !pStmt ){
int f = SQLITE_PREPARE_PERSISTENT|SQLITE_PREPARE_NO_VTAB;
char *zSql;
if( eStmt==SQL_CONTENT_INSERT ){
zSql = sqlite3_mprintf(azSql[eStmt], p->zDb, p->zName, p->zWriteExprlist);
}else if( eStmt==SQL_SELECT_CONTENT_BY_ROWID ){
f &= ~SQLITE_PREPARE_NO_VTAB;
zSql = sqlite3_mprintf(azSql[eStmt], p->zReadExprlist);
}else{
zSql = sqlite3_mprintf(azSql[eStmt], p->zDb, p->zName);
@@ -407,8 +409,7 @@ static int fts3SqlStmt(
if( !zSql ){
rc = SQLITE_NOMEM;
}else{
rc = sqlite3_prepare_v3(p->db, zSql, -1, SQLITE_PREPARE_PERSISTENT,
&pStmt, NULL);
rc = sqlite3_prepare_v3(p->db, zSql, -1, f, &pStmt, NULL);
sqlite3_free(zSql);
assert( rc==SQLITE_OK || pStmt==0 );
p->aStmt[eStmt] = pStmt;
@@ -566,7 +567,7 @@ static sqlite3_int64 getAbsoluteLevel(
int iLevel /* Level of segments */
){
sqlite3_int64 iBase; /* First absolute level for iLangid/iIndex */
assert( iLangid>=0 );
assert_fts3_nc( iLangid>=0 );
assert( p->nIndex>0 );
assert( iIndex>=0 && iIndex<p->nIndex );
@@ -1347,7 +1348,9 @@ static int fts3SegReaderNext(
/* If iCurrentBlock>=iLeafEndBlock, this is an EOF condition. All leaf
** blocks have already been traversed. */
assert( pReader->iCurrentBlock<=pReader->iLeafEndBlock );
#ifdef CORRUPT_DB
assert( pReader->iCurrentBlock<=pReader->iLeafEndBlock || CORRUPT_DB );
#endif
if( pReader->iCurrentBlock>=pReader->iLeafEndBlock ){
return SQLITE_OK;
}
@@ -1408,7 +1411,7 @@ static int fts3SegReaderNext(
** b-tree node. And that the final byte of the doclist is 0x00. If either
** of these statements is untrue, then the data structure is corrupt.
*/
if( (&pReader->aNode[pReader->nNode] - pReader->aDoclist)<pReader->nDoclist
if( pReader->nDoclist > pReader->nNode-(pReader->aDoclist-pReader->aNode)
|| (pReader->nPopulate==0 && pReader->aDoclist[pReader->nDoclist-1])
){
return FTS_CORRUPT_VTAB;
@@ -1608,8 +1611,13 @@ int sqlite3Fts3SegReaderNew(
Fts3SegReader *pReader; /* Newly allocated SegReader object */
int nExtra = 0; /* Bytes to allocate segment root node */
assert( iStartLeaf<=iEndLeaf );
assert( zRoot!=0 || nRoot==0 );
#ifdef CORRUPT_DB
assert( zRoot!=0 || CORRUPT_DB );
#endif
if( iStartLeaf==0 ){
if( iEndLeaf!=0 ) return FTS_CORRUPT_VTAB;
nExtra = nRoot + FTS3_NODE_PADDING;
}
@@ -1629,7 +1637,7 @@ int sqlite3Fts3SegReaderNew(
pReader->aNode = (char *)&pReader[1];
pReader->rootOnly = 1;
pReader->nNode = nRoot;
memcpy(pReader->aNode, zRoot, nRoot);
if( nRoot ) memcpy(pReader->aNode, zRoot, nRoot);
memset(&pReader->aNode[nRoot], 0, FTS3_NODE_PADDING);
}else{
pReader->iCurrentBlock = iStartLeaf-1;
@@ -2249,6 +2257,11 @@ static int fts3SegWriterAdd(
nPrefix = fts3PrefixCompress(pWriter->zTerm, pWriter->nTerm, zTerm, nTerm);
nSuffix = nTerm-nPrefix;
/* If nSuffix is zero or less, then zTerm/nTerm must be a prefix of
** pWriter->zTerm/pWriter->nTerm. i.e. must be equal to or less than when
** compared with BINARY collation. This indicates corruption. */
if( nSuffix<=0 ) return FTS_CORRUPT_VTAB;
/* Figure out how many bytes are required by this new entry */
nReq = sqlite3Fts3VarintLen(nPrefix) + /* varint containing prefix size */
sqlite3Fts3VarintLen(nSuffix) + /* varint containing suffix size */
@@ -2956,7 +2969,9 @@ int sqlite3Fts3SegReaderStep(
}else{
iDelta = iDocid - iPrev;
}
assert( iDelta>0 || (nDoclist==0 && iDelta==iDocid) );
if( iDelta<=0 && (nDoclist>0 || iDelta!=iDocid) ){
return FTS_CORRUPT_VTAB;
}
assert( nDoclist>0 || iDelta==iDocid );
nByte = sqlite3Fts3VarintLen(iDelta) + (isRequirePos?nList+1:0);
@@ -3222,8 +3237,10 @@ static int fts3SegmentMerge(
if( rc!=SQLITE_OK ) goto finished;
assert( csr.nSegment>0 );
assert( iNewLevel>=getAbsoluteLevel(p, iLangid, iIndex, 0) );
assert( iNewLevel<getAbsoluteLevel(p, iLangid, iIndex,FTS3_SEGDIR_MAXLEVEL) );
assert_fts3_nc( iNewLevel>=getAbsoluteLevel(p, iLangid, iIndex, 0) );
assert_fts3_nc(
iNewLevel<getAbsoluteLevel(p, iLangid, iIndex,FTS3_SEGDIR_MAXLEVEL)
);
memset(&filter, 0, sizeof(Fts3SegFilter));
filter.flags = FTS3_SEGMENT_REQUIRE_POS;
@@ -3322,14 +3339,16 @@ static void fts3DecodeIntArray(
const char *zBuf, /* The BLOB containing the varints */
int nBuf /* size of the BLOB */
){
int i, j;
UNUSED_PARAMETER(nBuf);
for(i=j=0; i<N; i++){
sqlite3_int64 x;
j += sqlite3Fts3GetVarint(&zBuf[j], &x);
assert(j<=nBuf);
a[i] = (u32)(x & 0xffffffff);
int i = 0;
if( nBuf && (zBuf[nBuf-1]&0x80)==0 ){
int j;
for(i=j=0; i<N && j<nBuf; i++){
sqlite3_int64 x;
j += sqlite3Fts3GetVarint(&zBuf[j], &x);
a[i] = (u32)(x & 0xffffffff);
}
}
while( i<N ) a[i++] = 0;
}
/*
@@ -3735,7 +3754,7 @@ static int nodeReaderNext(NodeReader *p){
p->iOff += fts3GetVarint32(&p->aNode[p->iOff], &nSuffix);
if( nPrefix>p->iOff || nSuffix>p->nNode-p->iOff ){
return SQLITE_CORRUPT_VTAB;
return FTS_CORRUPT_VTAB;
}
blobGrowBuffer(&p->term, nPrefix+nSuffix, &rc);
if( rc==SQLITE_OK ){
@@ -3745,7 +3764,7 @@ static int nodeReaderNext(NodeReader *p){
if( p->iChild==0 ){
p->iOff += fts3GetVarint32(&p->aNode[p->iOff], &p->nDoclist);
if( (p->nNode-p->iOff)<p->nDoclist ){
return SQLITE_CORRUPT_VTAB;
return FTS_CORRUPT_VTAB;
}
p->aDoclist = &p->aNode[p->iOff];
p->iOff += p->nDoclist;
+9 -8
View File
@@ -63,14 +63,15 @@ proc print_rd {map} {
}
puts ""
puts " \};"
puts " char aChar\[\] = \{"
puts "#define HIBIT ((unsigned char)0x80)"
puts " unsigned char aChar\[\] = \{"
puts -nonewline " '\\0', "
set i 1
foreach c $aChar f $aFlag {
if { $f } {
set str "'$c'|0x80, "
set str "'$c'|HIBIT, "
} else {
set str "'$c'|0x00, "
set str "'$c', "
}
if {$c == ""} { set str "'\\0', " }
@@ -134,8 +135,8 @@ proc print_isdiacritic {zFunc map} {
puts " if( c<$iFirst || c>$iLast ) return 0;"
puts " return (c < $iFirst+32) ?"
puts " (mask0 & (1 << (c-$iFirst))) :"
puts " (mask1 & (1 << (c-$iFirst-32)));"
puts " (mask0 & ((unsigned int)1 << (c-$iFirst))) :"
puts " (mask1 & ((unsigned int)1 << (c-$iFirst-32)));"
puts "\}"
}
@@ -699,7 +700,7 @@ proc print_categories {lMap} {
static u16 aFts5UnicodeMap[] = {$aMapArray};
static u16 aFts5UnicodeData[] = {$aDataArray};
int sqlite3Fts5UnicodeCategory(int iCode) {
int sqlite3Fts5UnicodeCategory(u32 iCode) {
int iRes = -1;
int iHi;
int iLo;
@@ -782,7 +783,7 @@ proc print_test_categories {lMap} {
aArray[0] = 1;
}
c = sqlite3Fts5UnicodeCategory(i);
c = sqlite3Fts5UnicodeCategory((u32)i);
if( aArray[c]==0 ){
*piCode = i;
return 1;
@@ -837,7 +838,7 @@ proc print_fold_test {zFunc mappings} {
proc print_fileheader {} {
puts [string trim {
/*
** 2012 May 25
** 2012-05-25
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
+10 -14
View File
@@ -120,12 +120,8 @@ struct Fts5PhraseIter {
**
** Usually, output parameter *piPhrase is set to the phrase number, *piCol
** to the column in which it occurs and *piOff the token offset of the
** first token of the phrase. The exception is if the table was created
** with the offsets=0 option specified. In this case *piOff is always
** set to -1.
**
** Returns SQLITE_OK if successful, or an error code (i.e. SQLITE_NOMEM)
** if an error occurs.
** first token of the phrase. Returns SQLITE_OK if successful, or an error
** code (i.e. SQLITE_NOMEM) if an error occurs.
**
** This API can be quite slow if used with an FTS5 table created with the
** "detail=none" or "detail=column" option.
@@ -166,7 +162,7 @@ struct Fts5PhraseIter {
** Save the pointer passed as the second argument as the extension functions
** "auxiliary data". The pointer may then be retrieved by the current or any
** future invocation of the same fts5 extension function made as part of
** of the same MATCH query using the xGetAuxdata() API.
** the same MATCH query using the xGetAuxdata() API.
**
** Each extension function is allocated a single auxiliary data slot for
** each FTS query (MATCH expression). If the extension function is invoked
@@ -181,7 +177,7 @@ struct Fts5PhraseIter {
** The xDelete callback, if one is specified, is also invoked on the
** auxiliary data pointer after the FTS5 query has finished.
**
** If an error (e.g. an OOM condition) occurs within this function, an
** If an error (e.g. an OOM condition) occurs within this function,
** the auxiliary data is set to NULL and an error code returned. If the
** xDelete parameter was not NULL, it is invoked on the auxiliary data
** pointer before returning.
@@ -414,11 +410,11 @@ struct Fts5ExtensionApi {
** the tokenizer substitutes "first" for "1st" and the query works
** as expected.
**
** <li> By adding multiple synonyms for a single term to the FTS index.
** In this case, when tokenizing query text, the tokenizer may
** provide multiple synonyms for a single term within the document.
** FTS5 then queries the index for each synonym individually. For
** example, faced with the query:
** <li> By querying the index for all synonyms of each query term
** separately. In this case, when tokenizing query text, the
** tokenizer may provide multiple synonyms for a single term
** within the document. FTS5 then queries the index for each
** synonym individually. For example, faced with the query:
**
** <codeblock>
** ... MATCH 'first place'</codeblock>
@@ -442,7 +438,7 @@ struct Fts5ExtensionApi {
** "place".
**
** This way, even if the tokenizer does not provide synonyms
** when tokenizing query text (it should not - to do would be
** when tokenizing query text (it should not - to do so would be
** inefficient), it doesn't matter if the user queries for
** 'first + place' or '1st + place', as there are entries in the
** FTS index corresponding to both forms of the first token.
+25 -6
View File
@@ -87,6 +87,12 @@ extern int sqlite3_fts5_may_be_corrupt;
# define assert_nc(x) assert(x)
#endif
/*
** A version of memcmp() that does not cause asan errors if one of the pointer
** parameters is NULL and the number of bytes to compare is zero.
*/
#define fts5Memcmp(s1, s2, n) ((n)==0 ? 0 : memcmp((s1), (s2), (n)))
/* Mark a function parameter as unused, to suppress nuisance compiler
** warnings. */
#ifndef UNUSED_PARAM
@@ -274,7 +280,7 @@ void sqlite3Fts5Put32(u8*, int);
int sqlite3Fts5Get32(const u8*);
#define FTS5_POS2COLUMN(iPos) (int)(iPos >> 32)
#define FTS5_POS2OFFSET(iPos) (int)(iPos & 0xFFFFFFFF)
#define FTS5_POS2OFFSET(iPos) (int)(iPos & 0x7FFFFFFF)
typedef struct Fts5PoslistReader Fts5PoslistReader;
struct Fts5PoslistReader {
@@ -309,7 +315,7 @@ int sqlite3Fts5PoslistNext64(
);
/* Malloc utility */
void *sqlite3Fts5MallocZero(int *pRc, int nByte);
void *sqlite3Fts5MallocZero(int *pRc, sqlite3_int64 nByte);
char *sqlite3Fts5Strndup(int *pRc, const char *pIn, int nIn);
/* Character set tests (like isspace(), isalpha() etc.) */
@@ -520,9 +526,19 @@ int sqlite3Fts5PutVarint(unsigned char *p, u64 v);
/**************************************************************************
** Interface to code in fts5.c.
** Interface to code in fts5_main.c.
*/
/*
** Virtual-table object.
*/
typedef struct Fts5Table Fts5Table;
struct Fts5Table {
sqlite3_vtab base; /* Base class used by SQLite core */
Fts5Config *pConfig; /* Virtual table configuration */
Fts5Index *pIndex; /* Full-text index */
};
int sqlite3Fts5GetTokenizer(
Fts5Global*,
const char **azArg,
@@ -532,7 +548,9 @@ int sqlite3Fts5GetTokenizer(
char **pzErr
);
Fts5Index *sqlite3Fts5IndexFromCsrid(Fts5Global*, i64, Fts5Config **);
Fts5Table *sqlite3Fts5TableFromCsrid(Fts5Global*, i64);
int sqlite3Fts5FlushToDisk(Fts5Table*);
/*
** End of interface to code in fts5.c.
@@ -565,8 +583,9 @@ void sqlite3Fts5HashClear(Fts5Hash*);
int sqlite3Fts5HashQuery(
Fts5Hash*, /* Hash table to query */
int nPre,
const char *pTerm, int nTerm, /* Query term */
const u8 **ppDoclist, /* OUT: Pointer to doclist for pTerm */
void **ppObj, /* OUT: Pointer to doclist for pTerm */
int *pnDoclist /* OUT: Size of doclist in bytes */
);
@@ -788,7 +807,7 @@ int sqlite3Fts5UnicodeIsdiacritic(int c);
int sqlite3Fts5UnicodeFold(int c, int bRemoveDiacritic);
int sqlite3Fts5UnicodeCatParse(const char*, u8*);
int sqlite3Fts5UnicodeCategory(int iCode);
int sqlite3Fts5UnicodeCategory(u32 iCode);
void sqlite3Fts5UnicodeAscii(u8*, u8*);
/*
** End of interface to code in fts5_unicode2.c.
+11 -9
View File
@@ -136,7 +136,7 @@ static void fts5HighlightAppend(
HighlightContext *p,
const char *z, int n
){
if( *pRc==SQLITE_OK ){
if( *pRc==SQLITE_OK && z ){
if( n<0 ) n = (int)strlen(z);
p->zOut = sqlite3_mprintf("%z%.*s", p->zOut, n, z);
if( p->zOut==0 ) *pRc = SQLITE_NOMEM;
@@ -268,7 +268,7 @@ static int fts5SentenceFinderAdd(Fts5SFinder *p, int iAdd){
int nNew = p->nFirstAlloc ? p->nFirstAlloc*2 : 64;
int *aNew;
aNew = (int*)sqlite3_realloc(p->aFirst, nNew*sizeof(int));
aNew = (int*)sqlite3_realloc64(p->aFirst, nNew*sizeof(int));
if( aNew==0 ) return SQLITE_NOMEM;
p->aFirst = aNew;
p->nFirstAlloc = nNew;
@@ -335,11 +335,12 @@ static int fts5SnippetScore(
int nInst;
int nScore = 0;
int iLast = 0;
sqlite3_int64 iEnd = (sqlite3_int64)iPos + nToken;
rc = pApi->xInstCount(pFts, &nInst);
for(i=0; i<nInst && rc==SQLITE_OK; i++){
rc = pApi->xInst(pFts, i, &ip, &ic, &iOff);
if( rc==SQLITE_OK && ic==iCol && iOff>=iPos && iOff<(iPos+nToken) ){
if( rc==SQLITE_OK && ic==iCol && iOff>=iPos && iOff<iEnd ){
nScore += (aSeen[ip] ? 1 : 1000);
aSeen[ip] = 1;
if( iFirst<0 ) iFirst = iOff;
@@ -349,7 +350,7 @@ static int fts5SnippetScore(
*pnScore = nScore;
if( piPos ){
int iAdj = iFirst - (nToken - (iLast-iFirst)) / 2;
sqlite3_int64 iAdj = iFirst - (nToken - (iLast-iFirst)) / 2;
if( (iAdj+nToken)>nDocsize ) iAdj = nDocsize - nToken;
if( iAdj<0 ) iAdj = 0;
*piPos = iAdj;
@@ -442,7 +443,9 @@ static void fts5SnippetFunction(
int jj;
rc = pApi->xInst(pFts, ii, &ip, &ic, &io);
if( ic!=i || rc!=SQLITE_OK ) continue;
if( ic!=i ) continue;
if( io>nDocsize ) rc = FTS5_CORRUPT;
if( rc!=SQLITE_OK ) continue;
memset(aSeen, 0, nPhrase);
rc = fts5SnippetScore(pApi, pFts, nDocsize, aSeen, i,
io, nToken, &nScore, &iAdj
@@ -568,13 +571,13 @@ static int fts5Bm25GetData(
int nPhrase; /* Number of phrases in query */
sqlite3_int64 nRow = 0; /* Number of rows in table */
sqlite3_int64 nToken = 0; /* Number of tokens in table */
int nByte; /* Bytes of space to allocate */
sqlite3_int64 nByte; /* Bytes of space to allocate */
int i;
/* Allocate the Fts5Bm25Data object */
nPhrase = pApi->xPhraseCount(pFts);
nByte = sizeof(Fts5Bm25Data) + nPhrase*2*sizeof(double);
p = (Fts5Bm25Data*)sqlite3_malloc(nByte);
p = (Fts5Bm25Data*)sqlite3_malloc64(nByte);
if( p==0 ){
rc = SQLITE_NOMEM;
}else{
@@ -586,6 +589,7 @@ static int fts5Bm25GetData(
/* Calculate the average document length for this FTS5 table */
if( rc==SQLITE_OK ) rc = pApi->xRowCount(pFts, &nRow);
assert( rc!=SQLITE_OK || nRow>0 );
if( rc==SQLITE_OK ) rc = pApi->xColumnTotalSize(pFts, -1, &nToken);
if( rc==SQLITE_OK ) p->avgdl = (double)nToken / (double)nRow;
@@ -710,5 +714,3 @@ int sqlite3Fts5AuxInit(fts5_api *pApi){
return rc;
}
+6 -6
View File
@@ -17,12 +17,12 @@
int sqlite3Fts5BufferSize(int *pRc, Fts5Buffer *pBuf, u32 nByte){
if( (u32)pBuf->nSpace<nByte ){
u32 nNew = pBuf->nSpace ? pBuf->nSpace : 64;
u64 nNew = pBuf->nSpace ? pBuf->nSpace : 64;
u8 *pNew;
while( nNew<nByte ){
nNew = nNew * 2;
}
pNew = sqlite3_realloc(pBuf->p, nNew);
pNew = sqlite3_realloc64(pBuf->p, nNew);
if( pNew==0 ){
*pRc = SQLITE_NOMEM;
return 1;
@@ -52,7 +52,7 @@ void sqlite3Fts5Put32(u8 *aBuf, int iVal){
}
int sqlite3Fts5Get32(const u8 *aBuf){
return (aBuf[0] << 24) + (aBuf[1] << 16) + (aBuf[2] << 8) + aBuf[3];
return (int)((((u32)aBuf[0])<<24) + (aBuf[1]<<16) + (aBuf[2]<<8) + aBuf[3]);
}
/*
@@ -183,7 +183,7 @@ int sqlite3Fts5PoslistNext64(
iOff = ((i64)iVal) << 32;
fts5FastGetVarint32(a, i, iVal);
}
*piOff = iOff + (iVal-2);
*piOff = iOff + ((iVal-2) & 0x7FFFFFFF);
*pi = i;
return 0;
}
@@ -244,10 +244,10 @@ int sqlite3Fts5PoslistWriterAppend(
return SQLITE_OK;
}
void *sqlite3Fts5MallocZero(int *pRc, int nByte){
void *sqlite3Fts5MallocZero(int *pRc, sqlite3_int64 nByte){
void *pRet = 0;
if( *pRc==SQLITE_OK ){
pRet = sqlite3_malloc(nByte);
pRet = sqlite3_malloc64(nByte);
if( pRet==0 ){
if( nByte>0 ) *pRc = SQLITE_NOMEM;
}else{
+4 -4
View File
@@ -295,7 +295,7 @@ static int fts5ConfigParseSpecial(
if( sqlite3_strnicmp("tokenize", zCmd, nCmd)==0 ){
const char *p = (const char*)zArg;
int nArg = (int)strlen(zArg) + 1;
sqlite3_int64 nArg = strlen(zArg) + 1;
char **azArg = sqlite3Fts5MallocZero(&rc, sizeof(char*) * nArg);
char *pDel = sqlite3Fts5MallocZero(&rc, nArg * 2);
char *pSpace = pDel;
@@ -425,8 +425,8 @@ static const char *fts5ConfigGobbleWord(
){
const char *zRet = 0;
int nIn = (int)strlen(zIn);
char *zOut = sqlite3_malloc(nIn+1);
sqlite3_int64 nIn = strlen(zIn);
char *zOut = sqlite3_malloc64(nIn+1);
assert( *pRc==SQLITE_OK );
*pbQuoted = 0;
@@ -529,7 +529,7 @@ int sqlite3Fts5ConfigParse(
int rc = SQLITE_OK; /* Return code */
Fts5Config *pRet; /* New object to return */
int i;
int nByte;
sqlite3_int64 nByte;
*ppOut = pRet = (Fts5Config*)sqlite3_malloc(sizeof(Fts5Config));
if( pRet==0 ) return SQLITE_NOMEM;
+29 -26
View File
@@ -211,7 +211,7 @@ static int fts5ExprGetToken(
return tok;
}
static void *fts5ParseAlloc(u64 t){ return sqlite3_malloc((int)t); }
static void *fts5ParseAlloc(u64 t){ return sqlite3_malloc64((sqlite3_int64)t);}
static void fts5ParseFree(void *p){ sqlite3_free(p); }
int sqlite3Fts5ExprNew(
@@ -356,8 +356,8 @@ static int fts5ExprSynonymList(
if( sqlite3Fts5IterEof(pIter)==0 && pIter->iRowid==iRowid ){
if( pIter->nData==0 ) continue;
if( nIter==nAlloc ){
int nByte = sizeof(Fts5PoslistReader) * nAlloc * 2;
Fts5PoslistReader *aNew = (Fts5PoslistReader*)sqlite3_malloc(nByte);
sqlite3_int64 nByte = sizeof(Fts5PoslistReader) * nAlloc * 2;
Fts5PoslistReader *aNew = (Fts5PoslistReader*)sqlite3_malloc64(nByte);
if( aNew==0 ){
rc = SQLITE_NOMEM;
goto synonym_poslist_out;
@@ -437,8 +437,8 @@ static int fts5ExprPhraseIsMatch(
/* If the aStatic[] array is not large enough, allocate a large array
** using sqlite3_malloc(). This approach could be improved upon. */
if( pPhrase->nTerm>ArraySize(aStatic) ){
int nByte = sizeof(Fts5PoslistReader) * pPhrase->nTerm;
aIter = (Fts5PoslistReader*)sqlite3_malloc(nByte);
sqlite3_int64 nByte = sizeof(Fts5PoslistReader) * pPhrase->nTerm;
aIter = (Fts5PoslistReader*)sqlite3_malloc64(nByte);
if( !aIter ) return SQLITE_NOMEM;
}
memset(aIter, 0, sizeof(Fts5PoslistReader) * pPhrase->nTerm);
@@ -572,7 +572,7 @@ static int fts5ExprNearIsMatch(int *pRc, Fts5ExprNearset *pNear){
/* If the aStatic[] array is not large enough, allocate a large array
** using sqlite3_malloc(). This approach could be improved upon. */
if( pNear->nPhrase>ArraySize(aStatic) ){
int nByte = sizeof(Fts5NearTrimmer) * pNear->nPhrase;
sqlite3_int64 nByte = sizeof(Fts5NearTrimmer) * pNear->nPhrase;
a = (Fts5NearTrimmer*)sqlite3Fts5MallocZero(&rc, nByte);
}else{
memset(aStatic, 0, sizeof(aStatic));
@@ -1481,8 +1481,9 @@ Fts5ExprNearset *sqlite3Fts5ParseNearset(
return pNear;
}
if( pNear==0 ){
int nByte = sizeof(Fts5ExprNearset) + SZALLOC * sizeof(Fts5ExprPhrase*);
pRet = sqlite3_malloc(nByte);
sqlite3_int64 nByte;
nByte = sizeof(Fts5ExprNearset) + SZALLOC * sizeof(Fts5ExprPhrase*);
pRet = sqlite3_malloc64(nByte);
if( pRet==0 ){
pParse->rc = SQLITE_NOMEM;
}else{
@@ -1490,9 +1491,10 @@ Fts5ExprNearset *sqlite3Fts5ParseNearset(
}
}else if( (pNear->nPhrase % SZALLOC)==0 ){
int nNew = pNear->nPhrase + SZALLOC;
int nByte = sizeof(Fts5ExprNearset) + nNew * sizeof(Fts5ExprPhrase*);
sqlite3_int64 nByte;
pRet = (Fts5ExprNearset*)sqlite3_realloc(pNear, nByte);
nByte = sizeof(Fts5ExprNearset) + nNew * sizeof(Fts5ExprPhrase*);
pRet = (Fts5ExprNearset*)sqlite3_realloc64(pNear, nByte);
if( pRet==0 ){
pParse->rc = SQLITE_NOMEM;
}
@@ -1556,8 +1558,8 @@ static int fts5ParseTokenize(
if( pPhrase && pPhrase->nTerm>0 && (tflags & FTS5_TOKEN_COLOCATED) ){
Fts5ExprTerm *pSyn;
int nByte = sizeof(Fts5ExprTerm) + sizeof(Fts5Buffer) + nToken+1;
pSyn = (Fts5ExprTerm*)sqlite3_malloc(nByte);
sqlite3_int64 nByte = sizeof(Fts5ExprTerm) + sizeof(Fts5Buffer) + nToken+1;
pSyn = (Fts5ExprTerm*)sqlite3_malloc64(nByte);
if( pSyn==0 ){
rc = SQLITE_NOMEM;
}else{
@@ -1573,7 +1575,7 @@ static int fts5ParseTokenize(
Fts5ExprPhrase *pNew;
int nNew = SZALLOC + (pPhrase ? pPhrase->nTerm : 0);
pNew = (Fts5ExprPhrase*)sqlite3_realloc(pPhrase,
pNew = (Fts5ExprPhrase*)sqlite3_realloc64(pPhrase,
sizeof(Fts5ExprPhrase) + sizeof(Fts5ExprTerm) * nNew
);
if( pNew==0 ){
@@ -1659,9 +1661,9 @@ Fts5ExprPhrase *sqlite3Fts5ParseTerm(
if( pAppend==0 ){
if( (pParse->nPhrase % 8)==0 ){
int nByte = sizeof(Fts5ExprPhrase*) * (pParse->nPhrase + 8);
sqlite3_int64 nByte = sizeof(Fts5ExprPhrase*) * (pParse->nPhrase + 8);
Fts5ExprPhrase **apNew;
apNew = (Fts5ExprPhrase**)sqlite3_realloc(pParse->apPhrase, nByte);
apNew = (Fts5ExprPhrase**)sqlite3_realloc64(pParse->apPhrase, nByte);
if( apNew==0 ){
pParse->rc = SQLITE_NOMEM;
fts5ExprPhraseFree(sCtx.pPhrase);
@@ -1716,8 +1718,10 @@ int sqlite3Fts5ExprClonePhrase(
if( rc==SQLITE_OK ){
Fts5Colset *pColsetOrig = pOrig->pNode->pNear->pColset;
if( pColsetOrig ){
int nByte = sizeof(Fts5Colset) + (pColsetOrig->nCol-1) * sizeof(int);
Fts5Colset *pColset = (Fts5Colset*)sqlite3Fts5MallocZero(&rc, nByte);
sqlite3_int64 nByte;
Fts5Colset *pColset;
nByte = sizeof(Fts5Colset) + (pColsetOrig->nCol-1) * sizeof(int);
pColset = (Fts5Colset*)sqlite3Fts5MallocZero(&rc, nByte);
if( pColset ){
memcpy(pColset, pColsetOrig, nByte);
}
@@ -1837,7 +1841,7 @@ static Fts5Colset *fts5ParseColset(
assert( pParse->rc==SQLITE_OK );
assert( iCol>=0 && iCol<pParse->pConfig->nCol );
pNew = sqlite3_realloc(p, sizeof(Fts5Colset) + sizeof(int)*nCol);
pNew = sqlite3_realloc64(p, sizeof(Fts5Colset) + sizeof(int)*nCol);
if( pNew==0 ){
pParse->rc = SQLITE_NOMEM;
}else{
@@ -1933,7 +1937,7 @@ Fts5Colset *sqlite3Fts5ParseColset(
static Fts5Colset *fts5CloneColset(int *pRc, Fts5Colset *pOrig){
Fts5Colset *pRet;
if( pOrig ){
int nByte = sizeof(Fts5Colset) + (pOrig->nCol-1) * sizeof(int);
sqlite3_int64 nByte = sizeof(Fts5Colset) + (pOrig->nCol-1) * sizeof(int);
pRet = (Fts5Colset*)sqlite3Fts5MallocZero(pRc, nByte);
if( pRet ){
memcpy(pRet, pOrig, nByte);
@@ -2087,7 +2091,7 @@ Fts5ExprNode *sqlite3Fts5ParseNode(
if( pParse->rc==SQLITE_OK ){
int nChild = 0; /* Number of children of returned node */
int nByte; /* Bytes of space to allocate for this node */
sqlite3_int64 nByte; /* Bytes of space to allocate for this node */
assert( (eType!=FTS5_STRING && !pNear)
|| (eType==FTS5_STRING && !pLeft && !pRight)
@@ -2219,7 +2223,7 @@ Fts5ExprNode *sqlite3Fts5ParseImplicitAnd(
}
static char *fts5ExprTermPrint(Fts5ExprTerm *pTerm){
int nByte = 0;
sqlite3_int64 nByte = 0;
Fts5ExprTerm *p;
char *zQuoted;
@@ -2227,7 +2231,7 @@ static char *fts5ExprTermPrint(Fts5ExprTerm *pTerm){
for(p=pTerm; p; p=p->pSynonym){
nByte += (int)strlen(pTerm->zTerm) * 2 + 3 + 2;
}
zQuoted = sqlite3_malloc(nByte);
zQuoted = sqlite3_malloc64(nByte);
if( zQuoted ){
int i = 0;
@@ -2467,7 +2471,7 @@ static void fts5ExprFunction(
}
nConfig = 3 + (nArg-iArg);
azConfig = (const char**)sqlite3_malloc(sizeof(char*) * nConfig);
azConfig = (const char**)sqlite3_malloc64(sizeof(char*) * nConfig);
if( azConfig==0 ){
sqlite3_result_error_nomem(pCtx);
return;
@@ -2553,7 +2557,7 @@ static void fts5ExprIsAlnum(
sqlite3Fts5UnicodeCatParse("N*", aArr);
sqlite3Fts5UnicodeCatParse("Co", aArr);
iCode = sqlite3_value_int(apVal[0]);
sqlite3_result_int(pCtx, aArr[sqlite3Fts5UnicodeCategory(iCode)]);
sqlite3_result_int(pCtx, aArr[sqlite3Fts5UnicodeCategory((u32)iCode)]);
}
static void fts5ExprFold(
@@ -2648,7 +2652,7 @@ struct Fts5PoslistPopulator {
Fts5PoslistPopulator *sqlite3Fts5ExprClearPoslists(Fts5Expr *pExpr, int bLive){
Fts5PoslistPopulator *pRet;
pRet = sqlite3_malloc(sizeof(Fts5PoslistPopulator)*pExpr->nPhrase);
pRet = sqlite3_malloc64(sizeof(Fts5PoslistPopulator)*pExpr->nPhrase);
if( pRet ){
int i;
memset(pRet, 0, sizeof(Fts5PoslistPopulator)*pExpr->nPhrase);
@@ -2847,4 +2851,3 @@ int sqlite3Fts5ExprPhraseCollist(
return rc;
}
+52 -29
View File
@@ -90,14 +90,14 @@ int sqlite3Fts5HashNew(Fts5Config *pConfig, Fts5Hash **ppNew, int *pnByte){
if( pNew==0 ){
rc = SQLITE_NOMEM;
}else{
int nByte;
sqlite3_int64 nByte;
memset(pNew, 0, sizeof(Fts5Hash));
pNew->pnByte = pnByte;
pNew->eDetail = pConfig->eDetail;
pNew->nSlot = 1024;
nByte = sizeof(Fts5HashEntry*) * pNew->nSlot;
pNew->aSlot = (Fts5HashEntry**)sqlite3_malloc(nByte);
pNew->aSlot = (Fts5HashEntry**)sqlite3_malloc64(nByte);
if( pNew->aSlot==0 ){
sqlite3_free(pNew);
*ppNew = 0;
@@ -165,7 +165,7 @@ static int fts5HashResize(Fts5Hash *pHash){
Fts5HashEntry **apNew;
Fts5HashEntry **apOld = pHash->aSlot;
apNew = (Fts5HashEntry**)sqlite3_malloc(nNew*sizeof(Fts5HashEntry*));
apNew = (Fts5HashEntry**)sqlite3_malloc64(nNew*sizeof(Fts5HashEntry*));
if( !apNew ) return SQLITE_NOMEM;
memset(apNew, 0, nNew*sizeof(Fts5HashEntry*));
@@ -187,19 +187,25 @@ static int fts5HashResize(Fts5Hash *pHash){
return SQLITE_OK;
}
static void fts5HashAddPoslistSize(Fts5Hash *pHash, Fts5HashEntry *p){
static int fts5HashAddPoslistSize(
Fts5Hash *pHash,
Fts5HashEntry *p,
Fts5HashEntry *p2
){
int nRet = 0;
if( p->iSzPoslist ){
u8 *pPtr = (u8*)p;
u8 *pPtr = p2 ? (u8*)p2 : (u8*)p;
int nData = p->nData;
if( pHash->eDetail==FTS5_DETAIL_NONE ){
assert( p->nData==p->iSzPoslist );
assert( nData==p->iSzPoslist );
if( p->bDel ){
pPtr[p->nData++] = 0x00;
pPtr[nData++] = 0x00;
if( p->bContent ){
pPtr[p->nData++] = 0x00;
pPtr[nData++] = 0x00;
}
}
}else{
int nSz = (p->nData - p->iSzPoslist - 1); /* Size in bytes */
int nSz = (nData - p->iSzPoslist - 1); /* Size in bytes */
int nPos = nSz*2 + p->bDel; /* Value of nPos field */
assert( p->bDel==0 || p->bDel==1 );
@@ -209,14 +215,19 @@ static void fts5HashAddPoslistSize(Fts5Hash *pHash, Fts5HashEntry *p){
int nByte = sqlite3Fts5GetVarintLen((u32)nPos);
memmove(&pPtr[p->iSzPoslist + nByte], &pPtr[p->iSzPoslist + 1], nSz);
sqlite3Fts5PutVarint(&pPtr[p->iSzPoslist], nPos);
p->nData += (nByte-1);
nData += (nByte-1);
}
}
p->iSzPoslist = 0;
p->bDel = 0;
p->bContent = 0;
nRet = nData - p->nData;
if( p2==0 ){
p->iSzPoslist = 0;
p->bDel = 0;
p->bContent = 0;
p->nData = nData;
}
}
return nRet;
}
/*
@@ -259,7 +270,7 @@ int sqlite3Fts5HashWrite(
if( p==0 ){
/* Figure out how much space to allocate */
char *zKey;
int nByte = sizeof(Fts5HashEntry) + (nToken+1) + 1 + 64;
sqlite3_int64 nByte = sizeof(Fts5HashEntry) + (nToken+1) + 1 + 64;
if( nByte<128 ) nByte = 128;
/* Grow the Fts5Hash.aSlot[] array if necessary. */
@@ -270,7 +281,7 @@ int sqlite3Fts5HashWrite(
}
/* Allocate new Fts5HashEntry and add it to the hash table. */
p = (Fts5HashEntry*)sqlite3_malloc(nByte);
p = (Fts5HashEntry*)sqlite3_malloc64(nByte);
if( !p ) return SQLITE_NOMEM;
memset(p, 0, sizeof(Fts5HashEntry));
p->nAlloc = nByte;
@@ -309,12 +320,12 @@ int sqlite3Fts5HashWrite(
** + 5 bytes for the new position offset (32-bit max).
*/
if( (p->nAlloc - p->nData) < (9 + 4 + 1 + 3 + 5) ){
int nNew = p->nAlloc * 2;
sqlite3_int64 nNew = p->nAlloc * 2;
Fts5HashEntry *pNew;
Fts5HashEntry **pp;
pNew = (Fts5HashEntry*)sqlite3_realloc(p, nNew);
pNew = (Fts5HashEntry*)sqlite3_realloc64(p, nNew);
if( pNew==0 ) return SQLITE_NOMEM;
pNew->nAlloc = nNew;
pNew->nAlloc = (int)nNew;
for(pp=&pHash->aSlot[iHash]; *pp!=p; pp=&(*pp)->pHashNext);
*pp = pNew;
p = pNew;
@@ -328,7 +339,7 @@ int sqlite3Fts5HashWrite(
/* If this is a new rowid, append the 4-byte size field for the previous
** entry, and the new rowid for this entry. */
if( iRowid!=p->iRowid ){
fts5HashAddPoslistSize(pHash, p);
fts5HashAddPoslistSize(pHash, p, 0);
p->nData += sqlite3Fts5PutVarint(&pPtr[p->nData], iRowid - p->iRowid);
p->iRowid = iRowid;
bNew = 1;
@@ -438,14 +449,16 @@ static int fts5HashEntrySort(
int i;
*ppSorted = 0;
ap = sqlite3_malloc(sizeof(Fts5HashEntry*) * nMergeSlot);
ap = sqlite3_malloc64(sizeof(Fts5HashEntry*) * nMergeSlot);
if( !ap ) return SQLITE_NOMEM;
memset(ap, 0, sizeof(Fts5HashEntry*) * nMergeSlot);
for(iSlot=0; iSlot<pHash->nSlot; iSlot++){
Fts5HashEntry *pIter;
for(pIter=pHash->aSlot[iSlot]; pIter; pIter=pIter->pHashNext){
if( pTerm==0 || 0==memcmp(fts5EntryKey(pIter), pTerm, nTerm) ){
if( pTerm==0
|| (pIter->nKey+1>=nTerm && 0==memcmp(fts5EntryKey(pIter), pTerm, nTerm))
){
Fts5HashEntry *pEntry = pIter;
pEntry->pScanNext = 0;
for(i=0; ap[i]; i++){
@@ -473,8 +486,9 @@ static int fts5HashEntrySort(
*/
int sqlite3Fts5HashQuery(
Fts5Hash *pHash, /* Hash table to query */
int nPre,
const char *pTerm, int nTerm, /* Query term */
const u8 **ppDoclist, /* OUT: Pointer to doclist for pTerm */
void **ppOut, /* OUT: Pointer to new object */
int *pnDoclist /* OUT: Size of doclist in bytes */
){
unsigned int iHash = fts5HashKey(pHash->nSlot, (const u8*)pTerm, nTerm);
@@ -483,15 +497,25 @@ int sqlite3Fts5HashQuery(
for(p=pHash->aSlot[iHash]; p; p=p->pHashNext){
zKey = fts5EntryKey(p);
if( memcmp(zKey, pTerm, nTerm)==0 && zKey[nTerm]==0 ) break;
assert( p->nKey+1==(int)strlen(zKey) );
if( nTerm==p->nKey+1 && memcmp(zKey, pTerm, nTerm)==0 ) break;
}
if( p ){
fts5HashAddPoslistSize(pHash, p);
*ppDoclist = (const u8*)&zKey[nTerm+1];
*pnDoclist = p->nData - (sizeof(Fts5HashEntry) + nTerm + 1);
int nHashPre = sizeof(Fts5HashEntry) + nTerm + 1;
int nList = p->nData - nHashPre;
u8 *pRet = (u8*)(*ppOut = sqlite3_malloc64(nPre + nList + 10));
if( pRet ){
Fts5HashEntry *pFaux = (Fts5HashEntry*)&pRet[nPre-nHashPre];
memcpy(&pRet[nPre], &((u8*)p)[nHashPre], nList);
nList += fts5HashAddPoslistSize(pHash, p, pFaux);
*pnDoclist = nList;
}else{
*pnDoclist = 0;
return SQLITE_NOMEM;
}
}else{
*ppDoclist = 0;
*ppOut = 0;
*pnDoclist = 0;
}
@@ -524,7 +548,7 @@ void sqlite3Fts5HashScanEntry(
if( (p = pHash->pScan) ){
char *zKey = fts5EntryKey(p);
int nTerm = (int)strlen(zKey);
fts5HashAddPoslistSize(pHash, p);
fts5HashAddPoslistSize(pHash, p, 0);
*pzTerm = zKey;
*ppDoclist = (const u8*)&zKey[nTerm+1];
*pnDoclist = p->nData - (sizeof(Fts5HashEntry) + nTerm + 1);
@@ -534,4 +558,3 @@ void sqlite3Fts5HashScanEntry(
*pnDoclist = 0;
}
}
+172 -107
View File
@@ -512,7 +512,6 @@ struct Fts5Iter {
Fts5IndexIter base; /* Base class containing output vars */
Fts5Index *pIndex; /* Index that owns this iterator */
Fts5Structure *pStruct; /* Database structure for this iterator */
Fts5Buffer poslist; /* Buffer containing current poslist */
Fts5Colset *pColset; /* Restrict matches to these columns */
@@ -573,7 +572,7 @@ static u16 fts5GetU16(const u8 *aIn){
** If an OOM error is encountered, return NULL and set the error code in
** the Fts5Index handle passed as the first argument.
*/
static void *fts5IdxMalloc(Fts5Index *p, int nByte){
static void *fts5IdxMalloc(Fts5Index *p, sqlite3_int64 nByte){
return sqlite3Fts5MallocZero(&p->rc, nByte);
}
@@ -607,7 +606,7 @@ static int fts5BufferCompareBlob(
*/
static int fts5BufferCompare(Fts5Buffer *pLeft, Fts5Buffer *pRight){
int nCmp = MIN(pLeft->n, pRight->n);
int res = memcmp(pLeft->p, pRight->p, nCmp);
int res = fts5Memcmp(pLeft->p, pRight->p, nCmp);
return (res==0 ? (pLeft->n - pRight->n) : res);
}
@@ -673,8 +672,8 @@ static Fts5Data *fts5DataRead(Fts5Index *p, i64 iRowid){
if( rc==SQLITE_OK ){
u8 *aOut = 0; /* Read blob data into this buffer */
int nByte = sqlite3_blob_bytes(p->pReader);
int nAlloc = sizeof(Fts5Data) + nByte + FTS5_DATA_PADDING;
pRet = (Fts5Data*)sqlite3_malloc(nAlloc);
sqlite3_int64 nAlloc = sizeof(Fts5Data) + nByte + FTS5_DATA_PADDING;
pRet = (Fts5Data*)sqlite3_malloc64(nAlloc);
if( pRet ){
pRet->nn = nByte;
aOut = pRet->p = (u8*)&pRet[1];
@@ -690,6 +689,7 @@ static Fts5Data *fts5DataRead(Fts5Index *p, i64 iRowid){
pRet = 0;
}else{
/* TODO1: Fix this */
pRet->p[nByte] = 0x00;
pRet->szLeaf = fts5GetU16(&pRet->p[2]);
}
}
@@ -729,7 +729,8 @@ static int fts5IndexPrepareStmt(
if( p->rc==SQLITE_OK ){
if( zSql ){
p->rc = sqlite3_prepare_v3(p->pConfig->db, zSql, -1,
SQLITE_PREPARE_PERSISTENT, ppStmt, 0);
SQLITE_PREPARE_PERSISTENT|SQLITE_PREPARE_NO_VTAB,
ppStmt, 0);
}else{
p->rc = SQLITE_NOMEM;
}
@@ -770,23 +771,12 @@ static void fts5DataDelete(Fts5Index *p, i64 iFirst, i64 iLast){
if( p->rc!=SQLITE_OK ) return;
if( p->pDeleter==0 ){
int rc;
Fts5Config *pConfig = p->pConfig;
char *zSql = sqlite3_mprintf(
"DELETE FROM '%q'.'%q_data' WHERE id>=? AND id<=?",
pConfig->zDb, pConfig->zName
);
if( zSql==0 ){
rc = SQLITE_NOMEM;
}else{
rc = sqlite3_prepare_v3(pConfig->db, zSql, -1,
SQLITE_PREPARE_PERSISTENT, &p->pDeleter, 0);
sqlite3_free(zSql);
}
if( rc!=SQLITE_OK ){
p->rc = rc;
return;
}
if( fts5IndexPrepareStmt(p, &p->pDeleter, zSql) ) return;
}
sqlite3_bind_int64(p->pDeleter, 1, iFirst);
@@ -858,7 +848,7 @@ static int fts5StructureDecode(
int iLvl;
int nLevel = 0;
int nSegment = 0;
int nByte; /* Bytes of space to allocate at pRet */
sqlite3_int64 nByte; /* Bytes of space to allocate at pRet */
Fts5Structure *pRet = 0; /* Structure object to return */
/* Grab the cookie value */
@@ -869,6 +859,11 @@ static int fts5StructureDecode(
** structure record. */
i += fts5GetVarint32(&pData[i], nLevel);
i += fts5GetVarint32(&pData[i], nSegment);
if( nLevel>FTS5_MAX_SEGMENT || nLevel<0
|| nSegment>FTS5_MAX_SEGMENT || nSegment<0
){
return FTS5_CORRUPT;
}
nByte = (
sizeof(Fts5Structure) + /* Main structure */
sizeof(Fts5StructureLevel) * (nLevel-1) /* aLevel[] array */
@@ -891,25 +886,35 @@ static int fts5StructureDecode(
}else{
i += fts5GetVarint32(&pData[i], pLvl->nMerge);
i += fts5GetVarint32(&pData[i], nTotal);
assert( nTotal>=pLvl->nMerge );
if( nTotal<pLvl->nMerge ) rc = FTS5_CORRUPT;
pLvl->aSeg = (Fts5StructureSegment*)sqlite3Fts5MallocZero(&rc,
nTotal * sizeof(Fts5StructureSegment)
);
nSegment -= nTotal;
}
if( rc==SQLITE_OK ){
pLvl->nSeg = nTotal;
for(iSeg=0; iSeg<nTotal; iSeg++){
Fts5StructureSegment *pSeg = &pLvl->aSeg[iSeg];
if( i>=nData ){
rc = FTS5_CORRUPT;
break;
}
i += fts5GetVarint32(&pData[i], pLvl->aSeg[iSeg].iSegid);
i += fts5GetVarint32(&pData[i], pLvl->aSeg[iSeg].pgnoFirst);
i += fts5GetVarint32(&pData[i], pLvl->aSeg[iSeg].pgnoLast);
i += fts5GetVarint32(&pData[i], pSeg->iSegid);
i += fts5GetVarint32(&pData[i], pSeg->pgnoFirst);
i += fts5GetVarint32(&pData[i], pSeg->pgnoLast);
if( pSeg->pgnoLast<pSeg->pgnoFirst ){
rc = FTS5_CORRUPT;
break;
}
}
if( iLvl>0 && pLvl[-1].nMerge && nTotal==0 ) rc = FTS5_CORRUPT;
if( iLvl==nLevel-1 && pLvl->nMerge ) rc = FTS5_CORRUPT;
}
}
if( nSegment!=0 && rc==SQLITE_OK ) rc = FTS5_CORRUPT;
if( rc!=SQLITE_OK ){
fts5StructureRelease(pRet);
pRet = 0;
@@ -927,12 +932,12 @@ static void fts5StructureAddLevel(int *pRc, Fts5Structure **ppStruct){
if( *pRc==SQLITE_OK ){
Fts5Structure *pStruct = *ppStruct;
int nLevel = pStruct->nLevel;
int nByte = (
sqlite3_int64 nByte = (
sizeof(Fts5Structure) + /* Main structure */
sizeof(Fts5StructureLevel) * (nLevel+1) /* aLevel[] array */
);
pStruct = sqlite3_realloc(pStruct, nByte);
pStruct = sqlite3_realloc64(pStruct, nByte);
if( pStruct ){
memset(&pStruct->aLevel[nLevel], 0, sizeof(Fts5StructureLevel));
pStruct->nLevel++;
@@ -957,10 +962,10 @@ static void fts5StructureExtendLevel(
if( *pRc==SQLITE_OK ){
Fts5StructureLevel *pLvl = &pStruct->aLevel[iLvl];
Fts5StructureSegment *aNew;
int nByte;
sqlite3_int64 nByte;
nByte = (pLvl->nSeg + nExtra) * sizeof(Fts5StructureSegment);
aNew = sqlite3_realloc(pLvl->aSeg, nByte);
aNew = sqlite3_realloc64(pLvl->aSeg, nByte);
if( aNew ){
if( bInsert==0 ){
memset(&aNew[pLvl->nSeg], 0, sizeof(Fts5StructureSegment) * nExtra);
@@ -1474,10 +1479,10 @@ static Fts5DlidxIter *fts5DlidxIterInit(
int bDone = 0;
for(i=0; p->rc==SQLITE_OK && bDone==0; i++){
int nByte = sizeof(Fts5DlidxIter) + i * sizeof(Fts5DlidxLvl);
sqlite3_int64 nByte = sizeof(Fts5DlidxIter) + i * sizeof(Fts5DlidxLvl);
Fts5DlidxIter *pNew;
pNew = (Fts5DlidxIter*)sqlite3_realloc(pIter, nByte);
pNew = (Fts5DlidxIter*)sqlite3_realloc64(pIter, nByte);
if( pNew==0 ){
p->rc = SQLITE_NOMEM;
}else{
@@ -1647,12 +1652,13 @@ static void fts5SegIterLoadTerm(Fts5Index *p, Fts5SegIter *pIter, int nKeep){
int nNew; /* Bytes of new data */
iOff += fts5GetVarint32(&a[iOff], nNew);
if( iOff+nNew>pIter->pLeaf->nn ){
if( iOff+nNew>pIter->pLeaf->szLeaf || nKeep>pIter->term.n || nNew==0 ){
p->rc = FTS5_CORRUPT;
return;
}
pIter->term.n = nKeep;
fts5BufferAppendBlob(&p->rc, &pIter->term, nNew, &a[iOff]);
assert( pIter->term.n<=pIter->term.nSpace );
iOff += nNew;
pIter->iTermLeafOffset = iOff;
pIter->iTermLeafPgno = pIter->iLeafPgno;
@@ -1717,7 +1723,7 @@ static void fts5SegIterInit(
if( p->rc==SQLITE_OK ){
pIter->iLeafOffset = 4;
assert_nc( pIter->pLeaf->nn>4 );
assert( fts5LeafFirstTermOff(pIter->pLeaf)==4 );
assert_nc( fts5LeafFirstTermOff(pIter->pLeaf)==4 );
pIter->iPgidxOff = pIter->pLeaf->szLeaf+1;
fts5SegIterLoadTerm(p, pIter, 0);
fts5SegIterLoadNPos(p, pIter);
@@ -1773,7 +1779,7 @@ static void fts5SegIterReverseInitPage(Fts5Index *p, Fts5SegIter *pIter){
/* If necessary, grow the pIter->aRowidOffset[] array. */
if( iRowidOffset>=pIter->nRowidOffset ){
int nNew = pIter->nRowidOffset + 8;
int *aNew = (int*)sqlite3_realloc(pIter->aRowidOffset, nNew*sizeof(int));
int *aNew = (int*)sqlite3_realloc64(pIter->aRowidOffset,nNew*sizeof(int));
if( aNew==0 ){
p->rc = SQLITE_NOMEM;
break;
@@ -2227,10 +2233,10 @@ static void fts5LeafSeek(
int szLeaf = pIter->pLeaf->szLeaf;
int n = pIter->pLeaf->nn;
int nMatch = 0;
int nKeep = 0;
int nNew = 0;
int iTermOff;
u32 nMatch = 0;
u32 nKeep = 0;
u32 nNew = 0;
u32 iTermOff;
int iPgidx; /* Current offset in pgidx */
int bEndOfPage = 0;
@@ -2254,15 +2260,15 @@ static void fts5LeafSeek(
assert( nKeep>=nMatch );
if( nKeep==nMatch ){
int nCmp;
int i;
nCmp = MIN(nNew, nTerm-nMatch);
u32 nCmp;
u32 i;
nCmp = (u32)MIN(nNew, nTerm-nMatch);
for(i=0; i<nCmp; i++){
if( a[iOff+i]!=pTerm[nMatch+i] ) break;
}
nMatch += i;
if( nTerm==nMatch ){
if( (u32)nTerm==nMatch ){
if( i==nNew ){
goto search_success;
}else{
@@ -2306,6 +2312,7 @@ static void fts5LeafSeek(
iPgidx += fts5GetVarint32(&pIter->pLeaf->p[iPgidx], iOff);
if( iOff<4 || iOff>=pIter->pLeaf->szLeaf ){
p->rc = FTS5_CORRUPT;
return;
}else{
nKeep = 0;
iTermOff = iOff;
@@ -2318,8 +2325,11 @@ static void fts5LeafSeek(
}
search_success:
pIter->iLeafOffset = iOff + nNew;
if( pIter->iLeafOffset>n || nNew<1 ){
p->rc = FTS5_CORRUPT;
return;
}
pIter->iTermLeafOffset = pIter->iLeafOffset;
pIter->iTermLeafPgno = pIter->iLeafPgno;
@@ -2426,7 +2436,7 @@ static void fts5SegIterSeekInit(
** 4) the FTS5INDEX_QUERY_SCAN flag was set and the iterator points
** to an entry with a term greater than or equal to (pTerm/nTerm).
*/
assert( p->rc!=SQLITE_OK /* 1 */
assert_nc( p->rc!=SQLITE_OK /* 1 */
|| pIter->pLeaf==0 /* 2 */
|| fts5BufferCompareBlob(&pIter->term, pTerm, nTerm)==0 /* 3 */
|| (bGe && fts5BufferCompareBlob(&pIter->term, pTerm, nTerm)>0) /* 4 */
@@ -2447,31 +2457,40 @@ static void fts5SegIterHashInit(
int flags, /* Mask of FTS5INDEX_XXX flags */
Fts5SegIter *pIter /* Object to populate */
){
const u8 *pList = 0;
int nList = 0;
const u8 *z = 0;
int n = 0;
Fts5Data *pLeaf = 0;
assert( p->pHash );
assert( p->rc==SQLITE_OK );
if( pTerm==0 || (flags & FTS5INDEX_QUERY_SCAN) ){
const u8 *pList = 0;
p->rc = sqlite3Fts5HashScanInit(p->pHash, (const char*)pTerm, nTerm);
sqlite3Fts5HashScanEntry(p->pHash, (const char**)&z, &pList, &nList);
n = (z ? (int)strlen((const char*)z) : 0);
if( pList ){
pLeaf = fts5IdxMalloc(p, sizeof(Fts5Data));
if( pLeaf ){
pLeaf->p = pList;
}
}
}else{
pIter->flags |= FTS5_SEGITER_ONETERM;
sqlite3Fts5HashQuery(p->pHash, (const char*)pTerm, nTerm, &pList, &nList);
p->rc = sqlite3Fts5HashQuery(p->pHash, sizeof(Fts5Data),
(const char*)pTerm, nTerm, (void**)&pLeaf, &nList
);
if( pLeaf ){
pLeaf->p = (u8*)&pLeaf[1];
}
z = pTerm;
n = nTerm;
pIter->flags |= FTS5_SEGITER_ONETERM;
}
if( pList ){
Fts5Data *pLeaf;
if( pLeaf ){
sqlite3Fts5BufferSet(&p->rc, &pIter->term, n, z);
pLeaf = fts5IdxMalloc(p, sizeof(Fts5Data));
if( pLeaf==0 ) return;
pLeaf->p = (u8*)pList;
pLeaf->nn = pLeaf->szLeaf = nList;
pIter->pLeaf = pLeaf;
pIter->iLeafOffset = fts5GetVarint(pLeaf->p, (u64*)&pIter->iRowid);
@@ -2524,7 +2543,7 @@ static void fts5AssertComparisonResult(
assert( pRes->iFirst==i1 );
}else{
int nMin = MIN(p1->term.n, p2->term.n);
int res = memcmp(p1->term.p, p2->term.p, nMin);
int res = fts5Memcmp(p1->term.p, p2->term.p, nMin);
if( res==0 ) res = p1->term.n - p2->term.n;
if( res==0 ){
@@ -2747,7 +2766,6 @@ static void fts5MultiIterFree(Fts5Iter *pIter){
for(i=0; i<pIter->nSeg; i++){
fts5SegIterClear(&pIter->aSeg[i]);
}
fts5StructureRelease(pIter->pStruct);
fts5BufferFree(&pIter->poslist);
sqlite3_free(pIter);
}
@@ -3095,7 +3113,8 @@ static void fts5SegiterPoslist(
Fts5Colset *pColset,
Fts5Buffer *pBuf
){
if( 0==fts5BufferGrow(&p->rc, pBuf, pSeg->nPos) ){
if( 0==fts5BufferGrow(&p->rc, pBuf, pSeg->nPos+FTS5_DATA_ZERO_PADDING) ){
memset(&pBuf->p[pBuf->n+pSeg->nPos], 0, FTS5_DATA_ZERO_PADDING);
if( pColset==0 ){
fts5ChunkIterate(p, pSeg, (void*)pBuf, fts5PoslistCallback);
}else{
@@ -3393,9 +3412,7 @@ static void fts5MultiIterNew(
if( pNew==0 ) return;
pNew->bRev = (0!=(flags & FTS5INDEX_QUERY_DESC));
pNew->bSkipEmpty = (0!=(flags & FTS5INDEX_QUERY_SKIPEMPTY));
pNew->pStruct = pStruct;
pNew->pColset = pColset;
fts5StructureRef(pStruct);
if( (flags & FTS5INDEX_QUERY_NOOUTPUT)==0 ){
fts5IterSetOutputCb(&p->rc, pNew);
}
@@ -3573,24 +3590,24 @@ static int fts5AllocateSegid(Fts5Index *p, Fts5Structure *pStruct){
for(iLvl=0; iLvl<pStruct->nLevel; iLvl++){
for(iSeg=0; iSeg<pStruct->aLevel[iLvl].nSeg; iSeg++){
int iId = pStruct->aLevel[iLvl].aSeg[iSeg].iSegid;
if( iId<=FTS5_MAX_SEGMENT ){
aUsed[(iId-1) / 32] |= 1 << ((iId-1) % 32);
if( iId<=FTS5_MAX_SEGMENT && iId>0 ){
aUsed[(iId-1) / 32] |= (u32)1 << ((iId-1) % 32);
}
}
}
for(i=0; aUsed[i]==0xFFFFFFFF; i++);
mask = aUsed[i];
for(iSegid=0; mask & (1 << iSegid); iSegid++);
for(iSegid=0; mask & ((u32)1 << iSegid); iSegid++);
iSegid += 1 + i*32;
#ifdef SQLITE_DEBUG
for(iLvl=0; iLvl<pStruct->nLevel; iLvl++){
for(iSeg=0; iSeg<pStruct->aLevel[iLvl].nSeg; iSeg++){
assert( iSegid!=pStruct->aLevel[iLvl].aSeg[iSeg].iSegid );
assert_nc( iSegid!=pStruct->aLevel[iLvl].aSeg[iSeg].iSegid );
}
}
assert( iSegid>0 && iSegid<=FTS5_MAX_SEGMENT );
assert_nc( iSegid>0 && iSegid<=FTS5_MAX_SEGMENT );
{
sqlite3_stmt *pIdxSelect = fts5IdxSelectStmt(p);
@@ -3598,7 +3615,7 @@ static int fts5AllocateSegid(Fts5Index *p, Fts5Structure *pStruct){
u8 aBlob[2] = {0xff, 0xff};
sqlite3_bind_int(pIdxSelect, 1, iSegid);
sqlite3_bind_blob(pIdxSelect, 2, aBlob, 2, SQLITE_STATIC);
assert( sqlite3_step(pIdxSelect)!=SQLITE_ROW );
assert_nc( sqlite3_step(pIdxSelect)!=SQLITE_ROW );
p->rc = sqlite3_reset(pIdxSelect);
sqlite3_bind_null(pIdxSelect, 2);
}
@@ -3668,7 +3685,7 @@ static int fts5WriteDlidxGrow(
int nLvl
){
if( p->rc==SQLITE_OK && nLvl>=pWriter->nDlidx ){
Fts5DlidxWriter *aDlidx = (Fts5DlidxWriter*)sqlite3_realloc(
Fts5DlidxWriter *aDlidx = (Fts5DlidxWriter*)sqlite3_realloc64(
pWriter->aDlidx, sizeof(Fts5DlidxWriter) * nLvl
);
if( aDlidx==0 ){
@@ -3747,8 +3764,10 @@ static void fts5WriteBtreeTerm(
int nTerm, const u8 *pTerm /* First term on new page */
){
fts5WriteFlushBtree(p, pWriter);
fts5BufferSet(&p->rc, &pWriter->btterm, nTerm, pTerm);
pWriter->iBtPage = pWriter->writer.pgno;
if( p->rc==SQLITE_OK ){
fts5BufferSet(&p->rc, &pWriter->btterm, nTerm, pTerm);
pWriter->iBtPage = pWriter->writer.pgno;
}
}
/*
@@ -3899,6 +3918,7 @@ static void fts5WriteAppendTerm(
int nPrefix; /* Bytes of prefix compression for term */
Fts5PageWriter *pPage = &pWriter->writer;
Fts5Buffer *pPgidx = &pWriter->writer.pgidx;
int nMin = MIN(pPage->term.n, nTerm);
assert( p->rc==SQLITE_OK );
assert( pPage->buf.n>=4 );
@@ -3908,6 +3928,7 @@ static void fts5WriteAppendTerm(
if( (pPage->buf.n + pPgidx->n + nTerm + 2)>=p->pConfig->pgsz ){
if( pPage->buf.n>4 ){
fts5WriteFlushLeaf(p, pWriter);
if( p->rc!=SQLITE_OK ) return;
}
fts5BufferGrow(&p->rc, &pPage->buf, nTerm+FTS5_DATA_PADDING);
}
@@ -3940,13 +3961,14 @@ static void fts5WriteAppendTerm(
** inefficient, but still correct. */
int n = nTerm;
if( pPage->term.n ){
n = 1 + fts5PrefixCompress(pPage->term.n, pPage->term.p, pTerm);
n = 1 + fts5PrefixCompress(nMin, pPage->term.p, pTerm);
}
fts5WriteBtreeTerm(p, pWriter, n, pTerm);
if( p->rc!=SQLITE_OK ) return;
pPage = &pWriter->writer;
}
}else{
nPrefix = fts5PrefixCompress(pPage->term.n, pPage->term.p, pTerm);
nPrefix = fts5PrefixCompress(nMin, pPage->term.p, pTerm);
fts5BufferAppendVarint(&p->rc, &pPage->buf, nPrefix);
}
@@ -3993,7 +4015,7 @@ static void fts5WriteAppendRowid(
if( pWriter->bFirstRowidInDoclist || pWriter->bFirstRowidInPage ){
fts5BufferAppendVarint(&p->rc, &pPage->buf, iRowid);
}else{
assert( p->rc || iRowid>pWriter->iPrevRowid );
assert_nc( p->rc || iRowid>pWriter->iPrevRowid );
fts5BufferAppendVarint(&p->rc, &pPage->buf, iRowid - pWriter->iPrevRowid);
}
pWriter->iPrevRowid = iRowid;
@@ -4115,7 +4137,7 @@ static void fts5TrimSegments(Fts5Index *p, Fts5Iter *pIter){
int i;
Fts5Buffer buf;
memset(&buf, 0, sizeof(Fts5Buffer));
for(i=0; i<pIter->nSeg; i++){
for(i=0; i<pIter->nSeg && p->rc==SQLITE_OK; i++){
Fts5SegIter *pSeg = &pIter->aSeg[i];
if( pSeg->pSeg==0 ){
/* no-op */
@@ -4133,35 +4155,44 @@ static void fts5TrimSegments(Fts5Index *p, Fts5Iter *pIter){
u8 aHdr[4] = {0x00, 0x00, 0x00, 0x00};
iLeafRowid = FTS5_SEGMENT_ROWID(iId, pSeg->iTermLeafPgno);
pData = fts5DataRead(p, iLeafRowid);
pData = fts5LeafRead(p, iLeafRowid);
if( pData ){
fts5BufferZero(&buf);
fts5BufferGrow(&p->rc, &buf, pData->nn);
fts5BufferAppendBlob(&p->rc, &buf, sizeof(aHdr), aHdr);
fts5BufferAppendVarint(&p->rc, &buf, pSeg->term.n);
fts5BufferAppendBlob(&p->rc, &buf, pSeg->term.n, pSeg->term.p);
fts5BufferAppendBlob(&p->rc, &buf, pData->szLeaf-iOff, &pData->p[iOff]);
if( p->rc==SQLITE_OK ){
/* Set the szLeaf field */
fts5PutU16(&buf.p[2], (u16)buf.n);
}
if( iOff>pData->szLeaf ){
/* This can occur if the pages that the segments occupy overlap - if
** a single page has been assigned to more than one segment. In
** this case a prior iteration of this loop may have corrupted the
** segment currently being trimmed. */
p->rc = FTS5_CORRUPT;
}else{
fts5BufferZero(&buf);
fts5BufferGrow(&p->rc, &buf, pData->nn);
fts5BufferAppendBlob(&p->rc, &buf, sizeof(aHdr), aHdr);
fts5BufferAppendVarint(&p->rc, &buf, pSeg->term.n);
fts5BufferAppendBlob(&p->rc, &buf, pSeg->term.n, pSeg->term.p);
fts5BufferAppendBlob(&p->rc, &buf, pData->szLeaf-iOff,&pData->p[iOff]);
if( p->rc==SQLITE_OK ){
/* Set the szLeaf field */
fts5PutU16(&buf.p[2], (u16)buf.n);
}
/* Set up the new page-index array */
fts5BufferAppendVarint(&p->rc, &buf, 4);
if( pSeg->iLeafPgno==pSeg->iTermLeafPgno
&& pSeg->iEndofDoclist<pData->szLeaf
){
int nDiff = pData->szLeaf - pSeg->iEndofDoclist;
fts5BufferAppendVarint(&p->rc, &buf, buf.n - 1 - nDiff - 4);
fts5BufferAppendBlob(&p->rc, &buf,
pData->nn - pSeg->iPgidxOff, &pData->p[pSeg->iPgidxOff]
);
}
/* Set up the new page-index array */
fts5BufferAppendVarint(&p->rc, &buf, 4);
if( pSeg->iLeafPgno==pSeg->iTermLeafPgno
&& pSeg->iEndofDoclist<pData->szLeaf
&& pSeg->iPgidxOff<=pData->nn
){
int nDiff = pData->szLeaf - pSeg->iEndofDoclist;
fts5BufferAppendVarint(&p->rc, &buf, buf.n - 1 - nDiff - 4);
fts5BufferAppendBlob(&p->rc, &buf,
pData->nn - pSeg->iPgidxOff, &pData->p[pSeg->iPgidxOff]
);
}
pSeg->pSeg->pgnoFirst = pSeg->iTermLeafPgno;
fts5DataDelete(p, FTS5_SEGMENT_ROWID(iId, 1), iLeafRowid);
fts5DataWrite(p, iLeafRowid, buf.p, buf.n);
}
fts5DataRelease(pData);
pSeg->pSeg->pgnoFirst = pSeg->iTermLeafPgno;
fts5DataDelete(p, FTS5_SEGMENT_ROWID(iId, 1), iLeafRowid);
fts5DataWrite(p, iLeafRowid, buf.p, buf.n);
}
}
}
@@ -4253,7 +4284,7 @@ static void fts5IndexMergeLevel(
const u8 *pTerm;
pTerm = fts5MultiIterTerm(pIter, &nTerm);
if( nTerm!=term.n || memcmp(pTerm, term.p, nTerm) ){
if( nTerm!=term.n || fts5Memcmp(pTerm, term.p, nTerm) ){
if( pnRem && writer.nLeafWritten>nRem ){
break;
}
@@ -4508,6 +4539,7 @@ static void fts5FlushOneHash(Fts5Index *p){
/* Write the term for this entry to disk. */
sqlite3Fts5HashScanEntry(pHash, &zTerm, &pDoclist, &nDoclist);
fts5WriteAppendTerm(p, &writer, (int)strlen(zTerm), (const u8*)zTerm);
if( p->rc!=SQLITE_OK ) break;
assert( writer.bFirstRowidInPage==0 );
if( pgsz>=(pBuf->n + pPgidx->n + nDoclist + 1) ){
@@ -4530,6 +4562,7 @@ static void fts5FlushOneHash(Fts5Index *p){
pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], iRowid);
writer.bFirstRowidInPage = 0;
fts5WriteDlidxAppend(p, &writer, iRowid);
if( p->rc!=SQLITE_OK ) break;
}else{
pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], iDelta);
}
@@ -4587,7 +4620,7 @@ static void fts5FlushOneHash(Fts5Index *p){
/* TODO2: Doclist terminator written here. */
/* pBuf->p[pBuf->n++] = '\0'; */
assert( pBuf->n<=pBuf->nSpace );
sqlite3Fts5HashScanNext(pHash);
if( p->rc==SQLITE_OK ) sqlite3Fts5HashScanNext(pHash);
}
sqlite3Fts5HashClear(pHash);
fts5WriteFinish(p, &writer, &pgnoLast);
@@ -4631,7 +4664,7 @@ static Fts5Structure *fts5IndexOptimizeStruct(
Fts5Structure *pStruct
){
Fts5Structure *pNew = 0;
int nByte = sizeof(Fts5Structure);
sqlite3_int64 nByte = sizeof(Fts5Structure);
int nSeg = pStruct->nSegment;
int i;
@@ -4761,11 +4794,13 @@ static void fts5AppendPoslist(
Fts5Buffer *pBuf
){
int nData = pMulti->base.nData;
int nByte = nData + 9 + 9 + FTS5_DATA_ZERO_PADDING;
assert( nData>0 );
if( p->rc==SQLITE_OK && 0==fts5BufferGrow(&p->rc, pBuf, nData+9+9) ){
if( p->rc==SQLITE_OK && 0==fts5BufferGrow(&p->rc, pBuf, nByte) ){
fts5BufferSafeAppendVarint(pBuf, iDelta);
fts5BufferSafeAppendVarint(pBuf, nData*2);
fts5BufferSafeAppendBlob(pBuf, pMulti->base.pData, nData);
memset(&pBuf->p[pBuf->n], 0, FTS5_DATA_ZERO_PADDING);
}
}
@@ -4946,6 +4981,8 @@ static void fts5MergePrefixLists(
int iOff2 = 0;
u8 *a1 = &i1.aPoslist[i1.nSize];
u8 *a2 = &i2.aPoslist[i2.nSize];
int nCopy;
u8 *aCopy;
i64 iPrev = 0;
Fts5PoslistWriter writer;
@@ -4977,7 +5014,7 @@ static void fts5MergePrefixLists(
sqlite3Fts5PoslistNext64(a1, i1.nPoslist, &iOff1, &iPos1);
if( iPos1<0 ) break;
}else{
assert( iPos2!=iPrev );
assert_nc( iPos2!=iPrev );
sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, iPos2);
sqlite3Fts5PoslistNext64(a2, i2.nPoslist, &iOff2, &iPos2);
if( iPos2<0 ) break;
@@ -4989,11 +5026,16 @@ static void fts5MergePrefixLists(
if( iPos1!=iPrev ){
sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, iPos1);
}
fts5BufferSafeAppendBlob(&tmp, &a1[iOff1], i1.nPoslist-iOff1);
aCopy = &a1[iOff1];
nCopy = i1.nPoslist - iOff1;
}else{
assert( iPos2>=0 && iPos2!=iPrev );
sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, iPos2);
fts5BufferSafeAppendBlob(&tmp, &a2[iOff2], i2.nPoslist-iOff2);
aCopy = &a2[iOff2];
nCopy = i2.nPoslist - iOff2;
}
if( nCopy>0 ){
fts5BufferSafeAppendBlob(&tmp, aCopy, nCopy);
}
/* WRITEPOSLISTSIZE */
@@ -5001,6 +5043,7 @@ static void fts5MergePrefixLists(
fts5BufferSafeAppendBlob(&out, tmp.p, tmp.n);
fts5DoclistIterNext(&i1);
fts5DoclistIterNext(&i2);
assert( out.n<=(p1->n+p2->n+9) );
if( i1.aPoslist==0 || i2.aPoslist==0 ) break;
}
}
@@ -5102,7 +5145,7 @@ static void fts5SetupPrefixIter(
}
fts5MultiIterFree(p1);
pData = fts5IdxMalloc(p, sizeof(Fts5Data) + doclist.n);
pData = fts5IdxMalloc(p, sizeof(Fts5Data)+doclist.n+FTS5_DATA_ZERO_PADDING);
if( pData ){
pData->p = (u8*)&pData[1];
pData->nn = pData->szLeaf = doclist.n;
@@ -5864,11 +5907,11 @@ static void fts5IndexIntegrityCheckSegment(
iOff = fts5LeafFirstTermOff(pLeaf);
iRowidOff = fts5LeafFirstRowidOff(pLeaf);
if( iRowidOff>=iOff ){
if( iRowidOff>=iOff || iOff>=pLeaf->szLeaf ){
p->rc = FTS5_CORRUPT;
}else{
iOff += fts5GetVarint32(&pLeaf->p[iOff], nTerm);
res = memcmp(&pLeaf->p[iOff], zIdxTerm, MIN(nTerm, nIdxTerm));
res = fts5Memcmp(&pLeaf->p[iOff], zIdxTerm, MIN(nTerm, nIdxTerm));
if( res==0 ) res = nTerm - nIdxTerm;
if( res<0 ) p->rc = FTS5_CORRUPT;
}
@@ -6263,7 +6306,7 @@ static void fts5DecodeFunction(
u8 *a = 0;
Fts5Buffer s; /* Build up text to return here */
int rc = SQLITE_OK; /* Return code */
int nSpace = 0;
sqlite3_int64 nSpace = 0;
int eDetailNone = (sqlite3_user_data(pCtx)!=0);
assert( nArg==2 );
@@ -6279,8 +6322,7 @@ static void fts5DecodeFunction(
nSpace = n + FTS5_DATA_ZERO_PADDING;
a = (u8*)sqlite3Fts5MallocZero(&rc, nSpace);
if( a==0 ) goto decode_out;
memcpy(a, aBlob, n);
if( n>0 ) memcpy(a, aBlob, n);
fts5DecodeRowid(iRowid, &iSegid, &bDlidx, &iHeight, &iPgno);
@@ -6375,6 +6417,9 @@ static void fts5DecodeFunction(
iPgidxOff = szLeaf = fts5GetU16(&a[2]);
if( iPgidxOff<n ){
fts5GetVarint32(&a[iPgidxOff], iTermOff);
}else if( iPgidxOff>n ){
rc = FTS5_CORRUPT;
goto decode_out;
}
}
@@ -6386,14 +6431,22 @@ static void fts5DecodeFunction(
}else{
iOff = szLeaf;
}
if( iOff>n ){
rc = FTS5_CORRUPT;
goto decode_out;
}
fts5DecodePoslist(&rc, &s, &a[4], iOff-4);
/* Decode any more doclist data that appears on the page before the
** first term. */
nDoclist = (iTermOff ? iTermOff : szLeaf) - iOff;
if( nDoclist+iOff>n ){
rc = FTS5_CORRUPT;
goto decode_out;
}
fts5DecodeDoclist(&rc, &s, &a[iOff], nDoclist);
while( iPgidxOff<n ){
while( iPgidxOff<n && rc==SQLITE_OK ){
int bFirst = (iPgidxOff==szLeaf); /* True for first term on page */
int nByte; /* Bytes of data */
int iEnd;
@@ -6408,12 +6461,24 @@ static void fts5DecodeFunction(
}else{
iEnd = szLeaf;
}
if( iEnd>szLeaf ){
rc = FTS5_CORRUPT;
break;
}
if( bFirst==0 ){
iOff += fts5GetVarint32(&a[iOff], nByte);
if( nByte>term.n ){
rc = FTS5_CORRUPT;
break;
}
term.n = nByte;
}
iOff += fts5GetVarint32(&a[iOff], nByte);
if( iOff+nByte>n ){
rc = FTS5_CORRUPT;
break;
}
fts5BufferAppendBlob(&rc, &term, nByte, &a[iOff]);
iOff += nByte;
+156 -150
View File
@@ -28,8 +28,8 @@ int sqlite3_fts5_may_be_corrupt = 1;
typedef struct Fts5Auxdata Fts5Auxdata;
typedef struct Fts5Auxiliary Fts5Auxiliary;
typedef struct Fts5Cursor Fts5Cursor;
typedef struct Fts5FullTable Fts5FullTable;
typedef struct Fts5Sorter Fts5Sorter;
typedef struct Fts5Table Fts5Table;
typedef struct Fts5TokenizerModule Fts5TokenizerModule;
/*
@@ -110,13 +110,8 @@ struct Fts5TokenizerModule {
Fts5TokenizerModule *pNext; /* Next registered tokenizer module */
};
/*
** Virtual-table object.
*/
struct Fts5Table {
sqlite3_vtab base; /* Base class used by SQLite core */
Fts5Config *pConfig; /* Virtual table configuration */
Fts5Index *pIndex; /* Full-text index */
struct Fts5FullTable {
Fts5Table p; /* Public class members from fts5Int.h */
Fts5Storage *pStorage; /* Document store */
Fts5Global *pGlobal; /* Global (connection wide) data */
Fts5Cursor *pSortCsr; /* Sort data from this cursor */
@@ -254,7 +249,7 @@ struct Fts5Auxdata {
#define FTS5_SAVEPOINT 5
#define FTS5_RELEASE 6
#define FTS5_ROLLBACKTO 7
static void fts5CheckTransactionState(Fts5Table *p, int op, int iSavepoint){
static void fts5CheckTransactionState(Fts5FullTable *p, int op, int iSavepoint){
switch( op ){
case FTS5_BEGIN:
assert( p->ts.eState==0 );
@@ -293,7 +288,7 @@ static void fts5CheckTransactionState(Fts5Table *p, int op, int iSavepoint){
case FTS5_ROLLBACKTO:
assert( p->ts.eState==1 );
assert( iSavepoint>=0 );
assert( iSavepoint>=-1 );
assert( iSavepoint<=p->ts.iSavepoint );
p->ts.iSavepoint = iSavepoint;
break;
@@ -306,18 +301,18 @@ static void fts5CheckTransactionState(Fts5Table *p, int op, int iSavepoint){
/*
** Return true if pTab is a contentless table.
*/
static int fts5IsContentless(Fts5Table *pTab){
return pTab->pConfig->eContent==FTS5_CONTENT_NONE;
static int fts5IsContentless(Fts5FullTable *pTab){
return pTab->p.pConfig->eContent==FTS5_CONTENT_NONE;
}
/*
** Delete a virtual table handle allocated by fts5InitVtab().
*/
static void fts5FreeVtab(Fts5Table *pTab){
static void fts5FreeVtab(Fts5FullTable *pTab){
if( pTab ){
sqlite3Fts5IndexClose(pTab->pIndex);
sqlite3Fts5IndexClose(pTab->p.pIndex);
sqlite3Fts5StorageClose(pTab->pStorage);
sqlite3Fts5ConfigFree(pTab->pConfig);
sqlite3Fts5ConfigFree(pTab->p.pConfig);
sqlite3_free(pTab);
}
}
@@ -326,7 +321,7 @@ static void fts5FreeVtab(Fts5Table *pTab){
** The xDisconnect() virtual table method.
*/
static int fts5DisconnectMethod(sqlite3_vtab *pVtab){
fts5FreeVtab((Fts5Table*)pVtab);
fts5FreeVtab((Fts5FullTable*)pVtab);
return SQLITE_OK;
}
@@ -337,7 +332,7 @@ static int fts5DestroyMethod(sqlite3_vtab *pVtab){
Fts5Table *pTab = (Fts5Table*)pVtab;
int rc = sqlite3Fts5DropAll(pTab->pConfig);
if( rc==SQLITE_OK ){
fts5FreeVtab((Fts5Table*)pVtab);
fts5FreeVtab((Fts5FullTable*)pVtab);
}
return rc;
}
@@ -366,28 +361,28 @@ static int fts5InitVtab(
const char **azConfig = (const char**)argv;
int rc = SQLITE_OK; /* Return code */
Fts5Config *pConfig = 0; /* Results of parsing argc/argv */
Fts5Table *pTab = 0; /* New virtual table object */
Fts5FullTable *pTab = 0; /* New virtual table object */
/* Allocate the new vtab object and parse the configuration */
pTab = (Fts5Table*)sqlite3Fts5MallocZero(&rc, sizeof(Fts5Table));
pTab = (Fts5FullTable*)sqlite3Fts5MallocZero(&rc, sizeof(Fts5FullTable));
if( rc==SQLITE_OK ){
rc = sqlite3Fts5ConfigParse(pGlobal, db, argc, azConfig, &pConfig, pzErr);
assert( (rc==SQLITE_OK && *pzErr==0) || pConfig==0 );
}
if( rc==SQLITE_OK ){
pTab->pConfig = pConfig;
pTab->p.pConfig = pConfig;
pTab->pGlobal = pGlobal;
}
/* Open the index sub-system */
if( rc==SQLITE_OK ){
rc = sqlite3Fts5IndexOpen(pConfig, bCreate, &pTab->pIndex, pzErr);
rc = sqlite3Fts5IndexOpen(pConfig, bCreate, &pTab->p.pIndex, pzErr);
}
/* Open the storage sub-system */
if( rc==SQLITE_OK ){
rc = sqlite3Fts5StorageOpen(
pConfig, pTab->pIndex, bCreate, &pTab->pStorage, pzErr
pConfig, pTab->p.pIndex, bCreate, &pTab->pStorage, pzErr
);
}
@@ -400,8 +395,8 @@ static int fts5InitVtab(
if( rc==SQLITE_OK ){
assert( pConfig->pzErrmsg==0 );
pConfig->pzErrmsg = pzErr;
rc = sqlite3Fts5IndexLoadConfig(pTab->pIndex);
sqlite3Fts5IndexRollback(pTab->pIndex);
rc = sqlite3Fts5IndexLoadConfig(pTab->p.pIndex);
sqlite3Fts5IndexRollback(pTab->p.pIndex);
pConfig->pzErrmsg = 0;
}
@@ -614,7 +609,7 @@ static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
return SQLITE_OK;
}
static int fts5NewTransaction(Fts5Table *pTab){
static int fts5NewTransaction(Fts5FullTable *pTab){
Fts5Cursor *pCsr;
for(pCsr=pTab->pGlobal->pCsr; pCsr; pCsr=pCsr->pNext){
if( pCsr->base.pVtab==(sqlite3_vtab*)pTab ) return SQLITE_OK;
@@ -626,16 +621,16 @@ static int fts5NewTransaction(Fts5Table *pTab){
** Implementation of xOpen method.
*/
static int fts5OpenMethod(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCsr){
Fts5Table *pTab = (Fts5Table*)pVTab;
Fts5Config *pConfig = pTab->pConfig;
Fts5FullTable *pTab = (Fts5FullTable*)pVTab;
Fts5Config *pConfig = pTab->p.pConfig;
Fts5Cursor *pCsr = 0; /* New cursor object */
int nByte; /* Bytes of space to allocate */
sqlite3_int64 nByte; /* Bytes of space to allocate */
int rc; /* Return code */
rc = fts5NewTransaction(pTab);
if( rc==SQLITE_OK ){
nByte = sizeof(Fts5Cursor) + pConfig->nCol * sizeof(int);
pCsr = (Fts5Cursor*)sqlite3_malloc(nByte);
pCsr = (Fts5Cursor*)sqlite3_malloc64(nByte);
if( pCsr ){
Fts5Global *pGlobal = pTab->pGlobal;
memset(pCsr, 0, nByte);
@@ -673,7 +668,7 @@ static void fts5CsrNewrow(Fts5Cursor *pCsr){
}
static void fts5FreeCursorComponents(Fts5Cursor *pCsr){
Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab);
Fts5FullTable *pTab = (Fts5FullTable*)(pCsr->base.pVtab);
Fts5Auxdata *pData;
Fts5Auxdata *pNext;
@@ -717,7 +712,7 @@ static void fts5FreeCursorComponents(Fts5Cursor *pCsr){
*/
static int fts5CloseMethod(sqlite3_vtab_cursor *pCursor){
if( pCursor ){
Fts5Table *pTab = (Fts5Table*)(pCursor->pVtab);
Fts5FullTable *pTab = (Fts5FullTable*)(pCursor->pVtab);
Fts5Cursor *pCsr = (Fts5Cursor*)pCursor;
Fts5Cursor **pp;
@@ -774,7 +769,7 @@ static int fts5SorterNext(Fts5Cursor *pCsr){
** Set the FTS5CSR_REQUIRE_RESEEK flag on all FTS5_PLAN_MATCH cursors
** open on table pTab.
*/
static void fts5TripCursors(Fts5Table *pTab){
static void fts5TripCursors(Fts5FullTable *pTab){
Fts5Cursor *pCsr;
for(pCsr=pTab->pGlobal->pCsr; pCsr; pCsr=pCsr->pNext){
if( pCsr->ePlan==FTS5_PLAN_MATCH
@@ -801,11 +796,11 @@ static int fts5CursorReseek(Fts5Cursor *pCsr, int *pbSkip){
int rc = SQLITE_OK;
assert( *pbSkip==0 );
if( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_RESEEK) ){
Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab);
Fts5FullTable *pTab = (Fts5FullTable*)(pCsr->base.pVtab);
int bDesc = pCsr->bDesc;
i64 iRowid = sqlite3Fts5ExprRowid(pCsr->pExpr);
rc = sqlite3Fts5ExprFirst(pCsr->pExpr, pTab->pIndex, iRowid, bDesc);
rc = sqlite3Fts5ExprFirst(pCsr->pExpr, pTab->p.pIndex, iRowid, bDesc);
if( rc==SQLITE_OK && iRowid!=sqlite3Fts5ExprRowid(pCsr->pExpr) ){
*pbSkip = 1;
}
@@ -902,18 +897,22 @@ static int fts5PrepareStatement(
return rc;
}
static int fts5CursorFirstSorted(Fts5Table *pTab, Fts5Cursor *pCsr, int bDesc){
Fts5Config *pConfig = pTab->pConfig;
static int fts5CursorFirstSorted(
Fts5FullTable *pTab,
Fts5Cursor *pCsr,
int bDesc
){
Fts5Config *pConfig = pTab->p.pConfig;
Fts5Sorter *pSorter;
int nPhrase;
int nByte;
sqlite3_int64 nByte;
int rc;
const char *zRank = pCsr->zRank;
const char *zRankArgs = pCsr->zRankArgs;
nPhrase = sqlite3Fts5ExprPhraseCount(pCsr->pExpr);
nByte = sizeof(Fts5Sorter) + sizeof(int) * (nPhrase-1);
pSorter = (Fts5Sorter*)sqlite3_malloc(nByte);
pSorter = (Fts5Sorter*)sqlite3_malloc64(nByte);
if( pSorter==0 ) return SQLITE_NOMEM;
memset(pSorter, 0, nByte);
pSorter->nIdx = nPhrase;
@@ -950,10 +949,10 @@ static int fts5CursorFirstSorted(Fts5Table *pTab, Fts5Cursor *pCsr, int bDesc){
return rc;
}
static int fts5CursorFirst(Fts5Table *pTab, Fts5Cursor *pCsr, int bDesc){
static int fts5CursorFirst(Fts5FullTable *pTab, Fts5Cursor *pCsr, int bDesc){
int rc;
Fts5Expr *pExpr = pCsr->pExpr;
rc = sqlite3Fts5ExprFirst(pExpr, pTab->pIndex, pCsr->iFirstRowid, bDesc);
rc = sqlite3Fts5ExprFirst(pExpr, pTab->p.pIndex, pCsr->iFirstRowid, bDesc);
if( sqlite3Fts5ExprEof(pExpr) ){
CsrFlagSet(pCsr, FTS5CSR_EOF);
}
@@ -968,7 +967,7 @@ static int fts5CursorFirst(Fts5Table *pTab, Fts5Cursor *pCsr, int bDesc){
** parameters.
*/
static int fts5SpecialMatch(
Fts5Table *pTab,
Fts5FullTable *pTab,
Fts5Cursor *pCsr,
const char *zQuery
){
@@ -979,18 +978,18 @@ static int fts5SpecialMatch(
while( z[0]==' ' ) z++;
for(n=0; z[n] && z[n]!=' '; n++);
assert( pTab->base.zErrMsg==0 );
assert( pTab->p.base.zErrMsg==0 );
pCsr->ePlan = FTS5_PLAN_SPECIAL;
if( 0==sqlite3_strnicmp("reads", z, n) ){
pCsr->iSpecial = sqlite3Fts5IndexReads(pTab->pIndex);
pCsr->iSpecial = sqlite3Fts5IndexReads(pTab->p.pIndex);
}
else if( 0==sqlite3_strnicmp("id", z, n) ){
pCsr->iSpecial = pCsr->iCsrId;
}
else{
/* An unrecognized directive. Return an error message. */
pTab->base.zErrMsg = sqlite3_mprintf("unknown special query: %.*s", n, z);
pTab->p.base.zErrMsg = sqlite3_mprintf("unknown special query: %.*s", n, z);
rc = SQLITE_ERROR;
}
@@ -1002,7 +1001,7 @@ static int fts5SpecialMatch(
** pTab. If one is found, return a pointer to the corresponding Fts5Auxiliary
** structure. Otherwise, if no such function exists, return NULL.
*/
static Fts5Auxiliary *fts5FindAuxiliary(Fts5Table *pTab, const char *zName){
static Fts5Auxiliary *fts5FindAuxiliary(Fts5FullTable *pTab, const char *zName){
Fts5Auxiliary *pAux;
for(pAux=pTab->pGlobal->pAux; pAux; pAux=pAux->pNext){
@@ -1015,8 +1014,8 @@ static Fts5Auxiliary *fts5FindAuxiliary(Fts5Table *pTab, const char *zName){
static int fts5FindRankFunction(Fts5Cursor *pCsr){
Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab);
Fts5Config *pConfig = pTab->pConfig;
Fts5FullTable *pTab = (Fts5FullTable*)(pCsr->base.pVtab);
Fts5Config *pConfig = pTab->p.pConfig;
int rc = SQLITE_OK;
Fts5Auxiliary *pAux = 0;
const char *zRank = pCsr->zRank;
@@ -1032,7 +1031,7 @@ static int fts5FindRankFunction(Fts5Cursor *pCsr){
assert( rc==SQLITE_OK || pCsr->pRankArgStmt==0 );
if( rc==SQLITE_OK ){
if( SQLITE_ROW==sqlite3_step(pStmt) ){
int nByte;
sqlite3_int64 nByte;
pCsr->nRankArg = sqlite3_column_count(pStmt);
nByte = sizeof(sqlite3_value*)*pCsr->nRankArg;
pCsr->apRankArg = (sqlite3_value**)sqlite3Fts5MallocZero(&rc, nByte);
@@ -1054,8 +1053,8 @@ static int fts5FindRankFunction(Fts5Cursor *pCsr){
if( rc==SQLITE_OK ){
pAux = fts5FindAuxiliary(pTab, zRank);
if( pAux==0 ){
assert( pTab->base.zErrMsg==0 );
pTab->base.zErrMsg = sqlite3_mprintf("no such function: %s", zRank);
assert( pTab->p.base.zErrMsg==0 );
pTab->p.base.zErrMsg = sqlite3_mprintf("no such function: %s", zRank);
rc = SQLITE_ERROR;
}
}
@@ -1130,8 +1129,8 @@ static int fts5FilterMethod(
int nVal, /* Number of elements in apVal */
sqlite3_value **apVal /* Arguments for the indexing scheme */
){
Fts5Table *pTab = (Fts5Table*)(pCursor->pVtab);
Fts5Config *pConfig = pTab->pConfig;
Fts5FullTable *pTab = (Fts5FullTable*)(pCursor->pVtab);
Fts5Config *pConfig = pTab->p.pConfig;
Fts5Cursor *pCsr = (Fts5Cursor*)pCursor;
int rc = SQLITE_OK; /* Error code */
int iVal = 0; /* Counter for apVal[] */
@@ -1160,8 +1159,8 @@ static int fts5FilterMethod(
assert( pCsr->zRank==0 );
assert( pCsr->zRankArgs==0 );
assert( pzErrmsg==0 || pzErrmsg==&pTab->base.zErrMsg );
pConfig->pzErrmsg = &pTab->base.zErrMsg;
assert( pzErrmsg==0 || pzErrmsg==&pTab->p.base.zErrMsg );
pConfig->pzErrmsg = &pTab->p.base.zErrMsg;
/* Decode the arguments passed through to this function.
**
@@ -1227,7 +1226,7 @@ static int fts5FilterMethod(
** but a request for an internal parameter. */
rc = fts5SpecialMatch(pTab, pCsr, &zExpr[1]);
}else{
char **pzErr = &pTab->base.zErrMsg;
char **pzErr = &pTab->p.base.zErrMsg;
rc = sqlite3Fts5ExprNew(pConfig, iCol, zExpr, &pCsr->pExpr, pzErr);
if( rc==SQLITE_OK ){
if( bOrderByRank ){
@@ -1250,7 +1249,7 @@ static int fts5FilterMethod(
** by rowid (ePlan==FTS5_PLAN_ROWID). */
pCsr->ePlan = (pRowidEq ? FTS5_PLAN_ROWID : FTS5_PLAN_SCAN);
rc = sqlite3Fts5StorageStmt(
pTab->pStorage, fts5StmtType(pCsr), &pCsr->pStmt, &pTab->base.zErrMsg
pTab->pStorage, fts5StmtType(pCsr), &pCsr->pStmt, &pTab->p.base.zErrMsg
);
if( rc==SQLITE_OK ){
if( pCsr->ePlan==FTS5_PLAN_ROWID ){
@@ -1333,12 +1332,12 @@ static int fts5SeekCursor(Fts5Cursor *pCsr, int bErrormsg){
/* If the cursor does not yet have a statement handle, obtain one now. */
if( pCsr->pStmt==0 ){
Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab);
Fts5FullTable *pTab = (Fts5FullTable*)(pCsr->base.pVtab);
int eStmt = fts5StmtType(pCsr);
rc = sqlite3Fts5StorageStmt(
pTab->pStorage, eStmt, &pCsr->pStmt, (bErrormsg?&pTab->base.zErrMsg:0)
pTab->pStorage, eStmt, &pCsr->pStmt, (bErrormsg?&pTab->p.base.zErrMsg:0)
);
assert( rc!=SQLITE_OK || pTab->base.zErrMsg==0 );
assert( rc!=SQLITE_OK || pTab->p.base.zErrMsg==0 );
assert( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_CONTENT) );
}
@@ -1360,11 +1359,11 @@ static int fts5SeekCursor(Fts5Cursor *pCsr, int bErrormsg){
return rc;
}
static void fts5SetVtabError(Fts5Table *p, const char *zFormat, ...){
static void fts5SetVtabError(Fts5FullTable *p, const char *zFormat, ...){
va_list ap; /* ... printf arguments */
va_start(ap, zFormat);
assert( p->base.zErrMsg==0 );
p->base.zErrMsg = sqlite3_vmprintf(zFormat, ap);
assert( p->p.base.zErrMsg==0 );
p->p.base.zErrMsg = sqlite3_vmprintf(zFormat, ap);
va_end(ap);
}
@@ -1384,11 +1383,11 @@ static void fts5SetVtabError(Fts5Table *p, const char *zFormat, ...){
** more commands are added to this function.
*/
static int fts5SpecialInsert(
Fts5Table *pTab, /* Fts5 table object */
Fts5FullTable *pTab, /* Fts5 table object */
const char *zCmd, /* Text inserted into table-name column */
sqlite3_value *pVal /* Value inserted into rank column */
){
Fts5Config *pConfig = pTab->pConfig;
Fts5Config *pConfig = pTab->p.pConfig;
int rc = SQLITE_OK;
int bError = 0;
@@ -1423,9 +1422,9 @@ static int fts5SpecialInsert(
pConfig->bPrefixIndex = sqlite3_value_int(pVal);
#endif
}else{
rc = sqlite3Fts5IndexLoadConfig(pTab->pIndex);
rc = sqlite3Fts5IndexLoadConfig(pTab->p.pIndex);
if( rc==SQLITE_OK ){
rc = sqlite3Fts5ConfigSetValue(pTab->pConfig, zCmd, pVal, &bError);
rc = sqlite3Fts5ConfigSetValue(pTab->p.pConfig, zCmd, pVal, &bError);
}
if( rc==SQLITE_OK ){
if( bError ){
@@ -1439,7 +1438,7 @@ static int fts5SpecialInsert(
}
static int fts5SpecialDelete(
Fts5Table *pTab,
Fts5FullTable *pTab,
sqlite3_value **apVal
){
int rc = SQLITE_OK;
@@ -1453,7 +1452,7 @@ static int fts5SpecialDelete(
static void fts5StorageInsert(
int *pRc,
Fts5Table *pTab,
Fts5FullTable *pTab,
sqlite3_value **apVal,
i64 *piRowid
){
@@ -1487,8 +1486,8 @@ static int fts5UpdateMethod(
sqlite3_value **apVal, /* Array of arguments */
sqlite_int64 *pRowid /* OUT: The affected (or effected) rowid */
){
Fts5Table *pTab = (Fts5Table*)pVtab;
Fts5Config *pConfig = pTab->pConfig;
Fts5FullTable *pTab = (Fts5FullTable*)pVtab;
Fts5Config *pConfig = pTab->p.pConfig;
int eType0; /* value_type() of apVal[0] */
int rc = SQLITE_OK; /* Return code */
@@ -1497,12 +1496,11 @@ static int fts5UpdateMethod(
assert( pVtab->zErrMsg==0 );
assert( nArg==1 || nArg==(2+pConfig->nCol+2) );
assert( nArg==1
|| sqlite3_value_type(apVal[1])==SQLITE_INTEGER
|| sqlite3_value_type(apVal[1])==SQLITE_NULL
assert( sqlite3_value_type(apVal[0])==SQLITE_INTEGER
|| sqlite3_value_type(apVal[0])==SQLITE_NULL
);
assert( pTab->pConfig->pzErrmsg==0 );
pTab->pConfig->pzErrmsg = &pTab->base.zErrMsg;
assert( pTab->p.pConfig->pzErrmsg==0 );
pTab->p.pConfig->pzErrmsg = &pTab->p.base.zErrMsg;
/* Put any active cursors into REQUIRE_SEEK state. */
fts5TripCursors(pTab);
@@ -1543,7 +1541,7 @@ static int fts5UpdateMethod(
/* Filter out attempts to run UPDATE or DELETE on contentless tables.
** This is not suported. */
if( eType0==SQLITE_INTEGER && fts5IsContentless(pTab) ){
pTab->base.zErrMsg = sqlite3_mprintf(
pTab->p.base.zErrMsg = sqlite3_mprintf(
"cannot %s contentless fts5 table: %s",
(nArg>1 ? "UPDATE" : "DELETE from"), pConfig->zName
);
@@ -1556,46 +1554,52 @@ static int fts5UpdateMethod(
rc = sqlite3Fts5StorageDelete(pTab->pStorage, iDel, 0);
}
/* INSERT */
else if( eType0!=SQLITE_INTEGER ){
/* If this is a REPLACE, first remove the current entry (if any) */
if( eConflict==SQLITE_REPLACE
&& sqlite3_value_type(apVal[1])==SQLITE_INTEGER
){
i64 iNew = sqlite3_value_int64(apVal[1]); /* Rowid to delete */
rc = sqlite3Fts5StorageDelete(pTab->pStorage, iNew, 0);
}
fts5StorageInsert(&rc, pTab, apVal, pRowid);
}
/* UPDATE */
/* INSERT or UPDATE */
else{
i64 iOld = sqlite3_value_int64(apVal[0]); /* Old rowid */
i64 iNew = sqlite3_value_int64(apVal[1]); /* New rowid */
if( iOld!=iNew ){
if( eConflict==SQLITE_REPLACE ){
rc = sqlite3Fts5StorageDelete(pTab->pStorage, iOld, 0);
if( rc==SQLITE_OK ){
rc = sqlite3Fts5StorageDelete(pTab->pStorage, iNew, 0);
}
fts5StorageInsert(&rc, pTab, apVal, pRowid);
}else{
rc = sqlite3Fts5StorageContentInsert(pTab->pStorage, apVal, pRowid);
if( rc==SQLITE_OK ){
rc = sqlite3Fts5StorageDelete(pTab->pStorage, iOld, 0);
}
if( rc==SQLITE_OK ){
rc = sqlite3Fts5StorageIndexInsert(pTab->pStorage, apVal, *pRowid);
}
int eType1 = sqlite3_value_numeric_type(apVal[1]);
if( eType1!=SQLITE_INTEGER && eType1!=SQLITE_NULL ){
rc = SQLITE_MISMATCH;
}
else if( eType0!=SQLITE_INTEGER ){
/* If this is a REPLACE, first remove the current entry (if any) */
if( eConflict==SQLITE_REPLACE && eType1==SQLITE_INTEGER ){
i64 iNew = sqlite3_value_int64(apVal[1]); /* Rowid to delete */
rc = sqlite3Fts5StorageDelete(pTab->pStorage, iNew, 0);
}
}else{
rc = sqlite3Fts5StorageDelete(pTab->pStorage, iOld, 0);
fts5StorageInsert(&rc, pTab, apVal, pRowid);
}
/* UPDATE */
else{
i64 iOld = sqlite3_value_int64(apVal[0]); /* Old rowid */
i64 iNew = sqlite3_value_int64(apVal[1]); /* New rowid */
if( eType1==SQLITE_INTEGER && iOld!=iNew ){
if( eConflict==SQLITE_REPLACE ){
rc = sqlite3Fts5StorageDelete(pTab->pStorage, iOld, 0);
if( rc==SQLITE_OK ){
rc = sqlite3Fts5StorageDelete(pTab->pStorage, iNew, 0);
}
fts5StorageInsert(&rc, pTab, apVal, pRowid);
}else{
rc = sqlite3Fts5StorageContentInsert(pTab->pStorage, apVal, pRowid);
if( rc==SQLITE_OK ){
rc = sqlite3Fts5StorageDelete(pTab->pStorage, iOld, 0);
}
if( rc==SQLITE_OK ){
rc = sqlite3Fts5StorageIndexInsert(pTab->pStorage, apVal,*pRowid);
}
}
}else{
rc = sqlite3Fts5StorageDelete(pTab->pStorage, iOld, 0);
fts5StorageInsert(&rc, pTab, apVal, pRowid);
}
}
}
}
pTab->pConfig->pzErrmsg = 0;
pTab->p.pConfig->pzErrmsg = 0;
return rc;
}
@@ -1604,12 +1608,12 @@ static int fts5UpdateMethod(
*/
static int fts5SyncMethod(sqlite3_vtab *pVtab){
int rc;
Fts5Table *pTab = (Fts5Table*)pVtab;
Fts5FullTable *pTab = (Fts5FullTable*)pVtab;
fts5CheckTransactionState(pTab, FTS5_SYNC, 0);
pTab->pConfig->pzErrmsg = &pTab->base.zErrMsg;
pTab->p.pConfig->pzErrmsg = &pTab->p.base.zErrMsg;
fts5TripCursors(pTab);
rc = sqlite3Fts5StorageSync(pTab->pStorage);
pTab->pConfig->pzErrmsg = 0;
pTab->p.pConfig->pzErrmsg = 0;
return rc;
}
@@ -1617,8 +1621,8 @@ static int fts5SyncMethod(sqlite3_vtab *pVtab){
** Implementation of xBegin() method.
*/
static int fts5BeginMethod(sqlite3_vtab *pVtab){
fts5CheckTransactionState((Fts5Table*)pVtab, FTS5_BEGIN, 0);
fts5NewTransaction((Fts5Table*)pVtab);
fts5CheckTransactionState((Fts5FullTable*)pVtab, FTS5_BEGIN, 0);
fts5NewTransaction((Fts5FullTable*)pVtab);
return SQLITE_OK;
}
@@ -1629,7 +1633,7 @@ static int fts5BeginMethod(sqlite3_vtab *pVtab){
*/
static int fts5CommitMethod(sqlite3_vtab *pVtab){
UNUSED_PARAM(pVtab); /* Call below is a no-op for NDEBUG builds */
fts5CheckTransactionState((Fts5Table*)pVtab, FTS5_COMMIT, 0);
fts5CheckTransactionState((Fts5FullTable*)pVtab, FTS5_COMMIT, 0);
return SQLITE_OK;
}
@@ -1639,7 +1643,7 @@ static int fts5CommitMethod(sqlite3_vtab *pVtab){
*/
static int fts5RollbackMethod(sqlite3_vtab *pVtab){
int rc;
Fts5Table *pTab = (Fts5Table*)pVtab;
Fts5FullTable *pTab = (Fts5FullTable*)pVtab;
fts5CheckTransactionState(pTab, FTS5_ROLLBACK, 0);
rc = sqlite3Fts5StorageRollback(pTab->pStorage);
return rc;
@@ -1663,13 +1667,13 @@ static int fts5ApiColumnTotalSize(
sqlite3_int64 *pnToken
){
Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab);
Fts5FullTable *pTab = (Fts5FullTable*)(pCsr->base.pVtab);
return sqlite3Fts5StorageSize(pTab->pStorage, iCol, pnToken);
}
static int fts5ApiRowCount(Fts5Context *pCtx, i64 *pnRow){
Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab);
Fts5FullTable *pTab = (Fts5FullTable*)(pCsr->base.pVtab);
return sqlite3Fts5StorageRowCount(pTab->pStorage, pnRow);
}
@@ -1704,7 +1708,9 @@ static int fts5ApiColumnText(
){
int rc = SQLITE_OK;
Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
if( fts5IsContentless((Fts5Table*)(pCsr->base.pVtab)) ){
if( fts5IsContentless((Fts5FullTable*)(pCsr->base.pVtab))
|| pCsr->ePlan==FTS5_PLAN_SPECIAL
){
*pz = 0;
*pn = 0;
}else{
@@ -1773,10 +1779,11 @@ static int fts5CacheInstArray(Fts5Cursor *pCsr){
int rc = SQLITE_OK;
Fts5PoslistReader *aIter; /* One iterator for each phrase */
int nIter; /* Number of iterators/phrases */
int nCol = ((Fts5Table*)pCsr->base.pVtab)->pConfig->nCol;
nIter = sqlite3Fts5ExprPhraseCount(pCsr->pExpr);
if( pCsr->aInstIter==0 ){
int nByte = sizeof(Fts5PoslistReader) * nIter;
sqlite3_int64 nByte = sizeof(Fts5PoslistReader) * nIter;
pCsr->aInstIter = (Fts5PoslistReader*)sqlite3Fts5MallocZero(&rc, nByte);
}
aIter = pCsr->aInstIter;
@@ -1811,7 +1818,7 @@ static int fts5CacheInstArray(Fts5Cursor *pCsr){
nInst++;
if( nInst>=pCsr->nInstAlloc ){
pCsr->nInstAlloc = pCsr->nInstAlloc ? pCsr->nInstAlloc*2 : 32;
aInst = (int*)sqlite3_realloc(
aInst = (int*)sqlite3_realloc64(
pCsr->aInst, pCsr->nInstAlloc*sizeof(int)*3
);
if( aInst ){
@@ -1826,6 +1833,10 @@ static int fts5CacheInstArray(Fts5Cursor *pCsr){
aInst[0] = iBest;
aInst[1] = FTS5_POS2COLUMN(aIter[iBest].iPos);
aInst[2] = FTS5_POS2OFFSET(aIter[iBest].iPos);
if( aInst[1]<0 || aInst[1]>=nCol ){
rc = FTS5_CORRUPT;
break;
}
sqlite3Fts5PoslistReaderNext(&aIter[iBest]);
}
}
@@ -1898,8 +1909,8 @@ static int fts5ColumnSizeCb(
static int fts5ApiColumnSize(Fts5Context *pCtx, int iCol, int *pnToken){
Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab);
Fts5Config *pConfig = pTab->pConfig;
Fts5FullTable *pTab = (Fts5FullTable*)(pCsr->base.pVtab);
Fts5Config *pConfig = pTab->p.pConfig;
int rc = SQLITE_OK;
if( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_DOCSIZE) ){
@@ -2155,7 +2166,7 @@ static int fts5ApiQueryPhrase(
int(*xCallback)(const Fts5ExtensionApi*, Fts5Context*, void*)
){
Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab);
Fts5FullTable *pTab = (Fts5FullTable*)(pCsr->base.pVtab);
int rc;
Fts5Cursor *pNew = 0;
@@ -2232,25 +2243,19 @@ static void fts5ApiCallback(
/*
** Given cursor id iId, return a pointer to the corresponding Fts5Index
** Given cursor id iId, return a pointer to the corresponding Fts5Table
** object. Or NULL If the cursor id does not exist.
**
** If successful, set *ppConfig to point to the associated config object
** before returning.
*/
Fts5Index *sqlite3Fts5IndexFromCsrid(
Fts5Table *sqlite3Fts5TableFromCsrid(
Fts5Global *pGlobal, /* FTS5 global context for db handle */
i64 iCsrId, /* Id of cursor to find */
Fts5Config **ppConfig /* OUT: Configuration object */
i64 iCsrId /* Id of cursor to find */
){
Fts5Cursor *pCsr;
Fts5Table *pTab;
pCsr = fts5CursorFromCsrid(pGlobal, iCsrId);
pTab = (Fts5Table*)pCsr->base.pVtab;
*ppConfig = pTab->pConfig;
return pTab->pIndex;
if( pCsr ){
return (Fts5Table*)pCsr->base.pVtab;
}
return 0;
}
/*
@@ -2330,8 +2335,8 @@ static int fts5ColumnMethod(
sqlite3_context *pCtx, /* Context for sqlite3_result_xxx() calls */
int iCol /* Index of column to read value from */
){
Fts5Table *pTab = (Fts5Table*)(pCursor->pVtab);
Fts5Config *pConfig = pTab->pConfig;
Fts5FullTable *pTab = (Fts5FullTable*)(pCursor->pVtab);
Fts5Config *pConfig = pTab->p.pConfig;
Fts5Cursor *pCsr = (Fts5Cursor*)pCursor;
int rc = SQLITE_OK;
@@ -2383,7 +2388,7 @@ static int fts5FindFunctionMethod(
void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), /* OUT: Result */
void **ppArg /* OUT: User data for *pxFunc */
){
Fts5Table *pTab = (Fts5Table*)pVtab;
Fts5FullTable *pTab = (Fts5FullTable*)pVtab;
Fts5Auxiliary *pAux;
UNUSED_PARAM(nUnused);
@@ -2405,21 +2410,24 @@ static int fts5RenameMethod(
sqlite3_vtab *pVtab, /* Virtual table handle */
const char *zName /* New name of table */
){
Fts5Table *pTab = (Fts5Table*)pVtab;
Fts5FullTable *pTab = (Fts5FullTable*)pVtab;
return sqlite3Fts5StorageRename(pTab->pStorage, zName);
}
int sqlite3Fts5FlushToDisk(Fts5Table *pTab){
fts5TripCursors((Fts5FullTable*)pTab);
return sqlite3Fts5StorageSync(((Fts5FullTable*)pTab)->pStorage);
}
/*
** The xSavepoint() method.
**
** Flush the contents of the pending-terms table to disk.
*/
static int fts5SavepointMethod(sqlite3_vtab *pVtab, int iSavepoint){
Fts5Table *pTab = (Fts5Table*)pVtab;
UNUSED_PARAM(iSavepoint); /* Call below is a no-op for NDEBUG builds */
fts5CheckTransactionState(pTab, FTS5_SAVEPOINT, iSavepoint);
fts5TripCursors(pTab);
return sqlite3Fts5StorageSync(pTab->pStorage);
fts5CheckTransactionState((Fts5FullTable*)pVtab, FTS5_SAVEPOINT, iSavepoint);
return sqlite3Fts5FlushToDisk((Fts5Table*)pVtab);
}
/*
@@ -2428,11 +2436,9 @@ static int fts5SavepointMethod(sqlite3_vtab *pVtab, int iSavepoint){
** This is a no-op.
*/
static int fts5ReleaseMethod(sqlite3_vtab *pVtab, int iSavepoint){
Fts5Table *pTab = (Fts5Table*)pVtab;
UNUSED_PARAM(iSavepoint); /* Call below is a no-op for NDEBUG builds */
fts5CheckTransactionState(pTab, FTS5_RELEASE, iSavepoint);
fts5TripCursors(pTab);
return sqlite3Fts5StorageSync(pTab->pStorage);
fts5CheckTransactionState((Fts5FullTable*)pVtab, FTS5_RELEASE, iSavepoint);
return sqlite3Fts5FlushToDisk((Fts5Table*)pVtab);
}
/*
@@ -2441,7 +2447,7 @@ static int fts5ReleaseMethod(sqlite3_vtab *pVtab, int iSavepoint){
** Discard the contents of the pending terms table.
*/
static int fts5RollbackToMethod(sqlite3_vtab *pVtab, int iSavepoint){
Fts5Table *pTab = (Fts5Table*)pVtab;
Fts5FullTable *pTab = (Fts5FullTable*)pVtab;
UNUSED_PARAM(iSavepoint); /* Call below is a no-op for NDEBUG builds */
fts5CheckTransactionState(pTab, FTS5_ROLLBACKTO, iSavepoint);
fts5TripCursors(pTab);
+17 -8
View File
@@ -115,7 +115,7 @@ static int fts5StorageGetStmt(
char *zBind;
int i;
zBind = sqlite3_malloc(1 + nCol*2);
zBind = sqlite3_malloc64(1 + nCol*2);
if( zBind ){
for(i=0; i<nCol; i++){
zBind[i*2] = '?';
@@ -136,8 +136,9 @@ static int fts5StorageGetStmt(
if( zSql==0 ){
rc = SQLITE_NOMEM;
}else{
rc = sqlite3_prepare_v3(pC->db, zSql, -1,
SQLITE_PREPARE_PERSISTENT, &p->aStmt[eStmt], 0);
int f = SQLITE_PREPARE_PERSISTENT;
if( eStmt>FTS5_STMT_LOOKUP ) f |= SQLITE_PREPARE_NO_VTAB;
rc = sqlite3_prepare_v3(pC->db, zSql, -1, f, &p->aStmt[eStmt], 0);
sqlite3_free(zSql);
if( rc!=SQLITE_OK && pzErrMsg ){
*pzErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(pC->db));
@@ -281,11 +282,11 @@ int sqlite3Fts5StorageOpen(
){
int rc = SQLITE_OK;
Fts5Storage *p; /* New object */
int nByte; /* Bytes of space to allocate */
sqlite3_int64 nByte; /* Bytes of space to allocate */
nByte = sizeof(Fts5Storage) /* Fts5Storage object */
+ pConfig->nCol * sizeof(i64); /* Fts5Storage.aTotalSize[] */
*pp = p = (Fts5Storage*)sqlite3_malloc(nByte);
*pp = p = (Fts5Storage*)sqlite3_malloc64(nByte);
if( !p ) return SQLITE_NOMEM;
memset(p, 0, nByte);
@@ -296,7 +297,7 @@ int sqlite3Fts5StorageOpen(
if( bCreate ){
if( pConfig->eContent==FTS5_CONTENT_NORMAL ){
int nDefn = 32 + pConfig->nCol*10;
char *zDefn = sqlite3_malloc(32 + pConfig->nCol * 10);
char *zDefn = sqlite3_malloc64(32 + (sqlite3_int64)pConfig->nCol * 10);
if( zDefn==0 ){
rc = SQLITE_NOMEM;
}else{
@@ -587,7 +588,7 @@ int sqlite3Fts5StorageRebuild(Fts5Storage *p){
Fts5Config *pConfig = p->pConfig;
sqlite3_stmt *pScan = 0;
Fts5InsertCtx ctx;
int rc;
int rc, rc2;
memset(&ctx, 0, sizeof(Fts5InsertCtx));
ctx.pStorage = p;
@@ -626,6 +627,8 @@ int sqlite3Fts5StorageRebuild(Fts5Storage *p){
}
}
sqlite3_free(buf.p);
rc2 = sqlite3_reset(pScan);
if( rc==SQLITE_OK ) rc = rc2;
/* Write the averages record */
if( rc==SQLITE_OK ){
@@ -875,7 +878,7 @@ int sqlite3Fts5StorageIntegrity(Fts5Storage *p){
memset(&ctx, 0, sizeof(Fts5IntegrityCtx));
ctx.pConfig = p->pConfig;
aTotalSize = (i64*)sqlite3_malloc(pConfig->nCol * (sizeof(int)+sizeof(i64)));
aTotalSize = (i64*)sqlite3_malloc64(pConfig->nCol*(sizeof(int)+sizeof(i64)));
if( !aTotalSize ) return SQLITE_NOMEM;
aColSize = (int*)&aTotalSize[pConfig->nCol];
memset(aTotalSize, 0, sizeof(i64) * pConfig->nCol);
@@ -1075,7 +1078,13 @@ int sqlite3Fts5StorageSize(Fts5Storage *p, int iCol, i64 *pnToken){
int sqlite3Fts5StorageRowCount(Fts5Storage *p, i64 *pnRow){
int rc = fts5StorageLoadTotals(p, 0);
if( rc==SQLITE_OK ){
/* nTotalRow being zero does not necessarily indicate a corrupt
** database - it might be that the FTS5 table really does contain zero
** rows. However this function is only called from the xRowCount() API,
** and there is no way for that API to be invoked if the table contains
** no rows. Hence the FTS5_CORRUPT return. */
*pnRow = p->nTotalRow;
if( p->nTotalRow<=0 ) rc = FTS5_CORRUPT;
}
return rc;
}
+2 -2
View File
@@ -309,7 +309,7 @@ static Fts5MatchinfoCtx *fts5MatchinfoNew(
int nPhrase;
int i;
int nInt;
int nByte;
sqlite3_int64 nByte;
int rc;
nCol = pApi->xColumnCount(pFts);
@@ -330,7 +330,7 @@ static Fts5MatchinfoCtx *fts5MatchinfoNew(
nByte = sizeof(Fts5MatchinfoCtx) /* The struct itself */
+ sizeof(u32) * nInt /* The p->aRet[] array */
+ (i+1); /* The p->zArg string */
p = (Fts5MatchinfoCtx*)sqlite3_malloc(nByte);
p = (Fts5MatchinfoCtx*)sqlite3_malloc64(nByte);
if( p==0 ){
sqlite3_result_error_nomem(pCtx);
return 0;
+3 -3
View File
@@ -137,7 +137,7 @@ static int fts5tokDequoteArray(
nByte += (int)(strlen(argv[i]) + 1);
}
*pazDequote = azDequote = sqlite3_malloc(sizeof(char *)*argc + nByte);
*pazDequote = azDequote = sqlite3_malloc64(sizeof(char *)*argc + nByte);
if( azDequote==0 ){
rc = SQLITE_NOMEM;
}else{
@@ -335,7 +335,7 @@ static int fts5tokCb(
if( (pCsr->nRow & (pCsr->nRow-1))==0 ){
int nNew = pCsr->nRow ? pCsr->nRow*2 : 32;
Fts5tokRow *aNew;
aNew = (Fts5tokRow*)sqlite3_realloc(pCsr->aRow, nNew*sizeof(Fts5tokRow));
aNew = (Fts5tokRow*)sqlite3_realloc64(pCsr->aRow, nNew*sizeof(Fts5tokRow));
if( aNew==0 ) return SQLITE_NOMEM;
memset(&aNew[pCsr->nRow], 0, sizeof(Fts5tokRow)*(nNew-pCsr->nRow));
pCsr->aRow = aNew;
@@ -378,7 +378,7 @@ static int fts5tokFilterMethod(
if( pCsr->zInput==0 ){
rc = SQLITE_NOMEM;
}else{
memcpy(pCsr->zInput, zByte, nByte);
if( nByte>0 ) memcpy(pCsr->zInput, zByte, nByte);
pCsr->zInput[nByte] = 0;
rc = pTab->tok.xTokenize(
pTab->pTok, (void*)pCsr, 0, zByte, nByte, fts5tokCb
+8 -9
View File
@@ -152,7 +152,7 @@ static int fts5AsciiTokenize(
nByte = ie-is;
if( nByte>nFold ){
if( pFold!=aFold ) sqlite3_free(pFold);
pFold = sqlite3_malloc(nByte*2);
pFold = sqlite3_malloc64((sqlite3_int64)nByte*2);
if( pFold==0 ){
rc = SQLITE_NOMEM;
break;
@@ -256,13 +256,14 @@ static int fts5UnicodeAddExceptions(
int *aNew;
if( n>0 ){
aNew = (int*)sqlite3_realloc(p->aiException, (n+p->nException)*sizeof(int));
aNew = (int*)sqlite3_realloc64(p->aiException,
(n+p->nException)*sizeof(int));
if( aNew ){
int nNew = p->nException;
const unsigned char *zCsr = (const unsigned char*)z;
const unsigned char *zTerm = (const unsigned char*)&z[n];
while( zCsr<zTerm ){
int iCode;
u32 iCode;
int bToken;
READ_UTF8(zCsr, zTerm, iCode);
if( iCode<128 ){
@@ -274,7 +275,7 @@ static int fts5UnicodeAddExceptions(
if( bToken!=bTokenChars && sqlite3Fts5UnicodeIsdiacritic(iCode)==0 ){
int i;
for(i=0; i<nNew; i++){
if( aNew[i]>iCode ) break;
if( (u32)aNew[i]>iCode ) break;
}
memmove(&aNew[i+1], &aNew[i], (nNew-i)*sizeof(int));
aNew[i] = iCode;
@@ -429,7 +430,7 @@ static int fts5UnicodeCreate(
*/
static int fts5UnicodeIsAlnum(Unicode61Tokenizer *p, int iCode){
return (
p->aCategory[sqlite3Fts5UnicodeCategory(iCode)]
p->aCategory[sqlite3Fts5UnicodeCategory((u32)iCode)]
^ fts5UnicodeIsException(p, iCode)
);
}
@@ -458,7 +459,7 @@ static int fts5UnicodeTokenize(
/* Each iteration of this loop gobbles up a contiguous run of separators,
** then the next token. */
while( rc==SQLITE_OK ){
int iCode; /* non-ASCII codepoint read from input */
u32 iCode; /* non-ASCII codepoint read from input */
char *zOut = aFold;
int is;
int ie;
@@ -490,7 +491,7 @@ static int fts5UnicodeTokenize(
/* Grow the output buffer so that there is sufficient space to fit the
** largest possible utf-8 character. */
if( zOut>pEnd ){
aFold = sqlite3_malloc(nFold*2);
aFold = sqlite3_malloc64((sqlite3_int64)nFold*2);
if( aFold==0 ){
rc = SQLITE_NOMEM;
goto tokenize_done;
@@ -1284,5 +1285,3 @@ int sqlite3Fts5TokenizerInit(fts5_api *pApi){
return rc;
}
+28 -26
View File
@@ -1,5 +1,5 @@
/*
** 2012 May 25
** 2012-05-25
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
@@ -47,28 +47,29 @@ static int fts5_remove_diacritic(int c, int bComplex){
62830, 62890, 62924, 62974, 63032, 63050, 63082, 63118,
63182, 63242, 63274, 63310, 63368, 63390,
};
char aChar[] = {
'\0', 'a'|0x00, 'c'|0x00, 'e'|0x00, 'i'|0x00, 'n'|0x00,
'o'|0x00, 'u'|0x00, 'y'|0x00, 'y'|0x00, 'a'|0x00, 'c'|0x00,
'd'|0x00, 'e'|0x00, 'e'|0x00, 'g'|0x00, 'h'|0x00, 'i'|0x00,
'j'|0x00, 'k'|0x00, 'l'|0x00, 'n'|0x00, 'o'|0x00, 'r'|0x00,
's'|0x00, 't'|0x00, 'u'|0x00, 'u'|0x00, 'w'|0x00, 'y'|0x00,
'z'|0x00, 'o'|0x00, 'u'|0x00, 'a'|0x00, 'i'|0x00, 'o'|0x00,
'u'|0x00, 'u'|0x80, 'a'|0x80, 'g'|0x00, 'k'|0x00, 'o'|0x00,
'o'|0x80, 'j'|0x00, 'g'|0x00, 'n'|0x00, 'a'|0x80, 'a'|0x00,
'e'|0x00, 'i'|0x00, 'o'|0x00, 'r'|0x00, 'u'|0x00, 's'|0x00,
't'|0x00, 'h'|0x00, 'a'|0x00, 'e'|0x00, 'o'|0x80, 'o'|0x00,
'o'|0x80, 'y'|0x00, '\0', '\0', '\0', '\0',
'\0', '\0', '\0', '\0', 'a'|0x00, 'b'|0x00,
'c'|0x80, 'd'|0x00, 'd'|0x00, 'e'|0x80, 'e'|0x00, 'e'|0x80,
'f'|0x00, 'g'|0x00, 'h'|0x00, 'h'|0x00, 'i'|0x00, 'i'|0x80,
'k'|0x00, 'l'|0x00, 'l'|0x80, 'l'|0x00, 'm'|0x00, 'n'|0x00,
'o'|0x80, 'p'|0x00, 'r'|0x00, 'r'|0x80, 'r'|0x00, 's'|0x00,
's'|0x80, 't'|0x00, 'u'|0x00, 'u'|0x80, 'v'|0x00, 'w'|0x00,
'w'|0x00, 'x'|0x00, 'y'|0x00, 'z'|0x00, 'h'|0x00, 't'|0x00,
'w'|0x00, 'y'|0x00, 'a'|0x00, 'a'|0x80, 'a'|0x80, 'a'|0x80,
'e'|0x00, 'e'|0x80, 'e'|0x80, 'i'|0x00, 'o'|0x00, 'o'|0x80,
'o'|0x80, 'o'|0x80, 'u'|0x00, 'u'|0x80, 'u'|0x80, 'y'|0x00,
#define HIBIT ((unsigned char)0x80)
unsigned char aChar[] = {
'\0', 'a', 'c', 'e', 'i', 'n',
'o', 'u', 'y', 'y', 'a', 'c',
'd', 'e', 'e', 'g', 'h', 'i',
'j', 'k', 'l', 'n', 'o', 'r',
's', 't', 'u', 'u', 'w', 'y',
'z', 'o', 'u', 'a', 'i', 'o',
'u', 'u'|HIBIT, 'a'|HIBIT, 'g', 'k', 'o',
'o'|HIBIT, 'j', 'g', 'n', 'a'|HIBIT, 'a',
'e', 'i', 'o', 'r', 'u', 's',
't', 'h', 'a', 'e', 'o'|HIBIT, 'o',
'o'|HIBIT, 'y', '\0', '\0', '\0', '\0',
'\0', '\0', '\0', '\0', 'a', 'b',
'c'|HIBIT, 'd', 'd', 'e'|HIBIT, 'e', 'e'|HIBIT,
'f', 'g', 'h', 'h', 'i', 'i'|HIBIT,
'k', 'l', 'l'|HIBIT, 'l', 'm', 'n',
'o'|HIBIT, 'p', 'r', 'r'|HIBIT, 'r', 's',
's'|HIBIT, 't', 'u', 'u'|HIBIT, 'v', 'w',
'w', 'x', 'y', 'z', 'h', 't',
'w', 'y', 'a', 'a'|HIBIT, 'a'|HIBIT, 'a'|HIBIT,
'e', 'e'|HIBIT, 'e'|HIBIT, 'i', 'o', 'o'|HIBIT,
'o'|HIBIT, 'o'|HIBIT, 'u', 'u'|HIBIT, 'u'|HIBIT, 'y',
};
unsigned int key = (((unsigned int)c)<<3) | 0x00000007;
@@ -99,8 +100,8 @@ int sqlite3Fts5UnicodeIsdiacritic(int c){
unsigned int mask1 = 0x000361F8;
if( c<768 || c>817 ) return 0;
return (c < 768+32) ?
(mask0 & (1 << (c-768))) :
(mask1 & (1 << (c-768-32)));
(mask0 & ((unsigned int)1 << (c-768))) :
(mask1 & ((unsigned int)1 << (c-768-32)));
}
@@ -248,6 +249,7 @@ int sqlite3Fts5UnicodeFold(int c, int eRemoveDiacritic){
return ret;
}
int sqlite3Fts5UnicodeCatParse(const char *zCat, u8 *aArray){
aArray[0] = 1;
switch( zCat[0] ){
@@ -729,7 +731,7 @@ static u16 aFts5UnicodeData[] = {
34, 3074, 7692, 63, 63,
};
int sqlite3Fts5UnicodeCategory(int iCode) {
int sqlite3Fts5UnicodeCategory(u32 iCode) {
int iRes = -1;
int iHi;
int iLo;
+1 -2
View File
@@ -76,7 +76,7 @@ int sqlite3Fts5GetVarint32(const unsigned char *p, u32 *v){
u8 n;
p -= 2;
n = sqlite3Fts5GetVarint(p, &v64);
*v = (u32)v64;
*v = ((u32)v64) & 0x7FFFFFFF;
assert( n>3 && n<=9 );
return n;
}
@@ -342,4 +342,3 @@ int sqlite3Fts5GetVarintLen(u32 iVal){
if( iVal<(1 << 28) ) return 4;
return 5;
}
+38 -31
View File
@@ -55,7 +55,7 @@ struct Fts5VocabTable {
struct Fts5VocabCursor {
sqlite3_vtab_cursor base;
sqlite3_stmt *pStmt; /* Statement holding lock on pIndex */
Fts5Index *pIndex; /* Associated FTS5 index */
Fts5Table *pFts5; /* Associated FTS5 table */
int bEof; /* True if this cursor is at EOF */
Fts5IndexIter *pIter; /* Term/rowid iterator object */
@@ -64,7 +64,6 @@ struct Fts5VocabCursor {
char *zLeTerm; /* (term <= $zLeTerm) paramater, or NULL */
/* These are used by 'col' tables only */
Fts5Config *pConfig; /* Fts5 table configuration */
int iCol;
i64 *aCnt;
i64 *aDoc;
@@ -327,8 +326,7 @@ static int fts5VocabOpenMethod(
sqlite3_vtab_cursor **ppCsr
){
Fts5VocabTable *pTab = (Fts5VocabTable*)pVTab;
Fts5Index *pIndex = 0;
Fts5Config *pConfig = 0;
Fts5Table *pFts5 = 0;
Fts5VocabCursor *pCsr = 0;
int rc = SQLITE_OK;
sqlite3_stmt *pStmt = 0;
@@ -347,31 +345,34 @@ static int fts5VocabOpenMethod(
if( pStmt && sqlite3_step(pStmt)==SQLITE_ROW ){
i64 iId = sqlite3_column_int64(pStmt, 0);
pIndex = sqlite3Fts5IndexFromCsrid(pTab->pGlobal, iId, &pConfig);
pFts5 = sqlite3Fts5TableFromCsrid(pTab->pGlobal, iId);
}
if( rc==SQLITE_OK && pIndex==0 ){
rc = sqlite3_finalize(pStmt);
pStmt = 0;
if( rc==SQLITE_OK ){
pVTab->zErrMsg = sqlite3_mprintf(
"no such fts5 table: %s.%s", pTab->zFts5Db, pTab->zFts5Tbl
);
rc = SQLITE_ERROR;
if( rc==SQLITE_OK ){
if( pFts5==0 ){
rc = sqlite3_finalize(pStmt);
pStmt = 0;
if( rc==SQLITE_OK ){
pVTab->zErrMsg = sqlite3_mprintf(
"no such fts5 table: %s.%s", pTab->zFts5Db, pTab->zFts5Tbl
);
rc = SQLITE_ERROR;
}
}else{
rc = sqlite3Fts5FlushToDisk(pFts5);
}
}
if( rc==SQLITE_OK ){
int nByte = pConfig->nCol * sizeof(i64) * 2 + sizeof(Fts5VocabCursor);
int nByte = pFts5->pConfig->nCol * sizeof(i64)*2 + sizeof(Fts5VocabCursor);
pCsr = (Fts5VocabCursor*)sqlite3Fts5MallocZero(&rc, nByte);
}
if( pCsr ){
pCsr->pIndex = pIndex;
pCsr->pFts5 = pFts5;
pCsr->pStmt = pStmt;
pCsr->pConfig = pConfig;
pCsr->aCnt = (i64*)&pCsr[1];
pCsr->aDoc = &pCsr->aCnt[pConfig->nCol];
pCsr->aDoc = &pCsr->aCnt[pFts5->pConfig->nCol];
}else{
sqlite3_finalize(pStmt);
}
@@ -387,6 +388,7 @@ static void fts5VocabResetCursor(Fts5VocabCursor *pCsr){
sqlite3_free(pCsr->zLeTerm);
pCsr->nLeTerm = -1;
pCsr->zLeTerm = 0;
pCsr->bEof = 0;
}
/*
@@ -425,7 +427,7 @@ static int fts5VocabInstanceNewTerm(Fts5VocabCursor *pCsr){
}
static int fts5VocabInstanceNext(Fts5VocabCursor *pCsr){
int eDetail = pCsr->pConfig->eDetail;
int eDetail = pCsr->pFts5->pConfig->eDetail;
int rc = SQLITE_OK;
Fts5IndexIter *pIter = pCsr->pIter;
i64 *pp = &pCsr->iInstPos;
@@ -460,7 +462,7 @@ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){
Fts5VocabCursor *pCsr = (Fts5VocabCursor*)pCursor;
Fts5VocabTable *pTab = (Fts5VocabTable*)pCursor->pVtab;
int rc = SQLITE_OK;
int nCol = pCsr->pConfig->nCol;
int nCol = pCsr->pFts5->pConfig->nCol;
pCsr->rowid++;
@@ -482,6 +484,7 @@ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){
int nTerm;
zTerm = sqlite3Fts5IterTerm(pCsr->pIter, &nTerm);
assert( nTerm>=0 );
if( pCsr->nLeTerm>=0 ){
int nCmp = MIN(nTerm, pCsr->nLeTerm);
int bCmp = memcmp(pCsr->zLeTerm, zTerm, nCmp);
@@ -498,7 +501,7 @@ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){
assert( pTab->eType==FTS5_VOCAB_COL || pTab->eType==FTS5_VOCAB_ROW );
while( rc==SQLITE_OK ){
int eDetail = pCsr->pConfig->eDetail;
int eDetail = pCsr->pFts5->pConfig->eDetail;
const u8 *pPos; int nPos; /* Position list */
i64 iPos = 0; /* 64-bit position read from poslist */
int iOff = 0; /* Current offset within position list */
@@ -521,7 +524,6 @@ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){
int iCol = -1;
while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff, &iPos) ){
int ii = FTS5_POS2COLUMN(iPos);
pCsr->aCnt[ii]++;
if( iCol!=ii ){
if( ii>=nCol ){
rc = FTS5_CORRUPT;
@@ -530,6 +532,7 @@ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){
pCsr->aDoc[ii]++;
iCol = ii;
}
pCsr->aCnt[ii]++;
}
}else if( eDetail==FTS5_DETAIL_COLUMNS ){
while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff,&iPos) ){
@@ -558,7 +561,9 @@ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){
if( rc==SQLITE_OK ){
zTerm = sqlite3Fts5IterTerm(pCsr->pIter, &nTerm);
if( nTerm!=pCsr->term.n || memcmp(zTerm, pCsr->term.p, nTerm) ){
if( nTerm!=pCsr->term.n
|| (nTerm>0 && memcmp(zTerm, pCsr->term.p, nTerm))
){
break;
}
if( sqlite3Fts5IterEof(pCsr->pIter) ) break;
@@ -569,7 +574,7 @@ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){
if( rc==SQLITE_OK && pCsr->bEof==0 && pTab->eType==FTS5_VOCAB_COL ){
while( pCsr->aDoc[pCsr->iCol]==0 ) pCsr->iCol++;
assert( pCsr->iCol<pCsr->pConfig->nCol );
assert( pCsr->iCol<pCsr->pFts5->pConfig->nCol );
}
return rc;
}
@@ -616,6 +621,7 @@ static int fts5VocabFilterMethod(
}
if( pLe ){
const char *zCopy = (const char *)sqlite3_value_text(pLe);
if( zCopy==0 ) zCopy = "";
pCsr->nLeTerm = sqlite3_value_bytes(pLe);
pCsr->zLeTerm = sqlite3_malloc(pCsr->nLeTerm+1);
if( pCsr->zLeTerm==0 ){
@@ -627,14 +633,15 @@ static int fts5VocabFilterMethod(
}
if( rc==SQLITE_OK ){
rc = sqlite3Fts5IndexQuery(pCsr->pIndex, zTerm, nTerm, f, 0, &pCsr->pIter);
Fts5Index *pIndex = pCsr->pFts5->pIndex;
rc = sqlite3Fts5IndexQuery(pIndex, zTerm, nTerm, f, 0, &pCsr->pIter);
}
if( rc==SQLITE_OK && eType==FTS5_VOCAB_INSTANCE ){
rc = fts5VocabInstanceNewTerm(pCsr);
}
if( rc==SQLITE_OK
&& !pCsr->bEof
&& (eType!=FTS5_VOCAB_INSTANCE || pCsr->pConfig->eDetail!=FTS5_DETAIL_NONE)
if( rc==SQLITE_OK && !pCsr->bEof
&& (eType!=FTS5_VOCAB_INSTANCE
|| pCsr->pFts5->pConfig->eDetail!=FTS5_DETAIL_NONE)
){
rc = fts5VocabNextMethod(pCursor);
}
@@ -657,7 +664,7 @@ static int fts5VocabColumnMethod(
int iCol /* Index of column to read value from */
){
Fts5VocabCursor *pCsr = (Fts5VocabCursor*)pCursor;
int eDetail = pCsr->pConfig->eDetail;
int eDetail = pCsr->pFts5->pConfig->eDetail;
int eType = ((Fts5VocabTable*)(pCursor->pVtab))->eType;
i64 iVal = 0;
@@ -669,7 +676,7 @@ static int fts5VocabColumnMethod(
assert( iCol==1 || iCol==2 || iCol==3 );
if( iCol==1 ){
if( eDetail!=FTS5_DETAIL_NONE ){
const char *z = pCsr->pConfig->azCol[pCsr->iCol];
const char *z = pCsr->pFts5->pConfig->azCol[pCsr->iCol];
sqlite3_result_text(pCtx, z, -1, SQLITE_STATIC);
}
}else if( iCol==2 ){
@@ -697,8 +704,8 @@ static int fts5VocabColumnMethod(
}else if( eDetail==FTS5_DETAIL_COLUMNS ){
ii = (int)pCsr->iInstPos;
}
if( ii>=0 && ii<pCsr->pConfig->nCol ){
const char *z = pCsr->pConfig->azCol[ii];
if( ii>=0 && ii<pCsr->pFts5->pConfig->nCol ){
const char *z = pCsr->pFts5->pConfig->azCol[ii];
sqlite3_result_text(pCtx, z, -1, SQLITE_STATIC);
}
break;
+34 -3
View File
@@ -38,8 +38,7 @@ do_execsql_test 1.0 {
do_execsql_test 1.1 {
DROP TABLE t1;
SELECT name, sql FROM sqlite_master;
} {
}
} {}
#-------------------------------------------------------------------------
#
@@ -428,7 +427,7 @@ proc funk {} {
db eval { UPDATE n1_config SET v=50 WHERE k='version' }
set fd [db incrblob main n1_data block 10]
fconfigure $fd -encoding binary -translation binary
puts -nonewline $fd "\x44\x45"
# puts -nonewline $fd "\x44\x45"
close $fd
}
db func funk funk
@@ -604,6 +603,38 @@ do_execsql_test 23.2 {
SELECT * FROM t11, t10 WHERE t10.rowid IS NULL;
}
#-------------------------------------------------------------------------
do_execsql_test 24.0 {
CREATE VIRTUAL TABLE t12 USING fts5(x, detail=%DETAIL%);
INSERT INTO t12 VALUES('aaaa');
}
do_execsql_test 24.1 {
BEGIN;
DELETE FROM t12 WHERE rowid=1;
SELECT * FROM t12('aaaa');
INSERT INTO t12 VALUES('aaaa');
END;
}
do_execsql_test 24.2 {
INSERT INTO t12(t12) VALUES('integrity-check');
}
do_execsql_test 24.3 {
SELECT * FROM t12('aaaa');
} {aaaa}
#-------------------------------------------------------------------------
do_execsql_test 25.0 {
CREATE VIRTUAL TABLE t13 USING fts5(x, detail=%DETAIL%);
}
do_execsql_test 25.1 {
BEGIN;
INSERT INTO t13 VALUES('AAAA');
SELECT * FROM t13('BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB*');
END;
}
}
expand_all_sql db
+6
View File
@@ -51,6 +51,12 @@ do_execsql_test 1.1 {
do_execsql_test 1.2 {
INSERT INTO t1(t1) VALUES('integrity-check');
}
do_execsql_test 1.3 {
SAVEPOINT one;
INSERT INTO t1 VALUES('v w x');
ROLLBACK TO one;
}
}
+8
View File
@@ -144,6 +144,14 @@ do_execsql_test 3.1 {
{[a b c d e]}
}
do_execsql_test 3.2 {
SELECT highlight(ft, 0, NULL, NULL) FROM ft WHERE ft MATCH 'a+b+c AND c+d+e';
} {
{a b c x c d e}
{a b c c d e}
{a b c d e}
}
}
finish_test
+31
View File
@@ -275,6 +275,37 @@ do_execsql_test 9.3 {
9 10
}
#-------------------------------------------------------------------------
# Test that aux. functions may not be used in aggregate queries.
#
reset_db
do_execsql_test 10.0 {
CREATE VIRTUAL TABLE t1 USING fts5(x, y, z);
INSERT INTO t1 VALUES('a', 'one two', 1);
INSERT INTO t1 VALUES('b', 'two three', 2);
INSERT INTO t1 VALUES('c', 'three four', 1);
INSERT INTO t1 VALUES('d', 'four five', 2);
INSERT INTO t1 VALUES('e', 'five six', 1);
INSERT INTO t1 VALUES('f', 'six seven', 2);
}
proc firstcol {cmd} { $cmd xColumnText 0 }
sqlite3_fts5_create_function db firstcol firstcol
do_execsql_test 10.1.1 {
SELECT firstcol(t1) FROM t1
} {a b c d e f}
do_execsql_test 10.1.2 {
SELECT group_concat(x, '.') FROM t1
} {a.b.c.d.e.f}
do_catchsql_test 10.1.3 {
SELECT group_concat(firstcol(t1), '.') FROM t1
} {1 {unable to use function firstcol in the requested context}}
do_catchsql_test 10.1.4 {
SELECT group_concat(firstcol(t1), '.') FROM t1 GROUP BY rowid
} {1 {unable to use function firstcol in the requested context}}
finish_test
+80
View File
@@ -0,0 +1,80 @@
# 2018 Dec 22
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#*************************************************************************
# This file implements regression tests for SQLite library. The
# focus of this script is testing the FTS5 module.
#
source [file join [file dirname [info script]] fts5_common.tcl]
set testprefix fts5circref
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
ifcapable !fts5 {
finish_test
return
}
do_execsql_test 1.0 {
CREATE VIRTUAL TABLE tt USING fts5(a);
SELECT name FROM sqlite_master ORDER BY 1;
} {
tt tt_config tt_content tt_data tt_docsize tt_idx
}
db_save_and_close
foreach {tn schema sql} {
1 {
CREATE TRIGGER tr1 AFTER INSERT ON tt_config BEGIN
SELECT * FROM tt;
END;
} {
INSERT INTO tt(tt, rank) VALUES('usermerge', 4);
}
2 {
CREATE TRIGGER tr1 AFTER INSERT ON tt_docsize BEGIN
SELECT * FROM tt;
END;
} {
INSERT INTO tt(a) VALUES('one two three');
}
3 {
CREATE TRIGGER tr1 AFTER INSERT ON tt_content BEGIN
SELECT * FROM tt;
END;
} {
INSERT INTO tt(a) VALUES('one two three');
}
4 {
CREATE TRIGGER tr1 AFTER INSERT ON tt_data BEGIN
SELECT * FROM tt;
END;
} {
INSERT INTO tt(a) VALUES('one two three');
}
5 {
CREATE TRIGGER tr1 AFTER INSERT ON tt_idx BEGIN
SELECT * FROM tt;
END;
} {
INSERT INTO tt(a) VALUES('one two three');
}
} {
db_restore_and_reopen
do_execsql_test 1.1.$tn.1 $schema
do_catchsql_test 1.1.$tn.2 $sql {1 {SQL logic error}}
db close
}
finish_test
File diff suppressed because one or more lines are too long
+67
View File
@@ -0,0 +1,67 @@
# 2019 Jan 4
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#*************************************************************************
# This file implements regression tests for SQLite library. The
# focus of this script is testing the FTS5 module.
#
source [file join [file dirname [info script]] fts5_common.tcl]
set testprefix fts5interrupt
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
ifcapable !fts5 {
finish_test
return
}
do_execsql_test 1.0 {
CREATE VIRTUAL TABLE t1 USING fts5(a);
INSERT INTO t1(t1, rank) VALUES('pgsz', 40);
}
db_save_and_close
proc progress_handler {args} {
incr ::progress_handler_delay -1
if {$::progress_handler_delay<=0} { return 1 }
return 0
}
foreach {tn sql} {
1 { INSERT INTO t1(rowid, a) VALUES(0, 'z z z z') }
2 { COMMIT }
} {
set bDone 0
for {set i 1} {$bDone==0} {incr i} {
do_test 1.$tn.$i {
db_restore_and_reopen
execsql {
BEGIN;
INSERT INTO t1(rowid, a) VALUES(1, 'a b c d');
INSERT INTO t1(rowid, a) VALUES(2, 'd e f g');
INSERT INTO t1(rowid, a) VALUES(3, 'h i j k');
INSERT INTO t1(rowid, a) VALUES(4, 'l m n o');
}
set ::progress_handler_delay $i
db progress 1 progress_handler
set res [catchsql $sql]
db close
if {$res=="0 {}"} {
set bDone 1
} else {
if {$res!="1 interrupted"} { error "got: $res" }
}
set {} {}
} {}
}
}
finish_test
+1 -1
View File
@@ -21,7 +21,7 @@ ifcapable !fts5 {
}
proc fts3_unicode_path {file} {
file join [file dirname [info script]] .. .. fts3 unicode $file
file join .. [file dirname [info script]] .. .. fts3 unicode $file
}
source [fts3_unicode_path parseunicode.tcl]
+38
View File
@@ -115,5 +115,43 @@ do_execsql_test 2.2.integrity {
INSERT INTO x2(x2) VALUES('integrity-check');
}
#-------------------------------------------------------------------------
#
do_execsql_test 3.0 {
CREATE VIRTUAL TABLE x3 USING fts5(x, detail=%DETAIL%);
INSERT INTO x3 VALUES('one');
INSERT INTO x3 VALUES('two');
INSERT INTO x3 VALUES('one');
INSERT INTO x3 VALUES('two');
INSERT INTO x3 VALUES('one');
}
do_test 3.1 {
db eval { SELECT * FROM x3('one') } {
db eval {
INSERT INTO x3(x3) VALUES('optimize');
}
}
} {}
do_execsql_test 4.0 {
CREATE VIRTUAL TABLE x4 USING fts5(a, detail=%DETAIL%);
INSERT INTO x4 VALUES('one two three');
INSERT INTO x4(rowid, a) VALUES('2', 'one two three');
INSERT INTO x4(rowid, a) VALUES('3.0', 'one two three');
}
do_catchsql_test 4.1 {
INSERT INTO x4(rowid, a) VALUES('four', 'one two three');
} {1 {datatype mismatch}}
do_catchsql_test 4.2 {
UPDATE x4 SET rowid = 'four' WHERE rowid=1;
} {1 {datatype mismatch}}
}
reset_db
do_catchsql_test 4.0 { CREATE VIRTUAL TABLE t1 USING fts5(a,b,c); } {0 {}}
do_catchsql_test 4.1 { DELETE FROM t1 WHERE t1 MATCH 'f*'; } {0 {}}
finish_test
+64 -2
View File
@@ -79,8 +79,8 @@ do_execsql_test 1.1.2 {
3 cnt {} 0 {} 0
}
do_execsql_test 1.2.1 { SELECT * FROM v1 } { }
do_execsql_test 1.2.2 { SELECT * FROM v2 } { }
do_execsql_test 1.2.1 { SELECT * FROM v1 } {}
do_execsql_test 1.2.2 { SELECT * FROM v2 } {}
do_execsql_test 1.3 {
INSERT INTO t1 VALUES('x y z');
@@ -479,6 +479,68 @@ do_test 9.6 {
expr [lsearch $e2 SorterSort]<0
} 0
#-------------------------------------------------------------------------
do_execsql_test 10.0 {
CREATE VIRTUAL TABLE ft USING fts5(a, b, c);
CREATE VIRTUAL TABLE t2 USING fts5vocab('ft','row');
CREATE VIRTUAL TABLE t3 USING fts5vocab('ft','row');
}
do_execsql_test 10.1 {
BEGIN;
INSERT INTO ft(b) VALUES('x y');
}
do_execsql_test 10.2 {
SELECT t2.term FROM t2;
} {x y}
do_execsql_test 10.3 {
SELECT t2.term, t3.term FROM t2, t3;
} {x x x y y x y y}
do_execsql_test 10.4 {
COMMIT;
}
do_execsql_test 10.5 {
BEGIN;
INSERT INTO ft(a) VALUES('1 2 3');
INSERT INTO ft(a) VALUES('4 5 6');
INSERT INTO ft(a) VALUES('1 2 3');
INSERT INTO ft(a) VALUES('4 5 6');
INSERT INTO ft(a) VALUES('1 2 3');
INSERT INTO ft(a) VALUES('4 5 6');
}
do_test 10.6 {
set res [list]
db eval { SELECT rowid FROM ft('4') } x {
db eval { SELECT * FROM t2 }
lappend res $x(rowid)
}
db eval COMMIT
set res
} {3 5 7}
do_execsql_test 10.6.1 {
SELECT * FROM t2 WHERE term<NULL;
}
do_execsql_test 10.6.2 {
SELECT * FROM t2 WHERE term>NULL;
}
do_execsql_test 10.6.3 {
SELECT * FROM t2 WHERE term=NULL;
}
do_execsql_test 10.7.1 {
SELECT * FROM t2 WHERE term<?;
}
do_execsql_test 10.7.2 {
SELECT * FROM t2 WHERE term>?;
}
do_execsql_test 10.7.3 {
SELECT * FROM t2 WHERE term=?;
}
finish_test
+34 -5
View File
@@ -80,8 +80,7 @@ do_execsql_test 1.4 {
do_execsql_test 1.5 {
DELETE FROM t1;
SELECT * FROM v1;
} {
}
} {}
#-------------------------------------------------------------------------
#
@@ -143,8 +142,7 @@ do_execsql_test 2.4 {
do_execsql_test 2.5 {
DELETE FROM t1;
SELECT * FROM v1;
} {
}
} {}
#-------------------------------------------------------------------------
#
@@ -202,7 +200,38 @@ do_execsql_test 3.4 {
do_execsql_test 3.5 {
DELETE FROM t1;
SELECT * FROM v1;
} {
} {}
#-------------------------------------------------------------------------
#
reset_db
do_execsql_test 4.0 {
CREATE VIRTUAL TABLE v1 USING fts5vocab(nosuchtable, col);
}
do_catchsql_test 4.1 {
SELECT * FROM v1 WHERE term=='nosuchterm';
} {1 {no such fts5 table: main.nosuchtable}}
do_execsql_test 4.2.1 {
CREATE TABLE nosuchtable(nosuchtable, y, z);
}
do_catchsql_test 4.2.2 {
SELECT * FROM v1 WHERE term=='nosuchterm';
} {1 {no such fts5 table: main.nosuchtable}}
ifcapable fts3 {
do_execsql_test 4.3.1 {
DROP TABLE nosuchtable;
CREATE VIRTUAL TABLE nosuchtable USING fts3(a, b);
} {}
do_catchsql_test 4.3.2 {
SELECT * FROM v1 WHERE term=='nosuchterm';
} {1 {no such fts5 table: main.nosuchtable}}
do_catchsql_test 4.3.3 {
INSERT INTO nosuchtable VALUES('id', '*id');
SELECT * FROM v1 WHERE term=='nosuchterm';
} {1 {no such fts5 table: main.nosuchtable}}
}
finish_test
+5 -5
View File
@@ -619,7 +619,7 @@ static int amatchLoadOneRule(
if( p->rDel==0 || p->rDel>rCost ) p->rDel = rCost;
}else
{
pRule = sqlite3_malloc( sizeof(*pRule) + nFrom + nTo );
pRule = sqlite3_malloc64( sizeof(*pRule) + nFrom + nTo );
if( pRule==0 ){
rc = SQLITE_NOMEM;
}else{
@@ -738,11 +738,11 @@ static int amatchLoadRules(
** `mno` becomes mno
*/
static char *amatchDequote(const char *zIn){
int nIn; /* Size of input string, in bytes */
sqlite3_int64 nIn; /* Size of input string, in bytes */
char *zOut; /* Output (dequoted) string */
nIn = (int)strlen(zIn);
zOut = sqlite3_malloc(nIn+1);
nIn = strlen(zIn);
zOut = sqlite3_malloc64(nIn+1);
if( zOut ){
char q = zIn[0]; /* Quote character (if any ) */
@@ -1069,7 +1069,7 @@ static void amatchAddWord(
}
return;
}
pWord = sqlite3_malloc( sizeof(*pWord) + nBase + nTail - 1 );
pWord = sqlite3_malloc64( sizeof(*pWord) + nBase + nTail - 1 );
if( pWord==0 ) return;
memset(pWord, 0, sizeof(*pWord));
pWord->rCost = rCost;
+3 -3
View File
@@ -422,11 +422,11 @@ static closure_avl *queuePull(closure_queue *pQueue){
** `mno` becomes mno
*/
static char *closureDequote(const char *zIn){
int nIn; /* Size of input string, in bytes */
sqlite3_int64 nIn; /* Size of input string, in bytes */
char *zOut; /* Output (dequoted) string */
nIn = (int)strlen(zIn);
zOut = sqlite3_malloc(nIn+1);
nIn = strlen(zIn);
zOut = sqlite3_malloc64(nIn+1);
if( zOut ){
char q = zIn[0]; /* Quote character (if any ) */
+1 -1
View File
@@ -621,7 +621,7 @@ static int csvtabConnect(
}else if( pNew->zData ){
pNew->iStart = (int)sRdr.iIn;
}else{
pNew->iStart = ftell(sRdr.in);
pNew->iStart = (int)(ftell(sRdr.in) - sRdr.nIn + sRdr.iIn);
}
csv_reader_reset(&sRdr);
rc = sqlite3_declare_vtab(db, CSV_SCHEMA);
+1 -1
View File
@@ -195,7 +195,7 @@ static char **tableColumnList(DState *p, const char *zTab){
if( nCol>=nAlloc-2 ){
char **azNew;
nAlloc = nAlloc*2 + nCol + 10;
azNew = sqlite3_realloc(azCol, nAlloc*sizeof(azCol[0]));
azNew = sqlite3_realloc64(azCol, nAlloc*sizeof(azCol[0]));
if( azNew==0 ) goto col_oom;
azCol = azNew;
azCol[0] = 0;
+1 -1
View File
@@ -44,7 +44,7 @@ static int callback(void *pCtx, int argc, char **argv, char **colnames){
/* Using sqlite3_realloc64() would be better, but it is a recent
** addition and will cause a segfault if loaded by an older version
** of SQLite. */
zNew = p->nAlloc<=0x7fffffff ? sqlite3_realloc(p->z, (int)p->nAlloc) : 0;
zNew = p->nAlloc<=0x7fffffff ? sqlite3_realloc64(p->z, p->nAlloc) : 0;
if( zNew==0 ){
sqlite3_free(p->z);
memset(p, 0, sizeof(*p));
+35 -10
View File
@@ -121,22 +121,47 @@ SQLITE_EXTENSION_INIT1
/*
** Set the result stored by context ctx to a blob containing the
** contents of file zName.
** contents of file zName. Or, leave the result unchanged (NULL)
** if the file does not exist or is unreadable.
**
** If the file exceeds the SQLite blob size limit, through an
** SQLITE_TOOBIG error.
**
** Throw an SQLITE_IOERR if there are difficulties pulling the file
** off of disk.
*/
static void readFileContents(sqlite3_context *ctx, const char *zName){
FILE *in;
long nIn;
sqlite3_int64 nIn;
void *pBuf;
sqlite3 *db;
int mxBlob;
in = fopen(zName, "rb");
if( in==0 ) return;
if( in==0 ){
/* File does not exist or is unreadable. Leave the result set to NULL. */
return;
}
fseek(in, 0, SEEK_END);
nIn = ftell(in);
rewind(in);
pBuf = sqlite3_malloc( nIn );
if( pBuf && 1==fread(pBuf, nIn, 1, in) ){
sqlite3_result_blob(ctx, pBuf, nIn, sqlite3_free);
db = sqlite3_context_db_handle(ctx);
mxBlob = sqlite3_limit(db, SQLITE_LIMIT_LENGTH, -1);
if( nIn>mxBlob ){
sqlite3_result_error_code(ctx, SQLITE_TOOBIG);
fclose(in);
return;
}
pBuf = sqlite3_malloc64( nIn ? nIn : 1 );
if( pBuf==0 ){
sqlite3_result_error_nomem(ctx);
fclose(in);
return;
}
if( nIn==fread(pBuf, 1, nIn, in) ){
sqlite3_result_blob64(ctx, pBuf, nIn, sqlite3_free);
}else{
sqlite3_result_error_code(ctx, SQLITE_IOERR);
sqlite3_free(pBuf);
}
fclose(in);
@@ -646,8 +671,8 @@ static int fsdirNext(sqlite3_vtab_cursor *cur){
FsdirLevel *pLvl;
if( iNew>=pCur->nLvl ){
int nNew = iNew+1;
int nByte = nNew*sizeof(FsdirLevel);
FsdirLevel *aNew = (FsdirLevel*)sqlite3_realloc(pCur->aLvl, nByte);
sqlite3_int64 nByte = nNew*sizeof(FsdirLevel);
FsdirLevel *aNew = (FsdirLevel*)sqlite3_realloc64(pCur->aLvl, nByte);
if( aNew==0 ) return SQLITE_NOMEM;
memset(&aNew[pCur->nLvl], 0, sizeof(FsdirLevel)*(nNew-pCur->nLvl));
pCur->aLvl = aNew;
@@ -727,7 +752,7 @@ static int fsdirColumn(
}else if( S_ISLNK(m) ){
char aStatic[64];
char *aBuf = aStatic;
int nBuf = 64;
sqlite3_int64 nBuf = 64;
int n;
while( 1 ){
@@ -735,7 +760,7 @@ static int fsdirColumn(
if( n<nBuf ) break;
if( aBuf!=aStatic ) sqlite3_free(aBuf);
nBuf = nBuf*2;
aBuf = sqlite3_malloc(nBuf);
aBuf = sqlite3_malloc64(nBuf);
if( aBuf==0 ){
sqlite3_result_error_nomem(ctx);
return SQLITE_NOMEM;
File diff suppressed because it is too large Load Diff
+8 -8
View File
@@ -337,7 +337,7 @@ static int fuzzerLoadOneRule(
rc = SQLITE_ERROR;
}else{
pRule = sqlite3_malloc( sizeof(*pRule) + nFrom + nTo );
pRule = sqlite3_malloc64( sizeof(*pRule) + nFrom + nTo );
if( pRule==0 ){
rc = SQLITE_NOMEM;
}else{
@@ -447,11 +447,11 @@ static int fuzzerLoadRules(
** `mno` becomes mno
*/
static char *fuzzerDequote(const char *zIn){
int nIn; /* Size of input string, in bytes */
sqlite3_int64 nIn; /* Size of input string, in bytes */
char *zOut; /* Output (dequoted) string */
nIn = (int)strlen(zIn);
zOut = sqlite3_malloc(nIn+1);
nIn = strlen(zIn);
zOut = sqlite3_malloc64(nIn+1);
if( zOut ){
char q = zIn[0]; /* Quote character (if any ) */
@@ -513,10 +513,10 @@ static int fuzzerConnect(
);
rc = SQLITE_ERROR;
}else{
int nModule; /* Length of zModule, in bytes */
sqlite3_int64 nModule; /* Length of zModule, in bytes */
nModule = (int)strlen(zModule);
pNew = sqlite3_malloc( sizeof(*pNew) + nModule + 1);
nModule = strlen(zModule);
pNew = sqlite3_malloc64( sizeof(*pNew) + nModule + 1);
if( pNew==0 ){
rc = SQLITE_NOMEM;
}else{
@@ -872,7 +872,7 @@ static fuzzer_stem *fuzzerNewStem(
fuzzer_rule *pRule;
unsigned int h;
pNew = sqlite3_malloc( sizeof(*pNew) + (int)strlen(zWord) + 1 );
pNew = sqlite3_malloc64( sizeof(*pNew) + strlen(zWord) + 1 );
if( pNew==0 ) return 0;
memset(pNew, 0, sizeof(*pNew));
pNew->zBasis = (char*)&pNew[1];
+3 -3
View File
@@ -691,7 +691,7 @@ static JSON_NOINLINE int jsonParseAddNodeExpand(
assert( pParse->nNode>=pParse->nAlloc );
if( pParse->oom ) return -1;
nNew = pParse->nAlloc*2 + 10;
pNew = sqlite3_realloc(pParse->aNode, sizeof(JsonNode)*nNew);
pNew = sqlite3_realloc64(pParse->aNode, sizeof(JsonNode)*nNew);
if( pNew==0 ){
pParse->oom = 1;
return -1;
@@ -965,7 +965,7 @@ static void jsonParseFillInParentage(JsonParse *pParse, u32 i, u32 iParent){
static int jsonParseFindParents(JsonParse *pParse){
u32 *aUp;
assert( pParse->aUp==0 );
aUp = pParse->aUp = sqlite3_malloc( sizeof(u32)*pParse->nNode );
aUp = pParse->aUp = sqlite3_malloc64( sizeof(u32)*pParse->nNode );
if( aUp==0 ){
pParse->oom = 1;
return SQLITE_NOMEM;
@@ -1027,7 +1027,7 @@ static JsonParse *jsonParseCached(
pMatch->iHold = iMaxHold+1;
return pMatch;
}
p = sqlite3_malloc( sizeof(*p) + nJson + 1 );
p = sqlite3_malloc64( sizeof(*p) + nJson + 1 );
if( p==0 ){
sqlite3_result_error_nomem(pCtx);
return 0;
+1 -1
View File
@@ -143,7 +143,7 @@ static int memstatFindSchemas(memstat_cursor *pCur){
}
while( sqlite3_step(pStmt)==SQLITE_ROW ){
char **az, *z;
az = sqlite3_realloc(pCur->azDb, sizeof(char*)*(pCur->nDb+1));
az = sqlite3_realloc64(pCur->azDb, sizeof(char*)*(pCur->nDb+1));
if( az==0 ){
memstatClearSchema(pCur);
return SQLITE_NOMEM;
+108
View File
@@ -0,0 +1,108 @@
/*
** 2019-01-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 an extension that uses the SQLITE_CONFIG_MALLOC
** mechanism to add a tracing layer on top of SQLite. If this extension
** is registered prior to sqlite3_initialize(), it will cause all memory
** allocation activities to be logged on standard output, or to some other
** FILE specified by the initializer.
**
** This file needs to be compiled into the application that uses it.
**
** This extension is used to implement the --memtrace option of the
** command-line shell.
*/
#include <assert.h>
#include <string.h>
#include <stdio.h>
/* The original memory allocation routines */
static sqlite3_mem_methods memtraceBase;
static FILE *memtraceOut;
/* Methods that trace memory allocations */
static void *memtraceMalloc(int n){
if( memtraceOut ){
fprintf(memtraceOut, "MEMTRACE: allocate %d bytes\n",
memtraceBase.xRoundup(n));
}
return memtraceBase.xMalloc(n);
}
static void memtraceFree(void *p){
if( p==0 ) return;
if( memtraceOut ){
fprintf(memtraceOut, "MEMTRACE: free %d bytes\n", memtraceBase.xSize(p));
}
memtraceBase.xFree(p);
}
static void *memtraceRealloc(void *p, int n){
if( p==0 ) return memtraceMalloc(n);
if( n==0 ){
memtraceFree(p);
return 0;
}
if( memtraceOut ){
fprintf(memtraceOut, "MEMTRACE: resize %d -> %d bytes\n",
memtraceBase.xSize(p), memtraceBase.xRoundup(n));
}
return memtraceBase.xRealloc(p, n);
}
static int memtraceSize(void *p){
return memtraceBase.xSize(p);
}
static int memtraceRoundup(int n){
return memtraceBase.xRoundup(n);
}
static int memtraceInit(void *p){
return memtraceBase.xInit(p);
}
static void memtraceShutdown(void *p){
memtraceBase.xShutdown(p);
}
/* The substitute memory allocator */
static sqlite3_mem_methods ersaztMethods = {
memtraceMalloc,
memtraceFree,
memtraceRealloc,
memtraceSize,
memtraceRoundup,
memtraceInit,
memtraceShutdown,
0
};
/* Begin tracing memory allocations to out. */
int sqlite3MemTraceActivate(FILE *out){
int rc = SQLITE_OK;
if( memtraceBase.xMalloc==0 ){
rc = sqlite3_config(SQLITE_CONFIG_GETMALLOC, &memtraceBase);
if( rc==SQLITE_OK ){
rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &ersaztMethods);
}
}
memtraceOut = out;
return rc;
}
/* Deactivate memory tracing */
int sqlite3MemTraceDeactivate(void){
int rc = SQLITE_OK;
if( memtraceBase.xMalloc!=0 ){
rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &memtraceBase);
if( rc==SQLITE_OK ){
memset(&memtraceBase, 0, sizeof(memtraceBase));
}
}
memtraceOut = 0;
return rc;
}
-1
View File
@@ -105,4 +105,3 @@ int sqlite3_mmap_warm(sqlite3 *db, const char *zDb){
return rc;
}
+2 -2
View File
@@ -85,7 +85,7 @@ static void nextCharAppend(nextCharContext *p, unsigned c){
if( p->nUsed+1 > p->nAlloc ){
unsigned int *aNew;
int n = p->nAlloc*2 + 30;
aNew = sqlite3_realloc(p->aResult, n*sizeof(unsigned int));
aNew = sqlite3_realloc64(p->aResult, n*sizeof(unsigned int));
if( aNew==0 ){
p->mallocFailed = 1;
return;
@@ -269,7 +269,7 @@ static void nextCharFunc(
sqlite3_result_error_nomem(context);
}else{
unsigned char *pRes;
pRes = sqlite3_malloc( c.nUsed*4 + 1 );
pRes = sqlite3_malloc64( c.nUsed*4 + 1 );
if( pRes==0 ){
sqlite3_result_error_nomem(context);
}else{
+3 -3
View File
@@ -108,8 +108,8 @@ static void percentStep(sqlite3_context *pCtx, int argc, sqlite3_value **argv){
/* Requirement 3: P must be a number between 0 and 100 */
eType = sqlite3_value_numeric_type(argv[1]);
rPct = sqlite3_value_double(argv[1]);
if( (eType!=SQLITE_INTEGER && eType!=SQLITE_FLOAT) ||
((rPct = sqlite3_value_double(argv[1]))<0.0 || rPct>100.0) ){
if( (eType!=SQLITE_INTEGER && eType!=SQLITE_FLOAT)
|| rPct<0.0 || rPct>100.0 ){
sqlite3_result_error(pCtx, "2nd argument to percentile() is not "
"a number between 0.0 and 100.0", -1);
return;
@@ -151,7 +151,7 @@ static void percentStep(sqlite3_context *pCtx, int argc, sqlite3_value **argv){
/* Allocate and store the Y */
if( p->nUsed>=p->nAlloc ){
unsigned n = p->nAlloc*2 + 250;
double *a = sqlite3_realloc(p->a, sizeof(double)*n);
double *a = sqlite3_realloc64(p->a, sizeof(double)*n);
if( a==0 ){
sqlite3_free(p->a);
memset(p, 0, sizeof(*p));
+319
View File
@@ -0,0 +1,319 @@
/*
** 2018-04-19
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
**
** This file implements a table-valued function:
**
** prefixes('abcdefg')
**
** The function has a single (non-HIDDEN) column named prefix that takes
** on all prefixes of the string in its argument, including an empty string
** and the input string itself. The order of prefixes is from longest
** to shortest.
*/
#if !defined(SQLITE_CORE) || !defined(SQLITE_OMIT_VIRTUALTABLE)
#if !defined(SQLITEINT_H)
#include "sqlite3ext.h"
#endif
SQLITE_EXTENSION_INIT1
#include <string.h>
#include <assert.h>
/* prefixes_vtab is a subclass of sqlite3_vtab which is
** underlying representation of the virtual table
*/
typedef struct prefixes_vtab prefixes_vtab;
struct prefixes_vtab {
sqlite3_vtab base; /* Base class - must be first */
/* No additional fields are necessary */
};
/* prefixes_cursor is a subclass of sqlite3_vtab_cursor which will
** serve as the underlying representation of a cursor that scans
** over rows of the result
*/
typedef struct prefixes_cursor prefixes_cursor;
struct prefixes_cursor {
sqlite3_vtab_cursor base; /* Base class - must be first */
sqlite3_int64 iRowid; /* The rowid */
char *zStr; /* Original string to be prefixed */
int nStr; /* Length of the string in bytes */
};
/*
** The prefixesConnect() method is invoked to create a new
** template virtual table.
**
** Think of this routine as the constructor for prefixes_vtab objects.
**
** All this routine needs to do is:
**
** (1) Allocate the prefixes_vtab object and initialize all fields.
**
** (2) Tell SQLite (via the sqlite3_declare_vtab() interface) what the
** result set of queries against the virtual table will look like.
*/
static int prefixesConnect(
sqlite3 *db,
void *pAux,
int argc, const char *const*argv,
sqlite3_vtab **ppVtab,
char **pzErr
){
prefixes_vtab *pNew;
int rc;
rc = sqlite3_declare_vtab(db,
"CREATE TABLE prefixes(prefix TEXT, original_string TEXT HIDDEN)"
);
if( rc==SQLITE_OK ){
pNew = sqlite3_malloc( sizeof(*pNew) );
*ppVtab = (sqlite3_vtab*)pNew;
if( pNew==0 ) return SQLITE_NOMEM;
memset(pNew, 0, sizeof(*pNew));
}
return rc;
}
/*
** This method is the destructor for prefixes_vtab objects.
*/
static int prefixesDisconnect(sqlite3_vtab *pVtab){
prefixes_vtab *p = (prefixes_vtab*)pVtab;
sqlite3_free(p);
return SQLITE_OK;
}
/*
** Constructor for a new prefixes_cursor object.
*/
static int prefixesOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
prefixes_cursor *pCur;
pCur = sqlite3_malloc( sizeof(*pCur) );
if( pCur==0 ) return SQLITE_NOMEM;
memset(pCur, 0, sizeof(*pCur));
*ppCursor = &pCur->base;
return SQLITE_OK;
}
/*
** Destructor for a prefixes_cursor.
*/
static int prefixesClose(sqlite3_vtab_cursor *cur){
prefixes_cursor *pCur = (prefixes_cursor*)cur;
sqlite3_free(pCur->zStr);
sqlite3_free(pCur);
return SQLITE_OK;
}
/*
** Advance a prefixes_cursor to its next row of output.
*/
static int prefixesNext(sqlite3_vtab_cursor *cur){
prefixes_cursor *pCur = (prefixes_cursor*)cur;
pCur->iRowid++;
return SQLITE_OK;
}
/*
** Return values of columns for the row at which the prefixes_cursor
** is currently pointing.
*/
static int prefixesColumn(
sqlite3_vtab_cursor *cur, /* The cursor */
sqlite3_context *ctx, /* First argument to sqlite3_result_...() */
int i /* Which column to return */
){
prefixes_cursor *pCur = (prefixes_cursor*)cur;
switch( i ){
case 0:
sqlite3_result_text(ctx, pCur->zStr, pCur->nStr - (int)pCur->iRowid,
0);
break;
default:
sqlite3_result_text(ctx, pCur->zStr, pCur->nStr, 0);
break;
}
return SQLITE_OK;
}
/*
** Return the rowid for the current row. In this implementation, the
** rowid is the same as the output value.
*/
static int prefixesRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
prefixes_cursor *pCur = (prefixes_cursor*)cur;
*pRowid = pCur->iRowid;
return SQLITE_OK;
}
/*
** Return TRUE if the cursor has been moved off of the last
** row of output.
*/
static int prefixesEof(sqlite3_vtab_cursor *cur){
prefixes_cursor *pCur = (prefixes_cursor*)cur;
return pCur->iRowid>pCur->nStr;
}
/*
** This method is called to "rewind" the prefixes_cursor object back
** to the first row of output. This method is always called at least
** once prior to any call to prefixesColumn() or prefixesRowid() or
** prefixesEof().
*/
static int prefixesFilter(
sqlite3_vtab_cursor *pVtabCursor,
int idxNum, const char *idxStr,
int argc, sqlite3_value **argv
){
prefixes_cursor *pCur = (prefixes_cursor *)pVtabCursor;
sqlite3_free(pCur->zStr);
if( argc>0 ){
pCur->zStr = sqlite3_mprintf("%s", sqlite3_value_text(argv[0]));
pCur->nStr = pCur->zStr ? (int)strlen(pCur->zStr) : 0;
}else{
pCur->zStr = 0;
pCur->nStr = 0;
}
pCur->iRowid = 0;
return SQLITE_OK;
}
/*
** SQLite will invoke this method one or more times while planning a query
** that uses the virtual table. This routine needs to create
** a query plan for each invocation and compute an estimated cost for that
** plan.
*/
static int prefixesBestIndex(
sqlite3_vtab *tab,
sqlite3_index_info *pIdxInfo
){
/* Search for a usable equality constraint against column 1
** (original_string) and use it if at all possible */
int i;
const struct sqlite3_index_constraint *p;
for(i=0, p=pIdxInfo->aConstraint; i<pIdxInfo->nConstraint; i++, p++){
if( p->iColumn!=1 ) continue;
if( p->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
if( !p->usable ) continue;
pIdxInfo->aConstraintUsage[i].argvIndex = 1;
pIdxInfo->aConstraintUsage[i].omit = 1;
pIdxInfo->estimatedCost = (double)10;
pIdxInfo->estimatedRows = 10;
return SQLITE_OK;
}
pIdxInfo->estimatedCost = (double)1000000000;
pIdxInfo->estimatedRows = 1000000000;
return SQLITE_OK;
}
/*
** This following structure defines all the methods for the
** virtual table.
*/
static sqlite3_module prefixesModule = {
/* iVersion */ 0,
/* xCreate */ 0,
/* xConnect */ prefixesConnect,
/* xBestIndex */ prefixesBestIndex,
/* xDisconnect */ prefixesDisconnect,
/* xDestroy */ 0,
/* xOpen */ prefixesOpen,
/* xClose */ prefixesClose,
/* xFilter */ prefixesFilter,
/* xNext */ prefixesNext,
/* xEof */ prefixesEof,
/* xColumn */ prefixesColumn,
/* xRowid */ prefixesRowid,
/* xUpdate */ 0,
/* xBegin */ 0,
/* xSync */ 0,
/* xCommit */ 0,
/* xRollback */ 0,
/* xFindMethod */ 0,
/* xRename */ 0,
/* xSavepoint */ 0,
/* xRelease */ 0,
/* xRollbackTo */ 0,
/* xShadowName */ 0
};
/*
** This is a copy of the SQLITE_SKIP_UTF8(zIn) macro in sqliteInt.h.
**
** Assuming zIn points to the first byte of a UTF-8 character,
** advance zIn to point to the first byte of the next UTF-8 character.
*/
#define PREFIX_SKIP_UTF8(zIn) { \
if( (*(zIn++))>=0xc0 ){ \
while( (*zIn & 0xc0)==0x80 ){ zIn++; } \
} \
}
/*
** Implementation of function prefix_length(). This function accepts two
** strings as arguments and returns the length in characters (not bytes),
** of the longest prefix shared by the two strings. For example:
**
** prefix_length('abcdxxx', 'abcyy') == 3
** prefix_length('abcdxxx', 'bcyyy') == 0
** prefix_length('abcdxxx', 'ab') == 2
** prefix_length('ab', 'abcd') == 2
**
** This function assumes the input is well-formed utf-8. If it is not,
** it is possible for this function to return -1.
*/
static void prefixLengthFunc(
sqlite3_context *ctx,
int nVal,
sqlite3_value **apVal
){
int nByte; /* Number of bytes to compare */
int nRet = 0; /* Return value */
const unsigned char *zL = sqlite3_value_text(apVal[0]);
const unsigned char *zR = sqlite3_value_text(apVal[1]);
int nL = sqlite3_value_bytes(apVal[0]);
int nR = sqlite3_value_bytes(apVal[1]);
int i;
nByte = (nL > nR ? nL : nR);
for(i=0; i<nByte; i++){
if( zL[i]!=zR[i] ) break;
if( (zL[i] & 0xC0)!=0x80 ) nRet++;
}
if( (zL[i] & 0xC0)==0x80 ) nRet--;
sqlite3_result_int(ctx, nRet);
}
#ifdef _WIN32
__declspec(dllexport)
#endif
int sqlite3_prefixes_init(
sqlite3 *db,
char **pzErrMsg,
const sqlite3_api_routines *pApi
){
int rc = SQLITE_OK;
SQLITE_EXTENSION_INIT2(pApi);
rc = sqlite3_create_module(db, "prefixes", &prefixesModule, 0);
if( rc==SQLITE_OK ){
rc = sqlite3_create_function(
db, "prefix_length", 2, SQLITE_UTF8, 0, prefixLengthFunc, 0, 0
);
}
return rc;
}
#endif /* !defined(SQLITE_CORE) || !defined(SQLITE_OMIT_VIRTUALTABLE) */
+3 -3
View File
@@ -225,7 +225,7 @@ static int re_match(ReCompiled *pRe, const unsigned char *zIn, int nIn){
pToFree = 0;
aStateSet[0].aState = aSpace;
}else{
pToFree = sqlite3_malloc( sizeof(ReStateNumber)*2*pRe->nState );
pToFree = sqlite3_malloc64( sizeof(ReStateNumber)*2*pRe->nState );
if( pToFree==0 ) return -1;
aStateSet[0].aState = pToFree;
}
@@ -337,10 +337,10 @@ re_match_end:
static int re_resize(ReCompiled *p, int N){
char *aOp;
int *aArg;
aOp = sqlite3_realloc(p->aOp, N*sizeof(p->aOp[0]));
aOp = sqlite3_realloc64(p->aOp, N*sizeof(p->aOp[0]));
if( aOp==0 ) return 1;
p->aOp = aOp;
aArg = sqlite3_realloc(p->aArg, N*sizeof(p->aArg[0]));
aArg = sqlite3_realloc64(p->aArg, N*sizeof(p->aArg[0]));
if( aArg==0 ) return 1;
p->aArg = aArg;
p->nAlloc = N;
+4 -4
View File
@@ -250,11 +250,11 @@ struct UnionCsr {
** is attempted but fails, NULL is returned and *pRc is set to
** SQLITE_NOMEM.
*/
static void *unionMalloc(int *pRc, int nByte){
static void *unionMalloc(int *pRc, sqlite3_int64 nByte){
void *pRet;
assert( nByte>0 );
if( *pRc==SQLITE_OK ){
pRet = sqlite3_malloc(nByte);
pRet = sqlite3_malloc64(nByte);
if( pRet ){
memset(pRet, 0, nByte);
}else{
@@ -276,7 +276,7 @@ static void *unionMalloc(int *pRc, int nByte){
static char *unionStrdup(int *pRc, const char *zIn){
char *zRet = 0;
if( zIn ){
int nByte = (int)strlen(zIn) + 1;
sqlite3_int64 nByte = strlen(zIn) + 1;
zRet = unionMalloc(pRc, nByte);
if( zRet ){
memcpy(zRet, zIn, nByte);
@@ -939,7 +939,7 @@ static int unionConnect(
/* Grow the pTab->aSrc[] array if required. */
if( nAlloc<=pTab->nSrc ){
int nNew = nAlloc ? nAlloc*2 : 8;
UnionSrc *aNew = (UnionSrc*)sqlite3_realloc(
UnionSrc *aNew = (UnionSrc*)sqlite3_realloc64(
pTab->aSrc, nNew*sizeof(UnionSrc)
);
if( aNew==0 ){
+1 -1
View File
@@ -276,7 +276,7 @@ static VLogLog *vlogLogOpen(const char *zFilename){
&& sqlite3_strglob("-mj??????9??", zFilename+nName-12)==0 ){
return 0; /* Do not log master journal files */
}
pTemp = sqlite3_malloc( sizeof(*pLog)*2 + nName + 60 );
pTemp = sqlite3_malloc64( sizeof(*pLog)*2 + nName + 60 );
if( pTemp==0 ) return 0;
pMutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER);
sqlite3_mutex_enter(pMutex);
+6 -3
View File
@@ -783,8 +783,8 @@ static sqlite3_module VfsStatModule = {
*/
static int vstatRegister(
sqlite3 *db,
const char **pzErrMsg,
const struct sqlite3_api_routines *pThunk
char **pzErrMsg,
const sqlite3_api_routines *pThunk
){
return sqlite3_create_module(db, "vfsstat", &VfsStatModule, 0);
}
@@ -809,7 +809,10 @@ int sqlite3_vfsstat_init(
vstat_vfs.base.szOsFile = sizeof(VStatFile) + vstat_vfs.pVfs->szOsFile;
rc = sqlite3_vfs_register(&vstat_vfs.base, 1);
if( rc==SQLITE_OK ){
rc = sqlite3_auto_extension(vstatRegister);
rc = vstatRegister(db, pzErrMsg, pApi);
if( rc==SQLITE_OK ){
rc = sqlite3_auto_extension(vstatRegister);
}
}
if( rc==SQLITE_OK ) rc = SQLITE_OK_LOAD_PERMANENTLY;
return rc;
+12 -12
View File
@@ -358,7 +358,7 @@ static int zipfileConnect(
rc = sqlite3_declare_vtab(db, ZIPFILE_SCHEMA);
if( rc==SQLITE_OK ){
pNew = (ZipfileTab*)sqlite3_malloc(nByte+nFile);
pNew = (ZipfileTab*)sqlite3_malloc64((sqlite3_int64)nByte+nFile);
if( pNew==0 ) return SQLITE_NOMEM;
memset(pNew, 0, nByte+nFile);
pNew->db = db;
@@ -806,7 +806,7 @@ static int zipfileGetEntry(
}
if( rc==SQLITE_OK ){
int nAlloc;
sqlite3_int64 nAlloc;
ZipfileEntry *pNew;
int nFile = zipfileGetU16(&aRead[ZIPFILE_CDS_NFILE_OFF]);
@@ -818,7 +818,7 @@ static int zipfileGetEntry(
nAlloc += zipfileGetU32(&aRead[ZIPFILE_CDS_SZCOMPRESSED_OFF]);
}
pNew = (ZipfileEntry*)sqlite3_malloc(nAlloc);
pNew = (ZipfileEntry*)sqlite3_malloc64(nAlloc);
if( pNew==0 ){
rc = SQLITE_NOMEM;
}else{
@@ -981,11 +981,11 @@ static int zipfileDeflate(
u8 **ppOut, int *pnOut, /* Output */
char **pzErr /* OUT: Error message */
){
int nAlloc = (int)compressBound(nIn);
sqlite3_int64 nAlloc = compressBound(nIn);
u8 *aOut;
int rc = SQLITE_OK;
aOut = (u8*)sqlite3_malloc(nAlloc);
aOut = (u8*)sqlite3_malloc64(nAlloc);
if( aOut==0 ){
rc = SQLITE_NOMEM;
}else{
@@ -1058,7 +1058,7 @@ static int zipfileColumn(
if( pCsr->pCurrent->aData ){
aBuf = pCsr->pCurrent->aData;
}else{
aBuf = aFree = sqlite3_malloc(sz);
aBuf = aFree = sqlite3_malloc64(sz);
if( aBuf==0 ){
rc = SQLITE_NOMEM;
}else{
@@ -1897,14 +1897,14 @@ struct ZipfileCtx {
static int zipfileBufferGrow(ZipfileBuffer *pBuf, int nByte){
if( pBuf->n+nByte>pBuf->nAlloc ){
u8 *aNew;
int nNew = pBuf->n ? pBuf->n*2 : 512;
sqlite3_int64 nNew = pBuf->n ? pBuf->n*2 : 512;
int nReq = pBuf->n + nByte;
while( nNew<nReq ) nNew = nNew*2;
aNew = sqlite3_realloc(pBuf->a, nNew);
aNew = sqlite3_realloc64(pBuf->a, nNew);
if( aNew==0 ) return SQLITE_NOMEM;
pBuf->a = aNew;
pBuf->nAlloc = nNew;
pBuf->nAlloc = (int)nNew;
}
return SQLITE_OK;
}
@@ -2095,7 +2095,7 @@ void zipfileStep(sqlite3_context *pCtx, int nVal, sqlite3_value **apVal){
void zipfileFinal(sqlite3_context *pCtx){
ZipfileCtx *p;
ZipfileEOCD eocd;
int nZip;
sqlite3_int64 nZip;
u8 *aZip;
p = (ZipfileCtx*)sqlite3_aggregate_context(pCtx, sizeof(ZipfileCtx));
@@ -2108,14 +2108,14 @@ void zipfileFinal(sqlite3_context *pCtx){
eocd.iOffset = p->body.n;
nZip = p->body.n + p->cds.n + ZIPFILE_EOCD_FIXED_SZ;
aZip = (u8*)sqlite3_malloc(nZip);
aZip = (u8*)sqlite3_malloc64(nZip);
if( aZip==0 ){
sqlite3_result_error_nomem(pCtx);
}else{
memcpy(aZip, p->body.a, p->body.n);
memcpy(&aZip[p->body.n], p->cds.a, p->cds.n);
zipfileSerializeEOCD(&eocd, &aZip[p->body.n + p->cds.n]);
sqlite3_result_blob(pCtx, aZip, nZip, zipfileFree);
sqlite3_result_blob(pCtx, aZip, (int)nZip, zipfileFree);
}
}
+7 -6
View File
@@ -86,12 +86,13 @@ proc step_rbu_legacy {target rbu} {
set rc
}
proc do_rbu_vacuum_test {tn step} {
forcedelete state.db
uplevel [list do_test $tn.1 {
if {$step==0} { sqlite3rbu_vacuum rbu test.db state.db }
proc do_rbu_vacuum_test {tn step {statedb state.db}} {
forcedelete $statedb
if {$statedb=="" && $step==1} breakpoint
uplevel [list do_test $tn.1 [string map [list %state% $statedb] {
if {$step==0} { sqlite3rbu_vacuum rbu test.db {%state%}}
while 1 {
if {$step==1} { sqlite3rbu_vacuum rbu test.db state.db }
if {$step==1} { sqlite3rbu_vacuum rbu test.db {%state%}}
set state [rbu state]
check_prestep_state test.db $state
set rc [rbu step]
@@ -100,7 +101,7 @@ proc do_rbu_vacuum_test {tn step} {
if {$step==1} { rbu close }
}
rbu close
} {SQLITE_DONE}]
}] {SQLITE_DONE}]
uplevel [list do_execsql_test $tn.2 {
PRAGMA integrity_check
+18 -9
View File
@@ -16,8 +16,11 @@
source [file join [file dirname [info script]] rbu_common.tcl]
foreach step {0 1} {
set ::testprefix rbuvacuum2-$step
foreach {step} {0 1} {
foreach {ttt state} {
s state.db t test.db-vacuum n {}
} {
set ::testprefix rbuvacuum2-$step$ttt
#-------------------------------------------------------------------------
# Test that a database that contains fts3 tables can be vacuumed.
@@ -29,7 +32,7 @@ foreach step {0 1} {
INSERT INTO t1 VALUES('fix this issue', 'at some point');
}
do_rbu_vacuum_test 1.2 $step
do_rbu_vacuum_test 1.2 $step $state
do_execsql_test 1.3 {
SELECT * FROM t1;
@@ -46,7 +49,7 @@ foreach step {0 1} {
INSERT INTO t1 VALUES('a b c', 'x y z');
}
do_rbu_vacuum_test 1.6 $step
do_rbu_vacuum_test 1.6 $step $state
do_execsql_test 1.7 {
INSERT INTO t1(t1) VALUES('integrity-check');
SELECT * FROM t1;
@@ -67,7 +70,7 @@ foreach step {0 1} {
INSERT INTO t1 VALUES('fix this issue', 'at some point');
}
do_rbu_vacuum_test 2.2 $step
do_rbu_vacuum_test 2.2 $step $state
do_execsql_test 2.3 {
SELECT * FROM t1;
@@ -84,7 +87,7 @@ foreach step {0 1} {
INSERT INTO t1 VALUES('a b c', 'x y z');
}
do_rbu_vacuum_test 2.6 $step
do_rbu_vacuum_test 2.6 $step $state
do_execsql_test 2.7 {
INSERT INTO t1(t1) VALUES('integrity-check');
SELECT * FROM t1;
@@ -107,7 +110,7 @@ foreach step {0 1} {
INSERT INTO rt VALUES(3, 55, 65);
}
do_rbu_vacuum_test 3.2 $step
do_rbu_vacuum_test 3.2 $step $state
do_execsql_test 3.3 {
SELECT * FROM rt;
@@ -120,7 +123,7 @@ foreach step {0 1} {
SELECT rowid FROM rt WHERE x2>59 AND x1 < 59
} {2 3}
do_rbu_vacuum_test 3.5 $step
do_rbu_vacuum_test 3.5 $step $state
do_execsql_test 3.6.1 {
SELECT rowid FROM rt WHERE x2>51 AND x1 < 51
@@ -147,7 +150,7 @@ foreach step {0 1} {
trigger tr1 t1 0 {CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN SELECT 1; END}
}
do_rbu_vacuum_test 4.3 $step
do_rbu_vacuum_test 4.3 $step $state
do_execsql_test 4.4 {
SELECT * FROM sqlite_master;
} {
@@ -157,6 +160,7 @@ foreach step {0 1} {
}
}
}
}
#-------------------------------------------------------------------------
# Test that passing a NULL value as the second argument to
@@ -231,4 +235,9 @@ do_test 6.3 {
execsql { PRAGMA integrity_check }
} {ok}
do_test 6.4 {
sqlite3rbu_vacuum rbu test.db test.db-vactmp
list [catch { rbu close } msg] $msg
} {1 SQLITE_MISUSE}
finish_test
+63
View File
@@ -0,0 +1,63 @@
# 2019 Jan 3
#
# 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 RBU module. More specifically, it
# contains tests to ensure that the sqlite3rbu_vacuum() API works as
# expected.
#
source [file join [file dirname [info script]] rbu_common.tcl]
set testprefix rbuvacuum3
do_execsql_test 1.0 {
CREATE TABLE t1(a PRIMARY KEY, b, c);
CREATE INDEX i1b ON t1(b);
CREATE INDEX i1c ON t1(c);
WITH s(i) AS (
VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<100
)
INSERT INTO t1 SELECT i, randomblob(100), randomblob(100) FROM s;
}
forcedelete state.db
do_test 1.1 {
sqlite3rbu_vacuum rbu test.db state.db
while {1} {
set rc [rbu step]
if {$rc!="SQLITE_OK"} break
rbu savestate
}
rbu close
} {SQLITE_DONE}
do_test 1.2 {
sqlite3rbu_vacuum rbu test.db state.db
while {1} {
set rc [rbu step]
if {$rc!="SQLITE_OK"} break
rbu savestate
}
rbu close
} {SQLITE_DONE}
do_test 1.3 {
while {1} {
sqlite3rbu_vacuum rbu test.db state.db
set rc [rbu step]
if {$rc!="SQLITE_OK"} break
rbu savestate
rbu close
}
rbu close
} {SQLITE_DONE}
finish_test
+12 -2
View File
@@ -684,6 +684,7 @@ static void rbuFossilDeltaFunc(
}else{
nOut2 = rbuDeltaApply(aOrig, nOrig, aDelta, nDelta, aOut);
if( nOut2!=nOut ){
sqlite3_free(aOut);
sqlite3_result_error(context, "corrupt fossil delta", -1);
}else{
sqlite3_result_blob(context, aOut, nOut, sqlite3_free);
@@ -2477,7 +2478,7 @@ static void rbuOpenDatabase(sqlite3rbu *p, int *pbRetry){
if( *zExtra=='\0' ) zExtra = 0;
}
zTarget = sqlite3_mprintf("file:%s-vacuum?rbu_memory=1%s%s",
zTarget = sqlite3_mprintf("file:%s-vactmp?rbu_memory=1%s%s",
sqlite3_db_filename(p->dbRbu, "main"),
(zExtra==0 ? "" : "&"), (zExtra==0 ? "" : zExtra)
);
@@ -3743,6 +3744,12 @@ sqlite3rbu *sqlite3rbu_vacuum(
const char *zState
){
if( zTarget==0 ){ return rbuMisuseError(); }
if( zState ){
int n = strlen(zState);
if( n>=7 && 0==memcmp("-vactmp", &zState[n-7], 7) ){
return rbuMisuseError();
}
}
/* TODO: Check that both arguments are non-NULL */
return openRbuHandle(0, zTarget, zState);
}
@@ -3939,7 +3946,10 @@ int sqlite3rbu_savestate(sqlite3rbu *p){
if( p->eStage==RBU_STAGE_OAL ){
assert( rc!=SQLITE_DONE );
if( rc==SQLITE_OK ) rc = sqlite3_exec(p->dbRbu, "COMMIT", 0, 0, 0);
if( rc==SQLITE_OK ) rc = sqlite3_exec(p->dbRbu, "BEGIN IMMEDIATE", 0, 0, 0);
if( rc==SQLITE_OK ){
const char *zBegin = rbuIsVacuum(p) ? "BEGIN" : "BEGIN IMMEDIATE";
rc = sqlite3_exec(p->dbRbu, zBegin, 0, 0, 0);
}
if( rc==SQLITE_OK ) rc = sqlite3_exec(p->dbMain, "BEGIN IMMEDIATE", 0, 0,0);
}
+5 -1
View File
@@ -333,7 +333,11 @@ SQLITE_API sqlite3rbu *sqlite3rbu_open(
** name of the state database is "<database>-vacuum", where <database>
** is the name of the target database file. In this case, on UNIX, if the
** state database is not already present in the file-system, it is created
** with the same permissions as the target db is made.
** with the same permissions as the target db is made.
**
** With an RBU vacuum, it is an SQLITE_MISUSE error if the name of the
** state database ends with "-vactmp". This name is reserved for internal
** use.
**
** This function does not delete the state database after an RBU vacuum
** is completed, even if it created it. However, if the call to
+1
View File
@@ -273,6 +273,7 @@ static int SQLITE_TCLAPI test_sqlite3rbu_vacuum(
zCmd = Tcl_GetString(objv[1]);
zTarget = Tcl_GetString(objv[2]);
if( objc==4 ) zStateDb = Tcl_GetString(objv[3]);
if( zStateDb && zStateDb[0]=='\0' ) zStateDb = 0;
pRbu = sqlite3rbu_vacuum(zTarget, zStateDb);
Tcl_CreateObjCommand(interp, zCmd, test_sqlite3rbu_cmd, (ClientData)pRbu, 0);
+53 -42
View File
@@ -124,6 +124,14 @@ struct GeoPoly {
*/
#define GEOPOLY_SZ(N) (sizeof(GeoPoly) + sizeof(GeoCoord)*2*((N)-4))
/* Macros to access coordinates of a GeoPoly.
** We have to use these macros, rather than just say p->a[i] in order
** to silence (incorrect) UBSAN warnings if the array index is too large.
*/
#define GeoX(P,I) (((GeoCoord*)(P)->a)[(I)*2])
#define GeoY(P,I) (((GeoCoord*)(P)->a)[(I)*2+1])
/*
** State of a parse of a GeoJSON input.
*/
@@ -316,8 +324,9 @@ static GeoPoly *geopolyFuncParam(
memcpy(p->hdr, a, nByte);
if( a[0] != *(unsigned char*)&x ){
int ii;
for(ii=0; ii<nVertex*2; ii++){
geopolySwab32((unsigned char*)&p->a[ii]);
for(ii=0; ii<nVertex; ii++){
geopolySwab32((unsigned char*)&GeoX(p,ii));
geopolySwab32((unsigned char*)&GeoY(p,ii));
}
p->hdr[0] ^= 1;
}
@@ -376,9 +385,9 @@ static void geopolyJsonFunc(
int i;
sqlite3_str_append(x, "[", 1);
for(i=0; i<p->nVertex; i++){
sqlite3_str_appendf(x, "[%!g,%!g],", p->a[i*2], p->a[i*2+1]);
sqlite3_str_appendf(x, "[%!g,%!g],", GeoX(p,i), GeoY(p,i));
}
sqlite3_str_appendf(x, "[%!g,%!g]]", p->a[0], p->a[1]);
sqlite3_str_appendf(x, "[%!g,%!g]]", GeoX(p,0), GeoY(p,0));
sqlite3_result_text(context, sqlite3_str_finish(x), -1, sqlite3_free);
sqlite3_free(p);
}
@@ -395,7 +404,9 @@ static void geopolySvgFunc(
int argc,
sqlite3_value **argv
){
GeoPoly *p = geopolyFuncParam(context, argv[0], 0);
GeoPoly *p;
if( argc<1 ) return;
p = geopolyFuncParam(context, argv[0], 0);
if( p ){
sqlite3 *db = sqlite3_context_db_handle(context);
sqlite3_str *x = sqlite3_str_new(db);
@@ -403,10 +414,10 @@ static void geopolySvgFunc(
char cSep = '\'';
sqlite3_str_appendf(x, "<polyline points=");
for(i=0; i<p->nVertex; i++){
sqlite3_str_appendf(x, "%c%g,%g", cSep, p->a[i*2], p->a[i*2+1]);
sqlite3_str_appendf(x, "%c%g,%g", cSep, GeoX(p,i), GeoY(p,i));
cSep = ' ';
}
sqlite3_str_appendf(x, " %g,%g'", p->a[0], p->a[1]);
sqlite3_str_appendf(x, " %g,%g'", GeoX(p,0), GeoY(p,0));
for(i=1; i<argc; i++){
const char *z = (const char*)sqlite3_value_text(argv[i]);
if( z && z[0] ){
@@ -451,12 +462,12 @@ static void geopolyXformFunc(
int ii;
if( p ){
for(ii=0; ii<p->nVertex; ii++){
x0 = p->a[ii*2];
y0 = p->a[ii*2+1];
x0 = GeoX(p,ii);
y0 = GeoY(p,ii);
x1 = (GeoCoord)(A*x0 + B*y0 + E);
y1 = (GeoCoord)(C*x0 + D*y0 + F);
p->a[ii*2] = x1;
p->a[ii*2+1] = y1;
GeoX(p,ii) = x1;
GeoY(p,ii) = y1;
}
sqlite3_result_blob(context, p->hdr,
4+8*p->nVertex, SQLITE_TRANSIENT);
@@ -475,12 +486,12 @@ static double geopolyArea(GeoPoly *p){
double rArea = 0.0;
int ii;
for(ii=0; ii<p->nVertex-1; ii++){
rArea += (p->a[ii*2] - p->a[ii*2+2]) /* (x0 - x1) */
* (p->a[ii*2+1] + p->a[ii*2+3]) /* (y0 + y1) */
rArea += (GeoX(p,ii) - GeoX(p,ii+1)) /* (x0 - x1) */
* (GeoY(p,ii) + GeoY(p,ii+1)) /* (y0 + y1) */
* 0.5;
}
rArea += (p->a[ii*2] - p->a[0]) /* (xN - x0) */
* (p->a[ii*2+1] + p->a[1]) /* (yN + y0) */
rArea += (GeoX(p,ii) - GeoX(p,0)) /* (xN - x0) */
* (GeoY(p,ii) + GeoY(p,0)) /* (yN + y0) */
* 0.5;
return rArea;
}
@@ -527,13 +538,13 @@ static void geopolyCcwFunc(
if( p ){
if( geopolyArea(p)<0.0 ){
int ii, jj;
for(ii=2, jj=p->nVertex*2 - 2; ii<jj; ii+=2, jj-=2){
GeoCoord t = p->a[ii];
p->a[ii] = p->a[jj];
p->a[jj] = t;
t = p->a[ii+1];
p->a[ii+1] = p->a[jj+1];
p->a[jj+1] = t;
for(ii=1, jj=p->nVertex-1; ii<jj; ii++, jj--){
GeoCoord t = GeoX(p,ii);
GeoX(p,ii) = GeoX(p,jj);
GeoX(p,jj) = t;
t = GeoY(p,ii);
GeoY(p,ii) = GeoY(p,jj);
GeoY(p,jj) = t;
}
}
sqlite3_result_blob(context, p->hdr,
@@ -593,8 +604,8 @@ static void geopolyRegularFunc(
p->hdr[3] = n&0xff;
for(i=0; i<n; i++){
double rAngle = 2.0*GEOPOLY_PI*i/n;
p->a[i*2] = x - r*geopolySine(rAngle-0.5*GEOPOLY_PI);
p->a[i*2+1] = y + r*geopolySine(rAngle);
GeoX(p,i) = x - r*geopolySine(rAngle-0.5*GEOPOLY_PI);
GeoY(p,i) = y + r*geopolySine(rAngle);
}
sqlite3_result_blob(context, p->hdr, 4+8*n, SQLITE_TRANSIENT);
sqlite3_free(p);
@@ -631,13 +642,13 @@ static GeoPoly *geopolyBBox(
}
if( p ){
int ii;
mnX = mxX = p->a[0];
mnY = mxY = p->a[1];
mnX = mxX = GeoX(p,0);
mnY = mxY = GeoY(p,0);
for(ii=1; ii<p->nVertex; ii++){
double r = p->a[ii*2];
double r = GeoX(p,ii);
if( r<mnX ) mnX = (float)r;
else if( r>mxX ) mxX = (float)r;
r = p->a[ii*2+1];
r = GeoY(p,ii);
if( r<mnY ) mnY = (float)r;
else if( r>mxY ) mxY = (float)r;
}
@@ -657,14 +668,14 @@ static GeoPoly *geopolyBBox(
pOut->hdr[1] = 0;
pOut->hdr[2] = 0;
pOut->hdr[3] = 4;
pOut->a[0] = mnX;
pOut->a[1] = mnY;
pOut->a[2] = mxX;
pOut->a[3] = mnY;
pOut->a[4] = mxX;
pOut->a[5] = mxY;
pOut->a[6] = mnX;
pOut->a[7] = mxY;
GeoX(pOut,0) = mnX;
GeoY(pOut,0) = mnY;
GeoX(pOut,1) = mxX;
GeoY(pOut,1) = mnY;
GeoX(pOut,2) = mxX;
GeoY(pOut,2) = mxY;
GeoX(pOut,3) = mnX;
GeoY(pOut,3) = mxY;
}else{
sqlite3_free(p);
aCoord[0].f = mnX;
@@ -802,14 +813,14 @@ static void geopolyContainsPointFunc(
int ii;
if( p1==0 ) return;
for(ii=0; ii<p1->nVertex-1; ii++){
v = pointBeneathLine(x0,y0,p1->a[ii*2],p1->a[ii*2+1],
p1->a[ii*2+2],p1->a[ii*2+3]);
v = pointBeneathLine(x0,y0,GeoX(p1,ii), GeoY(p1,ii),
GeoX(p1,ii+1),GeoY(p1,ii+1));
if( v==2 ) break;
cnt += v;
}
if( v!=2 ){
v = pointBeneathLine(x0,y0,p1->a[ii*2],p1->a[ii*2+1],
p1->a[0],p1->a[1]);
v = pointBeneathLine(x0,y0,GeoX(p1,ii), GeoY(p1,ii),
GeoX(p1,0), GeoY(p1,0));
}
if( v==2 ){
sqlite3_result_int(context, 1);
@@ -931,10 +942,10 @@ static void geopolyAddSegments(
unsigned int i;
GeoCoord *x;
for(i=0; i<(unsigned)pPoly->nVertex-1; i++){
x = pPoly->a + (i*2);
x = &GeoX(pPoly,i);
geopolyAddOneSegment(p, x[0], x[1], x[2], x[3], side, i);
}
x = pPoly->a + (i*2);
x = &GeoX(pPoly,i);
geopolyAddOneSegment(p, x[0], x[1], pPoly->a[0], pPoly->a[1], side, i);
}
+89 -46
View File
@@ -128,6 +128,9 @@ struct Rtree {
u8 inWrTrans; /* True if inside write transaction */
u8 nAux; /* # of auxiliary columns in %_rowid */
u8 nAuxNotNull; /* Number of initial not-null aux columns */
#ifdef SQLITE_DEBUG
u8 bCorrupt; /* Shadow table corruption detected */
#endif
int iDepth; /* Current depth of the r-tree structure */
char *zDb; /* Name of database containing r-tree table */
char *zName; /* Name of r-tree table */
@@ -187,6 +190,15 @@ struct Rtree {
# define RTREE_ZERO 0.0
#endif
/*
** Set the Rtree.bCorrupt flag
*/
#ifdef SQLITE_DEBUG
# define RTREE_IS_CORRUPT(X) ((X)->bCorrupt = 1)
#else
# define RTREE_IS_CORRUPT(X)
#endif
/*
** When doing a search of an r-tree, instances of the following structure
** record intermediate results from the tree walk.
@@ -553,8 +565,8 @@ static void nodeZero(Rtree *pRtree, RtreeNode *p){
** Given a node number iNode, return the corresponding key to use
** in the Rtree.aHash table.
*/
static int nodeHash(i64 iNode){
return iNode % HASHSIZE;
static unsigned int nodeHash(i64 iNode){
return ((unsigned)iNode) % HASHSIZE;
}
/*
@@ -599,7 +611,7 @@ static void nodeHashDelete(Rtree *pRtree, RtreeNode *pNode){
*/
static RtreeNode *nodeNew(Rtree *pRtree, RtreeNode *pParent){
RtreeNode *pNode;
pNode = (RtreeNode *)sqlite3_malloc(sizeof(RtreeNode) + pRtree->iNodeSize);
pNode = (RtreeNode *)sqlite3_malloc64(sizeof(RtreeNode) + pRtree->iNodeSize);
if( pNode ){
memset(pNode, 0, sizeof(RtreeNode) + pRtree->iNodeSize);
pNode->zData = (u8 *)&pNode[1];
@@ -623,6 +635,18 @@ static void nodeBlobReset(Rtree *pRtree){
}
}
/*
** Check to see if pNode is the same as pParent or any of the parents
** of pParent.
*/
static int nodeInParentChain(const RtreeNode *pNode, const RtreeNode *pParent){
do{
if( pNode==pParent ) return 1;
pParent = pParent->pParent;
}while( pParent );
return 0;
}
/*
** Obtain a reference to an r-tree node.
*/
@@ -641,6 +665,10 @@ static int nodeAcquire(
if( (pNode = nodeHashLookup(pRtree, iNode))!=0 ){
assert( !pParent || !pNode->pParent || pNode->pParent==pParent );
if( pParent && !pNode->pParent ){
if( nodeInParentChain(pNode, pParent) ){
RTREE_IS_CORRUPT(pRtree);
return SQLITE_CORRUPT_VTAB;
}
pParent->nRef++;
pNode->pParent = pParent;
}
@@ -671,9 +699,12 @@ static int nodeAcquire(
*ppNode = 0;
/* If unable to open an sqlite3_blob on the desired row, that can only
** be because the shadow tables hold erroneous data. */
if( rc==SQLITE_ERROR ) rc = SQLITE_CORRUPT_VTAB;
if( rc==SQLITE_ERROR ){
rc = SQLITE_CORRUPT_VTAB;
RTREE_IS_CORRUPT(pRtree);
}
}else if( pRtree->iNodeSize==sqlite3_blob_bytes(pRtree->pNodeBlob) ){
pNode = (RtreeNode *)sqlite3_malloc(sizeof(RtreeNode)+pRtree->iNodeSize);
pNode = (RtreeNode *)sqlite3_malloc64(sizeof(RtreeNode)+pRtree->iNodeSize);
if( !pNode ){
rc = SQLITE_NOMEM;
}else{
@@ -686,7 +717,6 @@ static int nodeAcquire(
pNode->pNext = 0;
rc = sqlite3_blob_read(pRtree->pNodeBlob, pNode->zData,
pRtree->iNodeSize, 0);
nodeReference(pParent);
}
}
@@ -700,6 +730,7 @@ static int nodeAcquire(
pRtree->iDepth = readInt16(pNode->zData);
if( pRtree->iDepth>RTREE_MAX_DEPTH ){
rc = SQLITE_CORRUPT_VTAB;
RTREE_IS_CORRUPT(pRtree);
}
}
@@ -710,14 +741,17 @@ static int nodeAcquire(
if( pNode && rc==SQLITE_OK ){
if( NCELL(pNode)>((pRtree->iNodeSize-4)/pRtree->nBytesPerCell) ){
rc = SQLITE_CORRUPT_VTAB;
RTREE_IS_CORRUPT(pRtree);
}
}
if( rc==SQLITE_OK ){
if( pNode!=0 ){
nodeReference(pParent);
nodeHashInsert(pRtree, pNode);
}else{
rc = SQLITE_CORRUPT_VTAB;
RTREE_IS_CORRUPT(pRtree);
}
*ppNode = pNode;
}else{
@@ -943,7 +977,7 @@ static void rtreeRelease(Rtree *pRtree){
pRtree->inWrTrans = 0;
assert( pRtree->nCursor==0 );
nodeBlobReset(pRtree);
assert( pRtree->nNodeRef==0 );
assert( pRtree->nNodeRef==0 || pRtree->bCorrupt );
sqlite3_finalize(pRtree->pWriteNode);
sqlite3_finalize(pRtree->pDeleteNode);
sqlite3_finalize(pRtree->pReadRowid);
@@ -1002,7 +1036,7 @@ static int rtreeOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
Rtree *pRtree = (Rtree *)pVTab;
RtreeCursor *pCsr;
pCsr = (RtreeCursor *)sqlite3_malloc(sizeof(RtreeCursor));
pCsr = (RtreeCursor *)sqlite3_malloc64(sizeof(RtreeCursor));
if( pCsr ){
memset(pCsr, 0, sizeof(RtreeCursor));
pCsr->base.pVtab = pVTab;
@@ -1275,6 +1309,7 @@ static int nodeRowidIndex(
return SQLITE_OK;
}
}
RTREE_IS_CORRUPT(pRtree);
return SQLITE_CORRUPT_VTAB;
}
@@ -1368,7 +1403,7 @@ static RtreeSearchPoint *rtreeEnqueue(
RtreeSearchPoint *pNew;
if( pCur->nPoint>=pCur->nPointAlloc ){
int nNew = pCur->nPointAlloc*2 + 8;
pNew = sqlite3_realloc(pCur->aPoint, nNew*sizeof(pCur->aPoint[0]));
pNew = sqlite3_realloc64(pCur->aPoint, nNew*sizeof(pCur->aPoint[0]));
if( pNew==0 ) return 0;
pCur->aPoint = pNew;
pCur->nPointAlloc = nNew;
@@ -1770,7 +1805,7 @@ static int rtreeFilter(
*/
rc = nodeAcquire(pRtree, 1, 0, &pRoot);
if( rc==SQLITE_OK && argc>0 ){
pCsr->aConstraint = sqlite3_malloc(sizeof(RtreeConstraint)*argc);
pCsr->aConstraint = sqlite3_malloc64(sizeof(RtreeConstraint)*argc);
pCsr->nConstraint = argc;
if( !pCsr->aConstraint ){
rc = SQLITE_NOMEM;
@@ -1915,20 +1950,20 @@ static int rtreeBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
){
u8 op;
switch( p->op ){
case SQLITE_INDEX_CONSTRAINT_EQ: op = RTREE_EQ; break;
case SQLITE_INDEX_CONSTRAINT_GT: op = RTREE_GT; break;
case SQLITE_INDEX_CONSTRAINT_LE: op = RTREE_LE; break;
case SQLITE_INDEX_CONSTRAINT_LT: op = RTREE_LT; break;
case SQLITE_INDEX_CONSTRAINT_GE: op = RTREE_GE; break;
default:
assert( p->op==SQLITE_INDEX_CONSTRAINT_MATCH );
op = RTREE_MATCH;
break;
case SQLITE_INDEX_CONSTRAINT_EQ: op = RTREE_EQ; break;
case SQLITE_INDEX_CONSTRAINT_GT: op = RTREE_GT; break;
case SQLITE_INDEX_CONSTRAINT_LE: op = RTREE_LE; break;
case SQLITE_INDEX_CONSTRAINT_LT: op = RTREE_LT; break;
case SQLITE_INDEX_CONSTRAINT_GE: op = RTREE_GE; break;
case SQLITE_INDEX_CONSTRAINT_MATCH: op = RTREE_MATCH; break;
default: op = 0; break;
}
if( op ){
zIdxStr[iIdx++] = op;
zIdxStr[iIdx++] = (char)(p->iColumn - 1 + '0');
pIdxInfo->aConstraintUsage[ii].argvIndex = (iIdx/2);
pIdxInfo->aConstraintUsage[ii].omit = 1;
}
zIdxStr[iIdx++] = op;
zIdxStr[iIdx++] = (char)(p->iColumn - 1 + '0');
pIdxInfo->aConstraintUsage[ii].argvIndex = (iIdx/2);
pIdxInfo->aConstraintUsage[ii].omit = 1;
}
}
@@ -1964,11 +1999,11 @@ static RtreeDValue cellArea(Rtree *pRtree, RtreeCell *p){
#endif
{
switch( pRtree->nDim ){
case 5: area = p->aCoord[9].i - p->aCoord[8].i;
case 4: area *= p->aCoord[7].i - p->aCoord[6].i;
case 3: area *= p->aCoord[5].i - p->aCoord[4].i;
case 2: area *= p->aCoord[3].i - p->aCoord[2].i;
default: area *= p->aCoord[1].i - p->aCoord[0].i;
case 5: area = (i64)p->aCoord[9].i - (i64)p->aCoord[8].i;
case 4: area *= (i64)p->aCoord[7].i - (i64)p->aCoord[6].i;
case 3: area *= (i64)p->aCoord[5].i - (i64)p->aCoord[4].i;
case 2: area *= (i64)p->aCoord[3].i - (i64)p->aCoord[2].i;
default: area *= (i64)p->aCoord[1].i - (i64)p->aCoord[0].i;
}
}
return area;
@@ -2137,12 +2172,14 @@ static int AdjustTree(
RtreeCell *pCell /* This cell was just inserted */
){
RtreeNode *p = pNode;
int cnt = 0;
while( p->pParent ){
RtreeNode *pParent = p->pParent;
RtreeCell cell;
int iCell;
if( nodeParentIndex(pRtree, p, &iCell) ){
if( (++cnt)>1000 || nodeParentIndex(pRtree, p, &iCell) ){
RTREE_IS_CORRUPT(pRtree);
return SQLITE_CORRUPT_VTAB;
}
@@ -2339,9 +2376,9 @@ static int splitNodeStartree(
int iBestSplit = 0;
RtreeDValue fBestMargin = RTREE_ZERO;
int nByte = (pRtree->nDim+1)*(sizeof(int*)+nCell*sizeof(int));
sqlite3_int64 nByte = (pRtree->nDim+1)*(sizeof(int*)+nCell*sizeof(int));
aaSorted = (int **)sqlite3_malloc(nByte);
aaSorted = (int **)sqlite3_malloc64(nByte);
if( !aaSorted ){
return SQLITE_NOMEM;
}
@@ -2462,7 +2499,7 @@ static int SplitNode(
/* Allocate an array and populate it with a copy of pCell and
** all cells from node pLeft. Then zero the original node.
*/
aCell = sqlite3_malloc((sizeof(RtreeCell)+sizeof(int))*(nCell+1));
aCell = sqlite3_malloc64((sizeof(RtreeCell)+sizeof(int))*(nCell+1));
if( !aCell ){
rc = SQLITE_NOMEM;
goto splitnode_out;
@@ -2610,7 +2647,10 @@ static int fixLeafParent(Rtree *pRtree, RtreeNode *pLeaf){
}
rc = sqlite3_reset(pRtree->pReadParent);
if( rc==SQLITE_OK ) rc = rc2;
if( rc==SQLITE_OK && !pChild->pParent ) rc = SQLITE_CORRUPT_VTAB;
if( rc==SQLITE_OK && !pChild->pParent ){
RTREE_IS_CORRUPT(pRtree);
rc = SQLITE_CORRUPT_VTAB;
}
pChild = pChild->pParent;
}
return rc;
@@ -2750,7 +2790,7 @@ static int Reinsert(
/* Allocate the buffers used by this operation. The allocation is
** relinquished before this function returns.
*/
aCell = (RtreeCell *)sqlite3_malloc(n * (
aCell = (RtreeCell *)sqlite3_malloc64(n * (
sizeof(RtreeCell) + /* aCell array */
sizeof(int) + /* aOrder array */
sizeof(int) + /* aSpare array */
@@ -2924,8 +2964,12 @@ static int rtreeDeleteRowid(Rtree *pRtree, sqlite3_int64 iDelete){
rc = findLeafNode(pRtree, iDelete, &pLeaf, 0);
}
#ifdef CORRUPT_DB
assert( pLeaf!=0 || rc!=SQLITE_OK || CORRUPT_DB );
#endif
/* Delete the cell in question from the leaf node. */
if( rc==SQLITE_OK ){
if( rc==SQLITE_OK && pLeaf ){
int rc2;
rc = nodeRowidIndex(pRtree, pLeaf, iDelete, &iCell);
if( rc==SQLITE_OK ){
@@ -3197,7 +3241,7 @@ static int rtreeUpdate(
rc = rc2;
}
}
if( pRtree->nAux ){
if( rc==SQLITE_OK && pRtree->nAux ){
sqlite3_stmt *pUp = pRtree->pWriteAux;
int jj;
sqlite3_bind_int64(pUp, 1, *pRowid);
@@ -3395,6 +3439,7 @@ static int rtreeSqlInit(
};
sqlite3_stmt **appStmt[N_STATEMENT];
int i;
const int f = SQLITE_PREPARE_PERSISTENT|SQLITE_PREPARE_NO_VTAB;
pRtree->db = db;
@@ -3451,8 +3496,7 @@ static int rtreeSqlInit(
}
zSql = sqlite3_mprintf(zFormat, zDb, zPrefix);
if( zSql ){
rc = sqlite3_prepare_v3(db, zSql, -1, SQLITE_PREPARE_PERSISTENT,
appStmt[i], 0);
rc = sqlite3_prepare_v3(db, zSql, -1, f, appStmt[i], 0);
}else{
rc = SQLITE_NOMEM;
}
@@ -3482,8 +3526,7 @@ static int rtreeSqlInit(
if( zSql==0 ){
rc = SQLITE_NOMEM;
}else{
rc = sqlite3_prepare_v3(db, zSql, -1, SQLITE_PREPARE_PERSISTENT,
&pRtree->pWriteAux, 0);
rc = sqlite3_prepare_v3(db, zSql, -1, f, &pRtree->pWriteAux, 0);
sqlite3_free(zSql);
}
}
@@ -3559,6 +3602,7 @@ static int getNodeSize(
*pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
}else if( pRtree->iNodeSize<(512-64) ){
rc = SQLITE_CORRUPT_VTAB;
RTREE_IS_CORRUPT(pRtree);
*pzErr = sqlite3_mprintf("undersize RTree blobs in \"%q_node\"",
pRtree->zName);
}
@@ -3614,7 +3658,7 @@ static int rtreeInit(
/* Allocate the sqlite3_vtab structure */
nDb = (int)strlen(argv[1]);
nName = (int)strlen(argv[2]);
pRtree = (Rtree *)sqlite3_malloc(sizeof(Rtree)+nDb+nName+2);
pRtree = (Rtree *)sqlite3_malloc64(sizeof(Rtree)+nDb+nName+2);
if( !pRtree ){
return SQLITE_NOMEM;
}
@@ -3882,8 +3926,7 @@ static void rtreeCheckAppendMsg(RtreeCheck *pCheck, const char *zFmt, ...){
static u8 *rtreeCheckGetNode(RtreeCheck *pCheck, i64 iNode, int *pnNode){
u8 *pRet = 0; /* Return value */
assert( pCheck->rc==SQLITE_OK );
if( pCheck->pGetNode==0 ){
if( pCheck->rc==SQLITE_OK && pCheck->pGetNode==0 ){
pCheck->pGetNode = rtreeCheckPrepare(pCheck,
"SELECT data FROM %Q.'%q_node' WHERE nodeno=?",
pCheck->zDb, pCheck->zTab
@@ -3895,7 +3938,7 @@ static u8 *rtreeCheckGetNode(RtreeCheck *pCheck, i64 iNode, int *pnNode){
if( sqlite3_step(pCheck->pGetNode)==SQLITE_ROW ){
int nNode = sqlite3_column_bytes(pCheck->pGetNode, 0);
const u8 *pNode = (const u8*)sqlite3_column_blob(pCheck->pGetNode, 0);
pRet = sqlite3_malloc(nNode);
pRet = sqlite3_malloc64(nNode);
if( pRet==0 ){
pCheck->rc = SQLITE_NOMEM;
}else{
@@ -4328,12 +4371,12 @@ static void rtreeMatchArgFree(void *pArg){
static void geomCallback(sqlite3_context *ctx, int nArg, sqlite3_value **aArg){
RtreeGeomCallback *pGeomCtx = (RtreeGeomCallback *)sqlite3_user_data(ctx);
RtreeMatchArg *pBlob;
int nBlob;
sqlite3_int64 nBlob;
int memErr = 0;
nBlob = sizeof(RtreeMatchArg) + (nArg-1)*sizeof(RtreeDValue)
+ nArg*sizeof(sqlite3_value*);
pBlob = (RtreeMatchArg *)sqlite3_malloc(nBlob);
pBlob = (RtreeMatchArg *)sqlite3_malloc64(nBlob);
if( !pBlob ){
sqlite3_result_error_nomem(ctx);
}else{
+14
View File
@@ -647,5 +647,19 @@ do_execsql_test 16.130 {
SELECT * FROM rt1 WHERE id IN (1, 2, 3, 4);
} {1 1.0 2.0 aux1 2 2.0 3.0 aux2 3 3.0 4.0 aux3 4 4.0 5.0 aux4}
reset_db
do_execsql_test 17.0 {
CREATE VIRTUAL TABLE t1 USING rtree(id, x1 PRIMARY KEY, x2, y1, y2);
CREATE VIRTUAL TABLE t2 USING rtree(id, x1, x2, y1, y2 UNIQUE);
}
do_execsql_test 17.1 {
REINDEX t1;
REINDEX t2;
} {}
do_execsql_test 17.2 {
REINDEX;
} {}
expand_all_sql db
finish_test
+13
View File
@@ -15,6 +15,7 @@ if {![info exists testdir]} {
set testdir [file join [file dirname [info script]] .. .. test]
}
source $testdir/tester.tcl
set testprefix rtree6
ifcapable {!rtree || rtree_int_only} {
finish_test
@@ -58,6 +59,9 @@ do_test rtree6-1.1 {
do_test rtree6-1.2 {
rtree_strategy {SELECT * FROM t1 WHERE x1>10}
} {E0}
do_test rtree6-1.2.1 {
rtree_strategy {SELECT * FROM t1 WHERE x1>10 AND x2 LIKE '%x%'}
} {E0}
do_test rtree6-1.3 {
rtree_strategy {SELECT * FROM t1 WHERE x1<10}
@@ -164,5 +168,14 @@ do_execsql_test rtree6-3.5 {
x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>1.1
} {}
#-------------------------------------------------------------------------
reset_db
do_execsql_test 4.0 {
CREATE VIRTUAL TABLE t1 USING rtree(id,x0,x1,y0,y1);
}
do_execsql_test 4.1 {
DELETE FROM t1 WHERE x0>1 AND x1<2 OR y0<92;
}
expand_all_sql db
finish_test
+66
View File
@@ -0,0 +1,66 @@
# 2018 Dec 22
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#*************************************************************************
# This file implements regression tests for SQLite library. The
# focus of this script is testing the FTS5 module.
#
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
set testprefix rtreecirc
ifcapable !rtree {
finish_test
return
}
do_execsql_test 1.0 {
CREATE VIRTUAL TABLE rt USING rtree(id, x1, x2, y1, y2);
SELECT name FROM sqlite_master ORDER BY 1;
} {
rt rt_node rt_parent rt_rowid
}
db_save_and_close
foreach {tn schema sql} {
1 {
CREATE TRIGGER tr1 AFTER INSERT ON rt_node BEGIN
SELECT * FROM rt;
END;
} {
INSERT INTO rt VALUES(1, 2, 3, 4, 5);
}
2 {
CREATE TRIGGER tr1 AFTER INSERT ON rt_parent BEGIN
SELECT * FROM rt;
END;
} {
INSERT INTO rt VALUES(1, 2, 3, 4, 5);
}
3 {
CREATE TRIGGER tr1 AFTER INSERT ON rt_rowid BEGIN
SELECT * FROM rt;
END;
} {
INSERT INTO rt VALUES(1, 2, 3, 4, 5);
}
} {
db_restore_and_reopen
do_execsql_test 1.1.$tn.1 $schema
do_catchsql_test 1.1.$tn.2 $sql {1 {no such table: main.rt}}
db close
}
finish_test
+777
View File
@@ -0,0 +1,777 @@
# 2012-12-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.
#
#***********************************************************************
#
# Test cases for corrupt database files.
if {![info exists testdir]} {
set testdir [file join [file dirname [info script]] .. .. test]
}
source $testdir/tester.tcl
ifcapable !deserialize||!rtree {
finish_test
return
}
database_may_be_corrupt
do_test rtreefuzz001-100 {
sqlite3 db {}
db deserialize [decode_hexdb {
| size 24576 pagesize 4096 filename c1b.db
| page 1 offset 0
| 0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00 SQLite format 3.
| 16: 10 00 01 01 00 40 20 20 00 00 00 03 00 00 00 06 .....@ ........
| 32: 00 00 00 00 00 00 00 00 00 00 00 03 00 00 00 04 ................
| 48: 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 ................
| 80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 03 ................
| 96: 00 2e 30 38 0d 00 00 00 04 0e 9c 00 0f ad 0f 4f ..08...........O
| 112: 0e fc 0e 9c 00 00 00 00 00 00 00 00 00 00 00 00 ................
| 3728: 00 00 00 00 00 00 00 00 00 00 00 00 5e 04 07 17 ............^...
| 3744: 1f 1f 01 81 0b 74 61 62 6c 65 74 31 5f 70 61 72 .....tablet1_par
| 3760: 65 6e 74 74 31 5f 70 61 72 65 6e 74 04 43 52 45 entt1_parent.CRE
| 3776: 41 54 45 20 54 41 42 4c 45 20 22 74 31 5f 70 61 ATE TABLE .t1_pa
| 3792: 72 66 6e 74 22 28 6e 6f 64 65 6e 6f 20 49 4e 54 rfnt.(nodeno INT
| 3808: 45 47 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59 EGER PRIMARY KEY
| 3824: 2c 70 61 72 65 6e 74 6e 6f 64 65 29 51 03 06 17 ,parentnode)Q...
| 3840: 1b 1b 01 7b 74 61 62 6c 65 74 31 5f 6e 6f 64 65 ....tablet1_node
| 3856: 74 31 5f 6e 6f 64 65 03 43 52 45 41 54 45 20 54 t1_node.CREATE T
| 3872: 41 42 4c 45 20 22 74 31 5f 6e 6f 64 65 22 28 6e ABLE .t1_node.(n
| 3888: 6f 64 65 6e 6f 20 49 4e 54 45 47 45 52 20 50 52 odeno INTEGER PR
| 3904: 49 4d 41 52 59 20 4b 45 59 2c 64 61 74 61 29 5c IMARY KEY,data).
| 3920: 02 07 17 1d 1d 01 81 0b 74 61 62 6c 65 74 31 5f ........tablet1_
| 3936: 72 6f 77 69 64 74 31 5f 72 6f 77 69 64 02 43 52 rowidt1_rowid.CR
| 3952: 45 41 54 45 20 54 41 42 4c 45 20 22 74 31 5f 72 EATE TABLE .t1_r
| 3968: 6f 77 69 64 22 28 72 6f 77 69 64 20 49 4e 54 45 owid.(rowid INTE
| 3984: 47 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59 2c GER PRIMARY KEY,
| 4000: 6e 6f 64 65 6e 6f 2c 61 30 2c 61 31 29 51 01 07 nodeno,a0,a1)Q..
| 4016: 17 11 11 08 81 0f 74 61 62 6c 65 74 31 74 31 43 ......tablet1t1C
| 4032: 52 45 41 54 45 20 56 49 52 54 55 41 4c 20 54 41 REATE VIRTUAL TA
| 4048: 42 4c 45 20 74 31 20 55 53 49 4e 47 20 72 74 72 BLE t1 USING rtr
| 4064: 65 65 28 69 64 2c 78 30 2c 78 31 2c 79 30 2c 79 ee(id,x0,x1,y0,y
| 4080: 31 2c 2b 6c 61 62 65 6c 2c 2b 6f 74 68 65 72 29 1,+label,+other)
| page 2 offset 4096
| 0: 0d 0c cd 00 74 08 75 01 0f e8 0c b3 0f d0 0f b7 ....t.u.........
| 16: 0f 9e 0f 91 0f 81 0f 70 0f 5e 0f 4f 0f 39 0f 29 .......p.^.O.9.)
| 32: 0f 18 0f 06 0e f7 0c 65 0e 58 0d c2 0d 2c 0c 25 .......e.X...,.%
| 48: 0b 85 0a e5 0a 45 09 a5 09 05 0c 83 0c 93 0c a3 .....E..........
| 64: 0f f0 0c 15 0b 75 0a d5 0a 35 09 95 08 f5 0e d8 .....u...5......
| 80: 0e 42 0d ac 0d 16 0c 05 0b 65 0a c5 0a 25 09 85 .B.......e...%..
| 96: 08 e5 0e c8 0e 32 0d 9c 0d 06 0b f5 0b 55 0a b5 .....2.......U..
| 112: 0a 15 09 75 08 d5 0e b8 0e 22 0d 8c 0c f6 0b e5 ...u............
| 128: 0b 45 0a a5 0a 05 09 65 08 c5 0e a8 0e 12 0d 7c .E.....e.......|
| 144: 0c e6 0b d5 0b 35 0a 95 09 f5 09 55 08 b5 0e 98 .....5.....U....
| 160: 0e 02 0d 6c 0c d6 0b c5 0b 25 0a 85 09 e5 09 45 ...l.....%.....E
| 176: 08 a5 0e 88 0d f2 0d 5c 0c 55 0b b5 0b 15 0a 75 .........U.....u
| 192: 09 d5 09 35 08 95 0e 78 0d e2 0d 4c 0c 45 0b a5 ...5...x...L.E..
| 208: 0b 05 0a 65 09 c5 09 25 08 85 0e 68 0d d2 0d 3c ...e...%...h...<
| 224: 0c 35 0b 95 0a f5 0a 55 09 b5 09 15 08 75 0c 75 .5.....U.....u.u
| 2160: 00 00 00 00 00 0d 8e 75 05 00 01 1b 00 04 62 6f .......u......bo
| 2176: 78 2d 39 2c 39 0d 8e 11 05 00 01 1b 00 02 62 6f x-9,9.........bo
| 2192: 78 2d 39 2c 38 0d 8d 2d 05 00 01 1b 00 02 62 6f x-9,8..-......bo
| 2208: 78 2d 39 2c 37 0d 8c 49 05 00 01 1b 00 02 62 6f x-9,7..I......bo
| 2224: 78 2d 39 2c 36 0d 8b 65 05 00 01 1b 00 02 62 6f x-9,6..e......bo
| 2240: 78 2d 39 2c 35 0d 8b 01 05 00 01 1b 00 02 62 6f x-9,5.........bo
| 2256: 78 2d 39 2c 34 0d 8a 1d 05 00 01 1b 00 02 62 6f x-9,4.........bo
| 2272: 78 2d 39 2c 33 0d 89 39 05 00 01 1b 00 02 62 6f x-9,3..9......bo
| 2288: 78 2d 39 2c 32 0d 88 55 05 00 01 1b 00 02 62 6f x-9,2..U......bo
| 2304: 78 2d 39 2c 31 0d 87 71 05 00 01 1b 00 02 62 6f x-9,1..q......bo
| 2320: 78 2d 39 2c 30 0d 8e 74 05 00 01 1b 00 04 62 6f x-9,0..t......bo
| 2336: 78 2d 38 2c 39 0d 8e 10 05 00 01 1b 00 02 62 6f x-8,9.........bo
| 2352: 78 2d 38 2c 38 0d 8d 2c 05 00 01 1b 00 02 62 6f x-8,8..,......bo
| 2368: 78 2d 38 2c 37 0d 8c 48 05 00 01 1b 00 02 62 6f x-8,7..H......bo
| 2384: 78 2d 38 2c 36 0d 8b 64 05 00 01 1b 00 02 62 6f x-8,6..d......bo
| 2400: 78 2d 38 2c 35 0d 8b 00 05 00 01 1b 00 02 62 6f x-8,5.........bo
| 2416: 78 2d 38 2c 34 0d 8a 1c 05 00 01 1b 00 02 62 6f x-8,4.........bo
| 2432: 78 2d 38 2c 33 0d 89 38 05 00 01 1b 00 02 62 6f x-8,3..8......bo
| 2448: 78 2d 38 2c 32 0d 88 54 05 00 01 1b 00 02 62 6f x-8,2..T......bo
| 2464: 78 2d 38 2c 31 0d 87 70 05 00 01 1b 00 02 62 6f x-8,1..p......bo
| 2480: 78 2d 38 2c 30 0d 8e 73 05 00 01 1b 00 05 62 6f x-8,0..s......bo
| 2496: 78 2d 37 2c 39 0d 8e 0f 05 00 01 1b 00 05 62 6f x-7,9.........bo
| 2512: 78 2d 37 2c 38 0d 8d 2b 05 00 01 1b 00 05 62 6f x-7,8..+......bo
| 2528: 78 2d 37 2c 37 0d 8c 47 05 00 01 1b 00 05 62 6f x-7,7..G......bo
| 2544: 78 2d 37 2c 36 0d 8b 63 05 00 01 1b 00 05 62 6f x-7,6..c......bo
| 2560: 78 2d 37 2c 35 0d 8a 7f 05 00 01 1b 00 05 62 6f x-7,5.........bo
| 2576: 78 2d 37 2c 34 0d 8a 1b 05 00 01 1b 00 05 62 6f x-7,4.........bo
| 2592: 78 2d 37 2c 33 0d 89 37 05 00 01 1b 00 05 62 6f x-7,3..7......bo
| 2608: 78 2d 37 2c 32 0d 88 53 05 00 01 1b 00 05 62 6f x-7,2..S......bo
| 2624: 78 2d 37 2c 31 0d 87 6f 05 00 01 1b 00 05 62 6f x-7,1..o......bo
| 2640: 78 2d 37 2c 30 0d 8e 72 05 00 01 1b 00 04 62 6f x-7,0..r......bo
| 2656: 78 2d 36 2c 39 0d 8e 0e 05 00 01 1b 00 05 62 6f x-6,9.........bo
| 2672: 78 2d 36 2c 38 0d 8d 2a 05 00 01 1b 00 05 62 6f x-6,8..*......bo
| 2688: 78 2d 36 2c 37 0d 8c 46 05 00 01 1b 00 05 62 6f x-6,7..F......bo
| 2704: 78 2d 36 2c 36 0d 8b 62 05 00 01 1b 00 05 62 6f x-6,6..b......bo
| 2720: 78 2d 36 2c 35 0d 8a 7e 05 00 01 1b 00 05 62 6f x-6,5..~......bo
| 2736: 78 2d 36 2c 34 0d 8a 1a 05 00 01 1b 00 05 62 6f x-6,4.........bo
| 2752: 78 2d 36 2c 33 0d 89 36 05 00 01 1b 00 05 62 6f x-6,3..6......bo
| 2768: 78 2d 36 2c 32 0d 88 52 05 00 01 1b 00 05 62 6f x-6,2..R......bo
| 2784: 78 2d 36 2c 31 0d 87 6e 05 00 01 1b 00 05 62 6f x-6,1..n......bo
| 2800: 78 2d 36 2c 30 0d 8e 71 05 00 01 1b 00 04 62 6f x-6,0..q......bo
| 2816: 78 2d 35 2c 39 0d 8e 0d 05 00 01 1b 00 05 62 6f x-5,9.........bo
| 2832: 78 2d 35 2c 38 0d 8d 29 05 00 01 1b 00 05 62 6f x-5,8..)......bo
| 2848: 78 2d 35 2c 37 0d 8c 45 05 00 01 1b 00 05 62 6f x-5,7..E......bo
| 2864: 78 2d 35 2c 36 0d 8b 61 05 00 01 1b 00 05 62 6f x-5,6..a......bo
| 2880: 78 2d 35 2c 35 0d 8a 7d 05 00 01 1b 00 05 62 6f x-5,5.........bo
| 2896: 78 2d 35 2c 34 0d 8a 19 05 00 01 1b 00 05 62 6f x-5,4.........bo
| 2912: 78 2d 35 2c 33 0d 89 35 05 00 01 1b 00 05 62 6f x-5,3..5......bo
| 2928: 78 2d 35 2c 32 0d 88 51 05 00 01 1b 00 05 62 6f x-5,2..Q......bo
| 2944: 78 2d 35 2c 31 0d 87 6d 05 00 01 1b 00 05 62 6f x-5,1..m......bo
| 2960: 78 2d 35 2c 30 0d 8e 70 05 00 01 1b 00 04 62 6f x-5,0..p......bo
| 2976: 78 2d 34 2c 39 0d 8e 0c 05 00 01 1b 00 04 62 6f x-4,9.........bo
| 2992: 78 2d 34 2c 38 0d 8d 28 05 00 01 1b 00 04 62 6f x-4,8..(......bo
| 3008: 78 2d 34 2c 37 0d 8c 44 05 00 01 1b 00 04 62 6f x-4,7..D......bo
| 3024: 78 2d 34 2c 36 0d 8b 60 05 00 01 1b 00 02 62 6f x-4,6..`......bo
| 3040: 78 2d 34 2c 35 0d 8a 7c 05 00 01 1b 00 02 62 6f x-4,5..|......bo
| 3056: 78 2d 34 2c 34 0d 8a 18 05 00 01 1b 00 02 62 6f x-4,4.........bo
| 3072: 78 2d 34 2c 33 0d 89 34 05 00 01 1b 00 02 62 6f x-4,3..4......bo
| 3088: 78 2d 34 2c 32 0d 88 50 05 00 01 1b 00 02 62 6f x-4,2..P......bo
| 3104: 78 2d 34 2c 31 0d 87 6c 05 00 01 1b 00 02 62 6f x-4,1..l......bo
| 3120: 78 2d 34 2c 30 0d 8e 6f 05 00 01 1b 00 04 62 6f x-4,0..o......bo
| 3136: 78 2d 33 2c 39 0d 8e 0b 05 00 01 1b 00 04 62 6f x-3,9.........bo
| 3152: 78 2d 33 2c 38 0d 8d 27 05 00 01 1b 00 04 62 6f x-3,8..'......bo
| 3168: 78 2d 33 2c 37 0d 87 68 05 00 01 1b 00 03 62 6f x-3,7..h......bo
| 3184: 78 2d 30 2c 30 06 90 d9 80 80 81 84 4c 05 00 01 x-0,0.......L...
| 3200: 00 00 03 0d 88 4c 05 00 01 1b 00 02 62 6f 78 2d .....L......box-
| 3216: 30 2c 31 0d 88 4d 05 00 01 1b 00 02 62 6f 78 2d 0,1..M......box-
| 3232: 31 2c 31 0d 88 4e 05 00 01 1b 00 02 62 6f 78 2d 1,1..N......box-
| 3248: 32 2c 31 17 01 05 00 01 2f 00 02 6c 6f 77 65 72 2,1...../..lower
| 3264: 2d 6c 65 66 74 20 63 6f 72 6e 65 72 0d 0d 26 00 -left corner..&.
| 3280: 09 00 01 00 00 04 0d 8c 43 05 00 01 1b 00 04 62 ........C......b
| 3296: 6f 78 2d 33 2c 36 0d 8b 5f 05 00 01 1b 00 02 62 ox-3,6.._......b
| 3312: 6f 78 2d 33 2c 35 0d 8a 7b 05 00 01 1b 00 02 62 ox-3,5.........b
| 3328: 6f 78 2d 33 2c 34 0d 8a 17 05 00 01 1b 00 02 62 ox-3,4.........b
| 3344: 6f 78 2d 33 2c 33 0d 89 33 05 00 01 1b 00 02 62 ox-3,3..3......b
| 3360: 6f 78 2d 33 2c 32 0d bc 00 06 00 09 0d 87 6b 05 ox-3,2........k.
| 3376: 00 01 1b 00 03 62 6f 78 2d 33 2c 30 0d 8e 6e 05 .....box-3,0..n.
| 3392: 00 01 1b 00 04 62 6f 78 2d 32 2c 39 0d 8e 0a 05 .....box-2,9....
| 3408: 00 01 1b 00 04 62 6f 78 2d 32 2c 38 0d 8d 26 05 .....box-2,8..&.
| 3424: 00 01 1b 00 04 62 6f 78 2d 32 2c 37 0d 8c 42 05 .....box-2,7..B.
| 3440: 00 01 1b 00 04 62 6f 78 2d 32 2c 36 0d 8b 5e 05 .....box-2,6..^.
| 3456: 00 01 1b 00 02 62 6f 78 2d 32 2c 35 0d 8a 7a 05 .....box-2,5..z.
| 3472: 00 01 1b 00 02 62 6f 78 2d 32 2c 34 0d 8a 16 05 .....box-2,4....
| 3488: 00 01 1b 00 02 62 6f 78 2d 32 2c 33 0d 89 32 05 .....box-2,3..2.
| 3504: 00 01 1b 00 02 62 6f 78 2d 32 2c 32 0e 52 00 06 .....box-2,2.R..
| 3520: 00 09 0d 87 6a 05 00 01 1b 00 03 62 6f 78 2d 32 ....j......box-2
| 3536: 2c 30 0d 8e 6d 05 00 01 1b 00 04 62 6f 78 2d 31 ,0..m......box-1
| 3552: 2c 39 0d 8e 09 05 00 01 1b 00 04 62 6f 78 2d 31 ,9.........box-1
| 3568: 2c 38 0d 8d 25 05 00 01 1b 00 04 62 6f 78 2d 31 ,8..%......box-1
| 3584: 2c 37 0d 8c 41 05 00 01 1b 00 04 62 6f 78 2d 31 ,7..A......box-1
| 3600: 2c 36 0d 8b 5d 05 00 01 1b 00 02 62 6f 78 2d 31 ,6..]......box-1
| 3616: 2c 35 0d 8a 79 05 00 01 1b 00 02 62 6f 78 2d 31 ,5..y......box-1
| 3632: 2c 34 0d 8a 15 05 00 01 1b 00 02 62 6f 78 2d 31 ,4.........box-1
| 3648: 2c 33 0d 89 31 05 00 01 1b 00 02 62 6f 78 2d 31 ,3..1......box-1
| 3664: 2c 32 0e e8 00 06 00 09 0d 87 69 05 00 01 1b 00 ,2........i.....
| 3680: 03 62 6f 78 2d 31 2c 30 0d 8e 6c 05 00 01 1b 00 .box-1,0..l.....
| 3696: 04 62 6f 78 2d 30 2c 39 0d 8e 08 05 00 01 1b 00 .box-0,9........
| 3712: 04 62 6f 78 2d 30 2c 38 0d 8d 24 05 00 01 1b 00 .box-0,8..$.....
| 3728: 04 62 6f 78 2d 30 2c 37 0d 8c 40 05 00 01 1b 00 .box-0,7..@.....
| 3744: 04 62 6f 78 2d 30 2c 36 0d 8b 5c 05 00 01 1b 00 .box-0,6........
| 3760: 02 62 6f 78 2d 30 2c 35 0d 8a 78 05 00 01 1b 00 .box-0,5..x.....
| 3776: 02 62 6f 78 2d 30 2c 34 0d 8a 14 05 00 01 1b 00 .box-0,4........
| 3792: 02 62 6f 78 2d 30 2c 33 0d 89 30 05 00 01 1b 00 .box-0,3..0.....
| 3808: 02 62 6f 78 2d 30 2c 32 00 00 00 0f 00 09 1b 00 .box-0,2........
| 3824: 62 6f 78 2d 30 2c 30 0d 0e 05 00 09 1d 00 74 6f box-0,0.......to
| 3840: 70 20 68 61 6c 66 10 0d 05 00 09 23 00 62 6f 74 p half.....#.bot
| 3856: 74 6f 6d 20 68 61 6c 66 0f 0c 02 05 09 01 00 72 tom half.......r
| 3872: 69 67 68 74 20 68 61 6c 66 0e 0b 05 00 09 1f 00 ight half.......
| 3888: 6c 65 66 74 20 68 61 6c 66 14 0a 05 00 09 2b 00 left half.....+.
| 3904: 74 68 65 20 77 68 6f 6c 65 20 74 68 69 6e 67 0d the whole thing.
| 3920: 09 05 00 09 1d 00 74 6f 70 20 65 64 67 65 10 08 ......top edge..
| 3936: 05 00 09 23 00 62 6f 74 74 6f 6d 20 65 64 67 65 ...#.bottom edge
| 3952: 0f 07 05 00 09 21 00 72 69 67 68 74 20 65 64 67 .....!.right edg
| 3968: 65 0e 06 05 00 09 1f 00 6c 65 66 74 20 65 64 67 e.......left edg
| 3984: 65 0b 05 05 00 09 19 00 63 65 6e 74 65 72 17 04 e.......center..
| 4000: 05 00 09 31 00 75 70 70 65 72 2d 72 69 67 68 74 ...1.upper-right
| 4016: 20 63 6f 72 6e 65 72 17 03 05 00 09 31 00 6c 6f corner.....1.lo
| 4032: 77 65 72 2d 72 69 67 68 74 20 63 6f 72 6e 65 72 wer-right corner
| 4048: 16 02 05 00 09 2f 00 75 70 70 65 72 2d 6c 65 66 ...../.upper-lef
| 4064: 74 20 63 6f 72 6e 65 72 06 00 05 00 01 00 00 03 t corner........
| 4080: 0d 88 4f 05 00 01 1b 00 02 62 6f 78 2d 33 2c 31 ..O......box-3,1
| page 3 offset 8192
| 0: 05 00 00 00 01 0f fb 00 00 00 00 06 0f fb 00 00 ................
| 384: 00 00 00 00 00 00 00 89 50 03 04 00 93 24 00 00 ........P....$..
| 400: 00 11 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
| 688: 00 00 00 00 42 c8 00 00 42 4c 00 00 42 00 00 00 ....B...BL..B...
| 720: 03 eb 40 40 00 00 40 80 00 00 00 00 00 00 3f 80 ..@@..@.......?.
| 736: 00 00 00 00 00 00 00 00 03 ea 40 00 00 00 40 40 ..........@...@@
| 752: 00 00 00 00 00 00 3f 80 00 00 00 00 00 00 00 00 ......?.........
| 768: 03 e9 3f 80 00 00 40 00 00 00 00 00 00 00 3f 80 ..?...@.......?.
| 784: 00 00 00 00 00 00 00 00 03 e8 00 00 00 00 3f 80 ..............?.
| 800: 00 00 00 00 00 00 3f 80 00 00 00 00 00 00 00 00 ......?.........
| 1616: 00 00 00 00 00 00 00 00 00 00 89 50 02 04 00 93 ...........P....
| 1632: 24 00 00 00 33 00 00 00 00 00 00 00 01 00 00 00 $...3...........
| 1648: 00 41 20 00 00 00 00 00 00 41 0e 00 00 00 00 00 .A ......A......
| 1664: 00 00 00 04 4f 40 40 00 00 40 80 00 00 3f 80 00 ....O@@..@...?..
| 1680: 00 40 00 00 00 00 00 00 00 00 00 04 4e 40 00 00 .@..........N@..
| 1696: 00 40 40 00 00 3f 80 00 00 40 00 00 00 00 00 00 .@@..?...@......
| 1712: 00 00 00 04 4d 3f 80 00 00 40 00 00 00 3f 80 00 ....M?...@...?..
| 1728: 00 40 00 00 00 00 00 00 00 00 00 04 4c 00 00 00 .@..........L...
| 1744: 00 3f 80 00 00 3f 80 00 00 40 00 00 00 00 00 00 .?...?...@......
| 1760: 00 00 00 04 b3 40 40 00 00 40 80 00 00 40 00 00 .....@@..@...@..
| 1776: 00 40 40 00 00 00 00 00 00 00 00 04 b2 40 00 00 .@@..........@..
| 1792: 00 40 40 00 00 40 00 00 00 40 40 00 00 00 00 00 .@@..@...@@.....
| 1808: 00 00 00 04 b1 3f 80 00 00 40 00 00 00 40 00 00 .....?...@...@..
| 1824: 00 40 40 00 00 00 00 00 00 00 00 04 b0 00 00 00 .@@.............
| 1840: 00 3f 80 00 00 40 00 00 00 40 40 00 00 00 00 00 .?...@...@@.....
| 1856: 00 00 00 05 17 40 40 00 00 40 80 00 00 40 40 00 .....@@..@...@@.
| 1872: 00 40 80 00 00 00 00 00 00 00 00 05 16 40 00 00 .@...........@..
| 1888: 00 40 40 00 00 40 40 00 00 40 80 00 00 00 00 00 .@@..@@..@......
| 1904: 00 00 00 05 15 3f 80 00 00 40 00 00 00 40 40 00 .....?...@...@@.
| 1920: 00 40 80 00 00 00 00 00 00 00 00 05 14 00 00 00 .@..............
| 1936: 00 3f 80 00 00 40 40 00 00 40 80 00 00 00 00 00 .?...@@..@......
| 1952: 00 00 00 05 7b 40 40 00 00 40 80 00 00 40 80 00 .....@@..@...@..
| 1968: 00 40 a0 00 00 00 00 00 00 00 00 05 7a 40 00 00 .@..........z@..
| 1984: 00 40 40 00 00 40 80 00 00 40 a0 00 00 00 00 00 .@@..@...@......
| 2000: 00 00 00 05 79 3f 80 00 00 40 00 00 00 40 80 00 ....y?...@...@..
| 2016: 00 40 a0 00 00 00 00 00 00 00 00 05 78 00 00 00 .@..........x...
| 2032: 00 3f 80 00 00 40 80 00 00 40 a0 00 00 00 00 00 .?...@...@......
| 2048: 00 00 00 05 df 40 40 00 00 40 80 00 00 40 a0 00 .....@@..@...@..
| 2064: 00 40 c0 00 00 00 00 00 00 00 00 05 de 40 00 00 .@...........@..
| 2080: 00 40 40 00 00 40 a0 00 00 40 c0 00 00 00 00 00 .@@..@...@......
| 2096: 00 00 00 05 dd 3f 80 00 00 40 00 00 00 40 a0 00 .....?...@...@..
| 2112: 00 40 c0 00 00 00 00 00 00 00 00 05 dc 00 00 00 .@..............
| 2128: 00 3f 80 00 00 40 a0 00 00 40 c0 00 00 00 00 00 .?...@...@......
| 2144: 00 00 00 06 43 40 40 00 00 40 80 00 00 40 c0 00 ....C@@..@...@..
| 2160: 00 40 e0 00 00 00 00 00 00 00 00 06 42 40 00 00 .@..........B@..
| 2176: 00 40 40 00 00 40 c0 00 00 40 e0 00 00 00 00 00 .@@..@...@......
| 2192: 00 00 00 06 41 3f 80 00 00 40 00 00 00 40 c0 00 ....A?...@...@..
| 2208: 00 40 e0 00 00 00 00 00 00 00 00 06 40 00 00 00 .@..........@...
| 2224: 00 3f 80 00 00 40 c0 00 00 40 e0 00 00 00 00 00 .?...@...@......
| 2240: 00 00 00 06 a7 40 40 00 00 40 80 00 00 40 e0 00 .....@@..@...@..
| 2256: 00 41 00 00 00 00 00 00 00 00 00 06 a6 40 00 00 .A...........@..
| 2272: 00 40 40 00 00 40 e0 00 00 41 00 00 00 00 00 00 .@@..@...A......
| 2288: 00 00 00 06 a5 3f 80 00 00 40 00 00 00 40 e0 00 .....?...@...@..
| 2304: 00 41 00 00 00 00 00 00 00 00 00 06 a4 00 00 00 .A..............
| 2320: 00 3f 80 00 00 40 e0 00 00 41 00 00 00 00 00 00 .?...@...A......
| 2336: 00 00 00 07 0a 40 00 00 00 40 40 00 00 41 00 00 .....@...@@..A..
| 2352: 00 41 10 00 00 00 00 00 00 00 00 07 09 3f 80 00 .A...........?..
| 2368: 00 40 00 00 00 41 00 00 00 41 10 00 00 00 00 00 .@...A...A......
| 2384: 00 00 00 07 08 00 00 00 00 3f 80 00 00 41 00 00 .........?...A..
| 2400: 00 41 10 00 00 00 00 00 00 00 00 07 6e 40 00 00 .A..........n@..
| 2416: 00 40 40 00 00 41 10 00 00 41 20 00 00 00 00 00 .@@..A...A .....
| 2432: 00 00 00 07 6d 3f 80 00 00 40 00 00 00 41 10 00 ....m?...@...A..
| 2448: 00 41 20 00 00 00 00 00 00 00 00 07 6c 00 00 00 .A .........l...
| 2464: 00 3f 80 00 00 41 10 00 00 41 20 00 00 00 00 00 .?...A...A .....
| 2480: 00 00 00 07 0b 40 40 00 00 40 80 00 00 41 00 00 .....@@..@...A..
| 2496: 00 41 10 00 00 00 00 00 00 00 00 07 6f 40 40 00 .A..........o@@.
| 2512: 00 40 80 00 00 41 10 00 00 41 20 00 00 00 00 00 .@...A...A .....
| 2528: 00 00 00 03 ec 40 80 00 00 40 a0 00 00 00 00 00 .....@...@......
| 2544: 00 3f 80 00 00 00 00 00 00 00 00 04 50 40 80 00 .?..........P@..
| 2560: 00 40 a0 00 00 3f 80 00 00 40 00 00 00 00 00 00 .@...?...@......
| 2576: 00 00 00 04 b4 40 80 00 00 40 a0 00 00 40 00 00 .....@...@...@..
| 2592: 00 40 40 00 00 00 00 00 00 00 00 05 18 40 80 00 .@@..........@..
| 2608: 00 40 a0 00 00 40 40 00 00 40 80 00 00 00 00 00 .@...@@..@......
| 2624: 00 00 00 05 7c 40 80 00 00 40 a0 00 00 40 80 00 ....|@...@...@..
| 2640: 00 40 a0 00 00 00 00 00 00 00 00 05 e0 40 80 00 .@...........@..
| 2656: 00 40 a0 00 00 40 a0 00 00 40 c0 00 00 00 00 00 .@...@...@......
| 2672: 00 00 00 06 44 40 80 00 00 40 a0 00 00 40 c0 00 ....D@...@...@..
| 2688: 00 40 e0 00 00 00 00 00 00 00 00 06 a8 40 80 00 .@...........@..
| 2704: 00 40 a0 00 00 40 e0 00 00 41 00 00 00 00 00 00 .@...@...A......
| 2720: 00 00 00 07 0c 40 80 00 00 40 a0 00 00 41 00 00 .....@...@...A..
| 2736: 00 41 10 00 00 00 00 00 00 00 00 07 70 40 80 00 .A..........p@..
| 2752: 00 40 a0 00 00 41 10 00 00 41 20 00 00 00 00 00 .@...A...A .....
| 2768: 00 00 00 03 ed 40 a0 00 00 40 c0 00 00 00 00 00 .....@...@......
| 2784: 00 3f 80 00 00 00 00 00 00 00 00 04 51 40 a0 00 .?..........Q@..
| 2800: 00 40 c0 00 00 3f 80 00 00 40 00 00 00 00 00 00 .@...?...@......
| 2816: 00 00 00 04 b5 40 a0 00 00 40 c0 00 00 40 00 00 .....@...@...@..
| 2832: 00 40 40 00 00 00 00 00 00 00 00 05 19 40 a0 00 .@@..........@..
| 2848: 00 40 c0 00 00 40 40 00 00 40 80 00 00 89 50 01 .@...@@..@....P.
| 2864: 04 00 93 24 00 01 00 02 00 00 00 00 00 00 00 03 ...$............
| 2880: 00 00 00 00 40 80 00 00 00 00 00 00 3f 80 00 00 ....@.......?...
| 2896: 00 00 00 00 00 00 00 02 00 00 00 00 41 20 00 00 ............A ..
| 2912: 00 00 00 00 41 20 00 00 00 00 00 00 00 00 00 00 ....A ..........
| 4080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 05 03 ................
| page 4 offset 12288
| 0: 0d 00 00 00 00 10 00 00 00 00 00 00 00 00 00 00 ................
| page 5 offset 16384
| 0: 0d 00 00 00 03 01 87 00 0b 2d 06 5a 01 87 00 00 .........-.Z....
| 384: 00 00 00 00 00 00 00 89 50 03 04 00 93 24 00 00 ........P....$..
| 400: 00 11 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
| 688: 00 00 00 00 42 c8 00 00 42 4c 00 00 42 00 00 00 ....B...BL..B...
| 720: 03 eb 40 40 00 00 40 80 00 00 00 00 00 00 3f 80 ..@@..@.......?.
| 736: 00 00 00 00 00 00 00 00 03 ea 40 00 00 00 40 40 ..........@...@@
| 752: 00 00 00 00 00 00 3f 80 00 00 00 00 00 00 00 00 ......?.........
| 768: 03 e9 3f 80 00 00 40 00 00 00 00 00 00 00 3f 80 ..?...@.......?.
| 784: 00 00 00 00 00 00 00 00 03 e8 00 00 00 00 3f 80 ..............?.
| 800: 00 00 00 00 00 00 3f 80 00 00 00 00 00 00 00 00 ......?.........
| 1616: 00 00 00 00 00 00 00 00 00 00 89 50 02 04 00 93 ...........P....
| 1632: 24 00 00 00 2d 00 00 00 00 00 00 04 4c 00 00 00 $...-.......L...
| 1648: 00 3f 80 00 00 3f 80 00 00 40 00 00 00 00 00 00 .?...?...@......
| 1664: 00 00 00 04 b0 00 00 00 00 3f 80 00 00 40 00 00 .........?...@..
| 1680: 00 40 40 00 00 00 00 00 00 00 00 05 14 00 00 00 .@@.............
| 1696: 00 3f 80 00 00 40 40 00 00 40 80 00 00 00 00 00 .?...@@..@......
| 1712: 00 00 00 05 78 00 00 00 00 3f 80 00 00 40 80 00 ....x....?...@..
| 1728: 00 40 a0 00 00 00 00 00 00 00 00 05 dc 00 00 00 .@..............
| 1744: 00 3f 80 00 00 40 a0 00 00 40 c0 00 00 00 00 00 .?...@...@......
| 1760: 00 00 00 00 01 00 00 00 00 41 20 00 00 00 00 00 .........A .....
| 1776: 00 41 0e 00 00 00 00 00 00 00 00 04 4d 3f 80 00 .A..........M?..
| 1792: 00 40 00 00 00 3f 80 00 00 40 00 00 00 00 00 00 .@...?...@......
| 1808: 00 00 00 04 b1 3f 80 00 00 40 00 00 00 40 00 00 .....?...@...@..
| 1824: 00 40 40 00 00 00 00 00 00 00 00 05 15 3f 80 00 .@@..........?..
| 1840: 00 40 00 00 00 40 40 00 00 40 80 00 00 00 00 00 .@...@@..@......
| 1856: 00 00 00 05 79 3f 80 00 00 40 00 00 00 40 80 00 ....y?...@...@..
| 1872: 00 40 a0 00 00 00 00 00 00 00 00 05 dd 3f 80 00 .@...........?..
| 1888: 00 40 00 00 00 40 a0 00 00 40 c0 00 00 00 00 00 .@...@...@......
| 1904: 00 00 00 04 4e 40 00 00 00 40 40 00 00 3f 80 00 ....N@...@@..?..
| 1920: 00 40 00 00 00 00 00 00 00 00 00 04 b2 40 00 00 .@...........@..
| 1936: 00 40 40 00 00 40 00 00 00 40 40 00 00 00 00 00 .@@..@...@@.....
| 1952: 00 00 00 05 16 40 00 00 00 40 40 00 00 40 40 00 .....@...@@..@@.
| 1968: 00 40 80 00 00 00 00 00 00 00 00 05 7a 40 00 00 .@..........z@..
| 1984: 00 40 40 00 00 40 80 00 00 40 a0 00 00 00 00 00 .@@..@...@......
| 2000: 00 00 00 05 de 40 00 00 00 40 40 00 00 40 a0 00 .....@...@@..@..
| 2016: 00 40 c0 00 00 00 00 00 00 00 00 04 4f 40 40 00 .@..........O@@.
| 2032: 00 40 80 00 00 3f 80 00 00 40 00 00 00 00 00 00 .@...?...@......
| 2048: 00 00 00 04 b3 40 40 00 00 40 80 00 00 40 00 00 .....@@..@...@..
| 2064: 00 40 40 00 00 00 00 00 00 00 00 05 17 40 40 00 .@@..........@@.
| 2080: 00 40 80 00 00 40 40 00 00 40 80 00 00 00 00 00 .@...@@..@......
| 2096: 00 00 00 05 7b 40 40 00 00 40 80 00 00 40 80 00 .....@@..@...@..
| 2112: 00 40 a0 00 00 00 00 00 00 00 00 05 df 40 40 00 .@...........@@.
| 2128: 00 40 80 00 00 40 a0 00 00 40 c0 00 00 00 00 00 .@...@...@......
| 2144: 00 00 00 03 ec 40 80 00 00 40 a0 00 00 00 00 00 .....@...@......
| 2160: 00 3f 80 00 00 00 00 00 00 00 00 04 50 40 80 00 .?..........P@..
| 2176: 00 40 a0 00 00 3f 80 00 00 40 00 00 00 00 00 00 .@...?...@......
| 2192: 00 00 00 04 b4 40 80 00 00 40 a0 00 00 40 00 00 .....@...@...@..
| 2208: 00 40 40 00 00 00 00 00 00 00 00 05 18 40 80 00 .@@..........@..
| 2224: 00 40 a0 00 00 40 40 00 00 40 80 00 00 00 00 00 .@...@@..@......
| 2240: 00 00 00 05 7c 40 80 00 00 40 a0 00 00 40 80 00 ....|@...@...@..
| 2256: 00 40 a0 00 00 00 00 00 00 00 00 05 e0 40 80 00 .@...........@..
| 2272: 00 40 a0 00 00 40 a0 00 00 40 c0 00 00 00 00 00 .@...@...@......
| 2288: 00 00 00 03 f0 41 00 00 00 41 10 00 00 00 00 00 .....A...A......
| 2304: 00 3f 80 00 00 00 00 00 00 00 00 04 54 41 00 00 .?..........TA..
| 2320: 00 41 10 00 00 3f 80 00 00 40 00 00 00 00 00 00 .A...?...@......
| 2336: 00 00 00 04 b8 41 00 00 00 41 10 00 00 40 00 00 .....A...A...@..
| 2352: 00 40 40 00 00 00 00 00 00 00 00 05 1c 41 00 00 .@@..........A..
| 2368: 00 41 10 00 00 40 40 00 00 40 80 00 00 00 00 00 .A...@@..@......
| 2384: 00 00 00 05 80 41 00 00 00 41 10 00 00 40 80 00 .....A...A...@..
| 2400: 00 40 a0 00 00 00 00 00 00 00 00 05 e4 41 00 00 .@...........A..
| 2416: 00 41 10 00 00 40 a0 00 00 40 c0 00 00 00 00 00 .A...@...@......
| 2432: 00 00 00 06 48 41 00 00 00 41 10 00 00 40 c0 00 ....HA...A...@..
| 2448: 00 40 e0 00 00 00 00 00 00 00 00 06 ac 41 00 00 .@...........A..
| 2464: 00 41 10 00 00 40 e0 00 00 41 00 00 00 00 00 00 .A...@...A......
| 2480: 00 00 00 07 10 41 00 00 00 41 10 00 00 41 00 00 .....A...A...A..
| 2496: 00 41 10 00 00 00 00 00 00 00 00 03 f1 41 10 00 .A...........A..
| 2512: 00 41 20 00 00 00 00 00 00 3f 80 00 00 00 00 00 .A ......?......
| 2528: 00 00 00 04 55 41 10 00 00 41 20 00 00 3f 80 00 ....UA...A ..?..
| 2544: 00 40 00 00 00 00 00 00 00 00 00 04 b9 41 10 00 .@...........A..
| 2560: 00 41 20 00 00 40 00 00 00 40 40 00 00 00 00 00 .A ..@...@@.....
| 2576: 00 00 00 05 1d 41 10 00 00 41 20 00 00 40 40 00 .....A...A ..@@.
| 2592: 00 40 80 00 00 00 00 00 00 00 00 05 81 41 10 00 .@...........A..
| 2608: 00 41 20 00 00 40 80 00 00 40 a0 00 00 00 00 00 .A ..@...@......
| 2624: 00 00 00 05 e5 41 10 00 00 41 20 00 00 40 a0 00 .....A...A ..@..
| 2640: 00 40 c0 00 00 00 00 00 00 00 00 06 49 41 10 00 .@..........IA..
| 2656: 00 41 20 00 00 40 c0 00 00 40 e0 00 00 00 00 00 .A ..@...@......
| 2672: 00 00 00 06 ad 41 10 00 00 41 20 00 00 40 e0 00 .....A...A ..@..
| 2688: 00 41 00 00 00 00 00 00 00 00 00 07 11 41 10 00 .A...........A..
| 2704: 00 41 20 00 00 41 00 00 00 41 10 00 00 00 00 00 .A ..A...A......
| 2848: 00 00 00 00 00 00 00 00 00 00 00 00 00 89 50 01 ..............P.
| 2864: 04 00 93 24 00 01 00 04 00 00 00 00 00 00 00 03 ...$............
| 2880: 00 00 00 00 40 80 00 00 00 00 00 00 3f 80 00 00 ....@.......?...
| 2896: 00 00 00 00 00 00 00 02 00 00 00 00 41 20 00 00 ............A ..
| 2912: 00 00 00 00 41 10 00 00 00 00 00 00 00 00 00 04 ....A...........
| 2928: 00 00 00 00 41 20 00 00 40 c0 00 00 41 20 00 00 ....A ..@...A ..
| 2944: 00 00 00 00 00 00 00 05 40 a0 00 00 41 00 00 00 ........@...A...
| 2960: 00 00 00 00 41 20 00 00 00 00 00 00 00 00 00 00 ....A ..........
| page 6 offset 20480
| 0: 0d 00 00 00 02 06 5a 00 0b 2d 06 5a 00 00 00 00 ......Z..-.Z....
| 1616: 00 00 00 00 00 00 00 00 00 00 89 50 05 04 00 93 ...........P....
| 1632: 24 00 00 00 1c 00 00 00 00 00 00 03 ed 40 a0 00 $............@..
| 1648: 00 40 c0 00 00 00 00 00 00 3f 80 00 00 00 00 00 .@.......?......
| 1664: 00 00 00 04 51 40 a0 00 00 40 c0 00 00 3f 80 00 ....Q@...@...?..
| 1680: 00 40 00 00 00 00 00 00 00 00 00 04 b5 40 a0 00 .@...........@..
| 1696: 00 40 c0 00 00 40 00 00 00 40 40 00 00 00 00 00 .@...@...@@.....
| 1712: 00 00 00 05 19 40 a0 00 00 40 c0 00 00 40 40 00 .....@...@...@@.
| 1728: 00 40 80 00 00 00 00 00 00 00 00 05 7d 40 a0 00 .@...........@..
| 1744: 00 40 c0 00 00 40 80 00 00 40 a0 00 00 00 00 00 .@...@...@......
| 1760: 00 00 00 05 e1 40 a0 00 00 40 c0 00 00 40 a0 00 .....@...@...@..
| 1776: 00 40 c0 00 00 00 00 00 00 00 00 06 45 40 a0 00 .@..........E@..
| 1792: 00 40 c0 00 00 40 c0 00 00 40 e0 00 00 00 00 00 .@...@...@......
| 1808: 00 00 00 06 a9 40 a0 00 00 40 c0 00 00 40 e0 00 .....@...@...@..
| 1824: 00 41 00 00 00 00 00 00 00 00 00 07 0d 40 a0 00 .A...........@..
| 1840: 00 40 c0 00 00 41 00 00 00 41 10 00 00 00 00 00 .@...A...A......
| 1856: 00 00 00 03 ee 40 c0 00 00 40 e0 00 00 00 00 00 .....@...@......
| 1872: 00 3f 80 00 00 00 00 00 00 00 00 04 52 40 c0 00 .?..........R@..
| 1888: 00 40 e0 00 00 3f 80 00 00 40 00 00 00 00 00 00 .@...?...@......
| 1904: 00 00 00 04 b6 40 c0 00 00 40 e0 00 00 40 00 00 .....@...@...@..
| 1920: 00 40 40 00 00 00 00 00 00 00 00 05 1a 40 c0 00 .@@..........@..
| 1936: 00 40 e0 00 00 40 40 00 00 40 80 00 00 00 00 00 .@...@@..@......
| 1952: 00 00 00 05 7e 40 c0 00 00 40 e0 00 00 40 80 00 ....~@...@...@..
| 1968: 00 40 a0 00 00 00 00 00 00 00 00 05 e2 40 c0 00 .@...........@..
| 1984: 00 40 e0 00 00 40 a0 00 00 40 c0 00 00 00 00 00 .@...@...@......
| 2000: 00 00 00 06 46 40 c0 00 00 40 e0 00 00 40 c0 00 ....F@...@...@..
| 2016: 00 40 e0 00 00 00 00 00 00 00 00 06 aa 40 c0 00 .@...........@..
| 2032: 00 40 e0 00 00 40 e0 00 00 41 00 00 00 00 00 00 .@...@...A......
| 2048: 00 00 00 07 0e 40 c0 00 00 40 e0 00 00 41 00 00 .....@...@...A..
| 2064: 00 41 10 00 00 00 00 00 00 00 00 03 ef 40 e0 00 .A...........@..
| 2080: 00 41 00 00 00 00 00 00 00 3f 80 00 00 00 00 00 .A.......?......
| 2096: 00 00 00 04 53 40 e0 00 00 41 00 00 00 3f 80 00 ....S@...A...?..
| 2112: 00 40 00 00 00 00 00 00 00 00 00 04 b7 40 e0 00 .@...........@..
| 2128: 00 41 00 00 00 40 00 00 00 40 40 00 00 00 00 00 .A...@...@@.....
| 2144: 00 00 00 05 1b 40 e0 00 00 41 00 00 00 40 40 00 .....@...A...@@.
| 2160: 00 40 80 00 00 00 00 00 00 00 00 05 7f 40 e0 00 .@...........@..
| 2176: 00 41 00 00 00 40 80 00 00 40 a0 00 00 00 00 00 .A...@...@......
| 2192: 00 00 00 05 e3 40 e0 00 00 41 00 00 00 40 a0 00 .....@...A...@..
| 2208: 00 40 c0 00 00 00 00 00 00 00 00 06 47 40 e0 00 .@..........G@..
| 2224: 00 41 00 00 00 40 c0 00 00 40 e0 00 00 00 00 00 .A...@...@......
| 2240: 00 00 00 06 ab 40 e0 00 00 41 00 00 00 40 e0 00 .....@...A...@..
| 2256: 00 41 00 00 00 00 00 00 00 00 00 07 0f 40 e0 00 .A...........@..
| 2272: 00 41 00 00 00 41 00 00 00 41 10 00 00 00 00 00 .A...A...A......
| 2288: 00 00 00 07 73 40 e0 00 00 41 00 00 00 41 10 00 ....s@...A...A..
| 2304: 00 41 20 00 00 00 00 00 00 00 00 00 00 00 00 00 .A .............
| 2848: 00 00 00 00 00 00 00 00 00 00 00 00 00 89 50 04 ..............P.
| 2864: 04 00 93 24 00 00 00 18 00 00 00 00 00 00 06 43 ...$...........C
| 2880: 40 40 00 00 40 80 00 00 40 c0 00 00 40 e0 00 00 @@..@...@...@...
| 2896: 00 00 00 00 00 00 06 42 40 00 00 00 40 40 00 00 .......B@...@@..
| 2912: 40 c0 00 00 40 e0 00 00 00 00 00 00 00 00 06 41 @...@..........A
| 2928: 3f 80 00 00 40 00 00 00 40 c0 00 00 40 e0 00 00 ?...@...@...@...
| 2944: 00 00 00 00 00 00 06 40 00 00 00 00 3f 80 00 00 .......@....?...
| 2960: 40 c0 00 00 40 e0 00 00 00 00 00 00 00 00 06 44 @...@..........D
| 2976: 40 80 00 00 40 a0 00 00 40 c0 00 00 40 e0 00 00 @...@...@...@...
| 2992: 00 00 00 00 00 00 06 a7 40 40 00 00 40 80 00 00 ........@@..@...
| 3008: 40 e0 00 00 41 00 00 00 00 00 00 00 00 00 06 a6 @...A...........
| 3024: 40 00 00 00 40 40 00 00 40 e0 00 00 41 00 00 00 @...@@..@...A...
| 3040: 00 00 00 00 00 00 06 a5 3f 80 00 00 40 00 00 00 ........?...@...
| 3056: 40 e0 00 00 41 00 00 00 00 00 00 00 00 00 06 a4 @...A...........
| 3072: 00 00 00 00 3f 80 00 00 40 e0 00 00 41 00 00 00 ....?...@...A...
| 3088: 00 00 00 00 00 00 06 a8 40 80 00 00 40 a0 00 00 ........@...@...
| 3104: 40 e0 00 00 41 00 00 00 00 00 00 00 00 00 07 0a @...A...........
| 3120: 40 00 00 00 40 40 00 00 41 00 00 00 41 10 00 00 @...@@..A...A...
| 3136: 00 00 00 00 00 00 07 09 3f 80 00 00 40 00 00 00 ........?...@...
| 3152: 41 00 00 00 41 10 00 00 00 00 00 00 00 00 07 08 A...A...........
| 3168: 00 00 00 00 3f 80 00 00 41 00 00 00 41 10 00 00 ....?...A...A...
| 3184: 00 00 00 00 00 00 07 0b 40 40 00 00 40 80 00 00 ........@@..@...
| 3200: 41 00 00 00 41 10 00 00 00 00 00 00 00 00 07 0c A...A...........
| 3216: 40 80 00 00 40 a0 00 00 41 00 00 00 41 10 00 00 @...@...A...A...
| 3232: 00 00 00 00 00 00 07 6e 40 00 00 00 40 40 00 00 .......n@...@@..
| 3248: 41 10 00 00 41 20 00 00 00 00 00 00 00 00 07 6d A...A .........m
| 3264: 3f 80 00 00 40 00 00 00 41 10 00 00 41 20 00 00 ?...@...A...A ..
| 3280: 00 00 00 00 00 00 07 6c 00 00 00 00 3f 80 00 00 .......l....?...
| 3296: 41 10 00 00 41 20 00 00 00 00 00 00 00 00 07 6f A...A .........o
| 3312: 40 40 00 00 40 80 00 00 41 10 00 00 41 20 00 00 @@..@...A...A ..
| 3328: 00 00 00 00 00 00 07 70 40 80 00 00 40 a0 00 00 .......p@...@...
| 3344: 41 10 00 00 41 20 00 00 00 00 00 00 00 00 07 71 A...A .........q
| 3360: 40 a0 00 00 40 c0 00 00 41 10 00 00 41 20 00 00 @...@...A...A ..
| 3376: 00 00 00 00 00 00 07 72 40 c0 00 00 40 e0 00 00 .......r@...@...
| 3392: 41 10 00 00 41 20 00 00 00 00 00 00 00 00 07 74 A...A .........t
| 3408: 41 00 00 00 41 10 00 00 41 10 00 00 41 20 00 00 A...A...A...A ..
| 3424: 00 00 00 00 00 00 07 75 41 10 00 00 41 20 00 00 .......uA...A ..
| 3440: 41 10 00 00 41 20 00 00 00 00 00 00 00 00 00 00 A...A ..........
| end c1b.db
}]
catchsql {
SELECT rtreecheck('t1');
}
} {1 {SQL logic error}}
do_test rtreefuzz001-200 {
sqlite3 db {}
db deserialize [decode_hexdb {
| size 16384 pagesize 4096 filename c3.db
| page 1 offset 0
| 0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00 SQLite format 3.
| 16: 10 00 01 01 00 40 20 20 00 00 00 00 00 00 00 04 .....@ ........
| 32: 00 00 00 00 01 00 00 00 00 00 00 04 00 00 00 04 ................
| 48: 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 ................
| 96: 00 00 00 00 0d 00 00 00 04 0e 9c 00 0f ad 0f 4f ...............O
| 112: 0e fc 0e 9c 00 00 00 00 00 00 00 00 00 00 00 00 ................
| 3728: 00 00 00 00 00 00 00 00 00 00 00 00 5e 04 07 17 ............^...
| 3744: 1f 1f 01 81 0b 74 61 62 6c 65 74 31 5f 70 61 72 .....tablet1_par
| 3760: 65 6e 74 74 31 5f 70 61 72 65 6e 74 04 43 52 45 entt1_parent.CRE
| 3776: 41 54 45 20 54 41 42 4c 45 20 22 74 31 5f 70 61 ATE TABLE .t1_pa
| 3792: 72 65 6e 74 22 28 6e 6f 64 65 6e 6f 20 49 4e 54 rent.(nodeno INT
| 3808: 45 47 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59 EGER PRIMARY KEY
| 3824: 2c 70 61 72 65 6e 74 6e 6f 64 65 29 51 03 06 17 ,parentnode)Q...
| 3840: 1b 1b 01 7b 74 61 62 6c 65 74 31 5f 6e 6f 64 65 ....tablet1_node
| 3856: 74 31 5f 6e 6f 64 65 03 43 52 45 41 54 45 20 54 t1_node.CREATE T
| 3872: 41 42 4c 45 20 22 74 31 5f 6e 6f 64 65 22 28 6e ABLE .t1_node.(n
| 3888: 6f 64 65 6e 6f 20 49 4e 54 45 47 45 52 20 50 52 odeno INTEGER PR
| 3904: 49 4d 41 52 59 20 4b 45 59 2c 64 61 74 61 29 5c IMARY KEY,data).
| 3920: 02 07 17 1d 1d 01 81 0b 74 61 62 6c 65 74 31 5f ........tablet1_
| 3936: 72 6f 77 69 64 74 31 5f 72 6f 77 69 64 02 43 52 rowidt1_rowid.CR
| 3952: 45 41 54 45 20 54 41 42 4c 45 20 22 74 31 5f 72 EATE TABLE .t1_r
| 3968: 6f 77 69 64 22 28 72 6f 77 69 64 20 49 4e 54 45 owid.(rowid INTE
| 3984: 47 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59 2c GER PRIMARY KEY,
| 4000: 6e 6f 64 65 6e 6f 2c 61 30 2c 61 31 29 51 01 07 nodeno,a0,a1)Q..
| 4016: 17 11 11 08 81 0f 74 61 62 6c 65 74 31 74 31 43 ......tablet1t1C
| 4032: 52 45 41 54 45 20 56 49 52 54 55 41 4c 20 54 41 REATE VIRTUAL TA
| 4048: 42 4c 45 20 74 31 20 55 53 49 4e 47 20 72 74 72 BLE t1 USING rtr
| 4064: 65 65 28 69 64 2c 78 30 2c 78 31 2c 79 30 2c 79 ee(id,x0,x1,y0,y
| 4080: 31 2c 2b 6c 61 62 65 6c 2c 2b 6f 74 68 65 72 29 1,+label,+other)
| page 2 offset 4096
| 0: 0d 00 00 00 0e 0e f7 00 0f e8 0f d0 0f b7 0f 9e ................
| 16: 0f 91 0f 81 0f 70 0f 5e 0f 4f 0f 39 0f 29 0f 18 .....p.^.O.9.)..
| 32: 0f 06 0e f7 00 00 00 00 00 00 00 00 00 00 00 00 ................
| 3824: 00 00 00 00 00 00 00 0d 0e 05 00 09 1d 00 74 6f ..............to
| 3840: 70 20 68 61 6c 66 10 0d 05 00 09 23 00 62 6f 74 p half.....#.bot
| 3856: 74 6f 6d 20 68 61 6c 66 0f 0c 05 00 09 21 00 72 tom half.....!.r
| 3872: 69 67 68 74 20 68 61 6c 66 0e 0b 05 00 09 1f 00 ight half.......
| 3888: 6c 65 66 74 20 68 61 6c 66 14 0a 05 00 09 2b 00 left half.....+.
| 3904: 74 68 65 20 77 68 6f 6c 65 20 74 68 69 6e 67 0d the whole thing.
| 3920: 09 05 00 09 1d 00 74 6f 70 20 65 64 67 65 10 08 ......top edge..
| 3936: 05 00 09 23 00 62 6f 74 74 6f 6d 20 65 64 67 65 ...#.bottom edge
| 3952: 0f 07 05 00 09 21 00 72 69 67 68 74 20 65 64 67 .....!.right edg
| 3968: 65 0e 06 05 00 09 1f 00 6c 65 66 74 20 65 64 67 e.......left edg
| 3984: 65 0b 05 05 00 09 19 00 63 65 6e 74 65 72 17 04 e.......center..
| 4000: 05 00 09 31 00 75 70 70 65 72 2d 72 69 67 68 74 ...1.upper-right
| 4016: 20 63 6f 72 6e 65 72 17 03 05 00 09 31 00 6c 6f corner.....1.lo
| 4032: 77 65 72 2d 72 69 67 68 74 27 60 f6 32 6e 65 72 wer-right'`.2ner
| 4048: 16 02 05 00 09 2f 00 75 70 70 65 72 2d 6c 65 66 ...../.upper-lef
| 4064: 74 20 63 6f 72 6e 65 72 16 01 05 00 09 2f 00 6c t corner...../.l
| 4080: 6f 77 65 72 2d 6c 65 66 74 20 63 6f 72 6e 65 72 ower-left corner
| page 3 offset 8192
| 0: 0d 00 00 00 02 0b 2d 00 0b 2d 00 00 00 00 00 00 ......-..-......
| 2848: 00 00 00 00 00 00 00 00 00 00 00 00 00 89 50 01 ..............P.
| 2864: 04 00 93 24 00 00 00 0e 00 00 00 00 00 00 00 01 ...$............
| 2880: 00 00 00 00 41 20 00 00 00 00 00 00 41 20 01 00 ....A ......A ..
| 2896: 00 00 00 00 00 00 00 02 00 00 00 00 41 00 00 04 ............A...
| 2912: 2b 40 00 0c 42 c8 00 00 00 00 00 00 00 00 00 03 +@..B...........
| 2928: 42 b4 00 00 42 c8 00 00 00 00 00 00 41 20 00 00 B...B.......A ..
| 2944: 00 00 00 00 00 00 00 04 42 b4 00 00 42 c8 00 00 ........B...B...
| 2960: 42 b4 00 00 42 c8 00 00 00 00 00 00 00 00 00 05 B...B...........
| 2976: 42 20 00 00 42 70 00 00 42 20 00 00 42 70 00 00 B ..Bp..B ..Bp..
| 2992: 00 00 00 00 00 00 00 60 00 00 00 04 0a 00 00 00 .......`........
| 3008: 00 00 00 42 c8 00 00 00 00 00 00 00 00 00 07 42 ...B...........B
| 3024: be 00 00 42 c8 00 00 00 00 00 00 42 c8 00 00 00 ...B.......B....
| 3040: 00 00 00 00 00 00 08 00 00 00 00 42 c8 00 00 00 ...........B....
| 3056: 00 00 00 40 a0 00 00 00 00 00 00 00 00 00 09 00 ...@............
| 3072: 00 00 00 42 c8 00 00 42 be 00 00 42 c8 00 00 00 ...B...B...B....
| 3088: 00 00 00 00 00 00 0a 00 00 00 00 42 c8 00 00 00 ...........B....
| 3104: 00 00 00 42 c8 00 00 00 00 00 00 00 00 00 0b 00 ...B............
| 3120: 00 00 00 42 48 00 00 00 00 00 04 2c 80 00 00 00 ...BH......,....
| 3136: 00 00 00 00 00 00 c4 24 c0 00 04 2c 80 00 00 00 .......$...,....
| 3152: 00 00 04 2c 80 00 00 00 00 00 00 00 00 00 d0 00 ...,............
| 3168: 00 00 04 2c 80 00 00 00 00 00 04 24 80 00 00 00 ...,.......$....
| 3184: 00 00 00 00 00 00 e0 00 00 00 04 2c 80 00 04 24 ...........,...$
| 3200: c0 00 04 2c 00 00 00 00 00 00 00 00 00 00 00 00 ...,............
| page 4 offset 12288
| 0: 0d 00 00 00 00 10 00 00 00 00 00 00 00 00 00 00 ................
| end c3.db
}]
catchsql {
WITH RECURSIVE
c1(x) AS (VALUES(0) UNION ALL SELECT x+1 FROM c1 WHERE x<99),
c2(y) AS (VALUES(0) UNION ALL SELECT y+1 FROM c2 WHERE y<99)
INSERT INTO t1(id, x0,x1,y0,y1,label)
SELECT 1000+x+y*100, x, x+1, y, y+1, printf('box-%d,%d',x,y) FROM c1, c2;
}
} {1 {database disk image is malformed}}
do_test rtreefuzz001-210 {
catchsql {
SELECT rtreecheck('t1');
}
} {/1 .*corrupt.*/}
do_test rtreefuzz001-300 {
sqlite3 db {}
db deserialize [decode_hexdb {
| size 16384 pagesize 4096 filename c4.db
| page 1 offset 0
| 0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00 SQLite format 3.
| 16: 10 00 01 01 00 40 20 20 00 00 00 00 00 00 00 04 .....@ ........
| 32: 00 00 00 00 00 00 00 00 00 00 00 04 00 00 00 04 ................
| 96: 00 00 00 00 0d 00 00 00 04 0e 9c 00 0f ad 0f 4f ...............O
| 112: 0e fc 0e 9c 00 00 00 00 00 00 00 00 00 00 00 00 ................
| 3728: 00 00 00 00 00 00 00 00 00 00 00 00 5e 04 07 17 ............^...
| 3744: 1f 1f 01 81 0b 74 61 62 6c 65 74 31 5f 70 61 72 .....tablet1_par
| 3760: 65 6e 74 74 31 5f 70 61 72 65 6e 74 04 43 52 45 entt1_parent.CRE
| 3776: 41 54 45 20 54 41 42 4c 45 20 22 74 31 5f 70 61 ATE TABLE .t1_pa
| 3792: 72 65 6e 74 22 28 6e 6f 64 65 6e 6f 20 49 4e 54 rent.(nodeno INT
| 3808: 45 47 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59 EGER PRIMARY KEY
| 3824: 2c 70 61 72 65 6e 74 6e 6f 64 65 29 51 03 06 17 ,parentnode)Q...
| 3840: 1b 1b 01 7b 74 61 62 6c 65 74 31 5f 6e 6f 64 65 ....tablet1_node
| 3856: 74 31 5f 6e 6f 64 65 03 43 52 45 41 54 45 20 54 t1_node.CREATE T
| 3872: 41 42 4c 45 20 22 74 31 5f 6e 6f 64 65 22 28 6e ABLE .t1_node.(n
| 3888: 6f 64 65 6e 6f 20 49 4e 54 45 47 45 52 20 50 52 odeno INTEGER PR
| 3904: 49 4d 41 52 59 20 4b 45 59 2c 64 61 74 61 29 5c IMARY KEY,data).
| 3920: 02 07 17 1d 1d 01 81 0b 74 61 62 6c 65 74 31 5f ........tablet1_
| 3936: 72 6f 77 69 64 74 31 5f 72 6f 77 69 64 02 43 52 rowidt1_rowid.CR
| 3952: 45 41 54 45 20 54 41 42 4c 45 20 22 74 31 5f 72 EATE TABLE .t1_r
| 3968: 6f 77 69 64 22 28 72 6f 77 69 64 20 49 4e 54 45 owid.(rowid INTE
| 3984: 47 45 72 20 50 52 49 4d 41 52 59 20 4b 45 59 2c GEr PRIMARY KEY,
| 4000: 6e 6f 64 65 6e 6f 2c 61 30 2c 61 31 29 51 01 07 nodeno,a0,a1)Q..
| 4016: 17 11 11 08 81 0f 74 61 62 6c 65 74 31 74 31 43 ......tablet1t1C
| 4032: 52 45 41 54 45 20 56 49 52 54 55 41 4c 20 54 41 REATE VIRTUAL TA
| 4048: 42 4c 45 20 74 31 20 55 53 49 4e 47 20 72 74 72 BLE t1 USING rtr
| 4064: 65 65 28 69 64 2c 78 30 2c 78 31 2c 79 30 2c 79 ee(id,x0,x1,y0,y
| 4080: 31 2c 2b 6c 61 62 65 6c 2c 2b 6f 74 68 65 72 29 1,+label,+other)
| page 2 offset 4096
| 0: 0d 00 00 00 0e 0e f7 00 0f e8 0f 00 fb 70 f9 e0 .............p..
| 16: f9 10 f8 10 f7 00 f5 e0 f4 f0 f3 90 f2 90 f1 80 ................
| 32: f0 60 ef 00 00 00 00 00 00 00 00 00 00 00 00 00 .`..............
| 3824: 00 00 00 00 00 00 00 0d 0e 05 00 09 1d 00 74 6f ..............to
| 3840: 70 20 68 61 6c 66 10 0d 05 00 09 23 00 62 6f 74 p half.....#.bot
| 3856: 74 6f 6d 20 68 61 6c 66 0f 0c 05 00 09 21 00 72 tom half.....!.r
| 3872: 69 67 68 74 20 68 61 6c 66 0e 0b 05 00 09 1f 00 ight half.......
| 3888: 6c 65 66 74 20 68 61 6c 66 14 0a 05 00 09 2b 00 left half.....+.
| 3904: 00 03 98 20 49 98 2f 6c 62 05 74 68 69 6e 67 0d ... I./lb.thing.
| 3920: 09 05 00 09 1d 00 74 6f 70 20 65 64 67 65 10 08 ......top edge..
| 3936: 05 00 09 23 00 62 6f 74 74 6f 6d 20 65 64 67 65 ...#.bottom edge
| 3952: 0f 07 05 00 09 21 00 72 69 67 68 74 20 65 64 67 .....!.right edg
| 3968: 65 0e 06 05 00 09 1f 00 6c 65 66 74 20 65 64 67 e.......left edg
| 3984: 65 0b 05 05 00 09 19 00 63 65 6e 74 65 72 17 04 e.......center..
| 4000: 05 00 09 31 00 75 70 70 65 72 2d 72 69 67 68 74 ...1.upper-right
| 4016: 20 63 6f 72 6e 65 72 17 03 05 00 09 31 00 6c 6f corner.....1.lo
| 4032: 77 65 72 2d 72 69 67 68 74 20 63 6f 72 6e 65 72 wer-right corner
| 4048: 16 02 05 00 09 2f 00 75 70 70 65 72 2d 6c 65 66 ...../.upper-lef
| 4064: 74 20 63 6f 72 6e 65 72 16 01 05 00 09 2f 00 6c t corner...../.l
| 4080: 6f 77 65 72 2d 6c 65 66 74 20 63 6f 72 6e 65 72 ower-left corner
| page 3 offset 8192
| 0: 0d 00 00 00 01 0b 2d 00 0b 2d 00 00 00 00 00 00 ......-..-......
| 2848: 00 00 00 00 00 00 00 00 00 00 00 00 00 89 50 01 ..............P.
| 2864: 04 00 93 24 00 00 00 0e 00 00 00 00 00 00 00 01 ...$............
| 2880: 00 00 00 04 01 20 00 00 00 00 00 04 12 00 00 00 ..... ..........
| 2896: 00 00 00 00 00 00 00 23 00 00 00 00 41 20 00 00 .......#....A ..
| 2912: 42 b4 00 00 42 c8 00 00 00 00 00 00 00 00 00 03 B...B...........
| 2928: 42 b4 00 00 42 c8 00 00 00 00 00 00 41 20 00 00 B...B.......A ..
| 2944: 00 00 00 00 00 00 00 04 42 b4 00 00 42 c8 00 00 ........B...B...
| 2960: 42 b4 00 00 42 c8 00 00 00 00 00 00 00 00 00 05 B...B...........
| 2976: 42 20 00 00 42 70 00 00 42 20 00 00 42 70 00 00 B ..Bp..B ..Bp..
| 2992: 00 00 00 00 00 00 00 06 00 00 00 00 40 a0 00 00 ............@...
| 3008: 00 00 00 04 2c 80 00 00 00 00 00 00 00 00 00 74 ....,..........t
| 3024: 2b e0 00 04 2c 80 00 04 2c 80 00 00 00 00 00 00 +...,...,.......
| 3040: 00 00 00 80 00 00 00 04 2c 80 00 00 00 00 00 04 ........,.......
| 3056: 0a 00 00 00 00 00 b0 80 00 00 04 2c 80 00 04 2b ...........,...+
| 3072: e0 00 04 2c 80 00 00 00 00 00 00 00 00 00 a0 00 ...,............
| 3088: 00 00 04 2c 80 00 00 00 00 00 04 2c 80 00 00 00 ...,.......,....
| 3104: 00 00 00 00 00 00 b0 00 00 00 04 24 80 00 00 00 ...........$....
| 3120: 00 00 04 2c 80 00 00 00 00 00 00 00 50 00 91 f0 ...,........P...
| 3136: 06 c6 56 67 42 06 86 16 c6 61 40 a0 50 00 92 b0 ..VgB....a@.P...
| 3152: 07 46 86 52 07 76 86 f6 c6 52 07 46 86 96 e6 70 .F.R.v...R.F...p
| 3168: d0 90 50 00 91 d0 07 46 f7 02 06 56 46 76 51 00 ..P....F...VFvQ.
| 3184: 80 50 00 92 30 06 26 f7 47 46 f6 d2 06 56 46 76 .P..0.&.GF...VFv
| 3200: 50 f0 70 50 00 92 10 07 26 96 76 87 42 06 56 46 P.pP....&.v.B.VF
| 3216: 76 50 e0 60 50 00 91 f0 06 c6 56 67 42 06 56 46 vP.`P.....VgB.VF
| 3232: 76 50 b0 50 50 00 91 90 06 36 56 e7 46 57 21 70 vP.PP....6V.FW!p
| 3248: 40 50 00 93 10 07 57 07 06 57 22 d7 26 96 76 87 @P....W..W..&.v.
| 3264: 42 06 36 f7 26 e6 57 21 70 30 50 00 93 10 06 c6 B.6.&.W!p0P.....
| 3280: f7 76 57 22 d7 26 96 76 87 42 06 36 f7 26 e6 57 .vW..&.v.B.6.&.W
| 3296: 21 60 20 50 00 92 f0 07 57 07 06 57 22 d6 c6 56 !` P....W..W...V
| 3312: 60 00 00 c4 24 c0 00 04 2c 80 00 00 00 00 00 04 `...$...,.......
| 3328: 2c 80 00 00 00 00 00 00 00 00 00 d0 00 00 00 04 ,...............
| 3344: 2c 80 00 00 00 00 00 04 24 80 00 00 00 00 00 00 ,.......$.......
| 3360: 00 00 00 e0 00 00 00 04 2c 80 00 04 24 c0 00 04 ........,...$...
| 3376: 2c 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ,...............
| page 4 offset 12288
| 0: 0d 00 00 00 00 10 00 00 00 00 00 00 00 00 00 00 ................
| end c4.db
}]
catchsql {
UPDATE t1 SET label='x';
}
} {1 {rtree constraint failed: t1.(y0<=y1)}}
do_test rtreefuzz001-310 {
catchsql {
SELECT rtreecheck('t1');
}
} {/1 .*corrupt.*/}
do_test rtreefuzz001-400 {
sqlite3 db {}
db deserialize [decode_hexdb {
| size 16384 pagesize 4096 filename c7.db
| page 1 offset 0
| 0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00 SQLite format 3.
| 16: 10 00 01 01 00 40 20 20 00 00 00 00 00 00 00 04 .....@ ........
| 32: 00 00 00 00 01 00 00 00 00 00 00 04 00 00 00 04 ................
| 48: 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 ................
| 96: 00 00 00 00 0d 00 00 00 04 0e 9c 00 0f ad 0f 4f ...............O
| 112: 0e fc 0e 9c 00 00 00 00 00 00 00 00 00 00 00 00 ................
| 3728: 00 00 00 00 00 00 00 00 00 00 00 00 5e 04 07 17 ............^...
| 3744: 1f 1f 01 81 0b 74 61 62 6c 65 74 31 5f 70 61 72 .....tablet1_par
| 3760: 65 6e 74 74 31 5f 70 61 72 65 6e 74 04 43 52 45 entt1_parent.CRE
| 3776: 41 54 45 20 54 41 42 4c 45 20 22 74 31 5f 70 61 ATE TABLE .t1_pa
| 3792: 72 65 6e 74 22 28 6e 6f 64 65 6e 6f 20 49 4e 54 rent.(nodeno INT
| 3808: 45 47 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59 EGER PRIMARY KEY
| 3824: 2c 70 61 72 65 6e 74 6e 6f 64 65 29 51 03 06 17 ,parentnode)Q...
| 3840: 1b 1b 01 7b 74 61 62 6c 65 74 31 5f 6e 6f 64 65 ....tablet1_node
| 3856: 74 31 5f 6e 6f 64 65 03 43 52 45 41 54 45 20 54 t1_node.CREATE T
| 3872: 41 42 4c 45 20 22 74 31 5f 6e 6f 64 65 22 28 6e ABLE .t1_node.(n
| 3888: 6f 64 65 6e 6f 20 49 4e 54 45 47 45 52 20 50 52 odeno INTEGER PR
| 3904: 49 4d 41 52 59 20 4b 45 59 2c 64 61 74 61 29 5c IMARY KEY,data).
| 3920: 02 07 17 1d 1d 01 81 0b 74 61 62 6c 65 74 31 5f ........tablet1_
| 3936: 72 6f 77 69 64 74 31 5f 72 6f 77 69 64 02 43 52 rowidt1_rowid.CR
| 3952: 45 41 54 45 20 54 41 42 4c 45 20 22 74 31 5f 72 EATE TABLE .t1_r
| 3968: 6f 77 69 64 22 28 72 6f 77 69 64 20 49 4e 54 45 owid.(rowid INTE
| 3984: 47 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59 2c GER PRIMARY KEY,
| 4000: 6e 6f 64 65 6e 6f 2c 61 30 2c 61 31 29 51 01 07 nodeno,a0,a1)Q..
| 4016: 17 11 11 08 81 0f 74 61 62 6c 65 74 31 74 31 43 ......tablet1t1C
| 4032: 52 45 41 54 45 20 56 49 52 54 55 41 4c 20 54 41 REATE VIRTUAL TA
| 4048: 42 4c 45 20 74 31 20 55 53 49 4e 47 20 72 74 72 BLE t1 USING rtr
| 4064: 65 65 28 69 64 2c 78 30 2c 78 31 2c 79 30 2c 79 ee(id,x0,x1,y0,y
| 4080: 31 2c 2b 6c 61 62 65 6c 2c 2b 6f 74 68 65 72 29 1,+label,+other)
| page 2 offset 4096
| 0: 0d 00 00 00 0e 0e f7 00 0f e8 0f d0 0f b7 0f 9e ................
| 16: 0f 91 0f 81 0f 70 0f 5e 0f 4f 0f 39 0f 29 0f 18 .....p.^.O.9.)..
| 32: 0f 06 0e f7 00 00 00 00 00 00 00 00 00 00 00 00 ................
| 3824: 00 00 00 00 00 00 00 0d 0e 05 00 09 1d 00 74 6f ..............to
| 3840: 70 20 68 61 6c 66 10 0d 05 00 09 23 00 62 6f 74 p half.....#.bot
| 3856: 74 6f 6d 20 68 61 6c 66 0f 0c 05 00 09 21 00 72 tom half.....!.r
| 3872: 69 67 68 74 20 68 61 6c 66 0e 0b 05 00 09 1f 00 ight half.......
| 3888: 6c 65 66 74 20 68 61 6c 66 14 0a 05 00 09 2b 00 left half.....+.
| 3904: 74 68 65 20 77 68 6f 6c 65 20 74 68 69 6e 67 0d the whole thing.
| 3920: 09 05 00 09 1d 00 74 6f 70 20 65 64 67 65 10 08 ......top edge..
| 3936: 05 00 09 23 00 62 6f 74 74 6f 6d 20 65 64 67 65 ...#.bottom edge
| 3952: 0f 07 05 00 09 21 00 72 69 67 68 74 20 65 64 67 .....!.right edg
| 3968: 65 0e 06 05 00 09 1f 00 6c 65 66 74 20 65 64 67 e.......left edg
| 3984: 65 0b 05 05 00 09 19 00 23 65 6e 74 65 72 17 04 e.......#enter..
| 4000: 05 00 09 31 00 75 70 70 65 72 2d 72 69 67 68 74 ...1.upper-right
| 4016: 20 63 6f 72 6e 65 72 17 03 05 00 09 31 00 6c 6f corner.....1.lo
| 4032: 77 65 72 2d 72 69 67 68 74 20 63 6f 72 6e 65 72 wer-right corner
| 4048: 16 02 05 00 09 2f 00 75 70 70 65 72 2d 6c 65 66 ...../.upper-lef
| 4064: 74 20 63 6f 72 6e 65 72 16 01 05 00 09 2f 00 6c t corner...../.l
| 4080: 6f 77 65 72 2d 6c 65 66 74 20 63 6f 72 6e 65 72 ower-left corner
| page 3 offset 8192
| 0: 0d 00 00 00 02 0b 2d 00 0b 2d 00 00 00 00 00 00 ......-..-......
| 2848: 00 00 00 00 00 00 00 00 00 00 00 00 00 89 50 01 ..............P.
| 2864: 04 00 93 24 00 00 00 00 00 00 00 00 08 00 00 00 ...$............
| 2880: 00 42 c8 00 00 00 00 00 00 40 a0 00 00 00 00 00 .B.......@......
| 2896: 00 00 00 00 42 c8 00 00 00 00 00 00 00 00 00 07 ....B...........
| 2912: 42 be 00 00 42 c8 00 00 00 00 00 00 42 c8 00 00 B...B.......B...
| 2928: 00 00 00 00 00 00 00 08 00 00 00 00 42 c8 00 00 ............B...
| 2944: 00 00 00 00 40 a0 00 00 00 00 00 00 00 00 00 09 ....@...........
| 2960: 00 00 00 00 42 c8 00 00 42 be 00 00 42 c8 00 00 ....B...B...B...
| 2976: 00 00 00 00 00 00 00 0a 00 00 00 00 42 c8 00 00 ............B...
| 2992: 00 00 00 00 42 c8 00 00 00 00 00 00 00 00 00 0b ....B...........
| 3008: 00 00 00 00 42 48 00 00 00 00 00 04 2c 80 00 00 ....BH......,...
| 3024: 00 00 00 00 00 00 00 c4 00 00 00 00 00 42 c8 00 .............B..
| 3040: 00 00 00 00 00 00 00 00 07 42 be 00 00 42 c8 00 .........B...B..
| 3056: 00 00 00 00 00 42 c8 00 00 00 00 00 00 00 00 00 .....B..........
| 3072: 08 00 00 00 00 42 c8 00 00 00 00 00 00 40 a0 00 .....B.......@..
| 3088: 00 00 00 00 00 00 00 00 09 00 00 00 00 42 c8 00 .............B..
| 3104: 00 42 be 00 00 42 c8 00 00 00 00 00 00 00 00 00 .B...B..........
| 3120: 0a 00 00 00 00 42 c8 00 00 00 00 00 00 42 c8 00 .....B.......B..
| 3136: 00 00 00 00 00 00 00 00 0b 00 00 00 00 42 48 00 .............BH.
| 3152: 00 00 00 00 04 2c 80 00 00 00 00 00 00 00 00 00 .....,..........
| 3168: c4 24 c0 00 04 2c 80 00 00 00 00 00 04 2c 80 00 .$...,.......,..
| 3184: 00 00 00 00 00 00 00 00 d0 00 00 00 04 2c 80 00 .............,..
| 3200: 00 00 00 00 04 24 80 00 00 00 00 00 00 00 00 00 .....$..........
| 3216: e0 00 00 00 04 2c 80 00 04 24 c0 00 04 2c 00 00 .....,...$...,..
| page 4 offset 12288
| 0: 0d 00 00 00 00 10 00 00 00 00 00 00 0e 00 00 00 ................
| 16: 00 42 c8 00 00 42 4c 00 00 42 c8 00 00 00 00 00 .B...BL..B......
| 32: 00 00 00 0a 00 00 00 00 42 c8 00 00 00 00 00 00 ........B.......
| 48: 42 c8 00 00 00 00 00 00 00 00 00 0b 00 00 00 00 B...............
| 64: 42 48 00 00 00 00 00 04 2c 80 00 00 00 00 00 00 BH......,.......
| 80: 00 00 00 c4 24 c0 00 04 2c 80 00 00 00 00 00 04 ....$...,.......
| 96: 2c 80 00 00 00 00 00 00 00 00 00 d0 00 00 00 04 ,...............
| 112: 2c 80 00 00 00 00 00 04 24 80 00 00 00 00 00 00 ,.......$.......
| 128: 00 00 00 e0 00 00 00 04 2c 80 00 04 24 c0 00 04 ........,...$...
| 144: 2c 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ,...............
| end c7.db
}]
catchsql {
WITH RECURSIVE
c1(x) AS (VALUES(0) UNION ALL SELECT x+1 FROM c1 WHERE x<8),
c2(y) AS (VALUES(0) UNION ALL SELECT y+1 FROM c2 WHERE y<5)
INSERT INTO t1(id, x0,x1,y0,y1,label)
SELECT 1000+x+y*100, x, x+1, y, y+1, printf('box-%d,%d',x,y) FROM c1, c2;
}
} {1 {database disk image is malformed}}
finish_test
+3 -3
View File
@@ -42,7 +42,7 @@ static void usage(const char *argv0){
*/
static void readFile(const char *zFilename, int *pSz, void **ppBuf){
FILE *f;
int sz;
sqlite3_int64 sz;
void *pBuf;
f = fopen(zFilename, "rb");
if( f==0 ){
@@ -50,9 +50,9 @@ static void readFile(const char *zFilename, int *pSz, void **ppBuf){
exit(1);
}
fseek(f, 0, SEEK_END);
sz = (int)ftell(f);
sz = ftell(f);
rewind(f);
pBuf = sqlite3_malloc( sz ? sz : 1 );
pBuf = sqlite3_malloc64( sz ? sz : 1 );
if( pBuf==0 ){
fprintf(stderr, "cannot allocate %d to hold content of \"%s\"\n",
sz, zFilename);
+7 -8
View File
@@ -141,7 +141,7 @@ static void usage(const char *argv0){
*/
static void fuzzReadFile(const char *zFilename, int *pSz, void **ppBuf){
FILE *f;
int sz;
sqlite3_int64 sz;
void *pBuf;
f = fopen(zFilename, "rb");
if( f==0 ){
@@ -149,9 +149,9 @@ static void fuzzReadFile(const char *zFilename, int *pSz, void **ppBuf){
exit(1);
}
fseek(f, 0, SEEK_END);
sz = (int)ftell(f);
sz = ftell(f);
rewind(f);
pBuf = sqlite3_malloc( sz ? sz : 1 );
pBuf = sqlite3_malloc64( sz ? sz : 1 );
if( pBuf==0 ){
fprintf(stderr, "cannot allocate %d to hold content of \"%s\"\n",
sz, zFilename);
@@ -340,8 +340,8 @@ struct FuzzChange {
/*
** Allocate and return nByte bytes of zeroed memory.
*/
static void *fuzzMalloc(int nByte){
void *pRet = sqlite3_malloc(nByte);
static void *fuzzMalloc(sqlite3_int64 nByte){
void *pRet = sqlite3_malloc64(nByte);
if( pRet ){
memset(pRet, 0, nByte);
}
@@ -631,7 +631,7 @@ static int fuzzParseChangeset(
/* If the table-header was successfully parsed, add the new change-group
** to the array and parse the associated changes. */
if( rc==SQLITE_OK ){
FuzzChangesetGroup **apNew = (FuzzChangesetGroup**)sqlite3_realloc(
FuzzChangesetGroup **apNew = (FuzzChangesetGroup**)sqlite3_realloc64(
pParse->apGroup, sizeof(FuzzChangesetGroup*)*(pParse->nGroup+1)
);
if( apNew==0 ){
@@ -1214,7 +1214,7 @@ int main(int argc, char **argv){
fuzzPrintGroup(&changeset, changeset.apGroup[i]);
}
}else{
pBuf = (u8*)fuzzMalloc(nChangeset*2 + 1024);
pBuf = (u8*)fuzzMalloc((sqlite3_int64)nChangeset*2 + 1024);
if( pBuf==0 ){
rc = SQLITE_NOMEM;
}else{
@@ -1237,4 +1237,3 @@ int main(int argc, char **argv){
return rc;
}
+1 -2
View File
@@ -258,8 +258,7 @@ do_patchconcat_test 4.3.3 {
INSERT INTO t2 VALUES('a', 'a', 'a', 'a');
} {
DELETE FROM t2 WHERE c = 'a';
} {
}
} {}
# INSERT + UPDATE
do_patchconcat_test 4.3.4 {
-2
View File
@@ -356,5 +356,3 @@ int main(int argc, char **argv){
return 0;
}
+60 -16
View File
@@ -30,27 +30,71 @@ proc test_reset {} {
sqlite3 db2 test.db2
}
foreach {tn wo} {
1 ""
2 "WITHOUT ROWID"
} {
reset_db
do_execsql_test 1.0 {
CREATE TABLE t1(a PRIMARY KEY, b) WITHOUT ROWID;
do_execsql_test 1.$tn.0 "CREATE TABLE t1(a PRIMARY KEY, b) $wo ;"
do_iterator_test 1.$tn.1 t1 {
INSERT INTO t1 VALUES('one', 'two');
} {
{INSERT t1 0 X. {} {t one t two}}
}
do_iterator_test 1.$tn.2 t1 {
UPDATE t1 SET b='three'
} {
{UPDATE t1 0 X. {t one t two} {{} {} t three}}
}
do_iterator_test 1.$tn.3 t1 {
REPLACE INTO t1 VALUES('one', 'four');
} {
{UPDATE t1 0 X. {t one t three} {{} {} t four}}
}
do_iterator_test 1.$tn.4 t1 {
DELETE FROM t1;
} {
{DELETE t1 0 X. {t one t four} {}}
}
}
do_iterator_test 1.1 t1 {
INSERT INTO t1 VALUES('one', 'two');
foreach {tn wo} {
1 ""
2 "WITHOUT ROWID"
} {
{INSERT t1 0 X. {} {t one t two}}
}
reset_db
do_iterator_test 1.2 t1 {
UPDATE t1 SET b='three'
} {
{UPDATE t1 0 X. {t one t two} {{} {} t three}}
}
do_iterator_test 1.3 t1 {
DELETE FROM t1;
} {
{DELETE t1 0 X. {t one t three} {}}
do_execsql_test 2.$tn.0 "CREATE TABLE t1(a INTEGER PRIMARY KEY, b) $wo ;"
do_iterator_test 1.1 t1 {
INSERT INTO t1 VALUES(1, 'two');
} {
{INSERT t1 0 X. {} {i 1 t two}}
}
do_iterator_test 2.$tn.2 t1 {
UPDATE t1 SET b='three'
} {
{UPDATE t1 0 X. {i 1 t two} {{} {} t three}}
}
do_iterator_test 2.$tn.3 t1 {
REPLACE INTO t1 VALUES(1, 'four');
} {
{UPDATE t1 0 X. {i 1 t three} {{} {} t four}}
}
do_iterator_test 2.$tn.4 t1 {
DELETE FROM t1;
} {
{DELETE t1 0 X. {i 1 t four} {}}
}
}
finish_test
+18 -18
View File
@@ -363,7 +363,7 @@ static void sessionPutI64(u8 *aBuf, sqlite3_int64 i){
static int sessionSerializeValue(
u8 *aBuf, /* If non-NULL, write serialized value here */
sqlite3_value *pValue, /* Value to serialize */
int *pnWrite /* IN/OUT: Increment by bytes written */
sqlite3_int64 *pnWrite /* IN/OUT: Increment by bytes written */
){
int nByte; /* Size of serialized value in bytes */
@@ -904,7 +904,7 @@ static int sessionGrowHash(int bPatchset, SessionTable *pTab){
SessionChange **apNew;
int nNew = (pTab->nChange ? pTab->nChange : 128) * 2;
apNew = (SessionChange **)sqlite3_malloc(sizeof(SessionChange *) * nNew);
apNew = (SessionChange **)sqlite3_malloc64(sizeof(SessionChange *) * nNew);
if( apNew==0 ){
if( pTab->nChange==0 ){
return SQLITE_ERROR;
@@ -970,7 +970,7 @@ static int sessionTableInfo(
char *zPragma;
sqlite3_stmt *pStmt;
int rc;
int nByte;
sqlite3_int64 nByte;
int nDbCol = 0;
int nThis;
int i;
@@ -1013,7 +1013,7 @@ static int sessionTableInfo(
if( rc==SQLITE_OK ){
nByte += nDbCol * (sizeof(const char *) + sizeof(u8) + 1);
pAlloc = sqlite3_malloc(nByte);
pAlloc = sqlite3_malloc64(nByte);
if( pAlloc==0 ){
rc = SQLITE_NOMEM;
}
@@ -1154,7 +1154,7 @@ static void sessionPreupdateOneChange(
int iHash;
int bNull = 0;
int rc = SQLITE_OK;
SessionStat1Ctx stat1 = {0};
SessionStat1Ctx stat1 = {{0,0,0,0,0},0};
if( pSession->rc ) return;
@@ -1211,7 +1211,7 @@ static void sessionPreupdateOneChange(
** this is an SQLITE_UPDATE or SQLITE_DELETE), or just the PK
** values (if this is an INSERT). */
SessionChange *pChange; /* New change object */
int nByte; /* Number of bytes to allocate */
sqlite3_int64 nByte; /* Number of bytes to allocate */
int i; /* Used to iterate through columns */
assert( rc==SQLITE_OK );
@@ -1236,7 +1236,7 @@ static void sessionPreupdateOneChange(
}
/* Allocate the change object */
pChange = (SessionChange *)sqlite3_malloc(nByte);
pChange = (SessionChange *)sqlite3_malloc64(nByte);
if( !pChange ){
rc = SQLITE_NOMEM;
goto error_out;
@@ -1680,7 +1680,7 @@ int sqlite3session_create(
*ppSession = 0;
/* Allocate and populate the new session object. */
pNew = (sqlite3_session *)sqlite3_malloc(sizeof(sqlite3_session) + nDb + 1);
pNew = (sqlite3_session *)sqlite3_malloc64(sizeof(sqlite3_session) + nDb + 1);
if( !pNew ) return SQLITE_NOMEM;
memset(pNew, 0, sizeof(sqlite3_session));
pNew->db = db;
@@ -1799,7 +1799,7 @@ int sqlite3session_attach(
if( !pTab ){
/* Allocate new SessionTable object. */
pTab = (SessionTable *)sqlite3_malloc(sizeof(SessionTable) + nName + 1);
pTab = (SessionTable *)sqlite3_malloc64(sizeof(SessionTable) + nName + 1);
if( !pTab ){
rc = SQLITE_NOMEM;
}else{
@@ -1859,7 +1859,7 @@ static int sessionBufferGrow(SessionBuffer *p, int nByte, int *pRc){
static void sessionAppendValue(SessionBuffer *p, sqlite3_value *pVal, int *pRc){
int rc = *pRc;
if( rc==SQLITE_OK ){
int nByte = 0;
sqlite3_int64 nByte = 0;
rc = sessionSerializeValue(0, pVal, &nByte);
sessionBufferGrow(p, nByte, &rc);
if( rc==SQLITE_OK ){
@@ -2735,7 +2735,7 @@ static int sessionValueSetStr(
** argument to sqlite3ValueSetStr() and have the copy created
** automatically. But doing so makes it difficult to detect any OOM
** error. Hence the code to create the copy externally. */
u8 *aCopy = sqlite3_malloc(nData+1);
u8 *aCopy = sqlite3_malloc64((sqlite3_int64)nData+1);
if( aCopy==0 ) return SQLITE_NOMEM;
memcpy(aCopy, aData, nData);
sqlite3ValueSetStr(pVal, nData, (char*)aCopy, enc, sqlite3_free);
@@ -3348,7 +3348,7 @@ static int sessionChangesetInvert(
int iCol;
if( 0==apVal ){
apVal = (sqlite3_value **)sqlite3_malloc(sizeof(apVal[0])*nCol*2);
apVal = (sqlite3_value **)sqlite3_malloc64(sizeof(apVal[0])*nCol*2);
if( 0==apVal ){
rc = SQLITE_NOMEM;
goto finished_invert;
@@ -4621,7 +4621,7 @@ static int sessionChangeMerge(
int rc = SQLITE_OK;
if( !pExist ){
pNew = (SessionChange *)sqlite3_malloc(sizeof(SessionChange) + nRec);
pNew = (SessionChange *)sqlite3_malloc64(sizeof(SessionChange) + nRec);
if( !pNew ){
return SQLITE_NOMEM;
}
@@ -4654,8 +4654,8 @@ static int sessionChangeMerge(
if( pExist->op==SQLITE_DELETE && pExist->bIndirect ){
*ppNew = pExist;
}else{
int nByte = nRec + pExist->nRecord + sizeof(SessionChange);
pNew = (SessionChange*)sqlite3_malloc(nByte);
sqlite3_int64 nByte = nRec + pExist->nRecord + sizeof(SessionChange);
pNew = (SessionChange*)sqlite3_malloc64(nByte);
if( pNew==0 ){
rc = SQLITE_NOMEM;
}else{
@@ -4715,14 +4715,14 @@ static int sessionChangeMerge(
assert( pNew==0 );
}else{
u8 *aExist = pExist->aRecord;
int nByte;
sqlite3_int64 nByte;
u8 *aCsr;
/* Allocate a new SessionChange object. Ensure that the aRecord[]
** buffer of the new object is large enough to hold any record that
** may be generated by combining the input records. */
nByte = sizeof(SessionChange) + pExist->nRecord + nRec;
pNew = (SessionChange *)sqlite3_malloc(nByte);
pNew = (SessionChange *)sqlite3_malloc64(nByte);
if( !pNew ){
sqlite3_free(pExist);
return SQLITE_NOMEM;
@@ -4828,7 +4828,7 @@ static int sessionChangesetToHash(
if( !pTab ){
SessionTable **ppTab;
pTab = sqlite3_malloc(sizeof(SessionTable) + nCol + nNew+1);
pTab = sqlite3_malloc64(sizeof(SessionTable) + nCol + nNew+1);
if( !pTab ){
rc = SQLITE_NOMEM;
break;
+1 -1
View File
@@ -548,7 +548,7 @@ int sqlite3changeset_next(sqlite3_changeset_iter *pIter);
** sqlite3changeset_next() is called on the iterator or until the
** conflict-handler function returns. If pnCol is not NULL, then *pnCol is
** set to the number of columns in the table affected by the change. If
** pbIncorrect is not NULL, then *pbIndirect is set to true (1) if the change
** pbIndirect is not NULL, then *pbIndirect is set to true (1) if the change
** is an indirect change, or false (0) otherwise. See the documentation for
** [sqlite3session_indirect()] for a description of direct and indirect
** changes. Finally, if pOp is not NULL, then *pOp is set to one of
+27 -2
View File
@@ -369,6 +369,7 @@ TESTSRC += \
$(TOP)/ext/misc/nextchar.c \
$(TOP)/ext/misc/normalize.c \
$(TOP)/ext/misc/percentile.c \
$(TOP)/ext/misc/prefixes.c \
$(TOP)/ext/misc/regexp.c \
$(TOP)/ext/misc/remember.c \
$(TOP)/ext/misc/series.c \
@@ -509,7 +510,8 @@ FUZZDATA = \
$(TOP)/test/fuzzdata4.db \
$(TOP)/test/fuzzdata5.db \
$(TOP)/test/fuzzdata6.db \
$(TOP)/test/fuzzdata7.db
$(TOP)/test/fuzzdata7.db \
$(TOP)/test/fuzzdata8.db
# Standard options to testfixture
#
@@ -530,6 +532,11 @@ FUZZERSHELL_OPT = -DSQLITE_ENABLE_JSON1
FUZZCHECK_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5
FUZZCHECK_OPT += -DSQLITE_MAX_MEMORY=50000000
FUZZCHECK_OPT += -DSQLITE_PRINTF_PRECISION_LIMIT=1000
FUZZCHECK_OPT += -DSQLITE_ENABLE_DESERIALIZE
FUZZCHECK_OPT += -DSQLITE_ENABLE_FTS4
FUZZCHECK_OPT += -DSQLITE_ENABLE_RTREE
FUZZCHECK_OPT += -DSQLITE_ENABLE_GEOPOLY
FUZZCHECK_OPT += -DSQLITE_ENABLE_DBSTAT_VTAB
DBFUZZ_OPT =
KV_OPT = -DSQLITE_THREADSAFE=0 -DSQLITE_DIRECT_OVERFLOW_READ
ST_OPT = -DSQLITE_THREADSAFE=0
@@ -574,6 +581,20 @@ dbfuzz$(EXE): $(TOP)/test/dbfuzz.c sqlite3.c sqlite3.h
$(DBFUZZ_OPT) $(TOP)/test/dbfuzz.c sqlite3.c \
$(TLIBS) $(THREADLIB)
DBFUZZ2_OPTS = \
-DSQLITE_THREADSAFE=0 \
-DSQLITE_OMIT_LOAD_EXTENSION \
-DSQLITE_ENABLE_DESERIALIZE \
-DSQLITE_DEBUG \
-DSQLITE_ENABLE_DBSTAT_VTAB \
-DSQLITE_ENABLE_RTREE \
-DSQLITE_ENABLE_FTS4 \
-DSQLITE_ENABLE_FTS5
dbfuzz2$(EXE): $(TOP)/test/dbfuzz2.c sqlite3.c sqlite3.h
$(TCCX) -I. -g -O0 -DSTANDALONE -o dbfuzz2$(EXE) \
$(DBFUZZ2_OPTS) $(TOP)/test/dbfuzz2.c sqlite3.c $(TLIBS) $(THREADLIB)
fuzzcheck$(EXE): $(TOP)/test/fuzzcheck.c sqlite3.c sqlite3.h $(TOP)/test/ossfuzz.c
$(TCCX) -o fuzzcheck$(EXE) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
-DSQLITE_ENABLE_MEMSYS5 $(FUZZCHECK_OPT) -DSQLITE_OSS_FUZZ \
@@ -719,6 +740,7 @@ SHELL_SRC = \
$(TOP)/ext/expert/sqlite3expert.c \
$(TOP)/ext/expert/sqlite3expert.h \
$(TOP)/ext/misc/zipfile.c \
$(TOP)/ext/misc/memtrace.c \
$(TOP)/src/test_windirent.c
shell.c: $(SHELL_SRC) $(TOP)/tool/mkshellc.tcl
@@ -976,6 +998,9 @@ $(TEST_EXTENSION): $(TOP)/src/test_loadext.c
extensiontest: testfixture$(EXE) $(TEST_EXTENSION)
./testfixture$(EXE) $(TOP)/test/loadext.test
dbtotxt$(EXE): $(TOP)/tool/dbtotxt.c
$(TCC) -o dbtotxt$(EXE) $(TOP)/tool/dbtotxt.c
showdb$(EXE): $(TOP)/tool/showdb.c sqlite3.o
$(TCC) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -o showdb$(EXE) \
$(TOP)/tool/showdb.c sqlite3.o $(THREADLIB)
@@ -996,7 +1021,7 @@ showshm$(EXE): $(TOP)/tool/showshm.c
$(TCC) -o showshm$(EXE) $(TOP)/tool/showshm.c
index_usage$(EXE): $(TOP)/tool/index_usage.c sqlite3.o
$(TCC) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_DEPRECATED -o index_usage$(EXE) \
$(TCC) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_DEPRECATED $(SHELL_OPTS) -o index_usage$(EXE) \
$(TOP)/tool/index_usage.c sqlite3.o $(THREADLIB)
changeset$(EXE): $(TOP)/ext/session/changeset.c sqlite3.o
+258 -227
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -1 +1 @@
df95455213c9d1db7229e94217e78edc05cbf9e40f39528105494ea6ac52be94
9aca86f98388ff66b2bccb3fbfc486a3931398d2a8da139f905826ae2cdbb205
+52 -16
View File
@@ -28,9 +28,16 @@
**
** Or, if zName is not a system table, zero is returned.
*/
static int isSystemTable(Parse *pParse, const char *zName){
if( 0==sqlite3StrNICmp(zName, "sqlite_", 7) ){
sqlite3ErrorMsg(pParse, "table %s may not be altered", zName);
static int isAlterableTable(Parse *pParse, Table *pTab){
if( 0==sqlite3StrNICmp(pTab->zName, "sqlite_", 7)
#ifndef SQLITE_OMIT_VIRTUALTABLE
|| ( (pTab->tabFlags & TF_Shadow)
&& (pParse->db->flags & SQLITE_Defensive)
&& pParse->db->nVdbeExec==0
)
#endif
){
sqlite3ErrorMsg(pParse, "table %s may not be altered", pTab->zName);
return 1;
}
return 0;
@@ -126,7 +133,7 @@ void sqlite3AlterRenameTable(
/* Make sure it is not a system table being altered, or a reserved name
** that the table is being renamed to.
*/
if( SQLITE_OK!=isSystemTable(pParse, pTab->zName) ){
if( SQLITE_OK!=isAlterableTable(pParse, pTab) ){
goto exit_rename_table;
}
if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){ goto
@@ -159,15 +166,15 @@ void sqlite3AlterRenameTable(
}
#endif
/* Begin a transaction for database iDb.
** Then modify the schema cookie (since the ALTER TABLE modifies the
** schema). Open a statement transaction if the table is a virtual
** table.
*/
/* Begin a transaction for database iDb. Then modify the schema cookie
** (since the ALTER TABLE modifies the schema). Call sqlite3MayAbort(),
** as the scalar functions (e.g. sqlite_rename_table()) invoked by the
** nested SQL may raise an exception. */
v = sqlite3GetVdbe(pParse);
if( v==0 ){
goto exit_rename_table;
}
sqlite3MayAbort(pParse);
/* figure out how many UTF-8 characters are in zName */
zTabName = pTab->zName;
@@ -236,7 +243,6 @@ void sqlite3AlterRenameTable(
int i = ++pParse->nMem;
sqlite3VdbeLoadString(v, i, zName);
sqlite3VdbeAddOp4(v, OP_VRename, i, 0, 0,(const char*)pVTab, P4_VTAB);
sqlite3MayAbort(pParse);
}
#endif
@@ -424,7 +430,7 @@ void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){
sqlite3ErrorMsg(pParse, "Cannot add a column to a view");
goto exit_begin_add_column;
}
if( SQLITE_OK!=isSystemTable(pParse, pTab->zName) ){
if( SQLITE_OK!=isAlterableTable(pParse, pTab) ){
goto exit_begin_add_column;
}
@@ -526,7 +532,7 @@ void sqlite3AlterRenameColumn(
if( !pTab ) goto exit_rename_column;
/* Cannot alter a system table */
if( SQLITE_OK!=isSystemTable(pParse, pTab->zName) ) goto exit_rename_column;
if( SQLITE_OK!=isAlterableTable(pParse, pTab) ) goto exit_rename_column;
if( SQLITE_OK!=isRealTable(pParse, pTab) ) goto exit_rename_column;
/* Which schema holds the table to be altered */
@@ -557,6 +563,7 @@ void sqlite3AlterRenameColumn(
** uses the sqlite_rename_column() SQL function to compute the new
** CREATE statement text for the sqlite_master table.
*/
sqlite3MayAbort(pParse);
zNew = sqlite3NameFromToken(db, pNew);
if( !zNew ) goto exit_rename_column;
assert( pNew->n>0 );
@@ -780,14 +787,31 @@ static void renameTokenFind(Parse *pParse, struct RenameCtx *pCtx, void *pPtr){
}
}
/*
** Iterate through the Select objects that are part of WITH clauses attached
** to select statement pSelect.
*/
static void renameWalkWith(Walker *pWalker, Select *pSelect){
if( pSelect->pWith ){
int i;
for(i=0; i<pSelect->pWith->nCte; i++){
Select *p = pSelect->pWith->a[i].pSelect;
NameContext sNC;
memset(&sNC, 0, sizeof(sNC));
sNC.pParse = pWalker->pParse;
sqlite3SelectPrep(sNC.pParse, p, &sNC);
sqlite3WalkSelect(pWalker, p);
}
}
}
/*
** This is a Walker select callback. It does nothing. It is only required
** because without a dummy callback, sqlite3WalkExpr() and similar do not
** descend into sub-select statements.
*/
static int renameColumnSelectCb(Walker *pWalker, Select *p){
UNUSED_PARAMETER(pWalker);
UNUSED_PARAMETER(p);
renameWalkWith(pWalker, p);
return WRC_Continue;
}
@@ -937,7 +961,6 @@ static int renameParseSql(
rc = sqlite3RunParser(p, zSql, &zErr);
assert( p->zErrMsg==0 );
assert( rc!=SQLITE_OK || zErr==0 );
assert( (0!=p->pNewTable) + (0!=p->pNewIndex) + (0!=p->pNewTrigger)<2 );
p->zErrMsg = zErr;
if( db->mallocFailed ) rc = SQLITE_NOMEM;
if( rc==SQLITE_OK
@@ -1120,6 +1143,7 @@ static int renameResolveTrigger(Parse *pParse, const char *zDb){
}
sNC.ncFlags = 0;
}
sNC.pSrcList = 0;
}
}
}
@@ -1157,11 +1181,15 @@ static void renameWalkTrigger(Walker *pWalker, Trigger *pTrigger){
*/
static void renameParseCleanup(Parse *pParse){
sqlite3 *db = pParse->db;
Index *pIdx;
if( pParse->pVdbe ){
sqlite3VdbeFinalize(pParse->pVdbe);
}
sqlite3DeleteTable(db, pParse->pNewTable);
if( pParse->pNewIndex ) sqlite3FreeIndex(db, pParse->pNewIndex);
while( (pIdx = pParse->pNewIndex)!=0 ){
pParse->pNewIndex = pIdx->pNext;
sqlite3FreeIndex(db, pIdx);
}
sqlite3DeleteTrigger(db, pParse->pNewTrigger);
sqlite3DbFree(db, pParse->zErrMsg);
renameTokenFree(db, pParse->pRename);
@@ -1272,6 +1300,9 @@ static void renameColumnFunc(
for(pIdx=sParse.pNewTable->pIndex; pIdx; pIdx=pIdx->pNext){
sqlite3WalkExprList(&sWalker, pIdx->aColExpr);
}
for(pIdx=sParse.pNewIndex; pIdx; pIdx=pIdx->pNext){
sqlite3WalkExprList(&sWalker, pIdx->aColExpr);
}
}
for(pFKey=sParse.pNewTable->pFKey; pFKey; pFKey=pFKey->pNextFrom){
@@ -1358,12 +1389,17 @@ static int renameTableSelectCb(Walker *pWalker, Select *pSelect){
int i;
RenameCtx *p = pWalker->u.pRename;
SrcList *pSrc = pSelect->pSrc;
if( pSrc==0 ){
assert( pWalker->pParse->db->mallocFailed );
return WRC_Abort;
}
for(i=0; i<pSrc->nSrc; i++){
struct SrcList_item *pItem = &pSrc->a[i];
if( pItem->pTab==p->pTab ){
renameTokenFind(pWalker->pParse, p, pItem->zName);
}
}
renameWalkWith(pWalker, pSelect);
return WRC_Continue;
}
+1 -1
View File
@@ -1156,7 +1156,7 @@ static void analyzeOneTable(
addrNextRow = sqlite3VdbeCurrentAddr(v);
if( nColTest>0 ){
int endDistinctTest = sqlite3VdbeMakeLabel(v);
int endDistinctTest = sqlite3VdbeMakeLabel(pParse);
int *aGotoChng; /* Array of jump instruction addresses */
aGotoChng = sqlite3DbMallocRawNN(db, sizeof(int)*nColTest);
if( aGotoChng==0 ) continue;
+12 -7
View File
@@ -155,8 +155,8 @@ static void attachFunc(
assert( pVfs );
flags |= SQLITE_OPEN_MAIN_DB;
rc = sqlite3BtreeOpen(pVfs, zPath, db, &pNew->pBt, 0, flags);
sqlite3_free( zPath );
db->nDb++;
pNew->zDbSName = sqlite3DbStrDup(db, zName);
}
db->noSharedCache = 0;
if( rc==SQLITE_CONSTRAINT ){
@@ -184,7 +184,6 @@ static void attachFunc(
sqlite3BtreeLeave(pNew->pBt);
}
pNew->safety_level = SQLITE_DEFAULT_SYNCHRONOUS+1;
if( !REOPEN_AS_MEMDB(db) ) pNew->zDbSName = sqlite3DbStrDup(db, zName);
if( rc==SQLITE_OK && pNew->zDbSName==0 ){
rc = SQLITE_NOMEM_BKPT;
}
@@ -212,15 +211,19 @@ static void attachFunc(
break;
case SQLITE_NULL:
/* No key specified. Use the key from the main database */
sqlite3CodecGetKey(db, 0, (void**)&zKey, &nKey);
if( nKey || sqlite3BtreeGetOptimalReserve(db->aDb[0].pBt)>0 ){
rc = sqlite3CodecAttach(db, db->nDb-1, zKey, nKey);
/* No key specified. Use the key from URI filename, or if none,
** use the key from the main database. */
if( sqlite3CodecQueryParameters(db, zName, zPath)==0 ){
sqlite3CodecGetKey(db, 0, (void**)&zKey, &nKey);
if( nKey || sqlite3BtreeGetOptimalReserve(db->aDb[0].pBt)>0 ){
rc = sqlite3CodecAttach(db, db->nDb-1, zKey, nKey);
}
}
break;
}
}
#endif
sqlite3_free( zPath );
/* If the file was opened successfully, read the schema for the new database.
** If this fails, or if opening the file failed, then close the file and
@@ -231,7 +234,9 @@ static void attachFunc(
sqlite3BtreeEnterAll(db);
db->init.iDb = 0;
db->mDbFlags &= ~(DBFLAG_SchemaKnownOk);
rc = sqlite3Init(db, &zErrDyn);
if( !REOPEN_AS_MEMDB(db) ){
rc = sqlite3Init(db, &zErrDyn);
}
sqlite3BtreeLeaveAll(db);
assert( zErrDyn==0 || rc!=SQLITE_OK );
}
+482 -238
View File
File diff suppressed because it is too large Load Diff
+1
View File
@@ -315,6 +315,7 @@ i64 sqlite3BtreeOffset(BtCursor*);
int sqlite3BtreePayload(BtCursor*, u32 offset, u32 amt, void*);
const void *sqlite3BtreePayloadFetch(BtCursor*, u32 *pAmt);
u32 sqlite3BtreePayloadSize(BtCursor*);
sqlite3_int64 sqlite3BtreeMaxRecordSize(BtCursor*);
char *sqlite3BtreeIntegrityCheck(Btree*, int *aRoot, int nRoot, int, int*);
struct Pager *sqlite3BtreePager(Btree*);
+11 -4
View File
@@ -286,7 +286,7 @@ struct MemPage {
u16 maxLocal; /* Copy of BtShared.maxLocal or BtShared.maxLeaf */
u16 minLocal; /* Copy of BtShared.minLocal or BtShared.minLeaf */
u16 cellOffset; /* Index in aData of first cell pointer */
u16 nFree; /* Number of free bytes on the page */
int nFree; /* Number of free bytes on the page. -1 for unknown */
u16 nCell; /* Number of cells on this page, local and ovfl */
u16 maskPage; /* Mask for page offset */
u16 aiOvfl[4]; /* Insert the i-th overflow cell before the aiOvfl-th
@@ -494,9 +494,16 @@ struct CellInfo {
** found at self->pBt->mutex.
**
** skipNext meaning:
** eState==SKIPNEXT && skipNext>0: Next sqlite3BtreeNext() is no-op.
** eState==SKIPNEXT && skipNext<0: Next sqlite3BtreePrevious() is no-op.
** eState==FAULT: Cursor fault with skipNext as error code.
** The meaning of skipNext depends on the value of eState:
**
** eState Meaning of skipNext
** VALID skipNext is meaningless and is ignored
** INVALID skipNext is meaningless and is ignored
** SKIPNEXT sqlite3BtreeNext() is a no-op if skipNext>0 and
** sqlite3BtreePrevious() is no-op if skipNext<0.
** REQUIRESEEK restoreCursorPosition() restores the cursor to
** eState=SKIPNEXT if skipNext!=0
** FAULT skipNext holds the cursor fault error code.
*/
struct BtCursor {
u8 eState; /* One of the CURSOR_XXX constants (see below) */
+95 -47
View File
@@ -260,7 +260,11 @@ void sqlite3NestedParse(Parse *pParse, const char *zFormat, ...){
zSql = sqlite3VMPrintf(db, zFormat, ap);
va_end(ap);
if( zSql==0 ){
return; /* A malloc must have failed */
/* This can result either from an OOM or because the formatted string
** exceeds SQLITE_LIMIT_LENGTH. In the latter case, we need to set
** an error */
if( !db->mallocFailed ) pParse->rc = SQLITE_TOOBIG;
return;
}
pParse->nested++;
memcpy(saveBuf, PARSE_TAIL(pParse), PARSE_TAIL_SZ);
@@ -354,26 +358,32 @@ Table *sqlite3LocateTable(
p = sqlite3FindTable(db, zName, zDbase);
if( p==0 ){
const char *zMsg = flags & LOCATE_VIEW ? "no such view" : "no such table";
#ifndef SQLITE_OMIT_VIRTUALTABLE
/* If zName is the not the name of a table in the schema created using
** CREATE, then check to see if it is the name of an virtual table that
** can be an eponymous virtual table. */
Module *pMod = (Module*)sqlite3HashFind(&db->aModule, zName);
if( pMod==0 && sqlite3_strnicmp(zName, "pragma_", 7)==0 ){
pMod = sqlite3PragmaVtabRegister(db, zName);
}
if( pMod && sqlite3VtabEponymousTableInit(pParse, pMod) ){
return pMod->pEpoTab;
if( pParse->disableVtab==0 ){
Module *pMod = (Module*)sqlite3HashFind(&db->aModule, zName);
if( pMod==0 && sqlite3_strnicmp(zName, "pragma_", 7)==0 ){
pMod = sqlite3PragmaVtabRegister(db, zName);
}
if( pMod && sqlite3VtabEponymousTableInit(pParse, pMod) ){
return pMod->pEpoTab;
}
}
#endif
if( (flags & LOCATE_NOERR)==0 ){
if( zDbase ){
sqlite3ErrorMsg(pParse, "%s: %s.%s", zMsg, zDbase, zName);
}else{
sqlite3ErrorMsg(pParse, "%s: %s", zMsg, zName);
}
pParse->checkSchema = 1;
if( flags & LOCATE_NOERR ) return 0;
pParse->checkSchema = 1;
}else if( IsVirtual(p) && pParse->disableVtab ){
p = 0;
}
if( p==0 ){
const char *zMsg = flags & LOCATE_VIEW ? "no such view" : "no such table";
if( zDbase ){
sqlite3ErrorMsg(pParse, "%s: %s.%s", zMsg, zDbase, zName);
}else{
sqlite3ErrorMsg(pParse, "%s: %s", zMsg, zName);
}
}
@@ -636,12 +646,6 @@ static void SQLITE_NOINLINE deleteTable(sqlite3 *db, Table *pTable){
/* Delete the Table structure itself.
*/
#ifdef SQLITE_ENABLE_NORMALIZE
if( pTable->pColHash ){
sqlite3HashClear(pTable->pColHash);
sqlite3_free(pTable->pColHash);
}
#endif
sqlite3DeleteColumnNames(db, pTable);
sqlite3DbFree(db, pTable->zName);
sqlite3DbFree(db, pTable->zColAff);
@@ -1821,6 +1825,7 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
pTab->iPKey = -1;
}else{
pPk = sqlite3PrimaryKeyIndex(pTab);
assert( pPk!=0 );
/*
** Remove all redundant columns from the PRIMARY KEY. For example, change
@@ -1990,6 +1995,11 @@ void sqlite3EndTable(
if( p->tnum==1 ) p->tabFlags |= TF_Readonly;
}
assert( (p->tabFlags & TF_HasPrimaryKey)==0
|| p->iPKey>=0 || sqlite3PrimaryKeyIndex(p)!=0 );
assert( (p->tabFlags & TF_HasPrimaryKey)!=0
|| (p->iPKey<0 && sqlite3PrimaryKeyIndex(p)==0) );
/* Special processing for WITHOUT ROWID Tables */
if( tabOpts & TF_WithoutRowid ){
if( (p->tabFlags & TF_Autoincrement) ){
@@ -2638,6 +2648,7 @@ void sqlite3CodeDropTable(Parse *pParse, Table *pTab, int iDb, int isView){
*/
if( IsVirtual(pTab) ){
sqlite3VdbeAddOp4(v, OP_VDestroy, iDb, 0, 0, pTab->zName, 0);
sqlite3MayAbort(pParse);
}
sqlite3VdbeAddOp4(v, OP_DropTable, iDb, 0, 0, pTab->zName, 0);
sqlite3ChangeCookie(pParse, iDb);
@@ -3466,6 +3477,11 @@ void sqlite3CreateIndex(
}
}
if( idxType==SQLITE_IDXTYPE_PRIMARYKEY ) pIdx->idxType = idxType;
if( IN_RENAME_OBJECT ){
pIndex->pNext = pParse->pNewIndex;
pParse->pNewIndex = pIndex;
pIndex = 0;
}
goto exit_create_index;
}
}
@@ -3481,6 +3497,14 @@ void sqlite3CreateIndex(
Index *p;
assert( !IN_SPECIAL_PARSE );
assert( sqlite3SchemaMutexHeld(db, 0, pIndex->pSchema) );
if( pTblName!=0 ){
pIndex->tnum = db->init.newTnum;
if( sqlite3IndexHasDuplicateRootPage(pIndex) ){
sqlite3ErrorMsg(pParse, "invalid rootpage");
pParse->rc = SQLITE_CORRUPT_BKPT;
goto exit_create_index;
}
}
p = sqlite3HashInsert(&pIndex->pSchema->idxHash,
pIndex->zName, pIndex);
if( p ){
@@ -3489,9 +3513,6 @@ void sqlite3CreateIndex(
goto exit_create_index;
}
db->mDbFlags |= DBFLAG_SchemaChange;
if( pTblName!=0 ){
pIndex->tnum = db->init.newTnum;
}
}
/* If this is the initial CREATE INDEX statement (or CREATE TABLE if the
@@ -3817,6 +3838,18 @@ int sqlite3IdListIndex(IdList *pList, const char *zName){
return -1;
}
/*
** Maximum size of a SrcList object.
** The SrcList object is used to represent the FROM clause of a
** SELECT statement, and the query planner cannot deal with more
** than 64 tables in a join. So any value larger than 64 here
** is sufficient for most uses. Smaller values, like say 10, are
** appropriate for small and memory-limited applications.
*/
#ifndef SQLITE_MAX_SRCLIST
# define SQLITE_MAX_SRCLIST 200
#endif
/*
** Expand the space allocated for the given SrcList object by
** creating nExtra new slots beginning at iStart. iStart is zero based.
@@ -3833,11 +3866,12 @@ int sqlite3IdListIndex(IdList *pList, const char *zName){
** the iStart value would be 0. The result then would
** be: nil, nil, nil, A, B.
**
** If a memory allocation fails the SrcList is unchanged. The
** db->mallocFailed flag will be set to true.
** If a memory allocation fails or the SrcList becomes too large, leave
** the original SrcList unchanged, return NULL, and leave an error message
** in pParse.
*/
SrcList *sqlite3SrcListEnlarge(
sqlite3 *db, /* Database connection to notify of OOM errors */
Parse *pParse, /* Parsing context into which errors are reported */
SrcList *pSrc, /* The SrcList to be enlarged */
int nExtra, /* Number of new slots to add to pSrc->a[] */
int iStart /* Index in pSrc->a[] of first new slot */
@@ -3854,16 +3888,22 @@ SrcList *sqlite3SrcListEnlarge(
if( (u32)pSrc->nSrc+nExtra>pSrc->nAlloc ){
SrcList *pNew;
int nAlloc = pSrc->nSrc*2+nExtra;
int nGot;
sqlite3 *db = pParse->db;
if( pSrc->nSrc+nExtra>=SQLITE_MAX_SRCLIST ){
sqlite3ErrorMsg(pParse, "too many FROM clause terms, max: %d",
SQLITE_MAX_SRCLIST);
return 0;
}
if( nAlloc>SQLITE_MAX_SRCLIST ) nAlloc = SQLITE_MAX_SRCLIST;
pNew = sqlite3DbRealloc(db, pSrc,
sizeof(*pSrc) + (nAlloc-1)*sizeof(pSrc->a[0]) );
if( pNew==0 ){
assert( db->mallocFailed );
return pSrc;
return 0;
}
pSrc = pNew;
nGot = (sqlite3DbMallocSize(db, pNew) - sizeof(*pSrc))/sizeof(pSrc->a[0])+1;
pSrc->nAlloc = nGot;
pSrc->nAlloc = nAlloc;
}
/* Move existing slots that come after the newly inserted slots
@@ -3888,7 +3928,8 @@ SrcList *sqlite3SrcListEnlarge(
** Append a new table name to the given SrcList. Create a new SrcList if
** need be. A new entry is created in the SrcList even if pTable is NULL.
**
** A SrcList is returned, or NULL if there is an OOM error. The returned
** A SrcList is returned, or NULL if there is an OOM error or if the
** SrcList grows to large. The returned
** SrcList might be the same as the SrcList that was input or it might be
** a new one. If an OOM error does occurs, then the prior value of pList
** that is input to this routine is automatically freed.
@@ -3919,27 +3960,32 @@ SrcList *sqlite3SrcListEnlarge(
** before being added to the SrcList.
*/
SrcList *sqlite3SrcListAppend(
sqlite3 *db, /* Connection to notify of malloc failures */
Parse *pParse, /* Parsing context, in which errors are reported */
SrcList *pList, /* Append to this SrcList. NULL creates a new SrcList */
Token *pTable, /* Table to append */
Token *pDatabase /* Database of the table */
){
struct SrcList_item *pItem;
sqlite3 *db;
assert( pDatabase==0 || pTable!=0 ); /* Cannot have C without B */
assert( db!=0 );
assert( pParse!=0 );
assert( pParse->db!=0 );
db = pParse->db;
if( pList==0 ){
pList = sqlite3DbMallocRawNN(db, sizeof(SrcList) );
pList = sqlite3DbMallocRawNN(pParse->db, sizeof(SrcList) );
if( pList==0 ) return 0;
pList->nAlloc = 1;
pList->nSrc = 1;
memset(&pList->a[0], 0, sizeof(pList->a[0]));
pList->a[0].iCursor = -1;
}else{
pList = sqlite3SrcListEnlarge(db, pList, 1, pList->nSrc);
}
if( db->mallocFailed ){
sqlite3SrcListDelete(db, pList);
return 0;
SrcList *pNew = sqlite3SrcListEnlarge(pParse, pList, 1, pList->nSrc);
if( pNew==0 ){
sqlite3SrcListDelete(db, pList);
return 0;
}else{
pList = pNew;
}
}
pItem = &pList->a[pList->nSrc-1];
if( pDatabase && pDatabase->z==0 ){
@@ -4028,7 +4074,7 @@ SrcList *sqlite3SrcListAppendFromTerm(
);
goto append_from_error;
}
p = sqlite3SrcListAppend(db, p, pTable, pDatabase);
p = sqlite3SrcListAppend(pParse, p, pTable, pDatabase);
if( p==0 ){
goto append_from_error;
}
@@ -4417,13 +4463,15 @@ static int collationMatch(const char *zColl, Index *pIndex){
*/
#ifndef SQLITE_OMIT_REINDEX
static void reindexTable(Parse *pParse, Table *pTab, char const *zColl){
Index *pIndex; /* An index associated with pTab */
if( !IsVirtual(pTab) ){
Index *pIndex; /* An index associated with pTab */
for(pIndex=pTab->pIndex; pIndex; pIndex=pIndex->pNext){
if( zColl==0 || collationMatch(zColl, pIndex) ){
int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
sqlite3BeginWriteOperation(pParse, 0, iDb);
sqlite3RefillIndex(pParse, pIndex, -1);
for(pIndex=pTab->pIndex; pIndex; pIndex=pIndex->pNext){
if( zColl==0 || collationMatch(zColl, pIndex) ){
int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
sqlite3BeginWriteOperation(pParse, 0, iDb);
sqlite3RefillIndex(pParse, pIndex, -1);
}
}
}
}
+3 -18
View File
@@ -283,7 +283,7 @@ static int matchQuality(
** Search a FuncDefHash for a function with the given name. Return
** a pointer to the matching FuncDef if found, or 0 if there is no match.
*/
static FuncDef *functionSearch(
FuncDef *sqlite3FunctionSearch(
int h, /* Hash of the name */
const char *zFunc /* Name of function */
){
@@ -295,21 +295,6 @@ static FuncDef *functionSearch(
}
return 0;
}
#ifdef SQLITE_ENABLE_NORMALIZE
FuncDef *sqlite3FunctionSearchN(
int h, /* Hash of the name */
const char *zFunc, /* Name of function */
int nFunc /* Length of the name */
){
FuncDef *p;
for(p=sqlite3BuiltinFunctions.a[h]; p; p=p->u.pHash){
if( sqlite3StrNICmp(p->zName, zFunc, nFunc)==0 ){
return p;
}
}
return 0;
}
#endif /* SQLITE_ENABLE_NORMALIZE */
/*
** Insert a new FuncDef into a FuncDefHash hash table.
@@ -325,7 +310,7 @@ void sqlite3InsertBuiltinFuncs(
int nName = sqlite3Strlen30(zName);
int h = SQLITE_FUNC_HASH(zName[0], nName);
assert( zName[0]>='a' && zName[0]<='z' );
pOther = functionSearch(h, zName);
pOther = sqlite3FunctionSearch(h, zName);
if( pOther ){
assert( pOther!=&aDef[i] && pOther->pNext!=&aDef[i] );
aDef[i].pNext = pOther->pNext;
@@ -403,7 +388,7 @@ FuncDef *sqlite3FindFunction(
if( !createFlag && (pBest==0 || (db->mDbFlags & DBFLAG_PreferBuiltin)!=0) ){
bestScore = 0;
h = SQLITE_FUNC_HASH(sqlite3UpperToLower[(u8)zName[0]], nName);
p = functionSearch(h, zName);
p = sqlite3FunctionSearch(h, zName);
while( p ){
int score = matchQuality(p, nArg, enc);
if( score>bestScore ){

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