Compare commits

..

226 Commits

Author SHA1 Message Date
drh c5b674231a Add an experimental SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION compile-time option.
When enabled, the "unknown function" error is suppressed for EXPLAIN and
a no-op function named "unknown" is substituted.  This facilitiates using
the command-line shell to analyze queries from applications that contain
many application-defined functions that are not normally available to the
shell.

FossilOrigin-Name: 4ada023ca075628fdafc3bc4520239b9789cff29
2016-08-04 01:47:01 +00:00
drh 8eebf02f53 Merge recent trunk fixes.
FossilOrigin-Name: 97657445860363f5bd62c37e6a565e782e7eb908
2016-07-28 18:42:21 +00:00
drh 1563c7a4d5 Merge fixes to sqlite3_scrub_backup() from trunk.
FossilOrigin-Name: 91e811f51e611a37372875e96a4c51bbed2dfdea
2016-07-26 15:17:14 +00:00
drh 6f7087211c Merge the cache_spill VACUUM fix from trunk.
FossilOrigin-Name: cc6bfdf814d5701591b69ba2d399d4a1f6f6cc98
2016-07-26 04:54:54 +00:00
drh 68cd37c10f Make sure affinity is applied correctly on lower-bound range constraints
in the min() optimization.  Fix for ticket [a0bac8b3c3d1bb].

FossilOrigin-Name: 0e9f534fef72ca142a4296ab5285c82aada38ba7
2016-07-26 04:23:55 +00:00
drh 9e89b957ef Merge the VACCUM cache_size adjustment from trunk.
FossilOrigin-Name: cdb7efd01ed7a8f11681b277098bb3eb12ca39d2
2016-07-25 22:46:06 +00:00
drh 114f5744d4 Add the experimental SQLITE_VACUUM_CACHE_SIZE macro.
FossilOrigin-Name: 68ecd8e042bd14b8ede69219bd4ed175bf097d0b
2016-07-25 18:50:08 +00:00
drh ebbee40a8f Merge 3.14 alpha changes from trunk.
FossilOrigin-Name: e98cefb17d03ca146d0ff42bdd4dd6a8f3ba6735
2016-07-25 17:31:24 +00:00
drh 9d32b7b042 Merge changes from trunk.
FossilOrigin-Name: 0f707d1532d6c8277cf0f70821a83e0af621ce9b
2016-06-15 10:21:06 +00:00
drh 74a7ef79f7 Merge changes from trunk.
FossilOrigin-Name: 815cc2bb48db713a0166b82a55ae931ac43783d1
2016-05-23 02:57:33 +00:00
drh 469077596f Merge the 3.13.0 release changes.
FossilOrigin-Name: e2e9b98556f45ed2d6fb34db67957539932bd2c5
2016-05-18 20:53:37 +00:00
drh 88b69f3fb5 Merge recent fixes from trunk.
FossilOrigin-Name: 0d9b82afeadf3d8d8ca2aacd3620717e773ebe30
2016-05-16 13:37:45 +00:00
drh 04600b249f Fix the build when SQLITE_ENABLE_DATA_PROTECTION is defined.
FossilOrigin-Name: 8f05e1402d0d26684bd15ffdb638d0a55abdce7f
2016-05-03 02:43:50 +00:00
drh adb9636887 Merge enhancements and bug fixes from trunk.
FossilOrigin-Name: f52765ee7bddf047ce32d7448ee0c409e27d349a
2016-05-02 15:00:23 +00:00
drh 9fc3d1cfa7 Fix the nolock VFS so that it supports shared memory.
FossilOrigin-Name: ce11f8e8a38b36fd78c104ba7b6900f77d7b586b
2016-04-29 17:07:39 +00:00
drh 2b78c0d38b Merge enhancements from trunk, and in particular the TEMP file deferred I/O
enhancements.

FossilOrigin-Name: 81b76901e63d670c0f2302f56f1aeafcc7ff9922
2016-04-29 15:52:58 +00:00
drh cb9e7a56af Merge all recent enhancements from trunk.
FossilOrigin-Name: a15c49aed09a6f431022bc73aa98b04165649192
2016-04-21 15:35:21 +00:00
drh 101f557a23 Merge 3.12.0 changes.
FossilOrigin-Name: eef557449cf665aa8deb85674b7db167b389776a
2016-03-29 10:30:24 +00:00
drh e5a060474a Merge the sqlite3_system_errno() change from trunk.
FossilOrigin-Name: 063f1b3705625b2f115af8e909d86705b892b529
2016-03-21 14:52:04 +00:00
drh a14dfe465c Fix a VDBE register allocation bug exposed by recent enhancements to
PRAGMA integrity_check.

FossilOrigin-Name: c73b5b9ccf3dcf48f403c866423bebbdc45d2b28
2016-03-19 00:40:06 +00:00
drh ce08336c43 Test case tweaks to better support the Apple configuration options.
FossilOrigin-Name: cb0ffe844c9c3e84cba8c4df90d4d0f2e9f61586
2016-03-18 11:03:15 +00:00
drh 72f0d40ac4 Merge recent enhancements from trunk.
FossilOrigin-Name: ec052b4f14a8a7019bfc1bbe474020abafa557f3
2016-03-18 00:58:39 +00:00
drh 0ecefeb10b Merge the SQLITE_OMIT_CODEC_FROM_TCL compile-time option from trunk.
FossilOrigin-Name: 161d91e485059efb36b7bc74d091f9721b76dcbf
2016-03-16 01:09:07 +00:00
drh 2a73755f4e Merge updates from trunk - FTS5 fixes and enhancemenets to the tests scripts
so that they work with SEE.

FossilOrigin-Name: f41a7361a1c59d0d681f2a81c2f70c1a9bbf7aee
2016-03-15 12:45:43 +00:00
drh 7991137311 Merge changes from trunk, especially the SQLITE_DEFAULT_SYNCHRONOUS
enhancements.

FossilOrigin-Name: 29741941238643dc0e41660d98b176d81f9fd6f1
2016-03-08 16:35:17 +00:00
drh 3db53ff77b Merge coverage improvements and comment fixes from trunk.
FossilOrigin-Name: 58023bfccce40c611791c1963d47b620ffb9447a
2016-03-08 14:01:52 +00:00
drh 04393bb585 Fix a typo and remove an unused variable from test logic.
FossilOrigin-Name: 9f31516c5dd4a3578fb66d00425fb3e44d792716
2016-03-07 21:28:41 +00:00
drh 2911e6c570 Merge recent enhancements from trunk.
FossilOrigin-Name: 84f09f00f8731b1b3e057bc629ec14103a44b81d
2016-03-07 20:48:49 +00:00
drh 07a6166f23 Merge recent enhancements from trunk, and especially the changes that
reduce the heap-memory footprint of schemas, and defer opening and writing
to statement journals.

FossilOrigin-Name: 2f0c195ccc3c9550f0664223fc355b1c27063eba
2016-03-04 14:57:51 +00:00
drh 93e52b35cc Merge all recent enhancements from trunk, and in particular the
SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER change.

FossilOrigin-Name: 4fb4aee83da5cd1d75627f96ab431132628aeef4
2016-02-26 16:14:59 +00:00
drh 4f25847dbd Merge the master-journal optimization and other recent changes from trunk.
FossilOrigin-Name: 18c3ab4784a4efab2cc583ef712c4db9d127418a
2016-02-22 16:32:39 +00:00
drh 62c831d829 Merge the tokenizer buffer overrun bug-fix from trunk.
FossilOrigin-Name: 82e7e31b09097b24876f69df56cdd8f4c1aad1f1
2016-02-18 14:53:52 +00:00
drh 241014c3f1 Merge recent performance enhancements and the enhanced API_ARMOR from trunk.
FossilOrigin-Name: b7fa0fb3399ad2bf1e6bc4c92d43278a40f19ec4
2016-02-18 01:36:47 +00:00
drh 264b78a7b0 Memory leak associated with SQLITE_WRITE_WALFRAME_PREBUFFERED
FossilOrigin-Name: 7bcd3ab5f0519cb9ac8f7b98827600b9eff8db85
2016-02-18 01:22:53 +00:00
drh 7aecd9ac20 Merge 3.11.0 changes.
FossilOrigin-Name: 5cecc509d05eb3d6ebf0bb736da23725827bc8b3
2016-02-15 17:40:37 +00:00
drh d774536f52 Merge changes from the 3.11.0 release candidate.
FossilOrigin-Name: d198a6db2e49d0205420f8ed08cfffd75ee93e1e
2016-02-13 17:35:48 +00:00
drh 1158cd750f Merge recent fixes and enhancements from trunk.
FossilOrigin-Name: f073401792c0a093d4324fc2636170f108656976
2016-02-09 15:50:33 +00:00
drh 81ab26904b Merge OOM handling optimizations and PRAGMA synchronous=EXTRA as well as
other enhancements from trunk.

FossilOrigin-Name: 201fcbeef35d3d06d71ef5770fb72152840fcc2e
2016-02-05 14:29:18 +00:00
drh 26bb3b2148 Merge recent enhancements from trunk.
FossilOrigin-Name: e6a4a16312bf71ed5f277cdcd326003eb2580e72
2016-02-02 02:30:01 +00:00
drh e2fe1a59b7 Merge all recent enhancements from trunk.
FossilOrigin-Name: 3ed49691a12455e8583d8b8394ab005124442e89
2016-01-20 11:40:31 +00:00
drh afd6cf1041 Merge the latest enhancements and fixes from trunk.
FossilOrigin-Name: d85774e0dcb6cb1958ecd85891ef785e4692f67b
2016-01-14 15:03:12 +00:00
drh f45491a09c Import the version number change to 3.11.0.
FossilOrigin-Name: 132772d1c415c63fa5bdcc298ad9a3746bfb56bb
2016-01-11 13:03:34 +00:00
drh a0fafa1dee Merge enhancements from trunk, and in particular the WAL overwrite feature.
FossilOrigin-Name: 79125ec9d2cdb96d65ceeb19c2862665f9267d4e
2016-01-11 12:49:55 +00:00
drh 6a09a46b10 Merge all version 3.10.0 updates.
FossilOrigin-Name: 77c28c2b2dc601e67a88f55afff53b6cb9a24833
2016-01-06 14:35:15 +00:00
drh 4a42d8faf2 Merge all recent trunk enhancements.
FossilOrigin-Name: 5b700f313d753a308d2c6b5e5a5ee42af2e6d180
2016-01-01 13:31:36 +00:00
drh 68b203fe4e Merge recent trunk enhancements, and in particular the snapshot interface.
FossilOrigin-Name: 7e7b24064510001ca4a0c8295fa7d0138bde8dae
2015-12-11 12:53:26 +00:00
drh 59158c25cb Merge all recent trunk enhancements, especially the unix VFS changes.
FossilOrigin-Name: e1fb33c7d2bfd8ea115e667d7671a7529cd116aa
2015-12-02 20:22:38 +00:00
drh b8a08d1237 Merge the latest enhancements from trunk.
FossilOrigin-Name: 2c9e5436bd9146f0d76eb58e75cb76109d074ff7
2015-11-19 19:48:24 +00:00
drh 9beb8702e8 Merge fixes from trunk.
FossilOrigin-Name: f9060b2a9860b09ea0e268f6c135a2c78bc8d12d
2015-11-13 02:13:18 +00:00
drh 6684c44a4c Import the test_sqllog.c enhancements from trunk.
FossilOrigin-Name: 178da33909ff8e524cdefeede40fa5bd908efb37
2015-11-12 21:55:02 +00:00
drh bee873abcc Merge the latest enhancements from trunk, and in particular the
"PRAGMA cache_spill=N" change.

FossilOrigin-Name: e72331c719375dcfcfaba160f00d26e5460e9230
2015-11-12 16:51:43 +00:00
drh 961c98618d Merge recent enhancements and fixes from trunk.
FossilOrigin-Name: 5429f99b98ea1e2ecf5f50dade52009adc431a12
2015-11-07 01:57:44 +00:00
dan 738394c069 Merge latest trunk changes, including the follow-symlinks functionality and 3.9.2 bugfixes, into this branch.
FossilOrigin-Name: 447521d747d94fa3028348bc48b897592fd8021c
2015-11-02 15:10:48 +00:00
drh 51b021eb64 Merge the 3.10.0 version number update from trunk.
FossilOrigin-Name: 980d6207431abf8549bf8dd82d65d707872a2a31
2015-10-30 16:37:44 +00:00
dan 00c43a4a3b Merge latest trunk changes, including sqlite3_db_cacheflush(), with this branch.
FossilOrigin-Name: 6e4306efaf5c0d34a1aead8ad1fe5aa836b61ca1
2015-10-30 16:23:03 +00:00
dan a297dbb897 Merge latest trunk changes, including the SQLITE_IOERR_AUTH error code, with this branch.
FossilOrigin-Name: bc195e1cd9dc1c7b97bd05cd7d0664fbc599a890
2015-10-26 20:50:15 +00:00
drh 8e11f8aec5 Merge the 3.9.1 changes.
FossilOrigin-Name: dd07688d3a478bead1174cf243fd5a667ccdda8d
2015-10-16 20:52:35 +00:00
drh f035e3ce68 Merge 3.9.0 prerelease changes into the apple-osx branch.
FossilOrigin-Name: 1900ce011c7e0c10d670d86833ac701ecf4fa223
2015-10-13 17:49:19 +00:00
drh 532676f142 Merge all changes through the first 3.9.0 beta from trunk.
FossilOrigin-Name: 1ccae39b8a7094c2cee2f3fea57c847d0063fa81
2015-10-09 17:28:56 +00:00
drh 7c5113fc3b Merge recent trunk enhancements into the apple-osx branch.
FossilOrigin-Name: 4dd06d8ba1548552a4fc781207efda810cf34e55
2015-09-24 14:43:42 +00:00
drh 9827122af5 Merge trunk enhancements into the apple-osx branch.
FossilOrigin-Name: f12b8a0f7958260cb8e6b9be1aaa583cf383b39c
2015-09-15 17:20:41 +00:00
drh 7712ac43e8 Merge enhancements from trunk.
FossilOrigin-Name: d01658adf8680f3d128bb42ea8cc2f1acf46a569
2015-09-03 14:31:00 +00:00
drh 99a9edc64a Merge the latest trunk enhancements.
FossilOrigin-Name: 4af79477fd1c156bc31c397117a85ae72c286fe2
2015-09-01 18:40:52 +00:00
drh 36813e51a6 Fix a potential segfault in the VFS logic that checks for fail renames out
from under SQLite.

FossilOrigin-Name: 650111f66721c33015f89cda4f5afcb6e0dc1643
2015-08-28 15:35:30 +00:00
drh cbce710443 Disable the read-only WAL-mode database tests on the apple-osx branch because
read-only WAL-mode databases are specifically disallowed by Apple-specific
changes.

FossilOrigin-Name: bd911496cb2343d9640c131d905c9f0bee8fc428
2015-08-28 13:27:00 +00:00
drh 5be04de862 Merge trunk enhancements into the apple-osx branch. Most tests works, but
there are yet a few issues to be resolved.

FossilOrigin-Name: da8646582a9a8c800ff2962d40ca215381d846dc
2015-08-28 02:12:45 +00:00
drh 296145ff14 Fix the retry mechanism on file locks.
FossilOrigin-Name: 600df309fc547db3dc21cfc41609eb3dcaa67273
2015-08-11 18:18:24 +00:00
drh 3fa3114310 Merge all recent trunk enhancements and fixes into the apple-osx branch.
FossilOrigin-Name: 74b7bf17446bc21a73fa5b75c2942b5660b0ad7e
2015-04-20 01:25:56 +00:00
drh e8c1a641b1 Merge recent trunk fixes and enhancements into the apple-osx branch.
FossilOrigin-Name: bfc7142ad295c4b04078f9c01030bdbd15f024e8
2015-04-15 13:51:38 +00:00
drh 05a43c305f Merge all recent trunk enhances into the apple-osx branch.
FossilOrigin-Name: e709d3b4e7b91331f58ed8319f98790cfb190cb1
2015-04-13 23:11:45 +00:00
drh 557437fd51 Merge in all version 3.8.9 changes from trunk.
FossilOrigin-Name: 301218704cfb6eebac32828b7b2dbc6803c63a26
2015-04-08 12:47:26 +00:00
drh 471a717ccb Merge all recent trunk fixes and enhancements into the apple-osx branch.
FossilOrigin-Name: 71b6f507f1c5feb897b8162c468ecf2547a3d50e
2015-04-01 16:13:35 +00:00
drh b13cc88cd3 Merge the latest trunk enhancements, and especially the fix for the infinite
loop on a DROP TABLE in a corrupt database, into the apple-osx branch.

FossilOrigin-Name: 4d42bf5e18485be302cf5a3f81d900d7921b4315
2015-03-30 23:52:57 +00:00
drh 2f1fbb5a88 Merge the latest trunk enhancements into the apple-osx branch.
FossilOrigin-Name: a2bd81e575321e23f08d8dc56d4682adb44a513b
2015-03-24 18:49:59 +00:00
drh fa95fecd1a Merge all recent trunk enhancements and especially the blocking WAL-lock fix
into the apple-osx branch.

FossilOrigin-Name: 9f1f8b331e05d88052e6fb6556a88591efaa44bf
2015-03-21 17:00:06 +00:00
drh aefbdc97bd Merge all recent trunk changes, and in particular the blocking WAL lock change,
into the apple-osx branch.

FossilOrigin-Name: 8abbeadbc028524c4a59c1af6c10f724ccb91d0a
2015-03-17 18:35:40 +00:00
drh 5817b2a18e Merge recent trunk enhancements into the apple-osx branch.
FossilOrigin-Name: 5e04eec88e4f5cb9d57577ee2d9e3569de930fbb
2015-03-09 13:18:22 +00:00
drh 4feacdeb25 Merge the latest trunk fixes and enhancements into the apple-osx branch.
FossilOrigin-Name: ba8294e2f76a0cfcf48200634e6076a8995024f0
2015-02-25 14:09:23 +00:00
drh 201959c95d Merge trunk changes into the apple-osx branch.
FossilOrigin-Name: 3896e23373d41371fc6839168a97a669106486af
2015-02-21 01:03:48 +00:00
drh 0a175660d2 Incremental merge to prevent a huge pileup of merge conflicts resulting
from editing the same code in two different branches.

FossilOrigin-Name: 82c4c4e248bfca38bc3285d5a8414f7180c2eab5
2015-02-19 15:56:27 +00:00
drh 03f275ea83 Move the os_unix.c file closer to trunk.
FossilOrigin-Name: 57d7024007c2a71bf6cb875b1f1daf26924d188e
2015-02-19 02:43:19 +00:00
drh f6aade2b1e Enhancements to SQLITE_ENABLE_API_ARMOR merged from trunk.
FossilOrigin-Name: 5147b94ae6dc3e1bae5c506563347880c3a302b1
2015-02-13 16:42:49 +00:00
drh b8963868c9 Merge all recent trunk fixes and enhancements into the apple-osx branch.
FossilOrigin-Name: b2449d67768f4d3d83877d9c45e5b4b17bb6a551
2015-02-13 12:13:43 +00:00
drh 3f73784941 Merge increment blob I/O fixes from trunk.
FossilOrigin-Name: 292cf68b4c934c3a666d938d3857f6bd8a484044
2015-02-07 15:30:08 +00:00
drh 77cb4f3bf5 Merge all recent trunk enhancements into the apple-osx branch.
FossilOrigin-Name: 44711921fea2bb2d804d57b23872ab84156a04ba
2015-02-06 16:03:44 +00:00
drh a3b2856ca5 Merge the 3.8.8 release changes from trunk.
FossilOrigin-Name: 518621f8dcd6c0cc107110991753731a19b263f6
2015-01-16 12:24:00 +00:00
drh 11a6d52005 Merge the testing enhancements and the unlimited VALUES enhancement from trunk.
FossilOrigin-Name: cc7808427f8e9df8e2810a6681b2ddd93e578c67
2015-01-08 19:55:13 +00:00
drh e4172fa884 Merge the latest changes from trunk into the apple-osx branch.
FossilOrigin-Name: df3cdf9f0690f2724c7e4e0adb2e3bd4b1a4dd26
2015-01-02 19:17:44 +00:00
drh 79e319ef93 Merge latest fixes and enhancements from trunk into apple-osx.
FossilOrigin-Name: 2c1d8ddab23b36dbdd30ff82401925f97ffc5d76
2014-12-16 00:29:06 +00:00
drh 38f940254a Increase the default PMA size from 10 to 250 pages and provide the
SQLITE_SORTER_PMASZ compile-time option to change this default.  Add
needed mutex call when clearing the KeyInfo cache in shared-cache mode.

FossilOrigin-Name: 6e2da589ad562e0e412eb6572a8681225259b46e
2014-12-09 15:01:07 +00:00
drh 417f98ddc9 Merge the shared-cache KeyInfo fix from trunk.
FossilOrigin-Name: 8a9b43f930de9c789b230909233eee64ad1db93d
2014-12-05 20:16:52 +00:00
drh 7151722191 Import compiler warning and autoconf makefile fixes from trunk.
FossilOrigin-Name: 5437e0534a9647b449474df140a88bb8e4e42791
2014-12-05 00:49:47 +00:00
drh 1dc14f78f0 Import from trunk support for SQLITE_CHECKPOINT_TRUNCATE and fixes for
a couple of obscure bugs.

FossilOrigin-Name: 463ad971d2a427f50564b409a021a910004c1423
2014-12-04 23:42:28 +00:00
drh 6f34c36a39 Merge all recent enhancements and bug fixes from trunk into the apple-osx
branch.

FossilOrigin-Name: 43c4ba26a20ca0230d898a6431ed9ae5cfdb63d3
2014-12-02 16:38:43 +00:00
drh 5a3d6b1a39 Merge recent trunk enhancements.
FossilOrigin-Name: ccb601f6dffba68a57d82db2d046aa27f6f1b755
2014-11-18 21:27:48 +00:00
drh 5d5a49d8da Merge all recent trunk enhancements into the apple-osx branch.
FossilOrigin-Name: fef8430f1284b08b1c2af3d5639037478c58fb7e
2014-10-31 15:20:47 +00:00
drh f6f002a3bb Merge latest enhancements, including the SQLITE_ENABLE_API_ARMOR patch,
from trunk.

FossilOrigin-Name: 10aaf3b148404df7912d9604ccb6921173e7ac80
2014-10-27 18:42:03 +00:00
drh 81f89ae38c Merge the 3.8.7 changes into the apple-osx branch.
FossilOrigin-Name: aa7bbed10b63078dcd3468b7b47c30044bc8586d
2014-10-17 12:11:07 +00:00
drh 6d88f0f145 Merge from trunk recent micro-optimizations and the fix for the DESC index
GROUP BY ORDER BY bug.

FossilOrigin-Name: 880df7568add1b5825f713688dcd7a03cd895389
2014-10-14 14:17:15 +00:00
drh 4cfde6344b Record the errno on fstat() failures.
FossilOrigin-Name: 2a6a0820010268593b8edd3c630734ee5f9aa5ab
2014-10-09 11:40:35 +00:00
drh 4a92cb5619 Merge the latest trunk enhancements into the apple-osx branch.
FossilOrigin-Name: 6fc7207727d50c3039c7a0c6c9151cad6b9d25de
2014-10-09 11:27:38 +00:00
drh 52c5d76673 Merge the latest enhancements from trunk.
FossilOrigin-Name: 2078454ac998ccb5e837c4f13d8d8b2f312f4f50
2014-10-01 01:46:35 +00:00
drh dde37a1cb0 Merge in all recent changes from trunk.
FossilOrigin-Name: 3967ebe83e7cbb1dde26e4c9a6713d5c70fefe46
2014-09-21 23:08:54 +00:00
drh 9cc5985bc4 Merge the latest trunk changes into the apple-osx branch.
FossilOrigin-Name: 696dc935f78dc883faf98cf446f75ce4028e98f8
2014-09-02 15:57:35 +00:00
drh edb586616b Merge recent performance enhancements and the CAST operator enhancements
into the apple-osx branch.

FossilOrigin-Name: 5c273111058fcb3a1707ea0f3c7ac4b04525aeb0
2014-08-26 02:02:40 +00:00
drh 1c68302a1a Merge the 3.8.6 changes into the apple-osx branch.
FossilOrigin-Name: b91fcb3b1b6d383e023bd0818a2075018fd33b98
2014-08-15 16:10:41 +00:00
drh 3f45cf5900 Merge the pre-3.8.6 changes from trunk into the apple-osx branch.
FossilOrigin-Name: 08058df3af18d28c3fbd306527734f507c06f156
2014-08-14 13:39:49 +00:00
drh 72ab0c824d Merge 3.8.6 beta changes in from trunk.
FossilOrigin-Name: b2e01080cce405de2bba7a5294001f9cc463a3c4
2014-08-06 01:51:19 +00:00
drh fd855ec1e9 Merge in the CREATE UNIQUE INDEX fix of ticket [9a6daf340df99ba93c53bcf].
FossilOrigin-Name: fa7912320fd92c957034164f51d993f86220cf36
2014-07-30 14:57:00 +00:00
drh c0c290d4f6 Merge all recent trunk changes, and especially the R-Tree IN operator fix
of ticket [d2889096e7bdeac].

FossilOrigin-Name: 654c6c658ba7557eb822b03264bb4d259c216c01
2014-07-30 11:49:32 +00:00
drh 7a00b6c815 Merge recent trunk changes into the apple-osx branch.
FossilOrigin-Name: 3810dc62d2739cfd4f0dae7cea6af481cc698a0b
2014-07-24 16:43:42 +00:00
drh 31447e8b01 Merge the latest trunk changes into the apple-osx branch.
FossilOrigin-Name: f426876fe1cc9ebcda5a52f823f417a4db358517
2014-06-30 19:57:04 +00:00
drh 59967e2d2e Merge in the 3.8.5 release changes and the FTS integrity-check fix.
FossilOrigin-Name: 2dbdfa51703bade30b66730191e4fb286edc500b
2014-06-05 12:53:41 +00:00
drh acf5e9d692 Merge trunk changes into the apple-osx branch.
FossilOrigin-Name: b9fad4490c437a2c49cf86cc1c068433d6d2866b
2014-05-29 20:36:56 +00:00
drh ef39ae556c Merge recent trunk changes into the apple-osx branch.
FossilOrigin-Name: 54b5fa77e9b2ae447fd25cbdb9abfe37f2226504
2014-05-26 20:08:23 +00:00
drh d419d42238 Merge all recent trunk changes into the apple-osx branch.
FossilOrigin-Name: 23722be49ad8ff21aed49a66174626798c428811
2014-05-20 00:27:19 +00:00
drh d6edcca767 Fix a misplaced #endif and a C99-ism in the unix VFS.
FossilOrigin-Name: c8d384d14650482ac7f311c49f8264a954b1d654
2014-05-09 14:56:16 +00:00
drh 8a9a68e2ae Fix compiler warnings. When forcing the delete of a WAL file, do not
fail if the WAL files does not exist.  All "veryquick.tcl" tests are now
passing on Linux under the standard compile-time options.

FossilOrigin-Name: eafd8aa1862fb4bbe0d2441cbd110aba1abc772c
2014-05-09 13:27:38 +00:00
drh b33a4fdffe Fix an incorrect check for API misuse.
FossilOrigin-Name: 856400dc20752e5630aaea8d17a707c502a1245b
2014-05-09 12:18:06 +00:00
drh 35d09b26e2 Bring the PRAGMA logic into closer alignment with trunk, and in the process
fix a couple of crashes.

FossilOrigin-Name: d66fe706dad000888a177c19aa217bbb68edb4d2
2014-05-09 11:45:55 +00:00
drh b9f41b4fd1 Initial attempt to merge in all trunk changes over the previous 1.5 years.
This check-in compiles but there are compiler warnings and "make test"
segfaults after only running a few test modules.

FossilOrigin-Name: 9411d7dc6fbee689730c6f74736341bccd333d9e
2014-05-08 23:01:59 +00:00
drh e1436049d8 Merge the latest trunk changes (PRAGMA busy_timeout and the ORDER BY
query planner enhancements) into the apple-osx branch.

FossilOrigin-Name: 6a5c59dd7e0de9b5a2136f1c333afe522f724a71
2012-09-28 10:57:42 +00:00
dan 4e76b64969 Merge in latest trunk changes.
FossilOrigin-Name: bc9b9cd0589c4a51ece2e4657d622a04fc203315
2012-08-31 14:10:24 +00:00
drh 78fffbf2c2 Merge all the latest trunk changes into the apple-osx branch.
FossilOrigin-Name: 6723add4f492c30b20db8de6ed818c191dedea40
2012-08-25 01:38:39 +00:00
drh 3314d12e03 Cherrypick [8c9ee1d78f] and [e416359633] from trunk:
Ensure that there is always at least one aReadMark slot usable by an unprivileged reader while a checkpoint is running. Also, if one or more transactions are recovered from a log file, initialize one of the aReadMark slots to contain mxFrame as part of the recovery process.

FossilOrigin-Name: 65035912264e3acbced5a3e16793327f0a2f17bb
2012-07-17 17:46:21 +00:00
drh b2eb39ea15 Merge the vtab1 test script fix and the FTS3 memory leak fix from trunk
into the apple-osx branch.

FossilOrigin-Name: 892d8779cc3c4037d6e21c04c39796284d811157
2012-06-08 14:11:30 +00:00
drh 1489c18b99 Merge trunk changes into the apple-osx branch.
FossilOrigin-Name: 9d1b8515625ce7fbde170180126bd1a273bb4994
2012-06-08 01:13:17 +00:00
adam 3aed0eb475 Only call fchown when running as root and supporting files mismatch the database owner & perms
FossilOrigin-Name: ed53b645cc791e2c75885866ecb668fff14f8e7e
2012-05-31 00:21:28 +00:00
drh ba1bce386c Version 3.7.12.1
FossilOrigin-Name: 972e75bb5d7349297b94cec2f19561ee105a22cf
2012-05-22 13:11:12 +00:00
drh 8f0e4e2a9c Stylistic fixes: limit source code line length to 80 characters. C89-style
comments only, not C++/C99 style.

FossilOrigin-Name: 4068abe05c3a94c9ac7cff72b77fb8e47a2b1a5d
2012-05-17 14:17:13 +00:00
adam 8a1c468c3c Improve error reporting from sqlite3_file_control, SQLITE_FCNTL_REPLACE_DATABASE shouldn't copy file security/ACL metadata, bad bit mask fixed
FossilOrigin-Name: 92e7bb907802c905f99ed4c47669f97723f63ed3
2012-05-16 22:08:18 +00:00
drh 29b2fb1c52 Version 3.7.12
FossilOrigin-Name: d9348b2a4e15873756adfd092e8128d9f1cf72b4
2012-05-14 02:05:15 +00:00
dan 8749d1c8e6 Merge trunk changes with apple-osx branch.
FossilOrigin-Name: bf57f0fb73500f384fc57cbe2501343c97dc433e
2012-05-12 14:59:45 +00:00
drh fc73c50fec Make sure the WAL file is deleted when changing to DELETE journal mode.
FossilOrigin-Name: 66708685909fb048edab7f15e4a81d5a554d88d9
2012-05-11 00:56:28 +00:00
drh 5fbe8d658f Merge in the legacy table constraint parsing fixes from trunk.
FossilOrigin-Name: e87702834ed50882fadb3dee66cafb7438f5e577
2012-05-10 12:09:34 +00:00
adam 02d2493753 Added support for SQLITE_ENABLE_PERSIST_WAL compile time macro, retrieving lastErrno from WAL file and setting last errno when writes fail due to space constraints
FossilOrigin-Name: 654792941011c96db879f6b779e99b1c65c587af
2012-05-09 22:36:25 +00:00
drh edd972a2ed Merge the latest trunk changes into the apple-osx branch.
FossilOrigin-Name: 2a99c0074aaabb4916d82464427be079d44d65e6
2012-05-05 01:03:31 +00:00
drh 42b4259a4a Update the apple-osx branch so that it includes all of the latest trunk
changes.

FossilOrigin-Name: b72f07b4a2cf62ac1b52d432f13057d5d93a4ec4
2012-04-19 20:43:54 +00:00
dan 8343a6bf5e Cherrypick commit [1d5e744cc6] from the trunk in order to avoid leaving a file-ddescriptor open in test scripts capi3.test and capi3c.test.
FossilOrigin-Name: 86b8481be7e76cccc92d14ce762d21bfb69504af
2012-04-03 19:43:07 +00:00
adam 4678255c4e bad assert
FossilOrigin-Name: 0c0150f2a349460d685e63be1a747d2bfbe5c8c4
2012-04-02 23:42:48 +00:00
adam 0cb33b650c Merge in latest changes, autologging options, read only file system wal support, test config conditionalization, WAL frame write prebuffering
FossilOrigin-Name: d51c086e5c006821e2ab932f229649a729d914b2
2012-04-02 23:35:45 +00:00
drh 9817307d2f Merge all the latest trunk changes into the apple-osx branch.
FossilOrigin-Name: 18ec60cacd37a70d598ac1af5e50faffa73bb134
2012-03-31 02:46:20 +00:00
dan 296c8cad4d Merge latest trunk changes into apple-osx branch.
FossilOrigin-Name: f999197b75465a1f71ac1dab8f22ba2167fc0c67
2012-03-19 16:21:28 +00:00
drh 40d50d1b0f Pull in all the latest trunk changes.
FossilOrigin-Name: 504bf4908618f4dc8c9d67380934016b311ca6d0
2012-03-05 16:39:56 +00:00
drh 2f1e7b8a74 Pull the latest trunk changes into the apple-osx branch.
FossilOrigin-Name: e248598649dd69ed4b4d3da80566d2a7a36a349a
2012-02-10 18:18:00 +00:00
drh e0ba85df8b Merge the latest trunk changes into the apple-osx branch.
FossilOrigin-Name: 2cc414cd144cd84aad6420058c6e674c2920ba72
2012-01-14 14:13:31 +00:00
drh 39ab1aef89 Pull all the latest trunk changes over into the apple-osx branch.
FossilOrigin-Name: 8a048423f0e409d2332558cb5148e5a1d251ae30
2012-01-03 21:54:09 +00:00
drh 90defefb85 Merge the latest trunk changes into the apple-osx branch.
FossilOrigin-Name: 59e0d4f3d9af81d0c920812a6583228faa300cd6
2011-12-08 21:08:53 +00:00
drh 48249a7397 Fix a problem with sqlite3_backup_step() that resulted from a faulty merge.
FossilOrigin-Name: dacdec78d010922b6357f5319108289d087b6028
2011-10-31 19:59:09 +00:00
drh ffa0ae9924 Fix the os_unix.c source file so that it will build as part of an
amalgamation on non-apple platforms.

FossilOrigin-Name: b2f7639c8faf962239d41bb3a151448fad84e84c
2011-10-31 19:34:47 +00:00
drh 495cd6b419 Pull the latest trunk changes into the apple-osx branch.
FossilOrigin-Name: 4fa9ee794713e7a2298f53d9b517c90745b3408b
2011-10-31 14:42:31 +00:00
drh 7d59b89dc9 Merge the latest trunk changes into the apple-osx branch.
FossilOrigin-Name: be62ef058bcee55b31127ee779f7ecbf762986f8
2011-10-21 17:18:20 +00:00
drh aa09d0503d Simplify the readonly_shm implementation so that it conforms to the
implementation on trunk.  Update the test cases to agree with the new
behavior.

FossilOrigin-Name: 9efb74cefb2b7444112e16f3da48d5645746fdfa
2011-10-11 18:38:13 +00:00
drh 3a0022dad4 Fix a locking error introduced when porting the new Apple locking code.
FossilOrigin-Name: cce1f521362a87cc46fc5bfba68b7c188e2ea34f
2011-10-11 15:03:45 +00:00
drh 0d92f761ed Merge the latest trunk changes into the apple-osx branch.
FossilOrigin-Name: 7e2c4898224f9fabf724a6d4e1ac597845a66f73
2011-10-11 14:19:38 +00:00
drh cc40f4ceb1 Forward port the Apple-specific changes from [db5b7b778c] in the
apple-osx-377 branch.  Fix this up so that it will compile and run on Linux.

FossilOrigin-Name: 6cb43f6c6e9d8054e00acab378b8af0d82d3084c
2011-10-10 23:53:48 +00:00
adam aec336af26 Merging in cherry picked diffs for persist wal, alloc padding, wal-safe vacuum and sqlite3_file_control based lockstate checking
FossilOrigin-Name: db5b7b778c09c57501cb8266895a0ea4f2de7649
2011-10-10 22:11:44 +00:00
drh d74c576ee6 Cherrypick the sqlite_data_count() changes from [d4f95b3b6e] and
[9913996e7b] into the apple-osx branch for version 3.7.7.

FossilOrigin-Name: aef7945c423a8338374572eeda9444866c64569b
2011-10-10 18:59:05 +00:00
drh 65f0fd40d6 Merge in all trunk changes through the 3.7.8 release.
FossilOrigin-Name: ade72b1874c7672ae8d62b9ebac8e4d63fee80cc
2011-09-19 20:32:36 +00:00
drh f9ae91deed Remove a couple of comments that were causing problems for the
amalgamation generator script.

FossilOrigin-Name: ffed86bf969b98d196ac50bb5e5faddecab4fc59
2011-09-17 18:56:19 +00:00
drh 8062d660f1 Merge the latest trunk fixes into the apple-osx branch.
FossilOrigin-Name: 070bf203bb7cd59d69c10b29d7d9374e0361a47a
2011-09-16 19:36:42 +00:00
drh b19e7036cd Merge in the latest changes from trunk.
FossilOrigin-Name: 2456b4d0d2522dd2541146031347bc5e51f2036f
2011-09-14 19:05:55 +00:00
drh 253df3a264 Merge the latest trunk changes into the apple-osx branch.
FossilOrigin-Name: 55af80035f0432bbd4c4b3f4dbc9def13c5356b3
2011-08-26 19:18:50 +00:00
dan 343811ce13 Merge latest trunk changes into the apple-osx branch.
FossilOrigin-Name: c5f7977b899e93bf90bd44572db78c744ea81c14
2011-08-23 18:06:04 +00:00
drh 1b1b8325e1 Merge all the latest trunk changes into the apple-osx branch.
FossilOrigin-Name: 77376b332b4460208f837f7bdf6df8c90d5071d5
2011-08-02 18:25:20 +00:00
adam 027200ec51 Changes to make pragma synchronous sticky when SQLITE_DEFAULT_WAL_SAFETYLEVEL is used
FossilOrigin-Name: c6158b254fabd02a3d58b1a047a3c5fa979b41a8
2011-06-25 21:43:15 +00:00
dan d819aea05f Fix test cases so that they work with SQLITE_DEFAULT_WAL_SAFETYLEVEL defined.
FossilOrigin-Name: 8f8b373eed7052e6e93c1805fc1effcf1db09366
2011-06-25 16:35:41 +00:00
drh e96ab66f34 Fix the build.
FossilOrigin-Name: 97729542d53a407de1bdfeb5fa6d80bbdb4813b6
2011-06-24 21:47:39 +00:00
adam 2e4491d4b1 Merging local changes to apple-osx
FossilOrigin-Name: 34f0efa2b12e8eb09331768b1524a076baeb34ea
2011-06-24 20:47:06 +00:00
drh 1b2327c509 Pull the last-minute fixes for 3.7.7 into the apple-osx branch.
FossilOrigin-Name: 2d4458af59c697ad453996815d14442230654670
2011-06-23 17:42:45 +00:00
drh 66f6ad7b94 Pull the latest changes from trunk into the apple-osx branch.
FossilOrigin-Name: b5acda0445db39d58229d65a361d539db30f3833
2011-06-23 02:30:36 +00:00
dan b5f87f4394 Update apple-osx branch with the latest trunk changes.
FossilOrigin-Name: fb7ad09dec805ccb709b138509d6e1eb77323c2f
2011-06-22 11:24:55 +00:00
drh fbea85d6cd Merge the latest trunk changes into the apple-osx branch.
FossilOrigin-Name: 76005fdca05d86f91e424698d86942264419c616
2011-06-21 01:30:53 +00:00
drh b09945e64c Merge the latest trunk changes into the apple-osx branch.
FossilOrigin-Name: 4c69e827f4d65e597e125e0d6691b0c8fb5588d7
2011-06-20 11:57:58 +00:00
drh c3835e0208 Merge the latest trunk changes, including the read-only shared memory
enhancement, into the apple-osx branch.

FossilOrigin-Name: ce5f95dee6989f17a6a7af89699a02f8c5c6f787
2011-06-02 13:07:43 +00:00
drh d736884f3d Pull all the latest trunk changes, and especially the fix for WAL cache
spills causing transactions to disappear, into the apple-osx branch.

FossilOrigin-Name: 8d1a6bb002a7817fa7df932f7cab7220c1d62c0e
2011-05-19 01:51:25 +00:00
drh 283f9e7ee6 Merge the latest trunk changes into the apple-osx branch.
FossilOrigin-Name: f9b149e53815235aaf92f722e37c4819503d72b3
2011-05-05 15:52:46 +00:00
drh fa64665a49 Update the apple-osx branch to version 3.7.6.1.
FossilOrigin-Name: 289194d68e891e4977407d07e452e48844777a36
2011-04-13 15:42:26 +00:00
drh e127a2ea9f Pull all the latest trunk changes into the apple-osx branch.
FossilOrigin-Name: 4eaef4ad4cfda519f18922a249904d16489ee606
2011-04-09 18:13:35 +00:00
drh 5be1b1f262 Merge the latest trunk changes into the apple-osx branch.
FossilOrigin-Name: c77a767cbd22354d9f6d5cef0d81ea721be593c7
2011-04-05 22:10:50 +00:00
drh 25d2380356 Pull the latest changes from trunk (and hence from schema-parse-refactor)
into the apple-osx branch.

FossilOrigin-Name: 8e885ddea0fc5d4c4256025c127e5d41d63c47a5
2011-04-05 13:38:12 +00:00
drh 69d67f5412 Merge in the latest changes from trunk.
FossilOrigin-Name: 6d78a25ddce75f63581be60c34dbc75f34c243df
2011-04-04 13:11:07 +00:00
drh 6f7fe3ef3e This is a version of the SQLite 3.7.5 release with Apple's changes for MacOS.
FossilOrigin-Name: 55d2e55b7b0f7851a565e3a982f772afdf8d7a12
2011-02-10 01:49:18 +00:00
drh e3a4e11bcc Pull in all the changes from trunk up through the version 3.7.5
release candidate 1.

FossilOrigin-Name: 09d6c91dcff0699daec02de0cfd1cdc4e61b4f6b
2011-01-27 18:48:02 +00:00
drh 67d225da53 Merge in all changes to the trunk through version 3.7.4rc3.
FossilOrigin-Name: d2ccf7fc0673e875ff7b84cd37b89c65df4bec7f
2010-12-07 15:49:03 +00:00
drh 5a5ced7da9 Merge all the latest changes from the trunk into the apple-osx branch.
FossilOrigin-Name: c8bc057c7def6bbbebd89ee52b582bad75fb0509
2010-11-19 23:50:48 +00:00
adam 985be1bce6 Integrated proxy locking file support for WAL journal mode and double free fix
FossilOrigin-Name: fd4d38fa66de85676189ff4922fb1bf5f8cac9c4
2010-11-09 00:43:59 +00:00
adam 99f24349ea fixed memory leak in proxy lock file error handling
FossilOrigin-Name: e01c5f3eda7fe6e6afe9c3894384f09b58173da1
2010-09-10 23:16:16 +00:00
adam 890b69fb83 replaced relative lock proxy paths with absolute
FossilOrigin-Name: 782c33512ab2b677b0734c591fcecddc5a655203
2010-09-10 20:19:06 +00:00
adam f5d6f1e0c5 replaced relative lock proxy paths with absolute
FossilOrigin-Name: 6a88cd46aeef3c50c91d5aadc61dd0b0982f8a4f
2010-09-10 00:59:28 +00:00
drh 5ec0cfe070 Make sure SQLite is running with MEMSTATUS enabled at the beginning of every
test script.

FossilOrigin-Name: b6e9a4d8f7d8b683b4098270e0be149df1ef295f
2010-09-10 00:18:12 +00:00
drh 3b3b1a538d Make sure MEMSTATUS is enabled at the beginning of the memsubsys2.test
script.

FossilOrigin-Name: cf23a354975f581c2cf2299e2b2a4e00819830ad
2010-09-09 23:40:42 +00:00
drh b0fa210aa3 The merge for check-in [415c448dc4] did not do exactly write, resulting in
a subtle bug in the SQLITE_FCNTL_SIZE_HINT logic.  This check-in is the
fix.

FossilOrigin-Name: badaaa18fd4a4402add6ae1b3ecadbb79f91fe37
2010-09-09 23:31:36 +00:00
drh 801829c812 Merge in the R-tree fix from the trunk.
FossilOrigin-Name: 02ee0bd5a305e3a6cd76f2e304f8a7effacd8433
2010-08-24 01:51:07 +00:00
drh 9b3c15e860 Merge changes through release 3.7.2 into the apple-osx branch.
FossilOrigin-Name: 415c448dc45a297bd1b0bbce25c4572eeab286f0
2010-08-24 01:08:11 +00:00
drh 61d3bfb78b Merge the 3.7.1 pre-release snapshot changes as of [2010-08-18]
into the apple-osx branch.

FossilOrigin-Name: 866e9286ae4226b2bec40ef18c672a41768abf1f
2010-08-18 00:24:09 +00:00
adam 45d55a254b Updating apple-osx with minor source fixes, database truncate and replace private calls and a bunch of conditionalization for tests running in different environments
FossilOrigin-Name: 5e2ee7db0f7a2a042b182336438107e2248d7b88
2010-08-18 00:09:47 +00:00
drh 51e5db70b6 Merge in all changes up to the 3.7.0.1 release.
FossilOrigin-Name: f88c6367d2f96cc93846ba38e6b963a1a3936e8d
2010-08-07 11:46:07 +00:00
drh f219bba933 Backport fix [a6bb2108bfb56] for a typo in the OS/2 interface.
FossilOrigin-Name: 042a1abb030a0711386add7eb6e10832cc8b0f57
2010-08-04 12:31:10 +00:00
drh a0166e1873 Update the version number to 3.7.0.1.
FossilOrigin-Name: 5074b85967df8f55739ba790924347c764288a88
2010-08-04 12:19:24 +00:00
drh aff0449d8f Backport fix [267492d3a7eff7b] for the performance regression caused by
automatic indexing and reported by ticket [8011086c85c6c4040].

FossilOrigin-Name: 3f367fe00e2adf87f3cc426466db4e3088e6f175
2010-08-04 12:13:35 +00:00
drh c55e9b815f Backport the [65b8636ac6e5] fix for ticket [51ae9cad317a1] to version 3.7.0.
FossilOrigin-Name: dec70c63d052bbe41fc4a065109d2845c67d3f15
2010-08-04 11:59:06 +00:00
drh 03ba419b3c Merge in changes up to and including the 3.6.23.1 release.
FossilOrigin-Name: 21ca87f69125a9e7124c6ddc566d17f64661b0d3
2010-06-16 19:48:56 +00:00
drh c4098a3d9f Cherry-pick the SQLITE_FCNTL_SIZE_HINT patch (check-in [2b7e3b4a30d6a7c4a8]
and bump the version number to 3.6.23.2.

FossilOrigin-Name: 776679af588625f13307369770979bccae7cf03a
2010-05-19 22:09:19 +00:00
drh 21ce77989a Disable the corruptE test which SQLITE_OVERSIZE_CELL_CHECK is enabled.
This is a cherrypick merge from check-in [1dc4f9fe9b83467ba].

FossilOrigin-Name: a40d080ca3c5f152f3296caf48f20728f61317de
2010-05-19 20:30:15 +00:00
drh 91973abb4b Include shell.c and sqlite3.def in the amalgamation ZIP archive.
Ticket [e063139eb3f8]

FossilOrigin-Name: b51fcac9fb4207810ee8d33ead47886e9c46d224
2010-03-31 11:56:47 +00:00
drh 722db051c6 Update the version number to 3.6.23.1.
FossilOrigin-Name: b078b588d617e07886ad156e9f54ade6d823568e
2010-03-26 22:28:06 +00:00
drh 87dd60cd8d Pull in other fixes from the trunk: check-ins [bea9258643],
[f186b6a619], and [bb591802ff].

FossilOrigin-Name: b1f342a6643829020beef542a0700d90822e6467
2010-03-26 21:53:11 +00:00
drh 7244fdc446 Fix to the crash8.test test script.
FossilOrigin-Name: f18a129a7aab09a1e0d34155e82bcbf7479a401d
2010-03-26 21:47:59 +00:00
drh 4f7e8fcded Enhance FTS3 to take advantage of the MAX() optimization.
Cherrypick of [b7e42ae774].

FossilOrigin-Name: 4b65b4805100852a2b6a834aa6efc0bbf25b539f
2010-03-26 17:42:57 +00:00
drh 95063a5774 Correctly handle strings with zero-length tokens in the FTS3 offsets()
function.  This is a cherrypick of [d37034f7fc].

FossilOrigin-Name: ff6ae4f0e461fb5f8d08a0092488b7cd71cffb05
2010-03-26 17:40:32 +00:00
drh ad7c2a87f5 After any rollback that modifies the database file, sync the database
before deleting the rollback journal.  This is a cherry-pick merge
of check-ins [b21b911f23] and [f2326dad4e]

FossilOrigin-Name: ca0bc2a22e893062876f67e0f53cbab44b45665d
2010-03-26 17:37:12 +00:00
adam cc3ec7cb2b fix merge error and compiler warning
FossilOrigin-Name: 5c0afe70a5ee2b378896bf30426823dc5ae4e95c
2010-02-26 22:05:01 +00:00
adam 3942b4b147 More double free paranoia
FossilOrigin-Name: 62dfb44b3b66c4acb1a7a10c44cbee1022a88883
2010-02-26 20:54:10 +00:00
drh 9aa0012a08 Merge latest changes from the trunk into the apple-osx branch.
FossilOrigin-Name: 4b72e39bd00572d9375639f4b978eff1b1d9aa20
2010-02-17 19:34:11 +00:00
adam efd8e3b33d Updated open mask to include SQLITE_OPEN_AUTOPROXY
FossilOrigin-Name: 7c3bede3f21812aa78105c6685654f12f0460eea
2010-01-26 01:14:33 +00:00
drh 0b90b2209f Align the os_unix.c source file with the version found on trunk.
FossilOrigin-Name: fa0f6c140e8ff9a5eed1d8a339fb6d55ecdca688
2010-01-20 13:20:22 +00:00
drh 9782039bde Update the Apple OS-X branch to include all of the latest changes in trunk.
FossilOrigin-Name: 96499b1dd69a0954e30e4b5b4f2272ab306afcdb
2010-01-20 01:26:07 +00:00
adam 332aa832ce robustness fixes for preventing a finalized statement from being reused
FossilOrigin-Name: a7a0c8d644873764cb799f9d6aacede4a4fb531f
2010-01-19 23:50:21 +00:00
drh bf4cad1e4c Update the OS-X branch to include all trunk changes through version 3.6.22.
FossilOrigin-Name: 541e2b488e4e40706e457c6d3b5647d53da02ce9
2010-01-06 13:12:48 +00:00
drh b0c5edcd06 Fix the main.mk makefile so that the sqlrr extension is built into the
amalgamation correctly.

FossilOrigin-Name: a3204d8a217d47e5120ab16918c1b7d4be5a021e
2009-12-23 18:06:49 +00:00
drh 2250799f0c Merge the latest changes on trunk (and especially the fix for
the (xANDy)OR(z) bug) into apple-osx.

FossilOrigin-Name: 5754a3a56144ee0e073c80651bf11cb23ee7f447
2009-12-16 23:46:11 +00:00
drh ca071dfd75 Merge all changes associated with the version 3.6.21 release into the OS-X
branch.

FossilOrigin-Name: ad08794d7239bb804eb39c00170821732b60cb65
2009-12-07 23:53:51 +00:00
adam ac0c39980a Fix for lock structure sharing with AFP-style locking
FossilOrigin-Name: 62f15c0aeaec5d778addb6edba62411c698bec0f
2009-11-09 19:30:44 +00:00
drh 04d4227255 Fix an undefined variable on non-Mac builds.
FossilOrigin-Name: 9552de8fb5ec7554c989edc138c0324c5fd0a206
2009-11-05 18:31:55 +00:00
adam e6c3c72c1b Merging in OSX customizations:
A ext/sqlrr/sqlrr.[ch]
-- add sql recording/replay support (very experimental extension -- pre alpha)

M ext/rtree/rtree.c
-- fix cast compiler warning

M src/func.c
-- substring backward compatiblity <rdar://problem/6778339> 

M src/legacy.c
-- replay recorder calls

M src/main.c
-- if SQLITE_ENABLE_AUTO_PROFILE, call sqlite3_profile when env(SQLITE_AUTO_PROFILE)   
-- replay recorder calls

M src/mem1.c
-- use custom malloc zone on single core systems

M src/os_unix.c
-- hostid via gethostuuid
-- read-only file system support for proxy locking
-- improved handling of simulated shared lock on AFP/SMB on 64 bit systems
-- disable whole-file-lock NFS file locking
-- fix for downgrading from exclusive to shared lock on NFS
-- proxy lock breaking & recreating local lock files
-- support SQLITE_OPEN_AUTOPROXY flag
-- only write 1st byte into new zero-length files if fs is DOS
-- cache fs type info in unixFile struct
-- force use of fsync() even if fdatasync() is available
-- remove flock locking style support for SMB
-- replace strcpy with strlcpy

M src/prepare.c
-- replay recorder calls

M src/sqlite.h.in
-- added SQLITE_OPEN_AUTOPROXY

M src/sqliteInt.h
-- include replay recorder header

M src/vdbeapi.c
-- checking for NULL statement for <rdar://6646331> 
-- replay recorder calls

FossilOrigin-Name: 941a01eb868815f566539e9ab21f807d9e798e40
2009-11-03 22:34:35 +00:00
856 changed files with 21089 additions and 117316 deletions
-1
View File
@@ -1 +0,0 @@
compat
-1
View File
@@ -1 +0,0 @@
compat/*
+57 -163
View File
@@ -63,7 +63,7 @@ LIBREADLINE = @TARGET_READLINE_LIBS@
# Should the database engine be compiled threadsafe
#
TCC += -DSQLITE_THREADSAFE=@SQLITE_THREADSAFE@
#TCC += -DSQLITE_THREADSAFE=@SQLITE_THREADSAFE@
# Any target libraries which libsqlite must be linked against
#
@@ -89,9 +89,6 @@ TCC += $(OPT_FEATURE_FLAGS)
# ie. make "OPTS=-DSQLITE_ENABLE_FOO=1 -DSQLITE_OMIT_FOO=1".
TCC += $(OPTS)
# Add in compile-time options for some libraries used by extensions
TCC += @HAVE_ZLIB@
# Version numbers and release number for the SQLite being compiled.
#
VERSION = @VERSION@
@@ -117,7 +114,7 @@ TCLSH_CMD = @TCLSH_CMD@
# Where do we want to install the tcl plugin
#
TCLLIBDIR = @TCLLIBDIR@
TCLLIBDIR = /System/Library/Tcl
# The suffix used on shared libraries. Ex: ".dll", ".so", ".dylib"
#
@@ -169,8 +166,7 @@ USE_AMALGAMATION = @USE_AMALGAMATION@
#
LIBOBJS0 = alter.lo analyze.lo attach.lo auth.lo \
backup.lo bitvec.lo btmutex.lo btree.lo build.lo \
callback.lo complete.lo ctime.lo \
date.lo dbpage.lo dbstat.lo delete.lo \
callback.lo complete.lo ctime.lo date.lo dbstat.lo delete.lo \
expr.lo fault.lo fkey.lo \
fts3.lo fts3_aux.lo fts3_expr.lo fts3_hash.lo fts3_icu.lo \
fts3_porter.lo fts3_snippet.lo fts3_tokenizer.lo fts3_tokenizer1.lo \
@@ -180,14 +176,14 @@ LIBOBJS0 = alter.lo analyze.lo attach.lo auth.lo \
func.lo global.lo hash.lo \
icu.lo insert.lo json1.lo legacy.lo loadext.lo \
main.lo malloc.lo mem0.lo mem1.lo mem2.lo mem3.lo mem5.lo \
memdb.lo memjournal.lo \
memjournal.lo \
mutex.lo mutex_noop.lo mutex_unix.lo mutex_w32.lo \
notify.lo opcodes.lo os.lo os_unix.lo os_win.lo \
pager.lo parse.lo pcache.lo pcache1.lo pragma.lo prepare.lo printf.lo \
random.lo resolve.lo rowset.lo rtree.lo \
sqlite3session.lo select.lo sqlite3rbu.lo status.lo stmt.lo \
sqlite3session.lo select.lo sqlite3rbu.lo status.lo \
table.lo threads.lo tokenize.lo treeview.lo trigger.lo \
update.lo upsert.lo util.lo vacuum.lo \
update.lo util.lo vacuum.lo \
vdbe.lo vdbeapi.lo vdbeaux.lo vdbeblob.lo vdbemem.lo vdbesort.lo \
vdbetrace.lo wal.lo walker.lo where.lo wherecode.lo whereexpr.lo \
utf.lo vtab.lo
@@ -219,7 +215,6 @@ SRC = \
$(TOP)/src/complete.c \
$(TOP)/src/ctime.c \
$(TOP)/src/date.c \
$(TOP)/src/dbpage.c \
$(TOP)/src/dbstat.c \
$(TOP)/src/delete.c \
$(TOP)/src/expr.c \
@@ -240,7 +235,6 @@ SRC = \
$(TOP)/src/mem2.c \
$(TOP)/src/mem3.c \
$(TOP)/src/mem5.c \
$(TOP)/src/memdb.c \
$(TOP)/src/memjournal.c \
$(TOP)/src/msvc.h \
$(TOP)/src/mutex.c \
@@ -271,7 +265,7 @@ SRC = \
$(TOP)/src/rowset.c \
$(TOP)/src/select.c \
$(TOP)/src/status.c \
$(TOP)/src/shell.c.in \
$(TOP)/src/shell.c \
$(TOP)/src/sqlite.h.in \
$(TOP)/src/sqlite3ext.h \
$(TOP)/src/sqliteInt.h \
@@ -284,7 +278,6 @@ SRC = \
$(TOP)/src/trigger.c \
$(TOP)/src/utf.c \
$(TOP)/src/update.c \
$(TOP)/src/upsert.c \
$(TOP)/src/util.c \
$(TOP)/src/vacuum.c \
$(TOP)/src/vdbe.c \
@@ -350,6 +343,9 @@ SRC += \
SRC += \
$(TOP)/ext/rtree/rtree.h \
$(TOP)/ext/rtree/rtree.c
SRC += \
$(TOP)/ext/sqlrr/sqlrr.h \
$(TOP)/ext/sqlrr/sqlrr.c
SRC += \
$(TOP)/ext/session/sqlite3session.c \
$(TOP)/ext/session/sqlite3session.h
@@ -357,8 +353,7 @@ SRC += \
$(TOP)/ext/rbu/sqlite3rbu.h \
$(TOP)/ext/rbu/sqlite3rbu.c
SRC += \
$(TOP)/ext/misc/json1.c \
$(TOP)/ext/misc/stmt.c
$(TOP)/ext/misc/json1.c
# Generated source code files
#
@@ -369,7 +364,6 @@ SRC += \
parse.c \
parse.h \
config.h \
shell.c \
sqlite3.h
# Source code to the test files.
@@ -391,7 +385,6 @@ TESTSRC = \
$(TOP)/src/test_blob.c \
$(TOP)/src/test_btree.c \
$(TOP)/src/test_config.c \
$(TOP)/src/test_delete.c \
$(TOP)/src/test_demovfs.c \
$(TOP)/src/test_devsym.c \
$(TOP)/src/test_fs.c \
@@ -401,7 +394,6 @@ TESTSRC = \
$(TOP)/src/test_intarray.c \
$(TOP)/src/test_journal.c \
$(TOP)/src/test_malloc.c \
$(TOP)/src/test_md5.c \
$(TOP)/src/test_multiplex.c \
$(TOP)/src/test_mutex.c \
$(TOP)/src/test_onefile.c \
@@ -413,7 +405,6 @@ TESTSRC = \
$(TOP)/src/test_server.c \
$(TOP)/src/test_superlock.c \
$(TOP)/src/test_syscall.c \
$(TOP)/src/test_tclsh.c \
$(TOP)/src/test_tclvar.c \
$(TOP)/src/test_thread.c \
$(TOP)/src/test_vfs.c \
@@ -427,8 +418,6 @@ TESTSRC = \
# Statically linked extensions
#
TESTSRC += \
$(TOP)/ext/expert/sqlite3expert.c \
$(TOP)/ext/expert/test_expert.c \
$(TOP)/ext/misc/amatch.c \
$(TOP)/ext/misc/carray.c \
$(TOP)/ext/misc/closure.c \
@@ -440,18 +429,13 @@ TESTSRC += \
$(TOP)/ext/fts5/fts5_test_mi.c \
$(TOP)/ext/fts5/fts5_test_tok.c \
$(TOP)/ext/misc/ieee754.c \
$(TOP)/ext/misc/mmapwarm.c \
$(TOP)/ext/misc/nextchar.c \
$(TOP)/ext/misc/normalize.c \
$(TOP)/ext/misc/percentile.c \
$(TOP)/ext/misc/regexp.c \
$(TOP)/ext/misc/remember.c \
$(TOP)/ext/misc/series.c \
$(TOP)/ext/misc/spellfix.c \
$(TOP)/ext/misc/totype.c \
$(TOP)/ext/misc/unionvtab.c \
$(TOP)/ext/misc/wholenumber.c \
$(TOP)/ext/misc/zipfile.c
$(TOP)/ext/misc/wholenumber.c
# Source code to the library files needed by the test fixture
#
@@ -463,7 +447,6 @@ TESTSRC2 = \
$(TOP)/src/build.c \
$(TOP)/src/ctime.c \
$(TOP)/src/date.c \
$(TOP)/src/dbpage.c \
$(TOP)/src/dbstat.c \
$(TOP)/src/expr.c \
$(TOP)/src/func.c \
@@ -501,8 +484,7 @@ TESTSRC2 = \
$(TOP)/ext/fts3/fts3_tokenizer.c \
$(TOP)/ext/fts3/fts3_write.c \
$(TOP)/ext/async/sqlite3async.c \
$(TOP)/ext/session/sqlite3session.c \
$(TOP)/ext/misc/stmt.c
$(TOP)/ext/session/sqlite3session.c
# Header files used by all library source files.
#
@@ -554,6 +536,17 @@ EXTHDR += \
$(TOP)/ext/icu/sqliteicu.h
EXTHDR += \
$(TOP)/ext/rtree/sqlite3rtree.h
EXTHDR += \
$(TOP)/ext/sqlrr/sqlrr.h
# If using the amalgamation, use sqlite3.c directly to build the test
# fixture. Otherwise link against libsqlite3.la. (This distinction is
# necessary because the test fixture requires non-API symbols which are
# hidden when the library is built via the amalgamation).
#
TESTFIXTURE_SRC0 = $(TESTSRC2) libsqlite3.la
TESTFIXTURE_SRC1 = sqlite3.c
TESTFIXTURE_SRC = $(TESTSRC) $(TOP)/src/tclsqlite.c $(TESTFIXTURE_SRC$(USE_AMALGAMATION))
# executables needed for testing
#
@@ -562,8 +555,7 @@ TESTPROGS = \
sqlite3$(TEXE) \
sqlite3_analyzer$(TEXE) \
sqldiff$(TEXE) \
dbhash$(TEXE) \
sqltclsh$(TEXE)
dbhash$(TEXE)
# Databases containing fuzzer test cases
#
@@ -571,9 +563,7 @@ FUZZDATA = \
$(TOP)/test/fuzzdata1.db \
$(TOP)/test/fuzzdata2.db \
$(TOP)/test/fuzzdata3.db \
$(TOP)/test/fuzzdata4.db \
$(TOP)/test/fuzzdata5.db \
$(TOP)/test/fuzzdata6.db
$(TOP)/test/fuzzdata4.db
# Standard options to testfixture
#
@@ -582,21 +572,11 @@ TESTOPTS = --verbose=file --output=test-out.txt
# Extra compiler options for various shell tools
#
SHELL_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS4
#SHELL_OPT += -DSQLITE_ENABLE_FTS5
SHELL_OPT += -DSQLITE_ENABLE_RTREE
# SHELL_OPT += -DSQLITE_ENABLE_FTS5
SHELL_OPT += -DSQLITE_ENABLE_EXPLAIN_COMMENTS
SHELL_OPT += -DSQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
SHELL_OPT += -DSQLITE_ENABLE_STMTVTAB
SHELL_OPT += -DSQLITE_ENABLE_DBPAGE_VTAB
SHELL_OPT += -DSQLITE_ENABLE_DBSTAT_VTAB
SHELL_OPT += -DSQLITE_ENABLE_OFFSET_SQL_FUNC
SHELL_OPT += -DSQLITE_INTROSPECTION_PRAGMAS
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_SRC = $(TOP)/test/fuzzcheck.c $(TOP)/test/ossfuzz.c
DBFUZZ_OPT =
FUZZCHECK_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5
# This is the default Makefile target. The objects listed here
# are what get build when you type just "make" with no arguments.
@@ -616,13 +596,12 @@ libsqlite3.la: $(LIBOBJ)
libtclsqlite3.la: tclsqlite.lo libsqlite3.la
$(LTLINK) -no-undefined -o $@ tclsqlite.lo \
libsqlite3.la @TCL_STUB_LIB_SPEC@ $(TLIBS) \
-rpath "$(TCLLIBDIR)" \
-version-info "8:6:8" \
-avoid-version
-rpath "$(TCLLIBDIR)/sqlite3" \
-version-info "8:6:8"
sqlite3$(TEXE): shell.c sqlite3.c
sqlite3$(TEXE): $(TOP)/src/shell.c sqlite3.c
$(LTLINK) $(READLINE_FLAGS) $(SHELL_OPT) -o $@ \
shell.c sqlite3.c \
$(TOP)/src/shell.c sqlite3.c \
$(LIBREADLINE) $(TLIBS) -rpath "$(libdir)"
sqldiff$(TEXE): $(TOP)/tool/sqldiff.c sqlite3.lo sqlite3.h
@@ -645,18 +624,8 @@ fuzzershell$(TEXE): $(TOP)/tool/fuzzershell.c sqlite3.c sqlite3.h
$(LTLINK) -o $@ $(FUZZERSHELL_OPT) \
$(TOP)/tool/fuzzershell.c sqlite3.c $(TLIBS)
fuzzcheck$(TEXE): $(FUZZCHECK_SRC) sqlite3.c sqlite3.h
$(LTLINK) -o $@ $(FUZZCHECK_OPT) $(FUZZCHECK_SRC) sqlite3.c $(TLIBS)
ossshell$(TEXE): $(TOP)/test/ossfuzz.c $(TOP)/test/ossshell.c sqlite3.c sqlite3.h
$(LTLINK) -o $@ $(FUZZCHECK_OPT) $(TOP)/test/ossshell.c \
$(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)
dbfuzz$(TEXE): $(TOP)/test/dbfuzz.c sqlite3.c sqlite3.h
$(LTLINK) -o $@ $(DBFUZZ_OPT) $(TOP)/test/dbfuzz.c sqlite3.c $(TLIBS)
fuzzcheck$(TEXE): $(TOP)/test/fuzzcheck.c sqlite3.c sqlite3.h
$(LTLINK) -o $@ $(FUZZCHECK_OPT) $(TOP)/test/fuzzcheck.c sqlite3.c $(TLIBS)
mptester$(TEXE): sqlite3.lo $(TOP)/mptest/mptest.c
$(LTLINK) -o $@ -I. $(TOP)/mptest/mptest.c sqlite3.lo \
@@ -694,7 +663,7 @@ mptest: mptester$(TEXE)
sqlite3.c: .target_source $(TOP)/tool/mksqlite3c.tcl
$(TCLSH_CMD) $(TOP)/tool/mksqlite3c.tcl
cp tsrc/sqlite3ext.h .
cp tsrc/shell.c tsrc/sqlite3ext.h .
cp $(TOP)/ext/session/sqlite3session.h .
sqlite3ext.h: .target_source
@@ -720,11 +689,6 @@ lemon$(BEXE): $(TOP)/tool/lemon.c $(TOP)/tool/lempar.c
$(BCC) -o $@ $(TOP)/tool/lemon.c
cp $(TOP)/tool/lempar.c .
# Rules to build the program that generates the source-id
#
mksourceid$(BEXE): $(TOP)/tool/mksourceid.c
$(BCC) -o $@ $(TOP)/tool/mksourceid.c
# Rules to build individual *.o files from generated *.c files. This
# applies to:
#
@@ -778,9 +742,6 @@ ctime.lo: $(TOP)/src/ctime.c $(HDR)
date.lo: $(TOP)/src/date.c $(HDR)
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/date.c
dbpage.lo: $(TOP)/src/dbpage.c $(HDR)
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/dbpage.c
dbstat.lo: $(TOP)/src/dbstat.c $(HDR)
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/dbstat.c
@@ -835,9 +796,6 @@ mem3.lo: $(TOP)/src/mem3.c $(HDR)
mem5.lo: $(TOP)/src/mem5.c $(HDR)
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/mem5.c
memdb.lo: $(TOP)/src/memdb.c $(HDR)
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/memdb.c
memjournal.lo: $(TOP)/src/memjournal.c $(HDR)
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/memjournal.c
@@ -916,9 +874,6 @@ trigger.lo: $(TOP)/src/trigger.c $(HDR)
update.lo: $(TOP)/src/update.c $(HDR)
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/update.c
upsert.lo: $(TOP)/src/upsert.c $(HDR)
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/upsert.c
utf.lo: $(TOP)/src/utf.c $(HDR)
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/utf.c
@@ -971,7 +926,7 @@ tclsqlite.lo: $(TOP)/src/tclsqlite.c $(HDR)
$(LTCOMPILE) -DUSE_TCL_STUBS=1 -c $(TOP)/src/tclsqlite.c
tclsqlite-shell.lo: $(TOP)/src/tclsqlite.c $(HDR)
$(LTCOMPILE) -DTCLSH -o $@ -c $(TOP)/src/tclsqlite.c
$(LTCOMPILE) -DTCLSH=1 -o $@ -c $(TOP)/src/tclsqlite.c
tclsqlite-stubs.lo: $(TOP)/src/tclsqlite.c $(HDR)
$(LTCOMPILE) -DUSE_TCL_STUBS=1 -o $@ -c $(TOP)/src/tclsqlite.c
@@ -999,30 +954,13 @@ parse.c: $(TOP)/src/parse.y lemon$(BEXE) $(TOP)/tool/addopcodes.tcl
mv parse.h parse.h.temp
$(TCLSH_CMD) $(TOP)/tool/addopcodes.tcl parse.h.temp >parse.h
sqlite3.h: $(TOP)/src/sqlite.h.in $(TOP)/manifest mksourceid$(BEXE) $(TOP)/VERSION
sqlite3.h: $(TOP)/src/sqlite.h.in $(TOP)/manifest.uuid $(TOP)/VERSION
$(TCLSH_CMD) $(TOP)/tool/mksqlite3h.tcl $(TOP) >sqlite3.h
keywordhash.h: $(TOP)/tool/mkkeywordhash.c
$(BCC) -o mkkeywordhash$(BEXE) $(OPT_FEATURE_FLAGS) $(OPTS) $(TOP)/tool/mkkeywordhash.c
./mkkeywordhash$(BEXE) >keywordhash.h
# Source files that go into making shell.c
SHELL_SRC = \
$(TOP)/src/shell.c.in \
$(TOP)/ext/misc/appendvfs.c \
$(TOP)/ext/misc/shathree.c \
$(TOP)/ext/misc/fileio.c \
$(TOP)/ext/misc/completion.c \
$(TOP)/ext/misc/sqlar.c \
$(TOP)/ext/expert/sqlite3expert.c \
$(TOP)/ext/expert/sqlite3expert.h \
$(TOP)/ext/misc/zipfile.c \
$(TOP)/src/test_windirent.c
shell.c: $(SHELL_SRC) $(TOP)/tool/mkshellc.tcl
$(TCLSH_CMD) $(TOP)/tool/mkshellc.tcl >shell.c
# Rules to build the extension objects.
@@ -1096,9 +1034,6 @@ sqlite3session.lo: $(TOP)/ext/session/sqlite3session.c $(HDR) $(EXTHDR)
json1.lo: $(TOP)/ext/misc/json1.c
$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/misc/json1.c
stmt.lo: $(TOP)/ext/misc/stmt.c
$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/misc/stmt.c
# FTS5 things
#
FTS5_SRC = \
@@ -1143,14 +1078,11 @@ sqlite3rbu.lo: $(TOP)/ext/rbu/sqlite3rbu.c $(HDR) $(EXTHDR)
# necessary because the test fixture requires non-API symbols which are
# hidden when the library is built via the amalgamation).
#
TESTFIXTURE_FLAGS = -DSQLITE_TEST=1 -DSQLITE_CRASH_TEST=1
TESTFIXTURE_FLAGS += -DTCLSH_INIT_PROC=sqlite3TestInit
TESTFIXTURE_FLAGS = -DTCLSH=1 -DSQLITE_TEST=1 -DSQLITE_CRASH_TEST=1
TESTFIXTURE_FLAGS += -DSQLITE_SERVER=1 -DSQLITE_PRIVATE="" -DSQLITE_CORE
TESTFIXTURE_FLAGS += -DBUILD_sqlite
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_SRC0 = $(TESTSRC2) libsqlite3.la
TESTFIXTURE_SRC1 = sqlite3.c
@@ -1174,22 +1106,14 @@ fulltestonly: $(TESTPROGS) fuzztest
./testfixture$(TEXE) $(TOP)/test/full.test
# Fuzz testing
fuzztest: fuzzcheck$(TEXE) $(FUZZDATA) sessionfuzz$(TEXE) $(TOP)/test/sessionfuzz-data1.db
fuzztest: fuzzcheck$(TEXE) $(FUZZDATA)
./fuzzcheck$(TEXE) $(FUZZDATA)
./sessionfuzz$(TEXE) run $(TOP)/test/sessionfuzz-data1.db
fastfuzztest: fuzzcheck$(TEXE) $(FUZZDATA) sessionfuzz$(TEXE) $(TOP)/test/sessionfuzz-data1.db
fastfuzztest: fuzzcheck$(TEXE) $(FUZZDATA)
./fuzzcheck$(TEXE) --limit-mem 100M $(FUZZDATA)
./sessionfuzz$(TEXE) run $(TOP)/test/sessionfuzz-data1.db
valgrindfuzz: fuzzcheck$(TEXT) $(FUZZDATA) sessionfuzz$(TEXE) $(TOP)/test/sessionfuzz-data1.db
valgrindfuzz: fuzzcheck$(TEXT) $(FUZZDATA)
valgrind ./fuzzcheck$(TEXE) --cell-size-check --limit-mem 10M --timeout 600 $(FUZZDATA)
valgrind ./sessionfuzz$(TEXE) run $(TOP)/test/sessionfuzz-data1.db
# The veryquick.test TCL tests.
#
tcltest: ./testfixture$(TEXE)
./testfixture$(TEXE) $(TOP)/test/veryquick.test $(TESTOPTS)
# Minimal testing that runs in less than 3 minutes
#
@@ -1199,7 +1123,8 @@ quicktest: ./testfixture$(TEXE)
# This is the common case. Run many tests that do not take too long,
# including fuzzcheck, sqlite3_analyzer, and sqldiff tests.
#
test: fastfuzztest sourcetest $(TESTPROGS) tcltest
test: $(TESTPROGS) sourcetest fastfuzztest
./testfixture$(TEXE) $(TOP)/test/veryquick.test $(TESTOPTS)
# Run a test using valgrind. This can take a really long time
# because valgrind is so much slower than a native machine.
@@ -1214,41 +1139,18 @@ valgrindtest: $(TESTPROGS) valgrindfuzz
smoketest: $(TESTPROGS) fuzzcheck$(TEXE)
./testfixture$(TEXE) $(TOP)/test/main.test $(TESTOPTS)
sqlite3_analyzer.c: sqlite3.c $(TOP)/src/tclsqlite.c $(TOP)/tool/spaceanal.tcl $(TOP)/tool/mkccode.tcl $(TOP)/tool/sqlite3_analyzer.c.in
$(TCLSH_CMD) $(TOP)/tool/mkccode.tcl $(TOP)/tool/sqlite3_analyzer.c.in >sqlite3_analyzer.c
sqlite3_analyzer.c: sqlite3.c $(TOP)/src/tclsqlite.c $(TOP)/tool/spaceanal.tcl
echo "#define TCLSH 2" > $@
echo "#define SQLITE_ENABLE_DBSTAT_VTAB 1" >> $@
cat sqlite3.c $(TOP)/src/tclsqlite.c >> $@
echo "static const char *tclsh_main_loop(void){" >> $@
echo "static const char *zMainloop = " >> $@
$(TCLSH_CMD) $(TOP)/tool/tostr.tcl $(TOP)/tool/spaceanal.tcl >> $@
echo "; return zMainloop; }" >> $@
sqlite3_analyzer$(TEXE): sqlite3_analyzer.c
$(LTLINK) sqlite3_analyzer.c -o $@ $(LIBTCL) $(TLIBS)
sqltclsh.c: sqlite3.c $(TOP)/src/tclsqlite.c $(TOP)/tool/sqltclsh.tcl $(TOP)/ext/misc/appendvfs.c $(TOP)/tool/mkccode.tcl $(TOP)/tool/sqltclsh.c.in
$(TCLSH_CMD) $(TOP)/tool/mkccode.tcl $(TOP)/tool/sqltclsh.c.in >sqltclsh.c
sqltclsh$(TEXE): sqltclsh.c
$(LTLINK) sqltclsh.c -o $@ $(LIBTCL) $(TLIBS)
sqlite3_expert$(TEXE): $(TOP)/ext/expert/sqlite3expert.h $(TOP)/ext/expert/sqlite3expert.c $(TOP)/ext/expert/expert.c sqlite3.c
$(LTLINK) $(TOP)/ext/expert/sqlite3expert.h $(TOP)/ext/expert/sqlite3expert.c $(TOP)/ext/expert/expert.c sqlite3.c -o sqlite3_expert $(TLIBS)
CHECKER_DEPS =\
$(TOP)/tool/mkccode.tcl \
sqlite3.c \
$(TOP)/src/tclsqlite.c \
$(TOP)/ext/repair/sqlite3_checker.tcl \
$(TOP)/ext/repair/checkindex.c \
$(TOP)/ext/repair/checkfreelist.c \
$(TOP)/ext/misc/btreeinfo.c \
$(TOP)/ext/repair/sqlite3_checker.c.in
sqlite3_checker.c: $(CHECKER_DEPS)
$(TCLSH_CMD) $(TOP)/tool/mkccode.tcl $(TOP)/ext/repair/sqlite3_checker.c.in >$@
sqlite3_checker$(TEXE): sqlite3_checker.c
$(LTLINK) sqlite3_checker.c -o $@ $(LIBTCL) $(TLIBS)
dbdump$(TEXE): $(TOP)/ext/misc/dbdump.c sqlite3.lo
$(LTLINK) -DDBDUMP_STANDALONE -o $@ \
$(TOP)/ext/misc/dbdump.c sqlite3.lo $(TLIBS)
showdb$(TEXE): $(TOP)/tool/showdb.c sqlite3.lo
$(LTLINK) -o $@ $(TOP)/tool/showdb.c sqlite3.lo $(TLIBS)
@@ -1261,9 +1163,6 @@ showjournal$(TEXE): $(TOP)/tool/showjournal.c sqlite3.lo
showwal$(TEXE): $(TOP)/tool/showwal.c sqlite3.lo
$(LTLINK) -o $@ $(TOP)/tool/showwal.c sqlite3.lo $(TLIBS)
showshm$(TEXE): $(TOP)/tool/showshm.c
$(LTLINK) -o $@ $(TOP)/tool/showshm.c
changeset$(TEXE): $(TOP)/ext/session/changeset.c sqlite3.lo
$(LTLINK) -o $@ $(TOP)/ext/session/changeset.c sqlite3.lo $(TLIBS)
@@ -1276,13 +1175,8 @@ LogEst$(TEXE): $(TOP)/tool/logest.c sqlite3.h
wordcount$(TEXE): $(TOP)/test/wordcount.c sqlite3.lo
$(LTLINK) -o $@ $(TOP)/test/wordcount.c sqlite3.lo $(TLIBS)
speedtest1$(TEXE): $(TOP)/test/speedtest1.c sqlite3.c
$(LTLINK) $(ST_OPT) -o $@ $(TOP)/test/speedtest1.c sqlite3.c $(TLIBS)
KV_OPT += -DSQLITE_DIRECT_OVERFLOW_READ
kvtest$(TEXE): $(TOP)/test/kvtest.c sqlite3.c
$(LTLINK) $(KV_OPT) -o $@ $(TOP)/test/kvtest.c sqlite3.c $(TLIBS)
speedtest1$(TEXE): $(TOP)/test/speedtest1.c sqlite3.lo
$(LTLINK) -o $@ $(TOP)/test/speedtest1.c sqlite3.lo $(TLIBS)
rbu$(EXE): $(TOP)/ext/rbu/rbu.c $(TOP)/ext/rbu/sqlite3rbu.c sqlite3.lo
$(LTLINK) -I. -o $@ $(TOP)/ext/rbu/rbu.c sqlite3.lo $(TLIBS)
@@ -1347,10 +1241,10 @@ install: sqlite3$(TEXE) lib_install sqlite3.h sqlite3.pc ${HAVE_TCL:1=tcl_instal
pkgIndex.tcl:
echo 'package ifneeded sqlite3 $(RELEASE) [list load $(TCLLIBDIR)/libtclsqlite3$(SHLIB_SUFFIX) sqlite3]' > $@
tcl_install: lib_install libtclsqlite3.la pkgIndex.tcl
$(INSTALL) -d $(DESTDIR)$(TCLLIBDIR)
$(LTINSTALL) libtclsqlite3.la $(DESTDIR)$(TCLLIBDIR)
rm -f $(DESTDIR)$(TCLLIBDIR)/libtclsqlite3.la $(DESTDIR)$(TCLLIBDIR)/libtclsqlite3.a
$(INSTALL) -m 0644 pkgIndex.tcl $(DESTDIR)$(TCLLIBDIR)
$(INSTALL) -d $(DESTDIR)$(TCLLIBDIR)/sqlite3
$(LTINSTALL) libtclsqlite3.la $(DESTDIR)$(TCLLIBDIR)/sqlite3
rm -f $(DESTDIR)$(TCLLIBDIR)/sqlite3/libtclsqlite3.la $(DESTDIR)$(TCLLIBDIR)/sqlite3/libtclsqlite3.a
$(INSTALL) -m 0644 pkgIndex.tcl $(DESTDIR)$(TCLLIBDIR)/sqlite3
clean:
rm -f *.lo *.la *.o sqlite3$(TEXE) libsqlite3.la
+83 -447
View File
@@ -21,28 +21,7 @@ USE_AMALGAMATION = 1
# Set this non-0 to enable full warnings (-W4, etc) when compiling.
#
!IFNDEF USE_FULLWARN
USE_FULLWARN = 1
!ENDIF
# Set this non-0 to enable treating warnings as errors (-WX, etc) when
# compiling.
#
!IFNDEF USE_FATAL_WARN
USE_FATAL_WARN = 0
!ENDIF
# Set this non-0 to enable full runtime error checks (-RTC1, etc). This
# has no effect if (any) optimizations are enabled.
#
!IFNDEF USE_RUNTIME_CHECKS
USE_RUNTIME_CHECKS = 0
!ENDIF
# Set this non-0 to create a SQLite amalgamation file that excludes the
# various built-in extensions.
#
!IFNDEF MINIMAL_AMALGAMATION
MINIMAL_AMALGAMATION = 0
USE_FULLWARN = 0
!ENDIF
# Set this non-0 to use "stdcall" calling convention for the core library
@@ -92,29 +71,6 @@ SPLIT_AMALGAMATION = 0
!ENDIF
# <<mark>>
# Set this non-0 to have this makefile assume the Tcl shell executable
# (tclsh*.exe) is available in the PATH. By default, this is disabled
# for compatibility with older build environments. This setting only
# applies if TCLSH_CMD is not set manually.
#
!IFNDEF USE_TCLSH_IN_PATH
USE_TCLSH_IN_PATH = 0
!ENDIF
# Set this non-0 to use zlib, possibly compiling it from source code.
#
!IFNDEF USE_ZLIB
USE_ZLIB = 0
!ENDIF
# Set this non-0 to build zlib from source code. This is enabled by
# default and in that case it will be assumed that the ZLIBDIR macro
# points to the top-level source code directory for zlib.
#
!IFNDEF BUILD_ZLIB
BUILD_ZLIB = 1
!ENDIF
# Set this non-0 to use the International Components for Unicode (ICU).
#
!IFNDEF USE_ICU
@@ -307,39 +263,12 @@ SQLITE3EXEPDB = /pdb:sqlite3sh.pdb
!ENDIF
!ENDIF
# <<mark>>
# These are the names of the customized Tcl header files used by various parts
# of this makefile when the stdcall calling convention is in use. It is not
# used for any other purpose.
#
!IFNDEF SQLITETCLH
SQLITETCLH = sqlite_tcl.h
!ENDIF
!IFNDEF SQLITETCLDECLSH
SQLITETCLDECLSH = sqlite_tclDecls.h
!ENDIF
# These are the additional targets that the targets that integrate with the
# Tcl library should depend on when compiling, etc.
#
!IFNDEF SQLITE_TCL_DEP
!IF $(USE_STDCALL)!=0 || $(FOR_WIN10)!=0
SQLITE_TCL_DEP = $(SQLITETCLDECLSH) $(SQLITETCLH)
!ELSE
SQLITE_TCL_DEP =
!ENDIF
!ENDIF
# <</mark>>
# These are the "standard" SQLite compilation options used when compiling for
# the Windows platform.
#
!IFNDEF OPT_FEATURE_FLAGS
!IF $(MINIMAL_AMALGAMATION)==0
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_FTS3=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_RTREE=1
!ENDIF
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_COLUMN_METADATA=1
!ENDIF
@@ -523,12 +452,6 @@ TCC = $(CC) -nologo -W4 -DINCLUDE_MSVC_H=1 $(CCOPTS) $(TCCOPTS)
TCC = $(CC) -nologo -W3 $(CCOPTS) $(TCCOPTS)
!ENDIF
# Check if warnings should be treated as errors when compiling.
#
!IF $(USE_FATAL_WARN)!=0
TCC = $(TCC) -WX
!ENDIF
TCC = $(TCC) -DSQLITE_OS_WIN=1 -I. -I$(TOP) -I$(TOP)\src -fp:precise
RCC = $(RC) -DSQLITE_OS_WIN=1 -I. -I$(TOP) -I$(TOP)\src $(RCOPTS) $(RCCOPTS)
@@ -541,32 +464,20 @@ RCC = $(RC) -DSQLITE_OS_WIN=1 -I. -I$(TOP) -I$(TOP)\src $(RCOPTS) $(RCCOPTS)
#
!IF $(USE_STDCALL)!=0 || $(FOR_WIN10)!=0
!IF "$(PLATFORM)"=="x86"
CORE_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
SHELL_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
# <<mark>>
TEST_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall -DINCLUDE_SQLITE_TCL_H=1 -DSQLITE_TCLAPI=__cdecl
# <</mark>>
CORE_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_STDCALL=__stdcall
SHELL_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_STDCALL=__stdcall
!ELSE
!IFNDEF PLATFORM
CORE_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
SHELL_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
# <<mark>>
TEST_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall -DINCLUDE_SQLITE_TCL_H=1 -DSQLITE_TCLAPI=__cdecl
# <</mark>>
CORE_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_STDCALL=__stdcall
SHELL_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_STDCALL=__stdcall
!ELSE
CORE_CCONV_OPTS =
SHELL_CCONV_OPTS =
# <<mark>>
TEST_CCONV_OPTS =
# <</mark>>
!ENDIF
!ENDIF
!ELSE
CORE_CCONV_OPTS =
SHELL_CCONV_OPTS =
# <<mark>>
TEST_CCONV_OPTS =
# <</mark>>
!ENDIF
# These are additional compiler options used for the core library.
@@ -635,15 +546,6 @@ SHELL_CORE_DEP =
!ENDIF
!ENDIF
# <<mark>>
# If zlib support is enabled, add the dependencies for it.
#
!IF $(USE_ZLIB)!=0 && $(BUILD_ZLIB)!=0
SHELL_CORE_DEP = zlib $(SHELL_CORE_DEP)
TESTFIXTURE_DEP = zlib $(TESTFIXTURE_DEP)
!ENDIF
# <</mark>>
# This is the core library that the shell executable should link with.
#
!IFNDEF SHELL_CORE_LIB
@@ -728,35 +630,12 @@ RCC = $(RCC) -I$(TOP)\ext\session
# options are necessary in order to allow debugging symbols to
# work correctly with Visual Studio when using the amalgamation.
#
!IFNDEF MKSQLITE3C_TOOL
!IF $(MINIMAL_AMALGAMATION)!=0
MKSQLITE3C_TOOL = $(TOP)\tool\mksqlite3c-noext.tcl
!ELSE
MKSQLITE3C_TOOL = $(TOP)\tool\mksqlite3c.tcl
!ENDIF
!ENDIF
!IFNDEF MKSQLITE3C_ARGS
!IF $(DEBUG)>1
MKSQLITE3C_ARGS = --linemacros
!ELSE
MKSQLITE3C_ARGS =
!ENDIF
!IF $(USE_STDCALL)!=0 || $(FOR_WIN10)!=0
MKSQLITE3C_ARGS = $(MKSQLITE3C_ARGS) --useapicall
!ENDIF
!ENDIF
# The mksqlite3h.tcl script accepts some options on the command line.
# When compiling with stdcall support, some of these options are
# necessary.
#
!IFNDEF MKSQLITE3H_ARGS
!IF $(USE_STDCALL)!=0 || $(FOR_WIN10)!=0
MKSQLITE3H_ARGS = --useapicall
!ELSE
MKSQLITE3H_ARGS =
!ENDIF
!ENDIF
# <</mark>>
@@ -778,10 +657,6 @@ RCC = $(RCC) -DSQLITE_ENABLE_API_ARMOR=1
!IF $(DEBUG)>2
TCC = $(TCC) -DSQLITE_DEBUG=1
RCC = $(RCC) -DSQLITE_DEBUG=1
!IF $(DYNAMIC_SHELL)==0
TCC = $(TCC) -DSQLITE_ENABLE_WHERETRACE -DSQLITE_ENABLE_SELECTTRACE
RCC = $(RCC) -DSQLITE_ENABLE_WHERETRACE -DSQLITE_ENABLE_SELECTTRACE
!ENDIF
!ENDIF
!IF $(DEBUG)>4 || $(OSTRACE)!=0
@@ -834,53 +709,24 @@ RCC = $(RCC) -DSQLITE_WIN32_MALLOC_VALIDATE=1
# prior to running nmake in order to match the actual installed location and
# version on this machine.
#
!IFNDEF TCLDIR
TCLDIR = $(TOP)\compat\tcl
!ENDIF
!IFNDEF TCLINCDIR
TCLINCDIR = $(TCLDIR)\include
TCLINCDIR = c:\tcl\include
!ENDIF
!IFNDEF TCLLIBDIR
TCLLIBDIR = $(TCLDIR)\lib
TCLLIBDIR = c:\tcl\lib
!ENDIF
!IFNDEF LIBTCL
LIBTCL = tcl86.lib
LIBTCL = tcl85.lib
!ENDIF
!IFNDEF LIBTCLSTUB
LIBTCLSTUB = tclstub86.lib
LIBTCLSTUB = tclstub85.lib
!ENDIF
!IFNDEF LIBTCLPATH
LIBTCLPATH = $(TCLDIR)\bin
!ENDIF
# The locations of the zlib header and library files. These variables
# (ZLIBINCDIR, ZLIBLIBDIR, and ZLIBLIB) may be overridden via the environment
# prior to running nmake in order to match the actual installed (or source
# code) location on this machine.
#
!IFNDEF ZLIBDIR
ZLIBDIR = $(TOP)\compat\zlib
!ENDIF
!IFNDEF ZLIBINCDIR
ZLIBINCDIR = $(ZLIBDIR)
!ENDIF
!IFNDEF ZLIBLIBDIR
ZLIBLIBDIR = $(ZLIBDIR)
!ENDIF
!IFNDEF ZLIBLIB
!IF $(DYNAMIC_SHELL)!=0
ZLIBLIB = zdll.lib
!ELSE
ZLIBLIB = zlib.lib
!ENDIF
LIBTCLPATH = c:\tcl\bin
!ENDIF
# The locations of the ICU header and library files. These variables
@@ -888,16 +734,12 @@ ZLIBLIB = zlib.lib
# prior to running nmake in order to match the actual installed location on
# this machine.
#
!IFNDEF ICUDIR
ICUDIR = $(TOP)\compat\icu
!ENDIF
!IFNDEF ICUINCDIR
ICUINCDIR = $(ICUDIR)\include
ICUINCDIR = c:\icu\include
!ENDIF
!IFNDEF ICULIBDIR
ICULIBDIR = $(ICUDIR)\lib
ICULIBDIR = c:\icu\lib
!ENDIF
!IFNDEF LIBICU
@@ -910,11 +752,7 @@ LIBICU = icuuc.lib icuin.lib
# specific Tcl shell to use.
#
!IFNDEF TCLSH_CMD
!IF $(USE_TCLSH_IN_PATH)!=0 || !EXIST("$(TCLDIR)\bin\tclsh.exe")
TCLSH_CMD = tclsh
!ELSE
TCLSH_CMD = $(TCLDIR)\bin\tclsh.exe
!ENDIF
TCLSH_CMD = tclsh85
!ENDIF
# <</mark>>
@@ -997,10 +835,6 @@ RCC = $(RCC) -D_DEBUG
!IF $(DEBUG)>1 || $(OPTIMIZATIONS)==0
TCC = $(TCC) -Od
BCC = $(BCC) -Od
!IF $(USE_RUNTIME_CHECKS)!=0
TCC = $(TCC) -RTC1
BCC = $(BCC) -RTC1
!ENDIF
!ELSEIF $(OPTIMIZATIONS)>=3
TCC = $(TCC) -Ox
BCC = $(BCC) -Ox
@@ -1020,15 +854,6 @@ BCC = $(BCC) -Zi
!ENDIF
# <<mark>>
# If zlib support is enabled, add the compiler options for it.
#
!IF $(USE_ZLIB)!=0
TCC = $(TCC) -DSQLITE_HAVE_ZLIB=1
RCC = $(RCC) -DSQLITE_HAVE_ZLIB=1
TCC = $(TCC) -I$(ZLIBINCDIR)
RCC = $(RCC) -I$(ZLIBINCDIR)
!ENDIF
# If ICU support is enabled, add the compiler options for it.
#
!IF $(USE_ICU)!=0
@@ -1052,7 +877,7 @@ LTLINK = $(TCC) -Fe$@
# If requested, link to the RPCRT4 library.
#
!IF $(USE_RPCRT4_LIB)!=0
LTLIBS = $(LTLIBS) rpcrt4.lib
LTLINK = $(LTLINK) rpcrt4.lib
!ENDIF
# If a platform was set, force the linker to target that.
@@ -1149,15 +974,8 @@ LDFLAGS = $(LDOPTS)
# Start with the Tcl related linker options.
#
!IF $(NO_TCL)==0
TCLLIBPATHS = $(TCLLIBPATHS) /LIBPATH:$(TCLLIBDIR)
TCLLIBS = $(TCLLIBS) $(LIBTCL)
!ENDIF
# If zlib support is enabled, add the linker options for it.
#
!IF $(USE_ZLIB)!=0
LTLIBPATHS = $(LTLIBPATHS) /LIBPATH:$(ZLIBLIBDIR)
LTLIBS = $(LTLIBS) $(ZLIBLIB)
LTLIBPATHS = /LIBPATH:$(TCLLIBDIR)
LTLIBS = $(LIBTCL)
!ENDIF
# If ICU support is enabled, add the linker options for it.
@@ -1176,8 +994,7 @@ LTLIBS = $(LTLIBS) $(LIBICU)
#
LIBOBJS0 = vdbe.lo parse.lo alter.lo analyze.lo attach.lo auth.lo \
backup.lo bitvec.lo btmutex.lo btree.lo build.lo \
callback.lo complete.lo ctime.lo \
date.lo dbpage.lo dbstat.lo delete.lo \
callback.lo complete.lo ctime.lo date.lo dbstat.lo delete.lo \
expr.lo fault.lo fkey.lo \
fts3.lo fts3_aux.lo fts3_expr.lo fts3_hash.lo fts3_icu.lo \
fts3_porter.lo fts3_snippet.lo fts3_tokenizer.lo fts3_tokenizer1.lo \
@@ -1186,14 +1003,14 @@ LIBOBJS0 = vdbe.lo parse.lo alter.lo analyze.lo attach.lo auth.lo \
func.lo global.lo hash.lo \
icu.lo insert.lo legacy.lo loadext.lo \
main.lo malloc.lo mem0.lo mem1.lo mem2.lo mem3.lo mem5.lo \
memdb.lo memjournal.lo \
memjournal.lo \
mutex.lo mutex_noop.lo mutex_unix.lo mutex_w32.lo \
notify.lo opcodes.lo os.lo os_unix.lo os_win.lo \
pager.lo pcache.lo pcache1.lo pragma.lo prepare.lo printf.lo \
random.lo resolve.lo rowset.lo rtree.lo \
sqlite3session.lo select.lo sqlite3rbu.lo status.lo \
table.lo threads.lo tokenize.lo treeview.lo trigger.lo \
update.lo upsert.lo util.lo vacuum.lo \
update.lo util.lo vacuum.lo \
vdbeapi.lo vdbeaux.lo vdbeblob.lo vdbemem.lo vdbesort.lo \
vdbetrace.lo wal.lo walker.lo where.lo wherecode.lo whereexpr.lo \
utf.lo vtab.lo
@@ -1240,7 +1057,6 @@ SRC00 = \
$(TOP)\src\complete.c \
$(TOP)\src\ctime.c \
$(TOP)\src\date.c \
$(TOP)\src\dbpage.c \
$(TOP)\src\dbstat.c \
$(TOP)\src\delete.c \
$(TOP)\src\expr.c \
@@ -1259,7 +1075,6 @@ SRC00 = \
$(TOP)\src\mem2.c \
$(TOP)\src\mem3.c \
$(TOP)\src\mem5.c \
$(TOP)\src\memdb.c \
$(TOP)\src\memjournal.c \
$(TOP)\src\mutex.c \
$(TOP)\src\mutex_noop.c \
@@ -1292,7 +1107,6 @@ SRC01 = \
$(TOP)\src\trigger.c \
$(TOP)\src\utf.c \
$(TOP)\src\update.c \
$(TOP)\src\upsert.c \
$(TOP)\src\util.c \
$(TOP)\src\vacuum.c \
$(TOP)\src\vdbe.c \
@@ -1309,6 +1123,11 @@ SRC01 = \
$(TOP)\src\wherecode.c \
$(TOP)\src\whereexpr.c
# Shell source code files.
#
SRC02 = \
$(TOP)\src\shell.c
# Core miscellaneous files.
#
SRC03 = \
@@ -1378,8 +1197,7 @@ SRC07 = \
$(TOP)\ext\rtree\rtree.c \
$(TOP)\ext\session\sqlite3session.c \
$(TOP)\ext\rbu\sqlite3rbu.c \
$(TOP)\ext\misc\json1.c \
$(TOP)\ext\misc\stmt.c
$(TOP)\ext\misc\json1.c
# Extension header files, part 1.
#
@@ -1415,22 +1233,11 @@ SRC11 = \
keywordhash.h \
opcodes.h \
parse.h \
shell.c \
$(SQLITE3H)
# Generated Tcl header files
#
!IF $(USE_STDCALL)!=0 || $(FOR_WIN10)!=0
SRC12 = \
$(SQLITETCLH) \
$(SQLITETCLDECLSH)
!ELSE
SRC12 =
!ENDIF
# All source code files.
#
SRC = $(SRC00) $(SRC01) $(SRC03) $(SRC04) $(SRC05) $(SRC06) $(SRC07) $(SRC08) $(SRC09) $(SRC10) $(SRC11)
SRC = $(SRC00) $(SRC01) $(SRC02) $(SRC03) $(SRC04) $(SRC05) $(SRC06) $(SRC07) $(SRC08) $(SRC09) $(SRC10) $(SRC11)
# Source code to the test files.
#
@@ -1451,7 +1258,6 @@ TESTSRC = \
$(TOP)\src\test_blob.c \
$(TOP)\src\test_btree.c \
$(TOP)\src\test_config.c \
$(TOP)\src\test_delete.c \
$(TOP)\src\test_demovfs.c \
$(TOP)\src\test_devsym.c \
$(TOP)\src\test_fs.c \
@@ -1461,7 +1267,6 @@ TESTSRC = \
$(TOP)\src\test_intarray.c \
$(TOP)\src\test_journal.c \
$(TOP)\src\test_malloc.c \
$(TOP)\src\test_md5.c \
$(TOP)\src\test_multiplex.c \
$(TOP)\src\test_mutex.c \
$(TOP)\src\test_onefile.c \
@@ -1473,7 +1278,6 @@ TESTSRC = \
$(TOP)\src\test_server.c \
$(TOP)\src\test_superlock.c \
$(TOP)\src\test_syscall.c \
$(TOP)\src\test_tclsh.c \
$(TOP)\src\test_tclvar.c \
$(TOP)\src\test_thread.c \
$(TOP)\src\test_vfs.c \
@@ -1487,8 +1291,6 @@ TESTSRC = \
# Statically linked extensions.
#
TESTEXT = \
$(TOP)\ext\expert\sqlite3expert.c \
$(TOP)\ext\expert\test_expert.c \
$(TOP)\ext\misc\amatch.c \
$(TOP)\ext\misc\carray.c \
$(TOP)\ext\misc\closure.c \
@@ -1500,24 +1302,14 @@ TESTEXT = \
$(TOP)\ext\fts5\fts5_test_mi.c \
$(TOP)\ext\fts5\fts5_test_tok.c \
$(TOP)\ext\misc\ieee754.c \
$(TOP)\ext\misc\mmapwarm.c \
$(TOP)\ext\misc\nextchar.c \
$(TOP)\ext\misc\normalize.c \
$(TOP)\ext\misc\percentile.c \
$(TOP)\ext\misc\regexp.c \
$(TOP)\ext\misc\remember.c \
$(TOP)\ext\misc\series.c \
$(TOP)\ext\misc\spellfix.c \
$(TOP)\ext\misc\totype.c \
$(TOP)\ext\misc\unionvtab.c \
$(TOP)\ext\misc\wholenumber.c
# If use of zlib is enabled, add the "zipfile.c" source file.
#
!IF $(USE_ZLIB)!=0
TESTEXT = $(TESTEXT) $(TOP)\ext\misc\zipfile.c
!ENDIF
# Source code to the library files needed by the test fixture
# (non-amalgamation)
#
@@ -1549,7 +1341,7 @@ HDR = \
parse.h \
$(TOP)\src\pragma.h \
$(SQLITE3H) \
sqlite3ext.h \
$(TOP)\src\sqlite3ext.h \
$(TOP)\src\sqliteInt.h \
$(TOP)\src\sqliteLimit.h \
$(TOP)\src\vdbe.h \
@@ -1587,10 +1379,8 @@ TESTPROGS = \
testfixture.exe \
$(SQLITE3EXE) \
sqlite3_analyzer.exe \
sqlite3_checker.exe \
sqldiff.exe \
dbhash.exe \
sqltclsh.exe
dbhash.exe
# Databases containing fuzzer test cases
#
@@ -1598,32 +1388,25 @@ FUZZDATA = \
$(TOP)\test\fuzzdata1.db \
$(TOP)\test\fuzzdata2.db \
$(TOP)\test\fuzzdata3.db \
$(TOP)\test\fuzzdata4.db \
$(TOP)\test\fuzzdata5.db \
$(TOP)\test\fuzzdata6.db
$(TOP)\test\fuzzdata4.db
# <</mark>>
# Additional compiler options for the shell. These are only effective
# when the shell is not being dynamically linked.
#
!IF $(DYNAMIC_SHELL)==0 && $(FOR_WIN10)==0
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_STMTVTAB
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_ENABLE_DBSTAT_VTAB
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_OFFSET_SQL_FUNC -DSQLITE_INTROSPECTION_PRAGMAS
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_RTREE
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_SHELL_JSON1 -DSQLITE_ENABLE_FTS4
# SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_FTS5
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_EXPLAIN_COMMENTS
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
!ENDIF
# <<mark>>
# Extra compiler options for various test tools.
#
MPTESTER_COMPILE_OPTS = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5
MPTESTER_COMPILE_OPTS = -DSQLITE_SHELL_JSON1 -DSQLITE_ENABLE_FTS5
FUZZERSHELL_COMPILE_OPTS = -DSQLITE_ENABLE_JSON1
FUZZCHECK_COMPILE_OPTS = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5 -DSQLITE_OSS_FUZZ -DSQLITE_MAX_MEMORY=50000000 -DSQLITE_PRINTF_PRECISION_LIMIT=1000
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
KV_COMPILE_OPTS = -DSQLITE_THREADSAFE=0 -DSQLITE_DIRECT_OVERFLOW_READ
ST_COMPILE_OPTS = -DSQLITE_THREADSAFE=0
FUZZCHECK_COMPILE_OPTS = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5
# Standard options to testfixture.
#
@@ -1641,15 +1424,7 @@ ALL_TCL_TARGETS =
# This is the default Makefile target. The objects listed here
# are what get build when you type just "make" with no arguments.
#
core: dll libsqlite3.lib shell
# Targets that require the Tcl library.
#
tcl: $(ALL_TCL_TARGETS)
# This Makefile target builds all of the standard binaries.
#
all: core tcl
all: dll libsqlite3.lib shell $(ALL_TCL_TARGETS)
# Dynamic link library section.
#
@@ -1674,12 +1449,12 @@ $(SQLITE3DLL): $(LIBOBJ) $(LIBRESOBJS) $(CORE_LINK_DEP)
sqlite3.def: libsqlite3.lib
echo EXPORTS > sqlite3.def
dumpbin /all libsqlite3.lib \
| $(TCLSH_CMD) $(TOP)\tool\replace.tcl include "^\s+1 _?(sqlite3(?:session|changeset|changegroup|rebaser)?_[^@]*)(?:@\d+)?$$" \1 \
| $(TCLSH_CMD) $(TOP)\tool\replace.tcl include "^\s+1 _?(sqlite3_[^@]*)(?:@\d+)?$$" \1 \
| sort >> sqlite3.def
# <</block2>>
$(SQLITE3EXE): shell.c $(SHELL_CORE_DEP) $(LIBRESOBJS) $(SHELL_CORE_SRC) $(SQLITE3H)
$(LTLINK) $(SHELL_COMPILE_OPTS) $(READLINE_FLAGS) shell.c $(SHELL_CORE_SRC) \
$(SQLITE3EXE): $(TOP)\src\shell.c $(SHELL_CORE_DEP) $(LIBRESOBJS) $(SHELL_CORE_SRC) $(SQLITE3H)
$(LTLINK) $(SHELL_COMPILE_OPTS) $(READLINE_FLAGS) $(TOP)\src\shell.c $(SHELL_CORE_SRC) \
/link $(SQLITE3EXEPDB) $(LDFLAGS) $(LTLINKOPTS) $(SHELL_LINK_OPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LIBREADLINE) $(LTLIBS) $(TLIBS)
# <<mark>>
@@ -1690,7 +1465,7 @@ dbhash.exe: $(TOP)\tool\dbhash.c $(SQLITE3C) $(SQLITE3H)
$(LTLINK) $(NO_WARN) $(TOP)\tool\dbhash.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
scrub.exe: $(TOP)\ext\misc\scrub.c $(SQLITE3C) $(SQLITE3H)
$(LTLINK) $(NO_WARN) -DSCRUB_STANDALONE=1 $(TOP)\ext\misc\scrub.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
$(LTLINK) $(NO_WARN) $(TOP)\ext\misc\scrub.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
srcck1.exe: $(TOP)\tool\srcck1.c
$(BCC) $(NO_WARN) -Fe$@ $(TOP)\tool\srcck1.c
@@ -1701,17 +1476,8 @@ sourcetest: srcck1.exe sqlite3.c
fuzzershell.exe: $(TOP)\tool\fuzzershell.c $(SQLITE3C) $(SQLITE3H)
$(LTLINK) $(NO_WARN) $(FUZZERSHELL_COMPILE_OPTS) $(TOP)\tool\fuzzershell.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
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)
ossshell.exe: $(OSSSHELL_SRC) $(SQLITE3C) $(SQLITE3H)
$(LTLINK) $(NO_WARN) $(FUZZCHECK_COMPILE_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)
fuzzcheck.exe: $(TOP)\test\fuzzcheck.c $(SQLITE3C) $(SQLITE3H)
$(LTLINK) $(NO_WARN) $(FUZZCHECK_COMPILE_OPTS) $(TOP)\test\fuzzcheck.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
mptester.exe: $(TOP)\mptest\mptest.c $(SQLITE3C) $(SQLITE3H)
$(LTLINK) $(NO_WARN) $(MPTESTER_COMPILE_OPTS) $(TOP)\mptest\mptest.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
@@ -1736,11 +1502,12 @@ mptest: mptester.exe
# files are automatically generated. This target takes care of
# all that automatic generation.
#
.target_source: $(SRC) $(TOP)\tool\vdbe-compress.tcl fts5.c $(SQLITE_TCL_DEP)
.target_source: $(SRC) $(TOP)\tool\vdbe-compress.tcl fts5.c
-rmdir /Q/S tsrc 2>NUL
-mkdir tsrc
for %i in ($(SRC00)) do copy /Y %i tsrc
for %i in ($(SRC01)) do copy /Y %i tsrc
for %i in ($(SRC02)) do copy /Y %i tsrc
for %i in ($(SRC03)) do copy /Y %i tsrc
for %i in ($(SRC04)) do copy /Y %i tsrc
for %i in ($(SRC05)) do copy /Y %i tsrc
@@ -1750,7 +1517,6 @@ mptest: mptester.exe
for %i in ($(SRC09)) do copy /Y %i tsrc
for %i in ($(SRC10)) do copy /Y %i tsrc
for %i in ($(SRC11)) do copy /Y %i tsrc
for %i in ($(SRC12)) do copy /Y %i tsrc
copy /Y fts5.c tsrc
copy /Y fts5.h tsrc
del /Q tsrc\sqlite.h.in tsrc\parse.y 2>NUL
@@ -1758,8 +1524,9 @@ mptest: mptester.exe
move vdbe.new tsrc\vdbe.c
echo > .target_source
sqlite3.c: .target_source sqlite3ext.h $(MKSQLITE3C_TOOL)
$(TCLSH_CMD) $(MKSQLITE3C_TOOL) $(MKSQLITE3C_ARGS)
sqlite3.c: .target_source sqlite3ext.h $(TOP)\tool\mksqlite3c.tcl
$(TCLSH_CMD) $(TOP)\tool\mksqlite3c.tcl $(MKSQLITE3C_ARGS)
copy tsrc\shell.c .
copy $(TOP)\ext\session\sqlite3session.h .
sqlite3-all.c: sqlite3.c $(TOP)\tool\split-sqlite3c.tcl
@@ -1781,12 +1548,6 @@ lemon.exe: $(TOP)\tool\lemon.c lempar.c
$(BCC) $(NO_WARN) -Daccess=_access \
-Fe$@ $(TOP)\tool\lemon.c /link $(LDFLAGS) $(NLTLINKOPTS) $(NLTLIBPATHS)
# <<mark>>
# Rules to build the source-id generator tool
#
mksourceid.exe: $(TOP)\tool\mksourceid.c
$(BCC) $(NO_WARN) -Fe$@ $(TOP)\tool\mksourceid.c /link $(LDFLAGS) $(NLTLINKOPTS) $(NLTLIBPATHS)
# Rules to build individual *.lo files from generated *.c files. This
# applies to:
#
@@ -1857,10 +1618,7 @@ ctime.lo: $(TOP)\src\ctime.c $(HDR)
date.lo: $(TOP)\src\date.c $(HDR)
$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\date.c
dbpage.lo: $(TOP)\src\dbpage.c $(HDR)
$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\dbpage.c
dbstat.lo: $(TOP)\src\dbstat.c $(HDR)
dbstat.lo: $(TOP)\src\date.c $(HDR)
$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\dbstat.c
delete.lo: $(TOP)\src\delete.c $(HDR)
@@ -1914,9 +1672,6 @@ mem3.lo: $(TOP)\src\mem3.c $(HDR)
mem5.lo: $(TOP)\src\mem5.c $(HDR)
$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\mem5.c
memdb.lo: $(TOP)\src\memdb.c $(HDR)
$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\memdb.c
memjournal.lo: $(TOP)\src\memjournal.c $(HDR)
$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\memjournal.c
@@ -1995,9 +1750,6 @@ trigger.lo: $(TOP)\src\trigger.c $(HDR)
update.lo: $(TOP)\src\update.c $(HDR)
$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\update.c
upsert.lo: $(TOP)\src\upsert.c $(HDR)
$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\upsert.c
utf.lo: $(TOP)\src\utf.c $(HDR)
$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\utf.c
@@ -2046,14 +1798,14 @@ wherecode.lo: $(TOP)\src\wherecode.c $(HDR)
whereexpr.lo: $(TOP)\src\whereexpr.c $(HDR)
$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\whereexpr.c
tclsqlite.lo: $(TOP)\src\tclsqlite.c $(HDR) $(SQLITE_TCL_DEP)
tclsqlite.lo: $(TOP)\src\tclsqlite.c $(HDR)
$(LTCOMPILE) $(NO_WARN) -DUSE_TCL_STUBS=1 -DBUILD_sqlite -I$(TCLINCDIR) -c $(TOP)\src\tclsqlite.c
tclsqlite-shell.lo: $(TOP)\src\tclsqlite.c $(HDR) $(SQLITE_TCL_DEP)
$(LTCOMPILE) $(NO_WARN) -DTCLSH -DBUILD_sqlite -I$(TCLINCDIR) -c $(TOP)\src\tclsqlite.c
tclsqlite-shell.lo: $(TOP)\src\tclsqlite.c $(HDR)
$(LTCOMPILE) $(NO_WARN) -DTCLSH=1 -DBUILD_sqlite -I$(TCLINCDIR) -c $(TOP)\src\tclsqlite.c
tclsqlite3.exe: tclsqlite-shell.lo $(SQLITE3C) $(SQLITE3H) $(LIBRESOBJS)
$(LTLINK) $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS) $(TCLLIBPATHS) $(LTLIBPATHS) /OUT:$@ tclsqlite-shell.lo $(LIBRESOBJS) $(TCLLIBS) $(LTLIBS) $(TLIBS)
$(LTLINK) $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) /OUT:$@ tclsqlite-shell.lo $(LIBRESOBJS) $(LTLIBS) $(TLIBS)
# Rules to build opcodes.c and opcodes.h
#
@@ -2074,17 +1826,11 @@ parse.c: $(TOP)\src\parse.y lemon.exe $(TOP)\tool\addopcodes.tcl
move parse.h parse.h.temp
$(TCLSH_CMD) $(TOP)\tool\addopcodes.tcl parse.h.temp > parse.h
$(SQLITE3H): $(TOP)\src\sqlite.h.in $(TOP)\manifest mksourceid.exe $(TOP)\VERSION
$(TCLSH_CMD) $(TOP)\tool\mksqlite3h.tcl $(TOP:\=/) > $(SQLITE3H) $(MKSQLITE3H_ARGS)
$(SQLITE3H): $(TOP)\src\sqlite.h.in $(TOP)\manifest.uuid $(TOP)\VERSION
$(TCLSH_CMD) $(TOP)\tool\mksqlite3h.tcl $(TOP:\=/) > $(SQLITE3H)
sqlite3ext.h: .target_source
!IF $(USE_STDCALL)!=0 || $(FOR_WIN10)!=0
type tsrc\sqlite3ext.h | $(TCLSH_CMD) $(TOP)\tool\replace.tcl regsub "\(\*\)" "(SQLITE_CALLBACK *)" \
| $(TCLSH_CMD) $(TOP)\tool\replace.tcl regsub "\(\*" "(SQLITE_APICALL *" > sqlite3ext.h
copy /Y sqlite3ext.h tsrc\sqlite3ext.h
!ELSE
copy /Y tsrc\sqlite3ext.h sqlite3ext.h
!ENDIF
copy tsrc\sqlite3ext.h .
mkkeywordhash.exe: $(TOP)\tool\mkkeywordhash.c
$(BCC) $(NO_WARN) -Fe$@ $(REQ_FEATURE_FLAGS) $(OPT_FEATURE_FLAGS) $(EXT_FEATURE_FLAGS) $(OPTS) \
@@ -2093,29 +1839,7 @@ mkkeywordhash.exe: $(TOP)\tool\mkkeywordhash.c
keywordhash.h: $(TOP)\tool\mkkeywordhash.c mkkeywordhash.exe
.\mkkeywordhash.exe > keywordhash.h
# Source files that go into making shell.c
SHELL_SRC = \
$(TOP)\src\shell.c.in \
$(TOP)\ext\misc\appendvfs.c \
$(TOP)\ext\misc\shathree.c \
$(TOP)\ext\misc\fileio.c \
$(TOP)\ext\misc\completion.c \
$(TOP)\ext\expert\sqlite3expert.c \
$(TOP)\ext\expert\sqlite3expert.h \
$(TOP)\src\test_windirent.c
# If use of zlib is enabled, add the "zipfile.c" source file.
#
!IF $(USE_ZLIB)!=0
SHELL_SRC = $(SHELL_SRC) $(TOP)\ext\misc\sqlar.c
SHELL_SRC = $(SHELL_SRC) $(TOP)\ext\misc\zipfile.c
!ENDIF
shell.c: $(SHELL_SRC) $(TOP)\tool\mkshellc.tcl
$(TCLSH_CMD) $(TOP)\tool\mkshellc.tcl > shell.c
zlib:
pushd $(ZLIBDIR) && $(MAKE) /f win32\Makefile.msc clean $(ZLIBLIB) && popd
# Rules to build the extension objects.
#
@@ -2204,24 +1928,6 @@ FTS5_SRC = \
$(TOP)\ext\fts5\fts5_varint.c \
$(TOP)\ext\fts5\fts5_vocab.c
LSM1_SRC = \
$(TOP)\ext\lsm1\lsm.h \
$(TOP)\ext\lsm1\lsmInt.h \
$(TOP)\ext\lsm1\lsm_ckpt.c \
$(TOP)\ext\lsm1\lsm_file.c \
$(TOP)\ext\lsm1\lsm_log.c \
$(TOP)\ext\lsm1\lsm_main.c \
$(TOP)\ext\lsm1\lsm_mem.c \
$(TOP)\ext\lsm1\lsm_mutex.c \
$(TOP)\ext\lsm1\lsm_shared.c \
$(TOP)\ext\lsm1\lsm_sorted.c \
$(TOP)\ext\lsm1\lsm_str.c \
$(TOP)\ext\lsm1\lsm_tree.c \
$(TOP)\ext\lsm1\lsm_unix.c \
$(TOP)\ext\lsm1\lsm_varint.c \
$(TOP)\ext\lsm1\lsm_vtab.c \
$(TOP)\ext\lsm1\lsm_win32.c
fts5parse.c: $(TOP)\ext\fts5\fts5parse.y lemon.exe
copy $(TOP)\ext\fts5\fts5parse.y .
del /Q fts5parse.h 2>NUL
@@ -2233,10 +1939,6 @@ fts5.c: $(FTS5_SRC)
$(TCLSH_CMD) $(TOP)\ext\fts5\tool\mkfts5c.tcl
copy $(TOP)\ext\fts5\fts5.h .
lsm1.c: $(LSM1_SRC)
$(TCLSH_CMD) $(TOP)\ext\lsm1\tool\mklsm1c.tcl
copy $(TOP)\ext\lsm1\lsm.h .
fts5.lo: fts5.c $(HDR) $(EXTHDR)
$(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c fts5.c
@@ -2256,15 +1958,11 @@ sqlite3rbu.lo: $(TOP)\ext\rbu\sqlite3rbu.c $(HDR) $(EXTHDR)
# necessary because the test fixture requires non-API symbols which are
# hidden when the library is built via the amalgamation).
#
TESTFIXTURE_FLAGS = -DTCLSH_INIT_PROC=sqlite3TestInit -DSQLITE_TEST=1 -DSQLITE_CRASH_TEST=1
TESTFIXTURE_FLAGS = -DTCLSH=1 -DSQLITE_TEST=1 -DSQLITE_CRASH_TEST=1
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_SERVER=1 -DSQLITE_PRIVATE=""
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_CORE $(NO_WARN)
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_SERIES_CONSTRAINT_VERIFY=1
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_DEFAULT_PAGE_SIZE=1024
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_ENABLE_STMTVTAB
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_ENABLE_DBPAGE_VTAB
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_ENABLE_JSON1
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) $(TEST_CCONV_OPTS)
TESTFIXTURE_SRC0 = $(TESTEXT) $(TESTSRC2)
TESTFIXTURE_SRC1 = $(TESTEXT) $(SQLITE3C)
@@ -2274,31 +1972,11 @@ TESTFIXTURE_SRC = $(TESTSRC) $(TOP)\src\tclsqlite.c $(TESTFIXTURE_SRC0)
TESTFIXTURE_SRC = $(TESTSRC) $(TOP)\src\tclsqlite.c $(TESTFIXTURE_SRC1)
!ENDIF
!IF $(USE_STDCALL)!=0 || $(FOR_WIN10)!=0
sqlite_tclDecls.h:
echo #ifndef SQLITE_TCLAPI > $(SQLITETCLDECLSH)
echo # define SQLITE_TCLAPI >> $(SQLITETCLDECLSH)
echo #endif >> $(SQLITETCLDECLSH)
type "$(TCLINCDIR)\tclDecls.h" \
| $(TCLSH_CMD) $(TOP)\tool\replace.tcl regsub "^(EXTERN(?: CONST\d+?)?\s+?[^\(]*?\s+?)Tcl_" "\1 SQLITE_TCLAPI Tcl_" \
| $(TCLSH_CMD) $(TOP)\tool\replace.tcl regsub "^(EXTERN\s+?(?:void|VOID)\s+?)TclFreeObj" "\1 SQLITE_TCLAPI TclFreeObj" \
| $(TCLSH_CMD) $(TOP)\tool\replace.tcl regsub "\(\*tcl_" "(SQLITE_TCLAPI *tcl_" \
| $(TCLSH_CMD) $(TOP)\tool\replace.tcl regsub "\(\*tclFreeObj" "(SQLITE_TCLAPI *tclFreeObj" \
| $(TCLSH_CMD) $(TOP)\tool\replace.tcl regsub "\(\*" "(SQLITE_TCLAPI *" >> $(SQLITETCLDECLSH)
sqlite_tcl.h:
type "$(TCLINCDIR)\tcl.h" | $(TCLSH_CMD) $(TOP)\tool\replace.tcl exact tclDecls.h sqlite_tclDecls.h \
| $(TCLSH_CMD) $(TOP)\tool\replace.tcl regsub "typedef (.*?)\(Tcl_" "typedef \1 (SQLITE_TCLAPI Tcl_" \
| $(TCLSH_CMD) $(TOP)\tool\replace.tcl exact "void (*freeProc)" "void (SQLITE_TCLAPI *freeProc)" \
| $(TCLSH_CMD) $(TOP)\tool\replace.tcl exact "Tcl_HashEntry *(*findProc)" "Tcl_HashEntry *(SQLITE_TCLAPI *findProc)" \
| $(TCLSH_CMD) $(TOP)\tool\replace.tcl exact "Tcl_HashEntry *(*createProc)" "Tcl_HashEntry *(SQLITE_TCLAPI *createProc)" >> $(SQLITETCLH)
!ENDIF
testfixture.exe: $(TESTFIXTURE_SRC) $(TESTFIXTURE_DEP) $(SQLITE3H) $(LIBRESOBJS) $(HDR) $(SQLITE_TCL_DEP)
testfixture.exe: $(TESTFIXTURE_SRC) $(SQLITE3H) $(LIBRESOBJS) $(HDR)
$(LTLINK) -DSQLITE_NO_SYNC=1 $(TESTFIXTURE_FLAGS) \
-DBUILD_sqlite -I$(TCLINCDIR) \
$(TESTFIXTURE_SRC) \
/link $(LDFLAGS) $(LTLINKOPTS) $(TCLLIBPATHS) $(LTLIBPATHS) $(LIBRESOBJS) $(TCLLIBS) $(LTLIBS) $(TLIBS)
/link $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LTLIBS) $(TLIBS)
extensiontest: testfixture.exe testloadext.dll
@set PATH=$(LIBTCLPATH);$(PATH)
@@ -2343,104 +2021,68 @@ smoketest: $(TESTPROGS)
@set PATH=$(LIBTCLPATH);$(PATH)
.\testfixture.exe $(TOP)\test\main.test $(TESTOPTS)
sqlite3_analyzer.c: $(SQLITE3C) $(SQLITE3H) $(TOP)\src\tclsqlite.c $(TOP)\tool\spaceanal.tcl $(TOP)\tool\mkccode.tcl $(TOP)\tool\sqlite3_analyzer.c.in $(SQLITE_TCL_DEP)
$(TCLSH_CMD) $(TOP)\tool\mkccode.tcl $(TOP)\tool\sqlite3_analyzer.c.in > $@
sqlite3_analyzer.c: $(SQLITE3C) $(SQLITE3H) $(TOP)\src\tclsqlite.c $(TOP)\tool\spaceanal.tcl
echo #define TCLSH 2 > $@
echo #define SQLITE_ENABLE_DBSTAT_VTAB 1 >> $@
copy $@ + $(SQLITE3C) + $(TOP)\src\tclsqlite.c $@
echo static const char *tclsh_main_loop(void){ >> $@
echo static const char *zMainloop = >> $@
$(TCLSH_CMD) $(TOP)\tool\tostr.tcl $(TOP)\tool\spaceanal.tcl >> $@
echo ; return zMainloop; } >> $@
sqlite3_analyzer.exe: sqlite3_analyzer.c $(LIBRESOBJS)
$(LTLINK) $(NO_WARN) -DBUILD_sqlite -I$(TCLINCDIR) sqlite3_analyzer.c \
/link $(LDFLAGS) $(LTLINKOPTS) $(TCLLIBPATHS) $(LTLIBPATHS) $(LIBRESOBJS) $(TCLLIBS) $(LTLIBS) $(TLIBS)
/link $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LTLIBS) $(TLIBS)
sqltclsh.c: sqlite3.c $(TOP)\src\tclsqlite.c $(TOP)\tool\sqltclsh.tcl $(TOP)\ext\misc\appendvfs.c $(TOP)\tool\mkccode.tcl $(TOP)\tool\sqltclsh.c.in
$(TCLSH_CMD) $(TOP)\tool\mkccode.tcl $(TOP)\tool\sqltclsh.c.in >sqltclsh.c
sqltclsh.exe: sqltclsh.c $(SHELL_CORE_DEP) $(LIBRESOBJS)
$(LTLINK) $(NO_WARN) -DBUILD_sqlite -I$(TCLINCDIR) sqltclsh.c \
/link $(LDFLAGS) $(LTLINKOPTS) $(TCLLIBPATHS) $(LTLIBPATHS) $(LIBRESOBJS) $(TCLLIBS) $(LTLIBS) $(TLIBS)
sqlite3_expert.exe: $(SQLITE3C) $(TOP)\ext\expert\sqlite3expert.h $(TOP)\ext\expert\sqlite3expert.c $(TOP)\ext\expert\expert.c
$(LTLINK) $(NO_WARN) $(TOP)\ext\expert\sqlite3expert.c $(TOP)\ext\expert\expert.c $(SQLITE3C) $(TLIBS)
CHECKER_DEPS =\
$(TOP)/tool/mkccode.tcl \
sqlite3.c \
$(TOP)/src/tclsqlite.c \
$(TOP)/ext/repair/sqlite3_checker.tcl \
$(TOP)/ext/repair/checkindex.c \
$(TOP)/ext/repair/checkfreelist.c \
$(TOP)/ext/misc/btreeinfo.c \
$(TOP)/ext/repair/sqlite3_checker.c.in
sqlite3_checker.c: $(CHECKER_DEPS)
$(TCLSH_CMD) $(TOP)\tool\mkccode.tcl $(TOP)\ext\repair\sqlite3_checker.c.in > $@
sqlite3_checker.exe: sqlite3_checker.c $(LIBRESOBJS)
$(LTLINK) $(NO_WARN) -DBUILD_sqlite -I$(TCLINCDIR) sqlite3_checker.c \
/link $(LDFLAGS) $(LTLINKOPTS) $(TCLLIBPATHS) $(LTLIBPATHS) $(LIBRESOBJS) $(TCLLIBS) $(LTLIBS) $(TLIBS)
dbdump.exe: $(TOP)\ext\misc\dbdump.c $(SQLITE3C) $(SQLITE3H) $(LIBRESOBJS)
$(LTLINK) $(NO_WARN) -DDBDUMP_STANDALONE $(TOP)\ext\misc\dbdump.c $(SQLITE3C) \
/link $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LTLIBS)
testloadext.lo: $(TOP)\src\test_loadext.c $(SQLITE3H)
testloadext.lo: $(TOP)\src\test_loadext.c
$(LTCOMPILE) $(NO_WARN) -c $(TOP)\src\test_loadext.c
testloadext.dll: testloadext.lo
$(LD) $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) /DLL /OUT:$@ testloadext.lo
showdb.exe: $(TOP)\tool\showdb.c $(SQLITE3C) $(SQLITE3H)
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \
$(TOP)\tool\showdb.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
showstat4.exe: $(TOP)\tool\showstat4.c $(SQLITE3C) $(SQLITE3H)
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \
$(TOP)\tool\showstat4.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
showjournal.exe: $(TOP)\tool\showjournal.c $(SQLITE3C) $(SQLITE3H)
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \
$(TOP)\tool\showjournal.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
showwal.exe: $(TOP)\tool\showwal.c $(SQLITE3C) $(SQLITE3H)
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \
$(TOP)\tool\showwal.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
showshm.exe: $(TOP)\tool\showshm.c
$(LTLINK) $(NO_WARN) $(TOP)\tool\showshm.c /link $(LDFLAGS) $(LTLINKOPTS)
changeset.exe: $(TOP)\ext\session\changeset.c $(SQLITE3C) $(SQLITE3H)
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
-DSQLITE_ENABLE_SESSION=1 -DSQLITE_ENABLE_PREUPDATE_HOOK=1 \
changeset.exe: $(TOP)\ext\session\changeset.c $(SQLITE3C)
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \
$(TOP)\ext\session\changeset.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
fts3view.exe: $(TOP)\ext\fts3\tool\fts3view.c $(SQLITE3C) $(SQLITE3H)
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \
$(TOP)\ext\fts3\tool\fts3view.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
rollback-test.exe: $(TOP)\tool\rollback-test.c $(SQLITE3C) $(SQLITE3H)
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \
$(TOP)\tool\rollback-test.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
LogEst.exe: $(TOP)\tool\logest.c $(SQLITE3H)
$(LTLINK) $(NO_WARN) $(TOP)\tool\LogEst.c /link $(LDFLAGS) $(LTLINKOPTS)
$(LTLINK) $(NO_WARN) -Fe$@ $(TOP)\tool\LogEst.c /link $(LDFLAGS) $(LTLINKOPTS)
wordcount.exe: $(TOP)\test\wordcount.c $(SQLITE3C) $(SQLITE3H)
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \
$(TOP)\test\wordcount.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
speedtest1.exe: $(TOP)\test\speedtest1.c $(SQLITE3C) $(SQLITE3H)
$(LTLINK) $(NO_WARN) $(ST_COMPILE_OPTS) -DSQLITE_OMIT_LOAD_EXTENSION \
$(LTLINK) $(NO_WARN) -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \
$(TOP)\test\speedtest1.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
kvtest.exe: $(TOP)\test\kvtest.c $(SQLITE3C) $(SQLITE3H)
$(LTLINK) $(NO_WARN) $(KV_COMPILE_OPTS) \
$(TOP)\test\kvtest.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
rbu.exe: $(TOP)\ext\rbu\rbu.c $(TOP)\ext\rbu\sqlite3rbu.c $(SQLITE3C) $(SQLITE3H)
$(LTLINK) $(NO_WARN) -DSQLITE_ENABLE_RBU \
$(LTLINK) $(NO_WARN) -DSQLITE_ENABLE_RBU -Fe$@ \
$(TOP)\ext\rbu\rbu.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
LSMDIR=$(TOP)\ext\lsm1
!INCLUDE $(LSMDIR)\Makefile.msc
moreclean: clean
del /Q $(SQLITE3C) $(SQLITE3H) 2>NUL
# <</mark>>
@@ -2453,17 +2095,16 @@ clean:
del /Q sqlite3.c sqlite3.h 2>NUL
del /Q opcodes.c opcodes.h 2>NUL
del /Q lemon.* lempar.c parse.* 2>NUL
del /Q mksourceid.* mkkeywordhash.* keywordhash.h 2>NUL
del /Q mkkeywordhash.* keywordhash.h 2>NUL
del /Q notasharedlib.* 2>NUL
-rmdir /Q/S .deps 2>NUL
-rmdir /Q/S .libs 2>NUL
-rmdir /Q/S tsrc 2>NUL
del /Q .target_source 2>NUL
del /Q tclsqlite3.exe $(SQLITETCLH) $(SQLITETCLDECLSH) 2>NUL
del /Q lsm.dll lsmtest.exe 2>NUL
del /Q tclsqlite3.exe 2>NUL
del /Q testloadext.dll 2>NUL
del /Q testfixture.exe test.db 2>NUL
del /Q LogEst.exe fts3view.exe rollback-test.exe showdb.exe dbdump.exe 2>NUL
del /Q LogEst.exe fts3view.exe rollback-test.exe showdb.exe 2>NUL
del /Q changeset.exe 2>NUL
del /Q showjournal.exe showstat4.exe showwal.exe speedtest1.exe 2>NUL
del /Q mptester.exe wordcount.exe rbu.exe srcck1.exe 2>NUL
@@ -2473,10 +2114,5 @@ clean:
del /Q sqlite3_analyzer.exe sqlite3_analyzer.c 2>NUL
del /Q sqlite-*-output.vsix 2>NUL
del /Q fuzzershell.exe fuzzcheck.exe sqldiff.exe dbhash.exe 2>NUL
del /Q sqltclsh.* 2>NUL
del /Q dbfuzz.exe sessionfuzz.exe 2>NUL
del /Q kvtest.exe ossshell.exe scrub.exe 2>NUL
del /Q showshm.exe sqlite3_checker.* sqlite3_expert.exe 2>NUL
del /Q fts5.* fts5parse.* 2>NUL
del /Q lsm.h lsm1.c 2>NUL
# <</mark>>
+52 -124
View File
@@ -1,59 +1,12 @@
<h1 align="center">SQLite Source Repository</h1>
This repository contains the complete source code for the SQLite database
engine. Some test scripts are also included. However, many other test scripts
engine. Some test scripts are also include. 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
SQLite sources are managed using the
[Fossil](https://www.fossil-scm.org/), a distributed version control system
that was specifically designed to support SQLite development.
If you do not want to use Fossil, you can download tarballs or ZIP
archives or [SQLite archives](https://sqlite.org/cli.html#sqlar) as follows:
* Lastest trunk check-in as
[Tarball](https://www.sqlite.org/src/tarball/sqlite.tar.gz),
[ZIP-archive](https://www.sqlite.org/src/zip/sqlite.zip), or
[SQLite-archive](https://www.sqlite.org/src/sqlar/sqlite.sqlar).
* Latest release as
[Tarball](https://www.sqlite.org/src/tarball/sqlite.tar.gz?r=release),
[ZIP-archive](https://www.sqlite.org/src/zip/sqlite.zip?r=release), or
[SQLite-archive](https://www.sqlite.org/src/sqlar/sqlite.sqlar?r=release).
* For other check-ins, substitute an appropriate branch name or
tag or hash prefix for "release" in the URLs of the previous
bullet. Or browse the [timeline](https://www.sqlite.org/src/timeline)
to locate the check-in desired, click on its information page link,
then click on the "Tarball" or "ZIP Archive" links on the information
page.
If you do want to use Fossil to check out the source tree,
first install Fossil version 2.0 or later.
(Source tarballs and precompiled binaries available
[here](https://www.fossil-scm.org/fossil/uv/download.html). Fossil is
a stand-alone program. To install, simply download or build the single
executable file and put that file someplace on your $PATH.)
Then run commands like this:
mkdir ~/sqlite
cd ~/sqlite
fossil clone https://www.sqlite.org/src sqlite.fossil
fossil open sqlite.fossil
After setting up a repository using the steps above, you can always
update to the lastest version using:
fossil update trunk ;# latest trunk check-in
fossil update release ;# latest official release
Or type "fossil ui" to get a web-based user interface.
If you are reading this on a Git mirror someplace, you are doing it wrong.
The [official repository](https://www.sqlite.org/src/) is better. Go there
now.
## Compiling
@@ -65,13 +18,13 @@ script found at the root of the source tree. Then run "make".
For example:
tar xzf sqlite.tar.gz ;# Unpack the source tree into "sqlite"
mkdir bld ;# Build will occur in a sibling directory
cd bld ;# Change to the build directory
../sqlite/configure ;# Run the configure script
make ;# Run the makefile.
make sqlite3.c ;# Build the "amalgamation" source file
make test ;# Run some tests (requires Tcl)
tar xzf sqlite.tar.gz ;# Unpack the source tree into "sqlite"
mkdir bld ;# Build will occur in a sibling directory
cd bld ;# Change to the build directory
../sqlite/configure ;# Run the configure script
make ;# Run the makefile.
make sqlite3.c ;# Build the "amalgamation" source file
make test ;# Run some tests (requires Tcl)
See the makefile for additional targets.
@@ -90,13 +43,13 @@ with the provided "Makefile.msc" to build one of the supported targets.
For example:
mkdir bld
cd bld
nmake /f Makefile.msc TOP=..\sqlite
nmake /f Makefile.msc sqlite3.c TOP=..\sqlite
nmake /f Makefile.msc sqlite3.dll TOP=..\sqlite
nmake /f Makefile.msc sqlite3.exe TOP=..\sqlite
nmake /f Makefile.msc test TOP=..\sqlite
mkdir bld
cd bld
nmake /f Makefile.msc TOP=..\sqlite
nmake /f Makefile.msc sqlite3.c TOP=..\sqlite
nmake /f Makefile.msc sqlite3.dll TOP=..\sqlite
nmake /f Makefile.msc sqlite3.exe TOP=..\sqlite
nmake /f Makefile.msc test TOP=..\sqlite
There are several build options that can be set via the NMAKE command
line. For example, to build for WinRT, simply add "FOR_WINRT=1" argument
@@ -107,25 +60,23 @@ recommended.
SQLite does not require [Tcl](http://www.tcl.tk/) to run, but a Tcl installation
is required by the makefiles (including those for MSVC). SQLite contains
a lot of generated code and Tcl is used to do much of that code generation.
The makefiles also require AWK.
## Source Code Tour
Most of the core source files are in the **src/** subdirectory. The
**src/** folder also contains files used to build the "testfixture" test
harness. The names of the source files used by "testfixture" all begin
with "test".
The **src/** also contains the "shell.c" file
which is the main program for the "sqlite3.exe"
[command-line shell](https://sqlite.org/cli.html) and
the "tclsqlite.c" file which implements the
[Tcl bindings](https://sqlite.org/tclsqlite.html) for SQLite.
(Historical note: SQLite began as a Tcl
Most of the core source files are in the **src/** subdirectory. But
src/ also contains files used to build the "testfixture" test harness;
those file all begin with "test". And src/ contains the "shell.c" file
which is the main program for the "sqlite3.exe" command-line shell and
the "tclsqlite.c" file which implements the bindings to SQLite from the
Tcl programming language. (Historical note: SQLite began as a Tcl
extension and only later escaped to the wild as an independent library.)
Test scripts and programs are found in the **test/** subdirectory.
Addtional test code is found in other source repositories.
See [How SQLite Is Tested](http://www.sqlite.org/testing.html) for
additional information.
There are other test suites for SQLite (see
[How SQLite Is Tested](http://www.sqlite.org/testing.html))
but those other test suites are
in separate source repositories.
The **ext/** subdirectory contains code for extensions. The
Full-text search engine is in **ext/fts3**. The R-Tree engine is in
@@ -149,7 +100,7 @@ manually-edited files and automatically-generated files.
The SQLite interface is defined by the **sqlite3.h** header file, which is
generated from src/sqlite.h.in, ./manifest.uuid, and ./VERSION. The
[Tcl script](http://www.tcl.tk) at tool/mksqlite3h.tcl does the conversion.
The manifest.uuid file contains the SHA3 hash of the particular check-in
The manifest.uuid file contains the SHA1 hash of the particular check-in
and is used to generate the SQLITE\_SOURCE\_ID macro. The VERSION file
contains the current SQLite version number. The sqlite3.h header is really
just a copy of src/sqlite.h.in with the source-id and version number inserted
@@ -160,19 +111,20 @@ used to generate that documentation are in a separate source repository.
The SQL language parser is **parse.c** which is generate from a grammar in
the src/parse.y file. The conversion of "parse.y" into "parse.c" is done
by the [lemon](./doc/lemon.html) LALR(1) parser generator. The source code
for lemon is at tool/lemon.c. Lemon uses the tool/lempar.c file as a
template for generating its parser.
for lemon is at tool/lemon.c. Lemon uses a
template for generating its parser. A generic template is in tool/lempar.c,
but SQLite uses a slightly modified template found in src/lempar.c.
Lemon also generates the **parse.h** header file, at the same time it
generates parse.c. But the parse.h header file is
modified further (to add additional symbols) using the ./addopcodes.tcl
Tcl script.
modified further (to add additional symbols) using the ./addopcodes.awk
AWK script.
The **opcodes.h** header file contains macros that define the numbers
corresponding to opcodes in the "VDBE" virtual machine. The opcodes.h
file is generated by the scanning the src/vdbe.c source file. The
Tcl script at ./mkopcodeh.tcl does this scan and generates opcodes.h.
A second Tcl script, ./mkopcodec.tcl, then scans opcodes.h to generate
AWK script at ./mkopcodeh.awk does this scan and generates opcodes.h.
A second AWK script, ./mkopcodec.awk, then scans opcodes.h to generate
the **opcodes.c** source file, which contains a reverse mapping from
opcode-number to opcode-name that is used for EXPLAIN output.
@@ -181,13 +133,6 @@ that maps SQL language keywords (ex: "CREATE", "SELECT", "INDEX", etc.) into
the numeric codes used by the parse.c parser. The keywordhash.h file is
generated by a C-language program at tool mkkeywordhash.c.
The **pragma.h** header file contains various definitions used to parse
and implement the PRAGMA statements. The header is generated by a
script **tool/mkpragmatab.tcl**. If you want to add a new PRAGMA, edit
the **tool/mkpragmatab.tcl** file to insert the information needed by the
parser for your new PRAGMA, then run the script to regenerate the
**pragma.h** header file.
### The Amalgamation
All of the individual C source code and header files (both manually-edited
@@ -205,12 +150,12 @@ subdirectory (using the equivalent of "make target_source") then the
tool/mksqlite3c.tcl script is run to copy them all together in just the
right order while resolving internal "#include" references.
The amalgamation source file is more than 200K lines long. Some symbolic
The amalgamation source file is more than 100K lines long. Some symbolic
debuggers (most notably MSVC) are unable to deal with files longer than 64K
lines. To work around this, a separate Tcl script, tool/split-sqlite3c.tcl,
can be run on the amalgamation to break it up into a single small C file
called **sqlite3-all.c** that does #include on about seven other files
named **sqlite3-1.c**, **sqlite3-2.c**, ..., **sqlite3-7.c**. In this way,
called **sqlite3-all.c** that does #include on about five other files
named **sqlite3-1.c**, **sqlite3-2.c**, ..., **sqlite3-5.c**. In this way,
all of the source code is contained within a single translation unit so
that the compiler can do extra cross-procedure optimization, but no
individual source file exceeds 32K lines in length.
@@ -222,15 +167,14 @@ See the [architectural description](http://www.sqlite.org/arch.html)
for details. Other documents that are useful in
(helping to understand how SQLite works include the
[file format](http://www.sqlite.org/fileformat2.html) description,
the [virtual machine](http://www.sqlite.org/opcode.html) that runs
the [virtual machine](http://www.sqlite.org/vdbe.html) that runs
prepared statements, the description of
[how transactions work](http://www.sqlite.org/atomiccommit.html), and
the [overview of the query planner](http://www.sqlite.org/optoverview.html).
Years of effort have gone into optimizating SQLite, both
Unfortunately, years of effort have gone into optimizating SQLite, both
for small size and high performance. And optimizations tend to result in
complex code. So there is a lot of complexity in the current SQLite
implementation. It will not be the easiest library in the world to hack.
complex code. So there is a lot of complexity in the SQLite implementation.
Key files:
@@ -239,10 +183,9 @@ Key files:
trying to understand how the library works internally.
* **sqliteInt.h** - this header file defines many of the data objects
used internally by SQLite. In addition to "sqliteInt.h", some
subsystems have their own header files.
used internally by SQLite.
* **parse.y** - This file describes the LALR(1) grammar that SQLite uses
* **parse.y** - This file describes the LALR(1) grammer that SQLite uses
to parse SQL statements, and the actions that are taken at each step
in the parsing process.
@@ -252,51 +195,36 @@ Key files:
which defines internal data objects. The rest of SQLite interacts
with the VDBE through an interface defined by vdbe.h.
* **where.c** - This file (together with its helper files named
by "where*.c") analyzes the WHERE clause and generates
* **where.c** - This file analyzes the WHERE clause and generates
virtual machine code to run queries efficiently. This file is
sometimes called the "query optimizer". It has its own private
header file, whereInt.h, that defines data objects used internally.
* **btree.c** - This file contains the implementation of the B-Tree
storage engine used by SQLite. The interface to the rest of the system
is defined by "btree.h". The "btreeInt.h" header defines objects
used internally by btree.c and not published to the rest of the system.
storage engine used by SQLite.
* **pager.c** - This file contains the "pager" implementation, the
module that implements transactions. The "pager.h" header file
defines the interface between pager.c and the rest of the system.
module that implements transactions.
* **os_unix.c** and **os_win.c** - These two files implement the interface
between SQLite and the underlying operating system using the run-time
pluggable VFS interface.
* **shell.c.in** - This file is not part of the core SQLite library. This
* **shell.c** - This file is not part of the core SQLite library. This
is the file that, when linked against sqlite3.a, generates the
"sqlite3.exe" command-line shell. The "shell.c.in" file is transformed
into "shell.c" as part of the build process.
"sqlite3.exe" command-line shell.
* **tclsqlite.c** - This file implements the Tcl bindings for SQLite. It
is not part of the core SQLite library. But as most of the tests in this
repository are written in Tcl, the Tcl language bindings are important.
* **test*.c** - Files in the src/ folder that begin with "test" go into
building the "testfixture.exe" program. The testfixture.exe program is
an enhanced Tcl shell. The testfixture.exe program runs scripts in the
test/ folder to validate the core SQLite code. The testfixture program
(and some other test programs too) is build and run when you type
"make test".
* **ext/misc/json1.c** - This file implements the various JSON functions
that are build into SQLite.
There are many other source files. Each has a succinct header comment that
There are many other source files. Each has a suscinct header comment that
describes its purpose and role within the larger system.
## Contacts
The main SQLite webpage is [http://www.sqlite.org/](http://www.sqlite.org/)
with geographically distributed backups at
with geographically distributed backup servers at
[http://www2.sqlite.org/](http://www2.sqlite.org) and
[http://www3.sqlite.org/](http://www3.sqlite.org).
+1 -1
View File
@@ -1 +1 @@
3.24.0
3.14.0
+2 -2
View File
@@ -1,5 +1,5 @@
AM_CFLAGS = @THREADSAFE_FLAGS@ @DYNAMIC_EXTENSION_FLAGS@ @FTS5_FLAGS@ @JSON1_FLAGS@ @ZLIB_FLAGS@ @SESSION_FLAGS@ -DSQLITE_ENABLE_FTS3 -DSQLITE_ENABLE_RTREE @DEBUG_FLAGS@
AM_CFLAGS = @THREADSAFE_FLAGS@ @DYNAMIC_EXTENSION_FLAGS@ @FTS5_FLAGS@ @JSON1_FLAGS@ @SESSION_FLAGS@ -DSQLITE_ENABLE_FTS3 -DSQLITE_ENABLE_RTREE
lib_LTLIBRARIES = libsqlite3.la
libsqlite3_la_SOURCES = sqlite3.c
@@ -10,7 +10,7 @@ sqlite3_SOURCES = shell.c sqlite3.h
EXTRA_sqlite3_SOURCES = sqlite3.c
sqlite3_LDADD = @EXTRA_SHELL_OBJ@ @READLINE_LIBS@
sqlite3_DEPENDENCIES = @EXTRA_SHELL_OBJ@
sqlite3_CFLAGS = $(AM_CFLAGS) -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_ENABLE_STMTVTAB -DSQLITE_ENABLE_DBSTAT_VTAB $(SHELL_CFLAGS)
sqlite3_CFLAGS = $(AM_CFLAGS) -DSQLITE_ENABLE_EXPLAIN_COMMENTS
include_HEADERS = sqlite3.h sqlite3ext.h
+12 -62
View File
@@ -21,28 +21,7 @@ TOP = .
# Set this non-0 to enable full warnings (-W4, etc) when compiling.
#
!IFNDEF USE_FULLWARN
USE_FULLWARN = 1
!ENDIF
# Set this non-0 to enable treating warnings as errors (-WX, etc) when
# compiling.
#
!IFNDEF USE_FATAL_WARN
USE_FATAL_WARN = 0
!ENDIF
# Set this non-0 to enable full runtime error checks (-RTC1, etc). This
# has no effect if (any) optimizations are enabled.
#
!IFNDEF USE_RUNTIME_CHECKS
USE_RUNTIME_CHECKS = 0
!ENDIF
# Set this non-0 to create a SQLite amalgamation file that excludes the
# various built-in extensions.
#
!IFNDEF MINIMAL_AMALGAMATION
MINIMAL_AMALGAMATION = 0
USE_FULLWARN = 0
!ENDIF
# Set this non-0 to use "stdcall" calling convention for the core library
@@ -269,15 +248,12 @@ SQLITE3EXEPDB = /pdb:sqlite3sh.pdb
!ENDIF
!ENDIF
# These are the "standard" SQLite compilation options used when compiling for
# the Windows platform.
#
!IFNDEF OPT_FEATURE_FLAGS
!IF $(MINIMAL_AMALGAMATION)==0
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_FTS3=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_RTREE=1
!ENDIF
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_COLUMN_METADATA=1
!ENDIF
@@ -461,12 +437,6 @@ TCC = $(CC) -nologo -W4 -DINCLUDE_MSVC_H=1 $(CCOPTS) $(TCCOPTS)
TCC = $(CC) -nologo -W3 $(CCOPTS) $(TCCOPTS)
!ENDIF
# Check if warnings should be treated as errors when compiling.
#
!IF $(USE_FATAL_WARN)!=0
TCC = $(TCC) -WX
!ENDIF
TCC = $(TCC) -DSQLITE_OS_WIN=1 -I. -I$(TOP) -fp:precise
RCC = $(RC) -DSQLITE_OS_WIN=1 -I. -I$(TOP) $(RCOPTS) $(RCCOPTS)
@@ -479,12 +449,12 @@ RCC = $(RC) -DSQLITE_OS_WIN=1 -I. -I$(TOP) $(RCOPTS) $(RCCOPTS)
#
!IF $(USE_STDCALL)!=0 || $(FOR_WIN10)!=0
!IF "$(PLATFORM)"=="x86"
CORE_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
SHELL_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
CORE_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_STDCALL=__stdcall
SHELL_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_STDCALL=__stdcall
!ELSE
!IFNDEF PLATFORM
CORE_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
SHELL_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
CORE_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_STDCALL=__stdcall
SHELL_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_STDCALL=__stdcall
!ELSE
CORE_CCONV_OPTS =
SHELL_CCONV_OPTS =
@@ -561,7 +531,6 @@ SHELL_CORE_DEP =
!ENDIF
!ENDIF
# This is the core library that the shell executable should link with.
#
!IFNDEF SHELL_CORE_LIB
@@ -646,10 +615,6 @@ RCC = $(RCC) -DSQLITE_ENABLE_API_ARMOR=1
!IF $(DEBUG)>2
TCC = $(TCC) -DSQLITE_DEBUG=1
RCC = $(RCC) -DSQLITE_DEBUG=1
!IF $(DYNAMIC_SHELL)==0
TCC = $(TCC) -DSQLITE_ENABLE_WHERETRACE -DSQLITE_ENABLE_SELECTTRACE
RCC = $(RCC) -DSQLITE_ENABLE_WHERETRACE -DSQLITE_ENABLE_SELECTTRACE
!ENDIF
!ENDIF
!IF $(DEBUG)>4 || $(OSTRACE)!=0
@@ -775,10 +740,6 @@ RCC = $(RCC) -D_DEBUG
!IF $(DEBUG)>1 || $(OPTIMIZATIONS)==0
TCC = $(TCC) -Od
BCC = $(BCC) -Od
!IF $(USE_RUNTIME_CHECKS)!=0
TCC = $(TCC) -RTC1
BCC = $(BCC) -RTC1
!ENDIF
!ELSEIF $(OPTIMIZATIONS)>=3
TCC = $(TCC) -Ox
BCC = $(BCC) -Ox
@@ -809,7 +770,7 @@ LTLINK = $(TCC) -Fe$@
# If requested, link to the RPCRT4 library.
#
!IF $(USE_RPCRT4_LIB)!=0
LTLIBS = $(LTLIBS) rpcrt4.lib
LTLINK = $(LTLINK) rpcrt4.lib
!ENDIF
# If a platform was set, force the linker to target that.
@@ -928,25 +889,14 @@ LIBRESOBJS =
# when the shell is not being dynamically linked.
#
!IF $(DYNAMIC_SHELL)==0 && $(FOR_WIN10)==0
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_STMTVTAB
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_ENABLE_DBSTAT_VTAB
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_OFFSET_SQL_FUNC -DSQLITE_INTROSPECTION_PRAGMAS
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_RTREE
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_SHELL_JSON1 -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS
!ENDIF
# This is the default Makefile target. The objects listed here
# are what get build when you type just "make" with no arguments.
#
core: dll shell
# Targets that require the Tcl library.
#
tcl: $(ALL_TCL_TARGETS)
# This Makefile target builds all of the standard binaries.
#
all: core tcl
all: dll shell
# Dynamic link library section.
#
@@ -966,11 +916,11 @@ Replace.exe:
sqlite3.def: Replace.exe $(LIBOBJ)
echo EXPORTS > sqlite3.def
dumpbin /all $(LIBOBJ) \
| .\Replace.exe "^\s+/EXPORT:_?(sqlite3(?:session|changeset|changegroup|rebaser)?_[^@,]*)(?:@\d+|,DATA)?$$" $$1 true \
| .\Replace.exe "^\s+/EXPORT:_?(sqlite3_[^@,]*)(?:@\d+|,DATA)?$$" $$1 true \
| sort >> sqlite3.def
$(SQLITE3EXE): shell.c $(SHELL_CORE_DEP) $(LIBRESOBJS) $(SHELL_CORE_SRC) $(SQLITE3H)
$(LTLINK) $(SHELL_COMPILE_OPTS) $(READLINE_FLAGS) shell.c $(SHELL_CORE_SRC) \
$(SQLITE3EXE): $(TOP)\shell.c $(SHELL_CORE_DEP) $(LIBRESOBJS) $(SHELL_CORE_SRC) $(SQLITE3H)
$(LTLINK) $(SHELL_COMPILE_OPTS) $(READLINE_FLAGS) $(TOP)\shell.c $(SHELL_CORE_SRC) \
/link $(SQLITE3EXEPDB) $(LDFLAGS) $(LTLINKOPTS) $(SHELL_LINK_OPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LIBREADLINE) $(LTLIBS) $(TLIBS)
@@ -985,7 +935,7 @@ sqlite3.lo: $(SQLITE3C)
!IF $(USE_RC)!=0
_HASHCHAR=^#
!IF ![echo !IFNDEF VERSION > rcver.vc] && \
![for /F "delims=" %V in ('type "$(SQLITE3H)" ^| "%SystemRoot%\System32\find.exe" "$(_HASHCHAR)define SQLITE_VERSION "') do (echo VERSION = ^^%V >> rcver.vc)] && \
![for /F "delims=" %V in ('type "$(SQLITE3H)" ^| find "$(_HASHCHAR)define SQLITE_VERSION "') do (echo VERSION = ^^%V >> rcver.vc)] && \
![echo !ENDIF >> rcver.vc]
!INCLUDE rcver.vc
!ENDIF
+6 -26
View File
@@ -12,7 +12,6 @@
AC_PREREQ(2.61)
AC_INIT(sqlite, --SQLITE-VERSION--, http://www.sqlite.org)
AC_CONFIG_SRCDIR([sqlite3.c])
AC_CONFIG_AUX_DIR([.])
# Use automake.
AM_INIT_AUTOMAKE([foreign])
@@ -56,9 +55,9 @@ AS_IF([ test x"$enable_editline" != xno ],[
LIBS=""
AC_SEARCH_LIBS([readline],[edit],[
AC_DEFINE([HAVE_EDITLINE],1,Define to use BSD editline)
READLINE_LIBS="$LIBS -ltinfo"
READLINE_LIBS=$LIBS
enable_readline=no
],[],[-ltinfo])
])
AS_UNSET(ac_cv_search_readline)
LIBS=$sLIBS
])
@@ -115,8 +114,8 @@ AC_SUBST(DYNAMIC_EXTENSION_FLAGS)
# --enable-fts5
#
AC_ARG_ENABLE(fts5, [AS_HELP_STRING(
[--enable-fts5], [include fts5 support [default=yes]])],
[], [enable_fts5=yes])
[--enable-fts5], [include fts5 support [default=no]])],
[], [enable_fts5=no])
if test x"$enable_fts5" = "xyes"; then
AC_SEARCH_LIBS(log, m)
FTS5_FLAGS=-DSQLITE_ENABLE_FTS5
@@ -128,8 +127,8 @@ AC_SUBST(FTS5_FLAGS)
# --enable-json1
#
AC_ARG_ENABLE(json1, [AS_HELP_STRING(
[--enable-json1], [include json1 support [default=yes]])],
[], [enable_json1=yes])
[--enable-json1], [include json1 support [default=no]])],
[], [enable_json1=no])
if test x"$enable_json1" = "xyes"; then
JSON1_FLAGS=-DSQLITE_ENABLE_JSON1
fi
@@ -148,18 +147,6 @@ fi
AC_SUBST(SESSION_FLAGS)
#-----------------------------------------------------------------------
#-----------------------------------------------------------------------
# --enable-debug
#
AC_ARG_ENABLE(debug, [AS_HELP_STRING(
[--enable-debug], [build with debugging features enabled [default=no]])],
[], [enable_session=no])
if test x"$enable_debug" = "xyes"; then
DEBUG_FLAGS="-DSQLITE_DEBUG -DSQLITE_ENABLE_SELECTTRACE -DSQLITE_ENABLE_WHERETRACE"
fi
AC_SUBST(DEBUG_FLAGS)
#-----------------------------------------------------------------------
#-----------------------------------------------------------------------
# --enable-static-shell
#
@@ -176,13 +163,6 @@ AC_SUBST(EXTRA_SHELL_OBJ)
#-----------------------------------------------------------------------
AC_CHECK_FUNCS(posix_fallocate)
AC_CHECK_HEADERS(zlib.h,[
AC_SEARCH_LIBS(deflate,z,[ZLIB_FLAGS="-DSQLITE_HAVE_ZLIB"])
])
AC_SUBST(ZLIB_FLAGS)
AC_SEARCH_LIBS(system,,,[SHELL_CFLAGS="-DSQLITE_NOHAVE_SYSTEM"])
AC_SUBST(SHELL_CFLAGS)
#-----------------------------------------------------------------------
# UPDATE: Maybe it's better if users just set CFLAGS before invoking
+1
View File
@@ -78,6 +78,7 @@ TEA_ADD_LIBS([])
TEA_ADD_CFLAGS([-DSQLITE_ENABLE_FTS3=1])
TEA_ADD_CFLAGS([-DSQLITE_3_SUFFIX_ONLY=1])
TEA_ADD_CFLAGS([-DSQLITE_ENABLE_RTREE=1])
TEA_ADD_CFLAGS([-DSQLITE_OMIT_DEPRECATED=1])
TEA_ADD_STUB_SOURCES([])
TEA_ADD_TCL_SOURCES([])
Vendored
+35 -126
View File
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.69 for sqlite 3.24.0.
# Generated by GNU Autoconf 2.69 for sqlite 3.14.0.
#
#
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
@@ -726,8 +726,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='sqlite'
PACKAGE_TARNAME='sqlite'
PACKAGE_VERSION='3.24.0'
PACKAGE_STRING='sqlite 3.24.0'
PACKAGE_VERSION='3.14.0'
PACKAGE_STRING='sqlite 3.14.0'
PACKAGE_BUGREPORT=''
PACKAGE_URL=''
@@ -772,7 +772,6 @@ LIBOBJS
BUILD_CFLAGS
USE_GCOV
OPT_FEATURE_FLAGS
HAVE_ZLIB
USE_AMALGAMATION
TARGET_DEBUG
TARGET_HAVE_EDITLINE
@@ -910,7 +909,6 @@ enable_fts3
enable_fts4
enable_fts5
enable_json1
enable_update_limit
enable_rtree
enable_session
enable_gcov
@@ -1465,7 +1463,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
\`configure' configures sqlite 3.24.0 to adapt to many kinds of systems.
\`configure' configures sqlite 3.14.0 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1530,7 +1528,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
short | recursive ) echo "Configuration of sqlite 3.24.0:";;
short | recursive ) echo "Configuration of sqlite 3.14.0:";;
esac
cat <<\_ACEOF
@@ -1562,7 +1560,6 @@ Optional Features:
--enable-fts4 Enable the FTS4 extension
--enable-fts5 Enable the FTS5 extension
--enable-json1 Enable the JSON1 extension
--enable-update-limit Enable the UPDATE/DELETE LIMIT clause
--enable-rtree Enable the RTREE extension
--enable-session Enable the SESSION extension
--enable-gcov Enable coverage testing using gcov
@@ -1655,7 +1652,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
sqlite configure 3.24.0
sqlite configure 3.14.0
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2074,7 +2071,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
It was created by sqlite $as_me 3.24.0, which was
It was created by sqlite $as_me 3.14.0, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -3932,13 +3929,13 @@ if ${lt_cv_nm_interface+:} false; then :
else
lt_cv_nm_interface="BSD nm"
echo "int some_variable = 0;" > conftest.$ac_ext
(eval echo "\"\$as_me:3935: $ac_compile\"" >&5)
(eval echo "\"\$as_me:3932: $ac_compile\"" >&5)
(eval "$ac_compile" 2>conftest.err)
cat conftest.err >&5
(eval echo "\"\$as_me:3938: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
(eval echo "\"\$as_me:3935: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
(eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
cat conftest.err >&5
(eval echo "\"\$as_me:3941: output\"" >&5)
(eval echo "\"\$as_me:3938: output\"" >&5)
cat conftest.out >&5
if $GREP 'External.*some_variable' conftest.out > /dev/null; then
lt_cv_nm_interface="MS dumpbin"
@@ -5144,7 +5141,7 @@ ia64-*-hpux*)
;;
*-*-irix6*)
# Find out which ABI we are using.
echo '#line 5147 "configure"' > conftest.$ac_ext
echo '#line 5144 "configure"' > conftest.$ac_ext
if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
(eval $ac_compile) 2>&5
ac_status=$?
@@ -6669,11 +6666,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
(eval echo "\"\$as_me:6672: $lt_compile\"" >&5)
(eval echo "\"\$as_me:6669: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
echo "$as_me:6676: \$? = $ac_status" >&5
echo "$as_me:6673: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
@@ -7008,11 +7005,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
(eval echo "\"\$as_me:7011: $lt_compile\"" >&5)
(eval echo "\"\$as_me:7008: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
echo "$as_me:7015: \$? = $ac_status" >&5
echo "$as_me:7012: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
@@ -7113,11 +7110,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
(eval echo "\"\$as_me:7116: $lt_compile\"" >&5)
(eval echo "\"\$as_me:7113: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
echo "$as_me:7120: \$? = $ac_status" >&5
echo "$as_me:7117: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
@@ -7168,11 +7165,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
(eval echo "\"\$as_me:7171: $lt_compile\"" >&5)
(eval echo "\"\$as_me:7168: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
echo "$as_me:7175: \$? = $ac_status" >&5
echo "$as_me:7172: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
@@ -9548,7 +9545,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
#line 9551 "configure"
#line 9548 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -9644,7 +9641,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
#line 9647 "configure"
#line 9644 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -10305,7 +10302,7 @@ USE_AMALGAMATION=1
# if not, then we fall back to plain tclsh.
# TODO: try other versions before falling back?
#
for ac_prog in tclsh8.7 tclsh8.6 tclsh8.5 tclsh
for ac_prog in tclsh8.6 tclsh8.5 tclsh
do
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
@@ -11255,7 +11252,7 @@ else
fi
if test "${use_debug}" = "yes" ; then
TARGET_DEBUG="-DSQLITE_DEBUG=1 -DSQLITE_ENABLE_SELECTTRACE -DSQLITE_ENABLE_WHERETRACE -O0"
TARGET_DEBUG="-DSQLITE_DEBUG=1"
else
TARGET_DEBUG="-DNDEBUG"
fi
@@ -11275,80 +11272,6 @@ if test "${use_amalgamation}" != "yes" ; then
fi
#########
# Look for zlib. Only needed by extensions and by the sqlite3.exe shell
for ac_header in zlib.h
do :
ac_fn_c_check_header_mongrel "$LINENO" "zlib.h" "ac_cv_header_zlib_h" "$ac_includes_default"
if test "x$ac_cv_header_zlib_h" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_ZLIB_H 1
_ACEOF
fi
done
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing deflate" >&5
$as_echo_n "checking for library containing deflate... " >&6; }
if ${ac_cv_search_deflate+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_func_search_save_LIBS=$LIBS
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char deflate ();
int
main ()
{
return deflate ();
;
return 0;
}
_ACEOF
for ac_lib in '' z; do
if test -z "$ac_lib"; then
ac_res="none required"
else
ac_res=-l$ac_lib
LIBS="-l$ac_lib $ac_func_search_save_LIBS"
fi
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_search_deflate=$ac_res
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext
if ${ac_cv_search_deflate+:} false; then :
break
fi
done
if ${ac_cv_search_deflate+:} false; then :
else
ac_cv_search_deflate=no
fi
rm conftest.$ac_ext
LIBS=$ac_func_search_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_deflate" >&5
$as_echo "$ac_cv_search_deflate" >&6; }
ac_res=$ac_cv_search_deflate
if test "$ac_res" != no; then :
test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
HAVE_ZLIB="-DSQLITE_HAVE_ZLIB=1"
else
HAVE_ZLIB=""
fi
#########
# See whether we should allow loadable extensions
# Check whether --enable-load-extension was given.
@@ -11433,7 +11356,7 @@ fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to support MEMSYS5" >&5
$as_echo_n "checking whether to support MEMSYS5... " >&6; }
if test "${enable_memsys5}" = "yes"; then
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_MEMSYS5"
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_MEMSYS5"
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
else
@@ -11450,7 +11373,7 @@ fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to support MEMSYS3" >&5
$as_echo_n "checking whether to support MEMSYS3... " >&6; }
if test "${enable_memsys3}" = "yes" -a "${enable_memsys5}" = "no"; then
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_MEMSYS3"
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_MEMSYS3"
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
else
@@ -11468,7 +11391,7 @@ else
fi
if test "${enable_fts3}" = "yes" ; then
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_FTS3"
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_FTS3"
fi
# Check whether --enable-fts4 was given.
if test "${enable_fts4+set}" = set; then :
@@ -11478,7 +11401,7 @@ else
fi
if test "${enable_fts4}" = "yes" ; then
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_FTS4"
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_FTS4"
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing log" >&5
$as_echo_n "checking for library containing log... " >&6; }
if ${ac_cv_search_log+:} false; then :
@@ -11544,7 +11467,7 @@ else
fi
if test "${enable_fts5}" = "yes" ; then
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_FTS5"
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_FTS5"
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing log" >&5
$as_echo_n "checking for library containing log... " >&6; }
if ${ac_cv_search_log+:} false; then :
@@ -11613,21 +11536,7 @@ else
fi
if test "${enable_json1}" = "yes" ; then
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_JSON1"
fi
#########
# See whether we should enable the LIMIT clause on UPDATE and DELETE
# statements.
# Check whether --enable-update-limit was given.
if test "${enable_update_limit+set}" = set; then :
enableval=$enable_update_limit; enable_udlimit=yes
else
enable_udlimit=no
fi
if test "${enable_udlimit}" = "yes" ; then
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_UPDATE_DELETE_LIMIT"
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_JSON1"
fi
#########
@@ -11640,7 +11549,7 @@ else
fi
if test "${enable_rtree}" = "yes" ; then
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_RTREE"
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_RTREE"
fi
#########
@@ -11653,12 +11562,12 @@ else
fi
if test "${enable_session}" = "yes" ; then
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_SESSION"
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_PREUPDATE_HOOK"
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_SESSION"
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_PREUPDATE_HOOK"
fi
#########
# attempt to duplicate any OMITS and ENABLES into the ${OPT_FEATURE_FLAGS} parameter
# attempt to duplicate any OMITS and ENABLES into the $(OPT_FEATURE_FLAGS) parameter
for option in $CFLAGS $CPPFLAGS
do
case $option in
@@ -12242,7 +12151,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
This file was extended by sqlite $as_me 3.24.0, which was
This file was extended by sqlite $as_me 3.14.0, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -12308,7 +12217,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
sqlite config.status 3.24.0
sqlite config.status 3.14.0
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
+12 -28
View File
@@ -120,7 +120,7 @@ USE_AMALGAMATION=1
# if not, then we fall back to plain tclsh.
# TODO: try other versions before falling back?
#
AC_CHECK_PROGS(TCLSH_CMD, [tclsh8.7 tclsh8.6 tclsh8.5 tclsh], none)
AC_CHECK_PROGS(TCLSH_CMD, [tclsh8.6 tclsh8.5 tclsh], none)
if test "$TCLSH_CMD" = "none"; then
# If we can't find a local tclsh, then building the amalgamation will fail.
# We act as though --disable-amalgamation has been used.
@@ -560,7 +560,7 @@ AC_SEARCH_LIBS(fdatasync, [rt])
AC_ARG_ENABLE(debug, AC_HELP_STRING([--enable-debug],[enable debugging & verbose explain]),
[use_debug=$enableval],[use_debug=no])
if test "${use_debug}" = "yes" ; then
TARGET_DEBUG="-DSQLITE_DEBUG=1 -DSQLITE_ENABLE_SELECTTRACE -DSQLITE_ENABLE_WHERETRACE -O0"
TARGET_DEBUG="-DSQLITE_DEBUG=1"
else
TARGET_DEBUG="-DNDEBUG"
fi
@@ -576,12 +576,6 @@ if test "${use_amalgamation}" != "yes" ; then
fi
AC_SUBST(USE_AMALGAMATION)
#########
# Look for zlib. Only needed by extensions and by the sqlite3.exe shell
AC_CHECK_HEADERS(zlib.h)
AC_SEARCH_LIBS(deflate, z, [HAVE_ZLIB="-DSQLITE_HAVE_ZLIB=1"], [HAVE_ZLIB=""])
AC_SUBST(HAVE_ZLIB)
#########
# See whether we should allow loadable extensions
AC_ARG_ENABLE(load-extension, AC_HELP_STRING([--disable-load-extension],
@@ -602,7 +596,7 @@ AC_ARG_ENABLE(memsys5,
[enable_memsys5=yes],[enable_memsys5=no])
AC_MSG_CHECKING([whether to support MEMSYS5])
if test "${enable_memsys5}" = "yes"; then
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_MEMSYS5"
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_MEMSYS5"
AC_MSG_RESULT([yes])
else
AC_MSG_RESULT([no])
@@ -612,7 +606,7 @@ AC_ARG_ENABLE(memsys3,
[enable_memsys3=yes],[enable_memsys3=no])
AC_MSG_CHECKING([whether to support MEMSYS3])
if test "${enable_memsys3}" = "yes" -a "${enable_memsys5}" = "no"; then
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_MEMSYS3"
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_MEMSYS3"
AC_MSG_RESULT([yes])
else
AC_MSG_RESULT([no])
@@ -624,20 +618,20 @@ AC_ARG_ENABLE(fts3, AC_HELP_STRING([--enable-fts3],
[Enable the FTS3 extension]),
[enable_fts3=yes],[enable_fts3=no])
if test "${enable_fts3}" = "yes" ; then
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_FTS3"
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_FTS3"
fi
AC_ARG_ENABLE(fts4, AC_HELP_STRING([--enable-fts4],
[Enable the FTS4 extension]),
[enable_fts4=yes],[enable_fts4=no])
if test "${enable_fts4}" = "yes" ; then
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_FTS4"
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_FTS4"
AC_SEARCH_LIBS([log],[m])
fi
AC_ARG_ENABLE(fts5, AC_HELP_STRING([--enable-fts5],
[Enable the FTS5 extension]),
[enable_fts5=yes],[enable_fts5=no])
if test "${enable_fts5}" = "yes" ; then
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_FTS5"
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_FTS5"
AC_SEARCH_LIBS([log],[m])
fi
@@ -647,17 +641,7 @@ AC_ARG_ENABLE(json1, AC_HELP_STRING([--enable-json1],
[Enable the JSON1 extension]),
[enable_json1=yes],[enable_json1=no])
if test "${enable_json1}" = "yes" ; then
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_JSON1"
fi
#########
# See whether we should enable the LIMIT clause on UPDATE and DELETE
# statements.
AC_ARG_ENABLE(update-limit, AC_HELP_STRING([--enable-update-limit],
[Enable the UPDATE/DELETE LIMIT clause]),
[enable_udlimit=yes],[enable_udlimit=no])
if test "${enable_udlimit}" = "yes" ; then
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_UPDATE_DELETE_LIMIT"
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_JSON1"
fi
#########
@@ -666,7 +650,7 @@ AC_ARG_ENABLE(rtree, AC_HELP_STRING([--enable-rtree],
[Enable the RTREE extension]),
[enable_rtree=yes],[enable_rtree=no])
if test "${enable_rtree}" = "yes" ; then
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_RTREE"
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_RTREE"
fi
#########
@@ -675,12 +659,12 @@ AC_ARG_ENABLE(session, AC_HELP_STRING([--enable-session],
[Enable the SESSION extension]),
[enable_session=yes],[enable_session=no])
if test "${enable_session}" = "yes" ; then
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_SESSION"
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_PREUPDATE_HOOK"
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_SESSION"
OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_PREUPDATE_HOOK"
fi
#########
# attempt to duplicate any OMITS and ENABLES into the ${OPT_FEATURE_FLAGS} parameter
# attempt to duplicate any OMITS and ENABLES into the $(OPT_FEATURE_FLAGS) parameter
for option in $CFLAGS $CPPFLAGS
do
case $option in
+178 -252
View File
@@ -2,12 +2,12 @@
<head>
<title>The Lemon Parser Generator</title>
</head>
<body bgcolor='white'>
<h1 align='center'>The Lemon Parser Generator</h1>
<body bgcolor=white>
<h1 align=center>The Lemon Parser Generator</h1>
<p>Lemon is an LALR(1) parser generator for C.
It does the same job as "bison" and "yacc".
But Lemon is not a bison or yacc clone. Lemon
But lemon is not a bison or yacc clone. Lemon
uses a different grammar syntax which is designed to
reduce the number of coding errors. Lemon also uses a
parsing engine that is faster than yacc and
@@ -16,33 +16,13 @@ bison and which is both reentrant and threadsafe.
has also been updated so that it too can generate a
reentrant and threadsafe parser.)
Lemon also implements features that can be used
to eliminate resource leaks, making it suitable for use
to eliminate resource leaks, making is suitable for use
in long-running programs such as graphical user interfaces
or embedded controllers.</p>
<p>This document is an introduction to the Lemon
parser generator.</p>
<h2>Security Note</h2>
<p>The language parser code created by Lemon is very robust and
is well-suited for use in internet-facing applications that need to
safely process maliciously crafted inputs.
<p>The "lemon.exe" command-line tool itself works great when given a valid
input grammar file and almost always gives helpful
error messages for malformed inputs. However, it is possible for
a malicious user to craft a grammar file that will cause
lemon.exe to crash.
We do not see this as a problem, as lemon.exe is not intended to be used
with hostile inputs.
To summarize:</p>
<ul>
<li>Parser code generated by lemon &rarr; Robust and secure
<li>The "lemon.exe" command line tool itself &rarr; Not so much
</ul>
<h2>Theory of Operation</h2>
<p>The main goal of Lemon is to translate a context free grammar (CFG)
@@ -58,8 +38,8 @@ Lemon comes with a default parser template which works fine for most
applications. But the user is free to substitute a different parser
template if desired.</p>
<p>Depending on command-line options, Lemon will generate up to
three output files.
<p>Depending on command-line options, Lemon will generate between
one and three files of outputs.
<ul>
<li>C code to implement the parser.
<li>A header file defining an integer ID for each terminal symbol.
@@ -90,33 +70,27 @@ the states used by the parser automaton.</p>
You can obtain a list of the available command-line options together
with a brief explanation of what each does by typing
<pre>
lemon "-?"
lemon -?
</pre>
As of this writing, the following command-line options are supported:
<ul>
<li><b>-b</b>
Show only the basis for each parser state in the report file.
<li><b>-c</b>
Do not compress the generated action tables. The parser will be a
little larger and slower, but it will detect syntax errors sooner.
<li><b>-d</b><i>directory</i>
Write all output files into <i>directory</i>. Normally, output files
are written into the directory that contains the input grammar file.
Do not compress the generated action tables.
<li><b>-D<i>name</i></b>
Define C preprocessor macro <i>name</i>. This macro is usable by
"<tt><a href='#pifdef'>%ifdef</a></tt>" and
"<tt><a href='#pifdef'>%ifndef</a></tt>" lines
in the grammar file.
Define C preprocessor macro <i>name</i>. This macro is useable by
"%ifdef" lines in the grammar file.
<li><b>-g</b>
Do not generate a parser. Instead write the input grammar to standard
output with all comments, actions, and other extraneous text removed.
<li><b>-l</b>
Omit "#line" directives in the generated parser C code.
Omit "#line" directives int the generated parser C code.
<li><b>-m</b>
Cause the output C source code to be compatible with the "makeheaders"
program.
program.
<li><b>-p</b>
Display all conflicts that are resolved by
Display all conflicts that are resolved by
<a href='#precrules'>precedence rules</a>.
<li><b>-q</b>
Suppress generation of the report file.
@@ -171,7 +145,7 @@ once for each token:
</pre>
The first argument to the Parse() routine is the pointer returned by
ParseAlloc().
The second argument is a small positive integer that tells the parser the
The second argument is a small positive integer that tells the parse the
type of the next token in the data stream.
There is one token type for each terminal symbol in the grammar.
The gram.h file generated by Lemon contains #define statements that
@@ -179,7 +153,7 @@ map symbolic terminal symbol names into appropriate integer values.
A value of 0 for the second argument is a special flag to the
parser to indicate that the end of input has been reached.
The third argument is the value of the given token. By default,
the type of the third argument is "void*", but the grammar will
the type of the third argument is integer, but the grammar will
usually redefine this type to be some kind of structure.
Typically the second argument will be a broad category of tokens
such as "identifier" or "number" and the third argument will
@@ -187,7 +161,7 @@ be the name of the identifier or the value of the number.</p>
<p>The Parse() function may have either three or four arguments,
depending on the grammar. If the grammar specification file requests
it (via the <tt><a href='#extraarg'>%extra_argument</a></tt> directive),
it (via the <a href='#extraarg'><tt>extra_argument</tt> directive</a>),
the Parse() function will have a fourth parameter that can be
of any type chosen by the programmer. The parser doesn't do anything
with this argument except to pass it through to action routines.
@@ -197,20 +171,20 @@ to the action routines without having to use global variables.</p>
<p>A typical use of a Lemon parser might look something like the
following:
<pre>
1 ParseTree *ParseFile(const char *zFilename){
2 Tokenizer *pTokenizer;
3 void *pParser;
4 Token sToken;
5 int hTokenId;
6 ParserState sState;
7
8 pTokenizer = TokenizerCreate(zFilename);
9 pParser = ParseAlloc( malloc );
10 InitParserState(&amp;sState);
11 while( GetNextToken(pTokenizer, &amp;hTokenId, &amp;sToken) ){
12 Parse(pParser, hTokenId, sToken, &amp;sState);
01 ParseTree *ParseFile(const char *zFilename){
02 Tokenizer *pTokenizer;
03 void *pParser;
04 Token sToken;
05 int hTokenId;
06 ParserState sState;
07
08 pTokenizer = TokenizerCreate(zFilename);
09 pParser = ParseAlloc( malloc );
10 InitParserState(&sState);
11 while( GetNextToken(pTokenizer, &hTokenId, &sToken) ){
12 Parse(pParser, hTokenId, sToken, &sState);
13 }
14 Parse(pParser, 0, sToken, &amp;sState);
14 Parse(pParser, 0, sToken, &sState);
15 ParseFree(pParser, free );
16 TokenizerFree(pTokenizer);
17 return sState.treeRoot;
@@ -223,10 +197,10 @@ simple.)
We assume the existence of some kind of tokenizer which is created
using TokenizerCreate() on line 8 and deleted by TokenizerFree()
on line 16. The GetNextToken() function on line 11 retrieves the
next token from the input file and puts its type in the
next token from the input file and puts its type in the
integer variable hTokenId. The sToken variable is assumed to be
some kind of structure that contains details about each token,
such as its complete text, what line it occurs on, etc.</p>
such as its complete text, what line it occurs on, etc. </p>
<p>This example also assumes the existence of structure of type
ParserState that holds state information about a particular parse.
@@ -243,7 +217,7 @@ tree.</p>
<pre>
ParseFile(){
pParser = ParseAlloc( malloc );
while( GetNextToken(pTokenizer,&amp;hTokenId, &amp;sToken) ){
while( GetNextToken(pTokenizer,&hTokenId, &sToken) ){
Parse(pParser, hTokenId, sToken);
}
Parse(pParser, 0, sToken);
@@ -303,25 +277,25 @@ specifies additional information Lemon requires to do its job.
Most of the work in using Lemon is in writing an appropriate
grammar file.</p>
<p>The grammar file for Lemon is, for the most part, free format.
<p>The grammar file for lemon is, for the most part, free format.
It does not have sections or divisions like yacc or bison. Any
declaration can occur at any point in the file.
Lemon ignores whitespace (except where it is needed to separate
tokens), and it honors the same commenting conventions as C and C++.</p>
tokens) and it honors the same commenting conventions as C and C++.</p>
<h3>Terminals and Nonterminals</h3>
<p>A terminal symbol (token) is any string of alphanumeric
and/or underscore characters
that begins with an uppercase letter.
that begins with an upper case letter.
A terminal can contain lowercase letters after the first character,
but the usual convention is to make terminals all uppercase.
but the usual convention is to make terminals all upper case.
A nonterminal, on the other hand, is any string of alphanumeric
and underscore characters than begins with a lowercase letter.
Again, the usual convention is to make nonterminals use all lowercase
letters.</p>
and underscore characters than begins with a lower case letter.
Again, the usual convention is to make nonterminals use all lower
case letters.</p>
<p>In Lemon, terminal and nonterminal symbols do not need to
<p>In Lemon, terminal and nonterminal symbols do not need to
be declared or identified in a separate section of the grammar file.
Lemon is able to generate a list of all terminals and nonterminals
by examining the grammar rules, and it can always distinguish a
@@ -345,8 +319,7 @@ The list of terminals and nonterminals on the right-hand side of the
rule can be empty.
Rules can occur in any order, except that the left-hand side of the
first rule is assumed to be the start symbol for the grammar (unless
specified otherwise using the <tt><a href='#start_symbol'>%start_symbol</a></tt>
directive described below.)
specified otherwise using the <tt>%start</tt> directive described below.)
A typical sequence of grammar rules might look something like this:
<pre>
expr ::= expr PLUS expr.
@@ -389,7 +362,7 @@ names to each symbol in a grammar rule and then using those symbolic
names in the action.
In yacc or bison, one would write this:
<pre>
expr -&gt; expr PLUS expr { $$ = $1 + $3; };
expr -> expr PLUS expr { $$ = $1 + $3; };
</pre>
But in Lemon, the same rule becomes the following:
<pre>
@@ -429,14 +402,14 @@ of the shift, and a reduce-reduce conflict is resolved by reducing
whichever rule comes first in the grammar file.</p>
<p>Just like in
yacc and bison, Lemon allows a measure of control
over the resolution of parsing conflicts using precedence rules.
yacc and bison, Lemon allows a measure of control
over the resolution of paring conflicts using precedence rules.
A precedence value can be assigned to any terminal symbol
using the
<tt><a href='#pleft'>%left</a></tt>,
<tt><a href='#pright'>%right</a></tt> or
<tt><a href='#pnonassoc'>%nonassoc</a></tt> directives. Terminal symbols
mentioned in earlier directives have a lower precedence than
using the
<a href='#pleft'>%left</a>,
<a href='#pright'>%right</a> or
<a href='#pnonassoc'>%nonassoc</a> directives. Terminal symbols
mentioned in earlier directives have a lower precedence that
terminal symbols mentioned in later directives. For example:</p>
<p><pre>
@@ -512,29 +485,29 @@ as follows:
<li> If the precedence of the token to be shifted is greater than
the precedence of the rule to reduce, then resolve in favor
of the shift. No parsing conflict is reported.
<li> If the precedence of the token to be shifted is less than the
<li> If the precedence of the token it be shifted is less than the
precedence of the rule to reduce, then resolve in favor of the
reduce action. No parsing conflict is reported.
<li> If the precedences are the same and the shift token is
right-associative, then resolve in favor of the shift.
No parsing conflict is reported.
<li> If the precedences are the same and the shift token is
<li> If the precedences are the same the shift token is
left-associative, then resolve in favor of the reduce.
No parsing conflict is reported.
<li> Otherwise, resolve the conflict by doing the shift, and
report a parsing conflict.
<li> Otherwise, resolve the conflict by doing the shift and
report the parsing conflict.
</ul>
Reduce-reduce conflicts are resolved this way:
<ul>
<li> If either reduce rule
<li> If either reduce rule
lacks precedence information, then resolve in favor of the
rule that appears first in the grammar, and report a parsing
rule that appears first in the grammar and report a parsing
conflict.
<li> If both rules have precedence and the precedence is different,
<li> If both rules have precedence and the precedence is different
then resolve the dispute in favor of the rule with the highest
precedence, and do not report a conflict.
precedence and do not report a conflict.
<li> Otherwise, resolve the conflict by reducing by the rule that
appears first in the grammar, and report a parsing conflict.
appears first in the grammar and report a parsing conflict.
</ul>
<h3>Special Directives</h3>
@@ -543,40 +516,40 @@ Reduce-reduce conflicts are resolved this way:
directives. We've described all the grammar rules, so now we'll
talk about the special directives.</p>
<p>Directives in Lemon can occur in any order. You can put them before
the grammar rules, or after the grammar rules, or in the midst of the
<p>Directives in lemon can occur in any order. You can put them before
the grammar rules, or after the grammar rules, or in the mist of the
grammar rules. It doesn't matter. The relative order of
directives used to assign precedence to terminals is important, but
other than that, the order of directives in Lemon is arbitrary.</p>
<p>Lemon supports the following special directives:
<ul>
<li><tt><a href='#pcode'>%code</a></tt>
<li><tt><a href='#default_destructor'>%default_destructor</a></tt>
<li><tt><a href='#default_type'>%default_type</a></tt>
<li><tt><a href='#destructor'>%destructor</a></tt>
<li><tt><a href='#pifdef'>%endif</a></tt>
<li><tt><a href='#extraarg'>%extra_argument</a></tt>
<li><tt><a href='#pfallback'>%fallback</a></tt>
<li><tt><a href='#pifdef'>%ifdef</a></tt>
<li><tt><a href='#pifdef'>%ifndef</a></tt>
<li><tt><a href='#pinclude'>%include</a></tt>
<li><tt><a href='#pleft'>%left</a></tt>
<li><tt><a href='#pname'>%name</a></tt>
<li><tt><a href='#pnonassoc'>%nonassoc</a></tt>
<li><tt><a href='#parse_accept'>%parse_accept</a></tt>
<li><tt><a href='#parse_failure'>%parse_failure</a></tt>
<li><tt><a href='#pright'>%right</a></tt>
<li><tt><a href='#stack_overflow'>%stack_overflow</a></tt>
<li><tt><a href='#stack_size'>%stack_size</a></tt>
<li><tt><a href='#start_symbol'>%start_symbol</a></tt>
<li><tt><a href='#syntax_error'>%syntax_error</a></tt>
<li><tt><a href='#token_class'>%token_class</a></tt>
<li><tt><a href='#token_destructor'>%token_destructor</a></tt>
<li><tt><a href='#token_prefix'>%token_prefix</a></tt>
<li><tt><a href='#token_type'>%token_type</a></tt>
<li><tt><a href='#ptype'>%type</a></tt>
<li><tt><a href='#pwildcard'>%wildcard</a></tt>
<li><tt>%code</tt>
<li><tt>%default_destructor</tt>
<li><tt>%default_type</tt>
<li><tt>%destructor</tt>
<li><tt>%endif</tt>
<li><tt>%extra_argument</tt>
<li><tt>%fallback</tt>
<li><tt>%ifdef</tt>
<li><tt>%ifndef</tt>
<li><tt>%include</tt>
<li><tt>%left</tt>
<li><tt>%name</tt>
<li><tt>%nonassoc</tt>
<li><tt>%parse_accept</tt>
<li><tt>%parse_failure </tt>
<li><tt>%right</tt>
<li><tt>%stack_overflow</tt>
<li><tt>%stack_size</tt>
<li><tt>%start_symbol</tt>
<li><tt>%syntax_error</tt>
<li><tt>%token_class</tt>
<li><tt>%token_destructor</tt>
<li><tt>%token_prefix</tt>
<li><tt>%token_type</tt>
<li><tt>%type</tt>
<li><tt>%wildcard</tt>
</ul>
Each of these directives will be described separately in the
following sections:</p>
@@ -584,42 +557,43 @@ following sections:</p>
<a name='pcode'></a>
<h4>The <tt>%code</tt> directive</h4>
<p>The <tt>%code</tt> directive is used to specify additional C code that
<p>The %code directive is used to specify addition C code that
is added to the end of the main output file. This is similar to
the <tt><a href='#pinclude'>%include</a></tt> directive except that
<tt>%include</tt> is inserted at the beginning of the main output file.</p>
the <a href='#pinclude'>%include</a> directive except that %include
is inserted at the beginning of the main output file.</p>
<p><tt>%code</tt> is typically used to include some action routines or perhaps
a tokenizer or even the "main()" function
<p>%code is typically used to include some action routines or perhaps
a tokenizer or even the "main()" function
as part of the output file.</p>
<a name='default_destructor'></a>
<h4>The <tt>%default_destructor</tt> directive</h4>
<p>The <tt>%default_destructor</tt> directive specifies a destructor to
<p>The %default_destructor directive specifies a destructor to
use for non-terminals that do not have their own destructor
specified by a separate <tt>%destructor</tt> directive. See the documentation
on the <tt><a name='#destructor'>%destructor</a></tt> directive below for
specified by a separate %destructor directive. See the documentation
on the <a name='#destructor'>%destructor</a> directive below for
additional information.</p>
<p>In some grammars, many different non-terminal symbols have the
same data type and hence the same destructor. This directive is
a convenient way to specify the same destructor for all those
<p>In some grammers, many different non-terminal symbols have the
same datatype and hence the same destructor. This directive is
a convenience way to specify the same destructor for all those
non-terminals using a single statement.</p>
<a name='default_type'></a>
<h4>The <tt>%default_type</tt> directive</h4>
<p>The <tt>%default_type</tt> directive specifies the data type of non-terminal
symbols that do not have their own data type defined using a separate
<tt><a href='#ptype'>%type</a></tt> directive.</p>
<p>The %default_type directive specifies the datatype of non-terminal
symbols that do no have their own datatype defined using a separate
<a href='#ptype'>%type</a> directive.
</p>
<a name='destructor'></a>
<h4>The <tt>%destructor</tt> directive</h4>
<p>The <tt>%destructor</tt> directive is used to specify a destructor for
<p>The %destructor directive is used to specify a destructor for
a non-terminal symbol.
(See also the <tt><a href='#token_destructor'>%token_destructor</a></tt>
(See also the <a href='#token_destructor'>%token_destructor</a>
directive which is used to specify a destructor for terminal symbols.)</p>
<p>A non-terminal's destructor is called to dispose of the
@@ -641,7 +615,7 @@ or other resources held by that non-terminal.</p>
%destructor nt { free($$); }
nt(A) ::= ID NUM. { A = malloc( 100 ); }
</pre>
This example is a bit contrived, but it serves to illustrate how
This example is a bit contrived but it serves to illustrate how
destructors work. The example shows a non-terminal named
"nt" that holds values of type "void*". When the rule for
an "nt" reduces, it sets the value of the non-terminal to
@@ -657,17 +631,17 @@ stack, unless the non-terminal is used in a C-code action. If
the non-terminal is used by C-code, then it is assumed that the
C-code will take care of destroying it.
More commonly, the value is used to build some
larger structure, and we don't want to destroy it, which is why
larger structure and we don't want to destroy it, which is why
the destructor is not called in this circumstance.</p>
<p>Destructors help avoid memory leaks by automatically freeing
allocated objects when they go out of scope.
To do the same using yacc or bison is much more difficult.</p>
<a name='extraarg'></a>
<a name="extraarg"></a>
<h4>The <tt>%extra_argument</tt> directive</h4>
The <tt>%extra_argument</tt> directive instructs Lemon to add a 4th parameter
The %extra_argument directive instructs Lemon to add a 4th parameter
to the parameter list of the Parse() function it generates. Lemon
doesn't do anything itself with this extra argument, but it does
make the argument available to C-code action routines, destructors,
@@ -682,91 +656,64 @@ of type "MyStruct*" and all action routines will have access to
a variable named "pAbc" that is the value of the 4th parameter
in the most recent call to Parse().</p>
<p>The <tt>%extra_context</tt> directive works the same except that it
is passed in on the ParseAlloc() or ParseInit() routines instead of
on Parse().
<a name='extractx'></a>
<h4>The <tt>%extra_context</tt> directive</h4>
The <tt>%extra_context</tt> directive instructs Lemon to add a 2th parameter
to the parameter list of the ParseAlloc() and ParseInif() functions. Lemon
doesn't do anything itself with these extra argument, but it does
store the value make it available to C-code action routines, destructors,
and so forth. For example, if the grammar file contains:</p>
<p><pre>
%extra_context { MyStruct *pAbc }
</pre></p>
<p>Then the ParseAlloc() and ParseInit() functions will have an 2th parameter
of type "MyStruct*" and all action routines will have access to
a variable named "pAbc" that is the value of that 2th parameter.</p>
<p>The <tt>%extra_argument</tt> directive works the same except that it
is passed in on the Parse() routine instead of on ParseAlloc()/ParseInit().
<a name='pfallback'></a>
<h4>The <tt>%fallback</tt> directive</h4>
<p>The <tt>%fallback</tt> directive specifies an alternative meaning for one
<p>The %fallback directive specifies an alternative meaning for one
or more tokens. The alternative meaning is tried if the original token
would have generated a syntax error.</p>
would have generated a syntax error.
<p>The <tt>%fallback</tt> directive was added to support robust parsing of SQL
syntax in <a href='https://www.sqlite.org/'>SQLite</a>.
<p>The %fallback directive was added to support robust parsing of SQL
syntax in <a href="https://www.sqlite.org/">SQLite</a>.
The SQL language contains a large assortment of keywords, each of which
appears as a different token to the language parser. SQL contains so
many keywords that it can be difficult for programmers to keep up with
many keywords, that it can be difficult for programmers to keep up with
them all. Programmers will, therefore, sometimes mistakenly use an
obscure language keyword for an identifier. The <tt>%fallback</tt> directive
obscure language keyword for an identifier. The %fallback directive
provides a mechanism to tell the parser: "If you are unable to parse
this keyword, try treating it as an identifier instead."</p>
this keyword, try treating it as an identifier instead."
<p>The syntax of <tt>%fallback</tt> is as follows:
<p>The syntax of %fallback is as follows:
<blockquote>
<tt>%fallback</tt> <i>ID</i> <i>TOKEN...</i> <b>.</b>
</blockquote></p>
<tt>%fallback</tt> <i>ID</i> <i>TOKEN...</i> <b>.</b>
</blockquote>
<p>In words, the <tt>%fallback</tt> directive is followed by a list of token
names terminated by a period.
The first token name is the fallback token &mdash; the
<p>In words, the %fallback directive is followed by a list of token names
terminated by a period. The first token name is the fallback token - the
token to which all the other tokens fall back to. The second and subsequent
arguments are tokens which fall back to the token identified by the first
argument.</p>
argument.
<a name='pifdef'></a>
<h4>The <tt>%ifdef</tt>, <tt>%ifndef</tt>, and <tt>%endif</tt> directives</h4>
<h4>The <tt>%ifdef</tt>, <tt>%ifndef</tt>, and <tt>%endif</tt> directives.</h4>
<p>The <tt>%ifdef</tt>, <tt>%ifndef</tt>, and <tt>%endif</tt> directives
are similar to #ifdef, #ifndef, and #endif in the C-preprocessor,
just not as general.
<p>The %ifdef, %ifndef, and %endif directives are similar to
#ifdef, #ifndef, and #endif in the C-preprocessor, just not as general.
Each of these directives must begin at the left margin. No whitespace
is allowed between the "%" and the directive name.</p>
is allowed between the "%" and the directive name.
<p>Grammar text in between "<tt>%ifdef MACRO</tt>" and the next nested
"<tt>%endif</tt>" is
<p>Grammar text in between "%ifdef MACRO" and the next nested "%endif" is
ignored unless the "-DMACRO" command-line option is used. Grammar text
betwen "<tt>%ifndef MACRO</tt>" and the next nested "<tt>%endif</tt>" is
included except when the "-DMACRO" command-line option is used.</p>
betwen "%ifndef MACRO" and the next nested "%endif" is included except when
the "-DMACRO" command-line option is used.
<p>Note that the argument to <tt>%ifdef</tt> and <tt>%ifndef</tt> must
be a single preprocessor symbol name, not a general expression.
There is no "<tt>%else</tt>" directive.</p>
<p>Note that the argument to %ifdef and %ifndef must be a single
preprocessor symbol name, not a general expression. There is no "%else"
directive.
<a name='pinclude'></a>
<h4>The <tt>%include</tt> directive</h4>
<p>The <tt>%include</tt> directive specifies C code that is included at the
top of the generated parser. You can include any text you want &mdash;
<p>The %include directive specifies C code that is included at the
top of the generated parser. You can include any text you want --
the Lemon parser generator copies it blindly. If you have multiple
<tt>%include</tt> directives in your grammar file, their values are concatenated
so that all <tt>%include</tt> code ultimately appears near the top of the
generated parser, in the same order as it appeared in the grammar.</p>
%include directives in your grammar file, their values are concatenated
so that all %include code ultimately appears near the top of the
generated parser, in the same order as it appeared in the grammer.</p>
<p>The <tt>%include</tt> directive is very handy for getting some extra #include
<p>The %include directive is very handy for getting some extra #include
preprocessor statements at the beginning of the generated parser.
For example:</p>
@@ -775,19 +722,17 @@ For example:</p>
</pre></p>
<p>This might be needed, for example, if some of the C actions in the
grammar call functions that are prototyped in unistd.h.</p>
grammar call functions that are prototyed in unistd.h.</p>
<a name='pleft'></a>
<h4>The <tt>%left</tt> directive</h4>
The <tt>%left</tt> directive is used (along with the
<tt><a href='#pright'>%right</a></tt> and
<tt><a href='#pnonassoc'>%nonassoc</a></tt> directives) to declare
precedences of terminal symbols.
Every terminal symbol whose name appears after
a <tt>%left</tt> directive but before the next period (".") is
The %left directive is used (along with the <a href='#pright'>%right</a> and
<a href='#pnonassoc'>%nonassoc</a> directives) to declare precedences of
terminal symbols. Every terminal symbol whose name appears after
a %left directive but before the next period (".") is
given the same left-associative precedence value. Subsequent
<tt>%left</tt> directives have higher precedence. For example:</p>
%left directives have higher precedence. For example:</p>
<p><pre>
%left AND.
@@ -798,21 +743,20 @@ given the same left-associative precedence value. Subsequent
%right EXP NOT.
</pre></p>
<p>Note the period that terminates each <tt>%left</tt>,
<tt>%right</tt> or <tt>%nonassoc</tt>
<p>Note the period that terminates each %left, %right or %nonassoc
directive.</p>
<p>LALR(1) grammars can get into a situation where they require
a large amount of stack space if you make heavy use or right-associative
operators. For this reason, it is recommended that you use <tt>%left</tt>
rather than <tt>%right</tt> whenever possible.</p>
operators. For this reason, it is recommended that you use %left
rather than %right whenever possible.</p>
<a name='pname'></a>
<h4>The <tt>%name</tt> directive</h4>
<p>By default, the functions generated by Lemon all begin with the
five-character string "Parse". You can change this string to something
different using the <tt>%name</tt> directive. For instance:</p>
different using the %name directive. For instance:</p>
<p><pre>
%name Abcde
@@ -826,22 +770,22 @@ functions named
<li> AbcdeTrace(), and
<li> Abcde().
</ul>
The <tt>%name</tt> directive allows you to generate two or more different
parsers and link them all into the same executable.</p>
The %name directive allows you to generator two or more different
parsers and link them all into the same executable.
</p>
<a name='pnonassoc'></a>
<h4>The <tt>%nonassoc</tt> directive</h4>
<p>This directive is used to assign non-associative precedence to
one or more terminal symbols. See the section on
one or more terminal symbols. See the section on
<a href='#precrules'>precedence rules</a>
or on the <tt><a href='#pleft'>%left</a></tt> directive
for additional information.</p>
or on the <a href='#pleft'>%left</a> directive for additional information.</p>
<a name='parse_accept'></a>
<h4>The <tt>%parse_accept</tt> directive</h4>
<p>The <tt>%parse_accept</tt> directive specifies a block of C code that is
<p>The %parse_accept directive specifies a block of C code that is
executed whenever the parser accepts its input string. To "accept"
an input string means that the parser was able to process all tokens
without error.</p>
@@ -857,7 +801,7 @@ without error.</p>
<a name='parse_failure'></a>
<h4>The <tt>%parse_failure</tt> directive</h4>
<p>The <tt>%parse_failure</tt> directive specifies a block of C code that
<p>The %parse_failure directive specifies a block of C code that
is executed whenever the parser fails complete. This code is not
executed until the parser has tried and failed to resolve an input
error using is usual error recovery strategy. The routine is
@@ -873,14 +817,14 @@ only invoked when parsing is unable to continue.</p>
<h4>The <tt>%right</tt> directive</h4>
<p>This directive is used to assign right-associative precedence to
one or more terminal symbols. See the section on
one or more terminal symbols. See the section on
<a href='#precrules'>precedence rules</a>
or on the <a href='#pleft'>%left</a> directive for additional information.</p>
<a name='stack_overflow'></a>
<h4>The <tt>%stack_overflow</tt> directive</h4>
<p>The <tt>%stack_overflow</tt> directive specifies a block of C code that
<p>The %stack_overflow directive specifies a block of C code that
is executed if the parser's internal stack ever overflows. Typically
this just prints an error message. After a stack overflow, the parser
will be unable to continue and must be reset.</p>
@@ -893,7 +837,7 @@ will be unable to continue and must be reset.</p>
<p>You can help prevent parser stack overflows by avoiding the use
of right recursion and right-precedence operators in your grammar.
Use left recursion and and left-precedence operators instead to
Use left recursion and and left-precedence operators instead, to
encourage rules to reduce sooner and keep the stack size down.
For example, do rules like this:
<pre>
@@ -904,7 +848,7 @@ Not like this:
<pre>
list ::= element list. // right-recursion. Bad!
list ::= .
</pre></p>
</pre>
<a name='stack_size'></a>
<h4>The <tt>%stack_size</tt> directive</h4>
@@ -912,7 +856,7 @@ Not like this:
<p>If stack overflow is a problem and you can't resolve the trouble
by using left-recursion, then you might want to increase the size
of the parser's stack using this directive. Put an positive integer
after the <tt>%stack_size</tt> directive and Lemon will generate a parse
after the %stack_size directive and Lemon will generate a parse
with a stack of the requested size. The default value is 100.</p>
<p><pre>
@@ -922,40 +866,25 @@ with a stack of the requested size. The default value is 100.</p>
<a name='start_symbol'></a>
<h4>The <tt>%start_symbol</tt> directive</h4>
<p>By default, the start symbol for the grammar that Lemon generates
<p>By default, the start-symbol for the grammar that Lemon generates
is the first non-terminal that appears in the grammar file. But you
can choose a different start symbol using the
<tt>%start_symbol</tt> directive.</p>
can choose a different start-symbol using the %start_symbol directive.</p>
<p><pre>
%start_symbol prog
</pre></p>
<a name='syntax_error'></a>
<h4>The <tt>%syntax_error</tt> directive</h4>
<p>See <a href='#error_processing'>Error Processing</a>.</p>
<a name='token_class'></a>
<h4>The <tt>%token_class</tt> directive</h4>
<p>Undocumented. Appears to be related to the MULTITERMINAL concept.
<a href='http://sqlite.org/src/fdiff?v1=796930d5fc2036c7&v2=624b24c5dc048e09&sbs=0'>Implementation</a>.</p>
<a name='token_destructor'></a>
<h4>The <tt>%token_destructor</tt> directive</h4>
<p>The <tt>%destructor</tt> directive assigns a destructor to a non-terminal
symbol. (See the description of the
<tt><a href='%destructor'>%destructor</a></tt> directive above.)
The <tt>%token_destructor</tt> directive does the same thing
for all terminal symbols.</p>
<p>The %destructor directive assigns a destructor to a non-terminal
symbol. (See the description of the %destructor directive above.)
This directive does the same thing for all terminal symbols.</p>
<p>Unlike non-terminal symbols which may each have a different data type
for their values, terminals all use the same data type (defined by
the <tt><a href='#token_type'>%token_type</a></tt> directive)
and so they use a common destructor.
Other than that, the token destructor works just like the non-terminal
the %token_type directive) and so they use a common destructor. Other
than that, the token destructor works just like the non-terminal
destructors.</p>
<a name='token_prefix'></a>
@@ -964,9 +893,8 @@ destructors.</p>
<p>Lemon generates #defines that assign small integer constants
to each terminal symbol in the grammar. If desired, Lemon will
add a prefix specified by this directive
to each of the #defines it generates.</p>
<p>So if the default output of Lemon looked like this:
to each of the #defines it generates.
So if the default output of Lemon looked like this:
<pre>
#define AND 1
#define MINUS 2
@@ -983,7 +911,7 @@ to cause Lemon to produce these symbols instead:
#define TOKEN_MINUS 2
#define TOKEN_OR 3
#define TOKEN_PLUS 4
</pre></p>
</pre>
<a name='token_type'></a><a name='ptype'></a>
<h4>The <tt>%token_type</tt> and <tt>%type</tt> directives</h4>
@@ -1001,10 +929,10 @@ token structure. Like this:</p>
</pre></p>
<p>If the data type of terminals is not specified, the default value
is "void*".</p>
is "int".</p>
<p>Non-terminal symbols can each have their own data types. Typically
the data type of a non-terminal is a pointer to the root of a parse tree
the data type of a non-terminal is a pointer to the root of a parse-tree
structure that contains all information about that non-terminal.
For example:</p>
@@ -1025,15 +953,14 @@ and able to pay that price, fine. You just need to know.</p>
<a name='pwildcard'></a>
<h4>The <tt>%wildcard</tt> directive</h4>
<p>The <tt>%wildcard</tt> directive is followed by a single token name and a
period. This directive specifies that the identified token should
match any input token.</p>
<p>The %wildcard directive is followed by a single token name and a
period. This directive specifies that the identified token should
match any input token.
<p>When the generated parser has the choice of matching an input against
the wildcard token and some other token, the other token is always used.
The wildcard token is only matched if there are no alternatives.</p>
The wildcard token is only matched if there are no other alternatives.
<a name='error_processing'></a>
<h3>Error Processing</h3>
<p>After extensive experimentation over several years, it has been
@@ -1041,20 +968,19 @@ discovered that the error recovery strategy used by yacc is about
as good as it gets. And so that is what Lemon uses.</p>
<p>When a Lemon-generated parser encounters a syntax error, it
first invokes the code specified by the <tt>%syntax_error</tt> directive, if
first invokes the code specified by the %syntax_error directive, if
any. It then enters its error recovery strategy. The error recovery
strategy is to begin popping the parsers stack until it enters a
state where it is permitted to shift a special non-terminal symbol
named "error". It then shifts this non-terminal and continues
parsing. The <tt>%syntax_error</tt> routine will not be called again
parsing. But the %syntax_error routine will not be called again
until at least three new tokens have been successfully shifted.</p>
<p>If the parser pops its stack until the stack is empty, and it still
is unable to shift the error symbol, then the
<tt><a href='#parse_failure'>%parse_failure</a></tt> routine
is unable to shift the error symbol, then the %parse_failed routine
is invoked and the parser resets itself to its start state, ready
to begin parsing a new file. This is what will happen at the very
first syntax error, of course, if there are no instances of the
first syntax error, of course, if there are no instances of the
"error" non-terminal in your grammar.</p>
</body>
-8
View File
@@ -1,8 +0,0 @@
## Loadable Extensions
Various [loadable extensions](https://www.sqlite.org/loadext.html) for
SQLite are found in subfolders.
Most subfolders are dedicated to a single loadable extension (for
example FTS5, or RTREE). But the misc/ subfolder contains a collection
of smaller single-file extensions.
+2
View File
@@ -0,0 +1,2 @@
Version loadable extensions to SQLite are found in subfolders
of this folder.
-83
View File
@@ -1,83 +0,0 @@
## SQLite Expert Extension
This folder contains code for a simple system to propose useful indexes
given a database and a set of SQL queries. It works as follows:
1. The user database schema is copied to a temporary database.
1. All SQL queries are prepared against the temporary database.
Information regarding the WHERE and ORDER BY clauses, and other query
features that affect index selection are recorded.
1. The information gathered in step 2 is used to create candidate
indexes - indexes that the planner might have made use of in the previous
step, had they been available.
1. A subset of the data in the user database is used to generate statistics
for all existing indexes and the candidate indexes generated in step 3
above.
1. The SQL queries are prepared a second time. If the planner uses any
of the indexes created in step 3, they are recommended to the user.
# C API
The SQLite expert C API is defined in sqlite3expert.h. Most uses will proceed
as follows:
1. An sqlite3expert object is created by calling **sqlite3\_expert\_new()**.
A database handle opened by the user is passed as an argument.
1. The sqlite3expert object is configured with one or more SQL statements
by making one or more calls to **sqlite3\_expert\_sql()**. Each call may
specify a single SQL statement, or multiple statements separated by
semi-colons.
1. Optionally, the **sqlite3\_expert\_config()** API may be used to
configure the size of the data subset used to generate index statistics.
Using a smaller subset of the data can speed up the analysis.
1. **sqlite3\_expert\_analyze()** is called to run the analysis.
1. One or more calls are made to **sqlite3\_expert\_report()** to extract
components of the results of the analysis.
1. **sqlite3\_expert\_destroy()** is called to free all resources.
Refer to comments in sqlite3expert.h for further details.
# sqlite3_expert application
The file "expert.c" contains the code for a command line application that
uses the API described above. It can be compiled with (for example):
<pre>
gcc -O2 sqlite3.c expert.c sqlite3expert.c -o sqlite3_expert
</pre>
Assuming the database is named "test.db", it can then be run to analyze a
single query:
<pre>
./sqlite3_expert -sql &lt;sql-query&gt; test.db
</pre>
Or an entire text file worth of queries with:
<pre>
./sqlite3_expert -file &lt;text-file&gt; test.db
</pre>
By default, sqlite3\_expert generates index statistics using all the data in
the user database. For a large database, this may be prohibitively time
consuming. The "-sample" option may be used to configure sqlite3\_expert to
generate statistics based on an integer percentage of the user database as
follows:
<pre>
# Generate statistics based on 25% of the user database rows:
./sqlite3_expert -sample 25 -sql &lt;sql-query&gt; test.db
# Do not generate any statistics at all:
./sqlite3_expert -sample 0 -sql &lt;sql-query&gt; test.db
</pre>
-156
View File
@@ -1,156 +0,0 @@
/*
** 2017 April 07
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
*/
#include <sqlite3.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "sqlite3expert.h"
static void option_requires_argument(const char *zOpt){
fprintf(stderr, "Option requires an argument: %s\n", zOpt);
exit(-3);
}
static int option_integer_arg(const char *zVal){
return atoi(zVal);
}
static void usage(char **argv){
fprintf(stderr, "\n");
fprintf(stderr, "Usage %s ?OPTIONS? DATABASE\n", argv[0]);
fprintf(stderr, "\n");
fprintf(stderr, "Options are:\n");
fprintf(stderr, " -sql SQL (analyze SQL statements passed as argument)\n");
fprintf(stderr, " -file FILE (read SQL statements from file FILE)\n");
fprintf(stderr, " -verbose LEVEL (integer verbosity level. default 1)\n");
fprintf(stderr, " -sample PERCENT (percent of db to sample. default 100)\n");
exit(-1);
}
static int readSqlFromFile(sqlite3expert *p, const char *zFile, char **pzErr){
FILE *in = fopen(zFile, "rb");
long nIn;
size_t nRead;
char *pBuf;
int rc;
if( in==0 ){
*pzErr = sqlite3_mprintf("failed to open file %s\n", zFile);
return SQLITE_ERROR;
}
fseek(in, 0, SEEK_END);
nIn = ftell(in);
rewind(in);
pBuf = sqlite3_malloc64( nIn+1 );
nRead = fread(pBuf, nIn, 1, in);
fclose(in);
if( nRead!=1 ){
sqlite3_free(pBuf);
*pzErr = sqlite3_mprintf("failed to read file %s\n", zFile);
return SQLITE_ERROR;
}
pBuf[nIn] = 0;
rc = sqlite3_expert_sql(p, pBuf, pzErr);
sqlite3_free(pBuf);
return rc;
}
int main(int argc, char **argv){
const char *zDb;
int rc = 0;
char *zErr = 0;
int i;
int iVerbose = 1; /* -verbose option */
sqlite3 *db = 0;
sqlite3expert *p = 0;
if( argc<2 ) usage(argv);
zDb = argv[argc-1];
if( zDb[0]=='-' ) usage(argv);
rc = sqlite3_open(zDb, &db);
if( rc!=SQLITE_OK ){
fprintf(stderr, "Cannot open db file: %s - %s\n", zDb, sqlite3_errmsg(db));
exit(-2);
}
p = sqlite3_expert_new(db, &zErr);
if( p==0 ){
fprintf(stderr, "Cannot run analysis: %s\n", zErr);
rc = 1;
}else{
for(i=1; i<(argc-1); i++){
char *zArg = argv[i];
int nArg;
if( zArg[0]=='-' && zArg[1]=='-' && zArg[2]!=0 ) zArg++;
nArg = (int)strlen(zArg);
if( nArg>=2 && 0==sqlite3_strnicmp(zArg, "-file", nArg) ){
if( ++i==(argc-1) ) option_requires_argument("-file");
rc = readSqlFromFile(p, argv[i], &zErr);
}
else if( nArg>=3 && 0==sqlite3_strnicmp(zArg, "-sql", nArg) ){
if( ++i==(argc-1) ) option_requires_argument("-sql");
rc = sqlite3_expert_sql(p, argv[i], &zErr);
}
else if( nArg>=3 && 0==sqlite3_strnicmp(zArg, "-sample", nArg) ){
int iSample;
if( ++i==(argc-1) ) option_requires_argument("-sample");
iSample = option_integer_arg(argv[i]);
sqlite3_expert_config(p, EXPERT_CONFIG_SAMPLE, iSample);
}
else if( nArg>=2 && 0==sqlite3_strnicmp(zArg, "-verbose", nArg) ){
if( ++i==(argc-1) ) option_requires_argument("-verbose");
iVerbose = option_integer_arg(argv[i]);
}
else{
usage(argv);
}
}
}
if( rc==SQLITE_OK ){
rc = sqlite3_expert_analyze(p, &zErr);
}
if( rc==SQLITE_OK ){
int nQuery = sqlite3_expert_count(p);
if( iVerbose>0 ){
const char *zCand = sqlite3_expert_report(p,0,EXPERT_REPORT_CANDIDATES);
fprintf(stdout, "-- Candidates -------------------------------\n");
fprintf(stdout, "%s\n", zCand);
}
for(i=0; i<nQuery; i++){
const char *zSql = sqlite3_expert_report(p, i, EXPERT_REPORT_SQL);
const char *zIdx = sqlite3_expert_report(p, i, EXPERT_REPORT_INDEXES);
const char *zEQP = sqlite3_expert_report(p, i, EXPERT_REPORT_PLAN);
if( zIdx==0 ) zIdx = "(no new indexes)\n";
if( iVerbose>0 ){
fprintf(stdout, "-- Query %d ----------------------------------\n",i+1);
fprintf(stdout, "%s\n\n", zSql);
}
fprintf(stdout, "%s\n%s\n", zIdx, zEQP);
}
}else{
fprintf(stderr, "Error: %s\n", zErr ? zErr : "?");
}
sqlite3_expert_destroy(p);
sqlite3_free(zErr);
return rc;
}
-383
View File
@@ -1,383 +0,0 @@
# 2009 Nov 11
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
#
# The focus of this file is testing the CLI shell tool. Specifically,
# the ".recommend" command.
#
#
# Test plan:
#
#
if {![info exists testdir]} {
set testdir [file join [file dirname [info script]] .. .. test]
}
source $testdir/tester.tcl
set testprefix expert1
if {[info commands sqlite3_expert_new]==""} {
finish_test
return
}
set CLI [test_binary_name sqlite3]
set CMD [test_binary_name sqlite3_expert]
proc squish {txt} {
regsub -all {[[:space:]]+} $txt { }
}
proc do_setup_rec_test {tn setup sql res} {
reset_db
db eval $setup
uplevel [list do_rec_test $tn $sql $res]
}
foreach {tn setup} {
1 {
if {![file executable $CMD]} { continue }
proc do_rec_test {tn sql res} {
set res [squish [string trim $res]]
set tst [subst -nocommands {
squish [string trim [exec $::CMD -verbose 0 -sql {$sql;} test.db]]
}]
uplevel [list do_test $tn $tst $res]
}
}
2 {
if {[info commands sqlite3_expert_new]==""} { continue }
proc do_rec_test {tn sql res} {
set expert [sqlite3_expert_new db]
$expert sql $sql
$expert analyze
set result [list]
for {set i 0} {$i < [$expert count]} {incr i} {
set idx [string trim [$expert report $i indexes]]
if {$idx==""} {set idx "(no new indexes)"}
lappend result $idx
lappend result [string trim [$expert report $i plan]]
}
$expert destroy
set tst [subst -nocommands {set {} [squish [join {$result}]]}]
uplevel [list do_test $tn $tst [string trim [squish $res]]]
}
}
3 {
if {![file executable $CLI]} { continue }
proc do_rec_test {tn sql res} {
set res [squish [string trim $res]]
set tst [subst -nocommands {
squish [string trim [exec $::CLI test.db ".expert" {$sql;}]]
}]
uplevel [list do_test $tn $tst $res]
}
}
} {
eval $setup
do_setup_rec_test $tn.1 { CREATE TABLE t1(a, b, c) } {
SELECT * FROM t1
} {
(no new indexes)
SCAN TABLE t1
}
do_setup_rec_test $tn.2 {
CREATE TABLE t1(a, b, c);
} {
SELECT * FROM t1 WHERE b>?;
} {
CREATE INDEX t1_idx_00000062 ON t1(b);
SEARCH TABLE t1 USING INDEX t1_idx_00000062 (b>?)
}
do_setup_rec_test $tn.3 {
CREATE TABLE t1(a, b, c);
} {
SELECT * FROM t1 WHERE b COLLATE nocase BETWEEN ? AND ?
} {
CREATE INDEX t1_idx_3e094c27 ON t1(b COLLATE NOCASE);
SEARCH TABLE t1 USING INDEX t1_idx_3e094c27 (b>? AND b<?)
}
do_setup_rec_test $tn.4 {
CREATE TABLE t1(a, b, c);
} {
SELECT a FROM t1 ORDER BY b;
} {
CREATE INDEX t1_idx_00000062 ON t1(b);
SCAN TABLE t1 USING INDEX t1_idx_00000062
}
do_setup_rec_test $tn.5 {
CREATE TABLE t1(a, b, c);
} {
SELECT a FROM t1 WHERE a=? ORDER BY b;
} {
CREATE INDEX t1_idx_000123a7 ON t1(a, b);
SEARCH TABLE t1 USING COVERING INDEX t1_idx_000123a7 (a=?)
}
do_setup_rec_test $tn.6 {
CREATE TABLE t1(a, b, c);
} {
SELECT min(a) FROM t1
} {
CREATE INDEX t1_idx_00000061 ON t1(a);
SEARCH TABLE t1 USING COVERING INDEX t1_idx_00000061
}
do_setup_rec_test $tn.7 {
CREATE TABLE t1(a, b, c);
} {
SELECT * FROM t1 ORDER BY a, b, c;
} {
CREATE INDEX t1_idx_033e95fe ON t1(a, b, c);
SCAN TABLE t1 USING COVERING INDEX t1_idx_033e95fe
}
#do_setup_rec_test $tn.1.8 {
# CREATE TABLE t1(a, b, c);
#} {
# SELECT * FROM t1 ORDER BY a ASC, b COLLATE nocase DESC, c ASC;
#} {
# CREATE INDEX t1_idx_5be6e222 ON t1(a, b COLLATE NOCASE DESC, c);
# 0|0|0|SCAN TABLE t1 USING COVERING INDEX t1_idx_5be6e222
#}
do_setup_rec_test $tn.8.1 {
CREATE TABLE t1(a COLLATE NOCase, b, c);
} {
SELECT * FROM t1 WHERE a=?
} {
CREATE INDEX t1_idx_00000061 ON t1(a);
SEARCH TABLE t1 USING INDEX t1_idx_00000061 (a=?)
}
do_setup_rec_test $tn.8.2 {
CREATE TABLE t1(a, b COLLATE nocase, c);
} {
SELECT * FROM t1 ORDER BY a ASC, b DESC, c ASC;
} {
CREATE INDEX t1_idx_5cb97285 ON t1(a, b DESC, c);
SCAN TABLE t1 USING COVERING INDEX t1_idx_5cb97285
}
# Tables with names that require quotes.
#
do_setup_rec_test $tn.9.1 {
CREATE TABLE "t t"(a, b, c);
} {
SELECT * FROM "t t" WHERE a=?
} {
CREATE INDEX 't t_idx_00000061' ON 't t'(a);
SEARCH TABLE t t USING INDEX t t_idx_00000061 (a=?)
}
do_setup_rec_test $tn.9.2 {
CREATE TABLE "t t"(a, b, c);
} {
SELECT * FROM "t t" WHERE b BETWEEN ? AND ?
} {
CREATE INDEX 't t_idx_00000062' ON 't t'(b);
SEARCH TABLE t t USING INDEX t t_idx_00000062 (b>? AND b<?)
}
# Columns with names that require quotes.
#
do_setup_rec_test $tn.10.1 {
CREATE TABLE t3(a, "b b", c);
} {
SELECT * FROM t3 WHERE "b b" = ?
} {
CREATE INDEX t3_idx_00050c52 ON t3('b b');
SEARCH TABLE t3 USING INDEX t3_idx_00050c52 (b b=?)
}
do_setup_rec_test $tn.10.2 {
CREATE TABLE t3(a, "b b", c);
} {
SELECT * FROM t3 ORDER BY "b b"
} {
CREATE INDEX t3_idx_00050c52 ON t3('b b');
SCAN TABLE t3 USING INDEX t3_idx_00050c52
}
# Transitive constraints
#
do_setup_rec_test $tn.11.1 {
CREATE TABLE t5(a, b);
CREATE TABLE t6(c, d);
} {
SELECT * FROM t5, t6 WHERE a=? AND b=c AND c=?
} {
CREATE INDEX t5_idx_000123a7 ON t5(a, b);
CREATE INDEX t6_idx_00000063 ON t6(c);
SEARCH TABLE t6 USING INDEX t6_idx_00000063 (c=?)
SEARCH TABLE t5 USING COVERING INDEX t5_idx_000123a7 (a=? AND b=?)
}
# OR terms.
#
do_setup_rec_test $tn.12.1 {
CREATE TABLE t7(a, b);
} {
SELECT * FROM t7 WHERE a=? OR b=?
} {
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=?)
}
# rowid terms.
#
do_setup_rec_test $tn.13.1 {
CREATE TABLE t8(a, b);
} {
SELECT * FROM t8 WHERE rowid=?
} {
(no new indexes)
SEARCH TABLE t8 USING INTEGER PRIMARY KEY (rowid=?)
}
do_setup_rec_test $tn.13.2 {
CREATE TABLE t8(a, b);
} {
SELECT * FROM t8 ORDER BY rowid
} {
(no new indexes)
SCAN TABLE t8
}
do_setup_rec_test $tn.13.3 {
CREATE TABLE t8(a, b);
} {
SELECT * FROM t8 WHERE a=? ORDER BY rowid
} {
CREATE INDEX t8_idx_00000061 ON t8(a);
SEARCH TABLE t8 USING INDEX t8_idx_00000061 (a=?)
}
# Triggers
#
do_setup_rec_test $tn.14 {
CREATE TABLE t9(a, b, c);
CREATE TABLE t10(a, b, c);
CREATE TRIGGER t9t AFTER INSERT ON t9 BEGIN
UPDATE t10 SET a=new.a WHERE b = new.b;
END;
} {
INSERT INTO t9 VALUES(?, ?, ?);
} {
CREATE INDEX t10_idx_00000062 ON t10(b);
-- TRIGGER t9t
SEARCH TABLE t10 USING INDEX t10_idx_00000062 (b=?)
}
do_setup_rec_test $tn.15 {
CREATE TABLE t1(a, b);
CREATE TABLE t2(c, d);
WITH s(i) AS ( VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<100)
INSERT INTO t1 SELECT (i-1)/50, (i-1)/20 FROM s;
WITH s(i) AS ( VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<100)
INSERT INTO t2 SELECT (i-1)/20, (i-1)/5 FROM s;
} {
SELECT * FROM t2, t1 WHERE b=? AND d=? AND t2.rowid=t1.rowid
} {
CREATE INDEX t2_idx_00000064 ON t2(d);
SEARCH TABLE t2 USING INDEX t2_idx_00000064 (d=?)
SEARCH TABLE t1 USING INTEGER PRIMARY KEY (rowid=?)
}
do_setup_rec_test $tn.16 {
CREATE TABLE t1(a, b);
} {
SELECT * FROM t1 WHERE b IS NOT NULL;
} {
(no new indexes)
SCAN TABLE t1
}
}
proc do_candidates_test {tn sql res} {
set res [squish [string trim $res]]
set expert [sqlite3_expert_new db]
$expert sql $sql
$expert analyze
set candidates [squish [string trim [$expert report 0 candidates]]]
$expert destroy
uplevel [list do_test $tn [list set {} $candidates] $res]
}
reset_db
do_execsql_test 3.0 {
CREATE TABLE t1(a, b);
CREATE TABLE t2(c, d);
WITH s(i) AS ( VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<100)
INSERT INTO t1 SELECT (i-1)/50, (i-1)/20 FROM s;
WITH s(i) AS ( VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<100)
INSERT INTO t2 SELECT (i-1)/20, (i-1)/5 FROM s;
}
do_candidates_test 3.1 {
SELECT * FROM t1,t2 WHERE (b=? OR a=?) AND (c=? OR d=?)
} {
CREATE INDEX t1_idx_00000062 ON t1(b); -- stat1: 100 20
CREATE INDEX t1_idx_00000061 ON t1(a); -- stat1: 100 50
CREATE INDEX t2_idx_00000063 ON t2(c); -- stat1: 100 20
CREATE INDEX t2_idx_00000064 ON t2(d); -- stat1: 100 5
}
do_candidates_test 3.2 {
SELECT * FROM t1,t2 WHERE a=? AND b=? AND c=? AND d=?
} {
CREATE INDEX t1_idx_000123a7 ON t1(a, b); -- stat1: 100 50 17
CREATE INDEX t2_idx_0001295b ON t2(c, d); -- stat1: 100 20 5
}
do_execsql_test 3.2 {
CREATE INDEX t1_idx_00000061 ON t1(a); -- stat1: 100 50
CREATE INDEX t1_idx_00000062 ON t1(b); -- stat1: 100 20
CREATE INDEX t1_idx_000123a7 ON t1(a, b); -- stat1: 100 50 16
CREATE INDEX t2_idx_00000063 ON t2(c); -- stat1: 100 20
CREATE INDEX t2_idx_00000064 ON t2(d); -- stat1: 100 5
CREATE INDEX t2_idx_0001295b ON t2(c, d); -- stat1: 100 20 5
ANALYZE;
SELECT * FROM sqlite_stat1 ORDER BY 1, 2;
} {
t1 t1_idx_00000061 {100 50}
t1 t1_idx_00000062 {100 20}
t1 t1_idx_000123a7 {100 50 17}
t2 t2_idx_00000063 {100 20}
t2 t2_idx_00000064 {100 5}
t2 t2_idx_0001295b {100 20 5}
}
finish_test
File diff suppressed because it is too large Load Diff
-168
View File
@@ -1,168 +0,0 @@
/*
** 2017 April 07
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
*/
#include "sqlite3.h"
typedef struct sqlite3expert sqlite3expert;
/*
** Create a new sqlite3expert object.
**
** If successful, a pointer to the new object is returned and (*pzErr) set
** to NULL. Or, if an error occurs, NULL is returned and (*pzErr) set to
** an English-language error message. In this case it is the responsibility
** of the caller to eventually free the error message buffer using
** sqlite3_free().
*/
sqlite3expert *sqlite3_expert_new(sqlite3 *db, char **pzErr);
/*
** Configure an sqlite3expert object.
**
** EXPERT_CONFIG_SAMPLE:
** By default, sqlite3_expert_analyze() generates sqlite_stat1 data for
** each candidate index. This involves scanning and sorting the entire
** contents of each user database table once for each candidate index
** associated with the table. For large databases, this can be
** prohibitively slow. This option allows the sqlite3expert object to
** be configured so that sqlite_stat1 data is instead generated based on a
** subset of each table, or so that no sqlite_stat1 data is used at all.
**
** A single integer argument is passed to this option. If the value is less
** than or equal to zero, then no sqlite_stat1 data is generated or used by
** the analysis - indexes are recommended based on the database schema only.
** Or, if the value is 100 or greater, complete sqlite_stat1 data is
** generated for each candidate index (this is the default). Finally, if the
** value falls between 0 and 100, then it represents the percentage of user
** table rows that should be considered when generating sqlite_stat1 data.
**
** Examples:
**
** // Do not generate any sqlite_stat1 data
** sqlite3_expert_config(pExpert, EXPERT_CONFIG_SAMPLE, 0);
**
** // Generate sqlite_stat1 data based on 10% of the rows in each table.
** sqlite3_expert_config(pExpert, EXPERT_CONFIG_SAMPLE, 10);
*/
int sqlite3_expert_config(sqlite3expert *p, int op, ...);
#define EXPERT_CONFIG_SAMPLE 1 /* int */
/*
** Specify zero or more SQL statements to be included in the analysis.
**
** Buffer zSql must contain zero or more complete SQL statements. This
** function parses all statements contained in the buffer and adds them
** to the internal list of statements to analyze. If successful, SQLITE_OK
** is returned and (*pzErr) set to NULL. Or, if an error occurs - for example
** due to a error in the SQL - an SQLite error code is returned and (*pzErr)
** may be set to point to an English language error message. In this case
** the caller is responsible for eventually freeing the error message buffer
** using sqlite3_free().
**
** If an error does occur while processing one of the statements in the
** buffer passed as the second argument, none of the statements in the
** buffer are added to the analysis.
**
** This function must be called before sqlite3_expert_analyze(). If a call
** to this function is made on an sqlite3expert object that has already
** been passed to sqlite3_expert_analyze() SQLITE_MISUSE is returned
** immediately and no statements are added to the analysis.
*/
int sqlite3_expert_sql(
sqlite3expert *p, /* From a successful sqlite3_expert_new() */
const char *zSql, /* SQL statement(s) to add */
char **pzErr /* OUT: Error message (if any) */
);
/*
** This function is called after the sqlite3expert object has been configured
** with all SQL statements using sqlite3_expert_sql() to actually perform
** the analysis. Once this function has been called, it is not possible to
** add further SQL statements to the analysis.
**
** If successful, SQLITE_OK is returned and (*pzErr) is set to NULL. Or, if
** an error occurs, an SQLite error code is returned and (*pzErr) set to
** point to a buffer containing an English language error message. In this
** case it is the responsibility of the caller to eventually free the buffer
** using sqlite3_free().
**
** If an error does occur within this function, the sqlite3expert object
** is no longer useful for any purpose. At that point it is no longer
** possible to add further SQL statements to the object or to re-attempt
** the analysis. The sqlite3expert object must still be freed using a call
** sqlite3_expert_destroy().
*/
int sqlite3_expert_analyze(sqlite3expert *p, char **pzErr);
/*
** Return the total number of statements loaded using sqlite3_expert_sql().
** The total number of SQL statements may be different from the total number
** to calls to sqlite3_expert_sql().
*/
int sqlite3_expert_count(sqlite3expert*);
/*
** Return a component of the report.
**
** This function is called after sqlite3_expert_analyze() to extract the
** results of the analysis. Each call to this function returns either a
** NULL pointer or a pointer to a buffer containing a nul-terminated string.
** The value passed as the third argument must be one of the EXPERT_REPORT_*
** #define constants defined below.
**
** For some EXPERT_REPORT_* parameters, the buffer returned contains
** information relating to a specific SQL statement. In these cases that
** SQL statement is identified by the value passed as the second argument.
** SQL statements are numbered from 0 in the order in which they are parsed.
** If an out-of-range value (less than zero or equal to or greater than the
** value returned by sqlite3_expert_count()) is passed as the second argument
** along with such an EXPERT_REPORT_* parameter, NULL is always returned.
**
** EXPERT_REPORT_SQL:
** Return the text of SQL statement iStmt.
**
** EXPERT_REPORT_INDEXES:
** Return a buffer containing the CREATE INDEX statements for all recommended
** indexes for statement iStmt. If there are no new recommeded indexes, NULL
** is returned.
**
** EXPERT_REPORT_PLAN:
** Return a buffer containing the EXPLAIN QUERY PLAN output for SQL query
** iStmt after the proposed indexes have been added to the database schema.
**
** EXPERT_REPORT_CANDIDATES:
** Return a pointer to a buffer containing the CREATE INDEX statements
** for all indexes that were tested (for all SQL statements). The iStmt
** parameter is ignored for EXPERT_REPORT_CANDIDATES calls.
*/
const char *sqlite3_expert_report(sqlite3expert*, int iStmt, int eReport);
/*
** Values for the third argument passed to sqlite3_expert_report().
*/
#define EXPERT_REPORT_SQL 1
#define EXPERT_REPORT_INDEXES 2
#define EXPERT_REPORT_PLAN 3
#define EXPERT_REPORT_CANDIDATES 4
/*
** Free an (sqlite3expert*) handle and all associated resources. There
** should be one call to this function for each successful call to
** sqlite3-expert_new().
*/
void sqlite3_expert_destroy(sqlite3expert*);
-220
View File
@@ -1,220 +0,0 @@
/*
** 2017 April 07
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
*/
#if defined(SQLITE_TEST)
#include "sqlite3expert.h"
#include <assert.h>
#include <string.h>
#if defined(INCLUDE_SQLITE_TCL_H)
# include "sqlite_tcl.h"
#else
# include "tcl.h"
# ifndef SQLITE_TCLAPI
# define SQLITE_TCLAPI
# endif
#endif
#ifndef SQLITE_OMIT_VIRTUALTABLE
/*
** Extract an sqlite3* db handle from the object passed as the second
** argument. If successful, set *pDb to point to the db handle and return
** TCL_OK. Otherwise, return TCL_ERROR.
*/
static int dbHandleFromObj(Tcl_Interp *interp, Tcl_Obj *pObj, sqlite3 **pDb){
Tcl_CmdInfo info;
if( 0==Tcl_GetCommandInfo(interp, Tcl_GetString(pObj), &info) ){
Tcl_AppendResult(interp, "no such handle: ", Tcl_GetString(pObj), 0);
return TCL_ERROR;
}
*pDb = *(sqlite3 **)info.objClientData;
return TCL_OK;
}
/*
** Tclcmd: $expert sql SQL
** $expert analyze
** $expert count
** $expert report STMT EREPORT
** $expert destroy
*/
static int SQLITE_TCLAPI testExpertCmd(
void *clientData,
Tcl_Interp *interp,
int objc,
Tcl_Obj *CONST objv[]
){
sqlite3expert *pExpert = (sqlite3expert*)clientData;
struct Subcmd {
const char *zSub;
int nArg;
const char *zMsg;
} aSub[] = {
{ "sql", 1, "TABLE", }, /* 0 */
{ "analyze", 0, "", }, /* 1 */
{ "count", 0, "", }, /* 2 */
{ "report", 2, "STMT EREPORT", }, /* 3 */
{ "destroy", 0, "", }, /* 4 */
{ 0 }
};
int iSub;
int rc = TCL_OK;
char *zErr = 0;
if( objc<2 ){
Tcl_WrongNumArgs(interp, 1, objv, "SUBCOMMAND ...");
return TCL_ERROR;
}
rc = Tcl_GetIndexFromObjStruct(interp,
objv[1], aSub, sizeof(aSub[0]), "sub-command", 0, &iSub
);
if( rc!=TCL_OK ) return rc;
if( objc!=2+aSub[iSub].nArg ){
Tcl_WrongNumArgs(interp, 2, objv, aSub[iSub].zMsg);
return TCL_ERROR;
}
switch( iSub ){
case 0: { /* sql */
char *zArg = Tcl_GetString(objv[2]);
rc = sqlite3_expert_sql(pExpert, zArg, &zErr);
break;
}
case 1: { /* analyze */
rc = sqlite3_expert_analyze(pExpert, &zErr);
break;
}
case 2: { /* count */
int n = sqlite3_expert_count(pExpert);
Tcl_SetObjResult(interp, Tcl_NewIntObj(n));
break;
}
case 3: { /* report */
const char *aEnum[] = {
"sql", "indexes", "plan", "candidates", 0
};
int iEnum;
int iStmt;
const char *zReport;
if( Tcl_GetIntFromObj(interp, objv[2], &iStmt)
|| Tcl_GetIndexFromObj(interp, objv[3], aEnum, "report", 0, &iEnum)
){
return TCL_ERROR;
}
assert( EXPERT_REPORT_SQL==1 );
assert( EXPERT_REPORT_INDEXES==2 );
assert( EXPERT_REPORT_PLAN==3 );
assert( EXPERT_REPORT_CANDIDATES==4 );
zReport = sqlite3_expert_report(pExpert, iStmt, 1+iEnum);
Tcl_SetObjResult(interp, Tcl_NewStringObj(zReport, -1));
break;
}
default: /* destroy */
assert( iSub==4 );
Tcl_DeleteCommand(interp, Tcl_GetString(objv[0]));
break;
}
if( rc!=TCL_OK ){
if( zErr ){
Tcl_SetObjResult(interp, Tcl_NewStringObj(zErr, -1));
}else{
extern const char *sqlite3ErrName(int);
Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
}
}
sqlite3_free(zErr);
return rc;
}
static void SQLITE_TCLAPI testExpertDel(void *clientData){
sqlite3expert *pExpert = (sqlite3expert*)clientData;
sqlite3_expert_destroy(pExpert);
}
/*
** sqlite3_expert_new DB
*/
static int SQLITE_TCLAPI test_sqlite3_expert_new(
void * clientData,
Tcl_Interp *interp,
int objc,
Tcl_Obj *CONST objv[]
){
static int iCmd = 0;
sqlite3 *db;
char *zCmd = 0;
char *zErr = 0;
sqlite3expert *pExpert;
int rc = TCL_OK;
if( objc!=2 ){
Tcl_WrongNumArgs(interp, 1, objv, "DB");
return TCL_ERROR;
}
if( dbHandleFromObj(interp, objv[1], &db) ){
return TCL_ERROR;
}
zCmd = sqlite3_mprintf("sqlite3expert%d", ++iCmd);
if( zCmd==0 ){
Tcl_AppendResult(interp, "out of memory", (char*)0);
return TCL_ERROR;
}
pExpert = sqlite3_expert_new(db, &zErr);
if( pExpert==0 ){
Tcl_AppendResult(interp, zErr, (char*)0);
rc = TCL_ERROR;
}else{
void *p = (void*)pExpert;
Tcl_CreateObjCommand(interp, zCmd, testExpertCmd, p, testExpertDel);
Tcl_SetObjResult(interp, Tcl_NewStringObj(zCmd, -1));
}
sqlite3_free(zCmd);
sqlite3_free(zErr);
return rc;
}
#endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */
int TestExpert_Init(Tcl_Interp *interp){
#ifndef SQLITE_OMIT_VIRTUALTABLE
struct Cmd {
const char *zCmd;
Tcl_ObjCmdProc *xProc;
} aCmd[] = {
{ "sqlite3_expert_new", test_sqlite3_expert_new },
};
int i;
for(i=0; i<sizeof(aCmd)/sizeof(struct Cmd); i++){
struct Cmd *p = &aCmd[i];
Tcl_CreateObjCommand(interp, p->zCmd, p->xProc, 0, 0);
}
#endif
return TCL_OK;
}
#endif
+1 -5
View File
@@ -99,11 +99,7 @@ static void scalarFunc(
#ifdef SQLITE_TEST
#if defined(INCLUDE_SQLITE_TCL_H)
# include "sqlite_tcl.h"
#else
# include "tcl.h"
#endif
#include <tcl.h>
#include <string.h>
/*
+167 -202
View File
@@ -349,9 +349,8 @@ int sqlite3Fts3PutVarint(char *p, sqlite_int64 v){
** Return the number of bytes read, or 0 on error.
** The value is stored in *v.
*/
int sqlite3Fts3GetVarint(const char *pBuf, sqlite_int64 *v){
const unsigned char *p = (const unsigned char*)pBuf;
const unsigned char *pStart = p;
int sqlite3Fts3GetVarint(const char *p, sqlite_int64 *v){
const char *pStart = p;
u32 a;
u64 b;
int shift;
@@ -372,8 +371,8 @@ int sqlite3Fts3GetVarint(const char *pBuf, sqlite_int64 *v){
}
/*
** Similar to sqlite3Fts3GetVarint(), except that the output is truncated to
** a non-negative 32-bit integer before it is returned.
** Similar to sqlite3Fts3GetVarint(), except that the output is truncated to a
** 32-bit integer before it is returned.
*/
int sqlite3Fts3GetVarint32(const char *p, int *pi){
u32 a;
@@ -389,9 +388,7 @@ int sqlite3Fts3GetVarint32(const char *p, int *pi){
GETVARINT_STEP(a, p, 14, 0x3FFF, 0x200000, *pi, 3);
GETVARINT_STEP(a, p, 21, 0x1FFFFF, 0x10000000, *pi, 4);
a = (a & 0x0FFFFFFF );
*pi = (int)(a | ((u32)(*p & 0x07) << 28));
assert( 0==(a & 0x80000000) );
assert( *pi>=0 );
*pi = (int)(a | ((u32)(*p & 0x0F) << 28));
return 5;
}
@@ -495,7 +492,6 @@ static int fts3DisconnectMethod(sqlite3_vtab *pVtab){
assert( p->pSegments==0 );
/* Free any prepared statements held */
sqlite3_finalize(p->pSeekStmt);
for(i=0; i<SizeofArray(p->aStmt); i++){
sqlite3_finalize(p->aStmt[i]);
}
@@ -1221,66 +1217,65 @@ static int fts3InitVtab(
break;
}
}
switch( iOpt ){
case 0: /* MATCHINFO */
if( strlen(zVal)!=4 || sqlite3_strnicmp(zVal, "fts3", 4) ){
sqlite3Fts3ErrMsg(pzErr, "unrecognized matchinfo: %s", zVal);
rc = SQLITE_ERROR;
}
bNoDocsize = 1;
break;
if( iOpt==SizeofArray(aFts4Opt) ){
sqlite3Fts3ErrMsg(pzErr, "unrecognized parameter: %s", z);
rc = SQLITE_ERROR;
}else{
switch( iOpt ){
case 0: /* MATCHINFO */
if( strlen(zVal)!=4 || sqlite3_strnicmp(zVal, "fts3", 4) ){
sqlite3Fts3ErrMsg(pzErr, "unrecognized matchinfo: %s", zVal);
rc = SQLITE_ERROR;
}
bNoDocsize = 1;
break;
case 1: /* PREFIX */
sqlite3_free(zPrefix);
zPrefix = zVal;
zVal = 0;
break;
case 1: /* PREFIX */
sqlite3_free(zPrefix);
zPrefix = zVal;
zVal = 0;
break;
case 2: /* COMPRESS */
sqlite3_free(zCompress);
zCompress = zVal;
zVal = 0;
break;
case 2: /* COMPRESS */
sqlite3_free(zCompress);
zCompress = zVal;
zVal = 0;
break;
case 3: /* UNCOMPRESS */
sqlite3_free(zUncompress);
zUncompress = zVal;
zVal = 0;
break;
case 3: /* UNCOMPRESS */
sqlite3_free(zUncompress);
zUncompress = zVal;
zVal = 0;
break;
case 4: /* ORDER */
if( (strlen(zVal)!=3 || sqlite3_strnicmp(zVal, "asc", 3))
&& (strlen(zVal)!=4 || sqlite3_strnicmp(zVal, "desc", 4))
){
sqlite3Fts3ErrMsg(pzErr, "unrecognized order: %s", zVal);
rc = SQLITE_ERROR;
}
bDescIdx = (zVal[0]=='d' || zVal[0]=='D');
break;
case 4: /* ORDER */
if( (strlen(zVal)!=3 || sqlite3_strnicmp(zVal, "asc", 3))
&& (strlen(zVal)!=4 || sqlite3_strnicmp(zVal, "desc", 4))
){
sqlite3Fts3ErrMsg(pzErr, "unrecognized order: %s", zVal);
rc = SQLITE_ERROR;
}
bDescIdx = (zVal[0]=='d' || zVal[0]=='D');
break;
case 5: /* CONTENT */
sqlite3_free(zContent);
zContent = zVal;
zVal = 0;
break;
case 5: /* CONTENT */
sqlite3_free(zContent);
zContent = zVal;
zVal = 0;
break;
case 6: /* LANGUAGEID */
assert( iOpt==6 );
sqlite3_free(zLanguageid);
zLanguageid = zVal;
zVal = 0;
break;
case 6: /* LANGUAGEID */
assert( iOpt==6 );
sqlite3_free(zLanguageid);
zLanguageid = zVal;
zVal = 0;
break;
case 7: /* NOTINDEXED */
azNotindexed[nNotindexed++] = zVal;
zVal = 0;
break;
default:
assert( iOpt==SizeofArray(aFts4Opt) );
sqlite3Fts3ErrMsg(pzErr, "unrecognized parameter: %s", z);
rc = SQLITE_ERROR;
break;
case 7: /* NOTINDEXED */
azNotindexed[nNotindexed++] = zVal;
zVal = 0;
break;
}
}
sqlite3_free(zVal);
}
@@ -1368,9 +1363,9 @@ static int fts3InitVtab(
p->pTokenizer = pTokenizer;
p->nMaxPendingData = FTS3_MAX_PENDING_DATA;
p->bHasDocsize = (isFts4 && bNoDocsize==0);
p->bHasStat = (u8)isFts4;
p->bFts4 = (u8)isFts4;
p->bDescIdx = (u8)bDescIdx;
p->bHasStat = isFts4;
p->bFts4 = isFts4;
p->bDescIdx = bDescIdx;
p->nAutoincrmerge = 0xff; /* 0xff means setting unknown */
p->zContentTbl = zContent;
p->zLanguageid = zLanguageid;
@@ -1401,9 +1396,7 @@ static int fts3InitVtab(
char *z;
int n = 0;
z = (char *)sqlite3Fts3NextToken(aCol[iCol], &n);
if( n>0 ){
memcpy(zCsr, z, n);
}
memcpy(zCsr, z, n);
zCsr[n] = '\0';
sqlite3Fts3Dequote(zCsr);
p->azColumn[iCol] = zCsr;
@@ -1687,39 +1680,6 @@ static int fts3OpenMethod(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCsr){
return SQLITE_OK;
}
/*
** Finalize the statement handle at pCsr->pStmt.
**
** Or, if that statement handle is one created by fts3CursorSeekStmt(),
** and the Fts3Table.pSeekStmt slot is currently NULL, save the statement
** pointer there instead of finalizing it.
*/
static void fts3CursorFinalizeStmt(Fts3Cursor *pCsr){
if( pCsr->bSeekStmt ){
Fts3Table *p = (Fts3Table *)pCsr->base.pVtab;
if( p->pSeekStmt==0 ){
p->pSeekStmt = pCsr->pStmt;
sqlite3_reset(pCsr->pStmt);
pCsr->pStmt = 0;
}
pCsr->bSeekStmt = 0;
}
sqlite3_finalize(pCsr->pStmt);
}
/*
** Free all resources currently held by the cursor passed as the only
** argument.
*/
static void fts3ClearCursor(Fts3Cursor *pCsr){
fts3CursorFinalizeStmt(pCsr);
sqlite3Fts3FreeDeferredTokens(pCsr);
sqlite3_free(pCsr->aDoclist);
sqlite3Fts3MIBufferFree(pCsr->pMIBuffer);
sqlite3Fts3ExprFree(pCsr->pExpr);
memset(&(&pCsr->base)[1], 0, sizeof(Fts3Cursor)-sizeof(sqlite3_vtab_cursor));
}
/*
** Close the cursor. For additional information see the documentation
** on the xClose method of the virtual table interface.
@@ -1727,7 +1687,11 @@ static void fts3ClearCursor(Fts3Cursor *pCsr){
static int fts3CloseMethod(sqlite3_vtab_cursor *pCursor){
Fts3Cursor *pCsr = (Fts3Cursor *)pCursor;
assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 );
fts3ClearCursor(pCsr);
sqlite3_finalize(pCsr->pStmt);
sqlite3Fts3ExprFree(pCsr->pExpr);
sqlite3Fts3FreeDeferredTokens(pCsr);
sqlite3_free(pCsr->aDoclist);
sqlite3Fts3MIBufferFree(pCsr->pMIBuffer);
assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 );
sqlite3_free(pCsr);
return SQLITE_OK;
@@ -1741,23 +1705,20 @@ static int fts3CloseMethod(sqlite3_vtab_cursor *pCursor){
**
** (or the equivalent for a content=xxx table) and set pCsr->pStmt to
** it. If an error occurs, return an SQLite error code.
**
** Otherwise, set *ppStmt to point to pCsr->pStmt and return SQLITE_OK.
*/
static int fts3CursorSeekStmt(Fts3Cursor *pCsr){
static int fts3CursorSeekStmt(Fts3Cursor *pCsr, sqlite3_stmt **ppStmt){
int rc = SQLITE_OK;
if( pCsr->pStmt==0 ){
Fts3Table *p = (Fts3Table *)pCsr->base.pVtab;
char *zSql;
if( p->pSeekStmt ){
pCsr->pStmt = p->pSeekStmt;
p->pSeekStmt = 0;
}else{
zSql = sqlite3_mprintf("SELECT %s WHERE rowid = ?", p->zReadExprlist);
if( !zSql ) return SQLITE_NOMEM;
rc = sqlite3_prepare_v3(p->db, zSql,-1,SQLITE_PREPARE_PERSISTENT,&pCsr->pStmt,0);
sqlite3_free(zSql);
}
if( rc==SQLITE_OK ) pCsr->bSeekStmt = 1;
zSql = sqlite3_mprintf("SELECT %s WHERE rowid = ?", p->zReadExprlist);
if( !zSql ) return SQLITE_NOMEM;
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pCsr->pStmt, 0);
sqlite3_free(zSql);
}
*ppStmt = pCsr->pStmt;
return rc;
}
@@ -1769,7 +1730,9 @@ static int fts3CursorSeekStmt(Fts3Cursor *pCsr){
static int fts3CursorSeek(sqlite3_context *pContext, Fts3Cursor *pCsr){
int rc = SQLITE_OK;
if( pCsr->isRequireSeek ){
rc = fts3CursorSeekStmt(pCsr);
sqlite3_stmt *pStmt = 0;
rc = fts3CursorSeekStmt(pCsr, &pStmt);
if( rc==SQLITE_OK ){
sqlite3_bind_int64(pCsr->pStmt, 1, pCsr->iPrevId);
pCsr->isRequireSeek = 0;
@@ -1858,8 +1821,7 @@ static int fts3ScanInteriorNode(
isFirstTerm = 0;
zCsr += fts3GetVarint32(zCsr, &nSuffix);
assert( nPrefix>=0 && nSuffix>=0 );
if( &zCsr[nSuffix]>zEnd ){
if( nPrefix<0 || nSuffix<0 || &zCsr[nSuffix]>zEnd ){
rc = FTS_CORRUPT_VTAB;
goto finish_scan;
}
@@ -2669,7 +2631,7 @@ int sqlite3Fts3FirstFilter(
fts3ColumnlistCopy(0, &p);
}
while( p<pEnd ){
while( p<pEnd && *p==0x01 ){
sqlite3_int64 iCol;
p++;
p += sqlite3Fts3GetVarint(p, &iCol);
@@ -3228,7 +3190,11 @@ static int fts3FilterMethod(
assert( iIdx==nVal );
/* In case the cursor has been used before, clear it now. */
fts3ClearCursor(pCsr);
sqlite3_finalize(pCsr->pStmt);
sqlite3_free(pCsr->aDoclist);
sqlite3Fts3MIBufferFree(pCsr->pMIBuffer);
sqlite3Fts3ExprFree(pCsr->pExpr);
memset(&pCursor[1], 0, sizeof(Fts3Cursor)-sizeof(sqlite3_vtab_cursor));
/* Set the lower and upper bounds on docids to return */
pCsr->iMinDocid = fts3DocidRange(pDocidGe, SMALLEST_INT64);
@@ -3286,13 +3252,13 @@ static int fts3FilterMethod(
);
}
if( zSql ){
rc = sqlite3_prepare_v3(p->db,zSql,-1,SQLITE_PREPARE_PERSISTENT,&pCsr->pStmt,0);
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pCsr->pStmt, 0);
sqlite3_free(zSql);
}else{
rc = SQLITE_NOMEM;
}
}else if( eSearch==FTS3_DOCID_SEARCH ){
rc = fts3CursorSeekStmt(pCsr);
rc = fts3CursorSeekStmt(pCsr, &pCsr->pStmt);
if( rc==SQLITE_OK ){
rc = sqlite3_bind_value(pCsr->pStmt, 1, pCons);
}
@@ -3307,12 +3273,7 @@ static int fts3FilterMethod(
** routine to find out if it has reached the end of a result set.
*/
static int fts3EofMethod(sqlite3_vtab_cursor *pCursor){
Fts3Cursor *pCsr = (Fts3Cursor*)pCursor;
if( pCsr->isEof ){
fts3ClearCursor(pCsr);
pCsr->isEof = 1;
}
return pCsr->isEof;
return ((Fts3Cursor *)pCursor)->isEof;
}
/*
@@ -3350,37 +3311,33 @@ static int fts3ColumnMethod(
/* The column value supplied by SQLite must be in range. */
assert( iCol>=0 && iCol<=p->nColumn+2 );
switch( iCol-p->nColumn ){
case 0:
/* The special 'table-name' column */
sqlite3_result_pointer(pCtx, pCsr, "fts3cursor", 0);
break;
if( iCol==p->nColumn+1 ){
/* This call is a request for the "docid" column. Since "docid" is an
** alias for "rowid", use the xRowid() method to obtain the value.
*/
sqlite3_result_int64(pCtx, pCsr->iPrevId);
}else if( iCol==p->nColumn ){
/* The extra column whose name is the same as the table.
** Return a blob which is a pointer to the cursor. */
sqlite3_result_blob(pCtx, &pCsr, sizeof(pCsr), SQLITE_TRANSIENT);
}else if( iCol==p->nColumn+2 && pCsr->pExpr ){
sqlite3_result_int64(pCtx, pCsr->iLangid);
}else{
/* The requested column is either a user column (one that contains
** indexed data), or the language-id column. */
rc = fts3CursorSeek(0, pCsr);
case 1:
/* The docid column */
sqlite3_result_int64(pCtx, pCsr->iPrevId);
break;
case 2:
if( pCsr->pExpr ){
sqlite3_result_int64(pCtx, pCsr->iLangid);
break;
}else if( p->zLanguageid==0 ){
sqlite3_result_int(pCtx, 0);
break;
}else{
iCol = p->nColumn;
/* fall-through */
}
default:
/* A user column. Or, if this is a full-table scan, possibly the
** language-id column. Seek the cursor. */
rc = fts3CursorSeek(0, pCsr);
if( rc==SQLITE_OK && sqlite3_data_count(pCsr->pStmt)-1>iCol ){
if( rc==SQLITE_OK ){
if( iCol==p->nColumn+2 ){
int iLangid = 0;
if( p->zLanguageid ){
iLangid = sqlite3_column_int(pCsr->pStmt, p->nColumn+1);
}
sqlite3_result_int(pCtx, iLangid);
}else if( sqlite3_data_count(pCsr->pStmt)>(iCol+1) ){
sqlite3_result_value(pCtx, sqlite3_column_value(pCsr->pStmt, iCol+1));
}
break;
}
}
assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 );
@@ -3429,10 +3386,8 @@ static int fts3SyncMethod(sqlite3_vtab *pVtab){
const u32 nMinMerge = 64; /* Minimum amount of incr-merge work to do */
Fts3Table *p = (Fts3Table*)pVtab;
int rc;
i64 iLastRowid = sqlite3_last_insert_rowid(p->db);
int rc = sqlite3Fts3PendingTermsFlush(p);
rc = sqlite3Fts3PendingTermsFlush(p);
if( rc==SQLITE_OK
&& p->nLeafAdd>(nMinMerge/16)
&& p->nAutoincrmerge && p->nAutoincrmerge!=0xff
@@ -3447,7 +3402,6 @@ static int fts3SyncMethod(sqlite3_vtab *pVtab){
if( A>(int)nMinMerge ) rc = sqlite3Fts3Incrmerge(p, A, p->nAutoincrmerge);
}
sqlite3Fts3SegmentsClose(p);
sqlite3_set_last_insert_rowid(p->db, iLastRowid);
return rc;
}
@@ -3460,11 +3414,17 @@ static int fts3SyncMethod(sqlite3_vtab *pVtab){
static int fts3SetHasStat(Fts3Table *p){
int rc = SQLITE_OK;
if( p->bHasStat==2 ){
char *zTbl = sqlite3_mprintf("%s_stat", p->zName);
if( zTbl ){
int res = sqlite3_table_column_metadata(p->db, p->zDb, zTbl, 0,0,0,0,0,0);
sqlite3_free(zTbl);
p->bHasStat = (res==SQLITE_OK);
const char *zFmt ="SELECT 1 FROM %Q.sqlite_master WHERE tbl_name='%q_stat'";
char *zSql = sqlite3_mprintf(zFmt, p->zDb, p->zName);
if( zSql ){
sqlite3_stmt *pStmt = 0;
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
if( rc==SQLITE_OK ){
int bHasStat = (sqlite3_step(pStmt)==SQLITE_ROW);
rc = sqlite3_finalize(pStmt);
if( rc==SQLITE_OK ) p->bHasStat = bHasStat;
}
sqlite3_free(zSql);
}else{
rc = SQLITE_NOMEM;
}
@@ -3571,17 +3531,18 @@ static int fts3FunctionArg(
sqlite3_value *pVal, /* argv[0] passed to function */
Fts3Cursor **ppCsr /* OUT: Store cursor handle here */
){
int rc;
*ppCsr = (Fts3Cursor*)sqlite3_value_pointer(pVal, "fts3cursor");
if( (*ppCsr)!=0 ){
rc = SQLITE_OK;
}else{
Fts3Cursor *pRet;
if( sqlite3_value_type(pVal)!=SQLITE_BLOB
|| sqlite3_value_bytes(pVal)!=sizeof(Fts3Cursor *)
){
char *zErr = sqlite3_mprintf("illegal first argument to %s", zFunc);
sqlite3_result_error(pContext, zErr, -1);
sqlite3_free(zErr);
rc = SQLITE_ERROR;
return SQLITE_ERROR;
}
return rc;
memcpy(&pRet, sqlite3_value_blob(pVal), sizeof(Fts3Cursor *));
*ppCsr = pRet;
return SQLITE_OK;
}
/*
@@ -3963,12 +3924,12 @@ int sqlite3Fts3Init(sqlite3 *db){
#ifdef SQLITE_TEST
if( rc==SQLITE_OK ){
rc = sqlite3Fts3ExprInitTestInterface(db, pHash);
rc = sqlite3Fts3ExprInitTestInterface(db);
}
#endif
/* Create the virtual table wrapper around the hash-table and overload
** the four scalar functions. If this is successful, register the
** the two scalar functions. If this is successful, register the
** module with sqlite.
*/
if( SQLITE_OK==rc
@@ -4551,7 +4512,7 @@ static int fts3EvalIncrPhraseNext(
** one incremental token. In which case the bIncr flag is set. */
assert( p->bIncr==1 );
if( p->nToken==1 ){
if( p->nToken==1 && p->bIncr ){
rc = sqlite3Fts3MsrIncrNext(pTab, p->aToken[0].pSegcsr,
&pDL->iDocid, &pDL->pList, &pDL->nList
);
@@ -4784,7 +4745,6 @@ static void fts3EvalTokenCosts(
** the number of overflow pages consumed by a record B bytes in size.
*/
static int fts3EvalAverageDocsize(Fts3Cursor *pCsr, int *pnPage){
int rc = SQLITE_OK;
if( pCsr->nRowAvg==0 ){
/* The average document size, which is required to calculate the cost
** of each doclist, has not yet been determined. Read the required
@@ -4797,6 +4757,7 @@ static int fts3EvalAverageDocsize(Fts3Cursor *pCsr, int *pnPage){
** data stored in all rows of each column of the table, from left
** to right.
*/
int rc;
Fts3Table *p = (Fts3Table*)pCsr->base.pVtab;
sqlite3_stmt *pStmt;
sqlite3_int64 nDoc = 0;
@@ -4823,10 +4784,11 @@ static int fts3EvalAverageDocsize(Fts3Cursor *pCsr, int *pnPage){
pCsr->nRowAvg = (int)(((nByte / nDoc) + p->nPgsz) / p->nPgsz);
assert( pCsr->nRowAvg>0 );
rc = sqlite3_reset(pStmt);
if( rc!=SQLITE_OK ) return rc;
}
*pnPage = pCsr->nRowAvg;
return rc;
return SQLITE_OK;
}
/*
@@ -5176,8 +5138,7 @@ static void fts3EvalNextRow(
pExpr->iDocid = pLeft->iDocid;
pExpr->bEof = (pLeft->bEof || pRight->bEof);
if( pExpr->eType==FTSQUERY_NEAR && pExpr->bEof ){
assert( pRight->eType==FTSQUERY_PHRASE );
if( pRight->pPhrase->doclist.aAll ){
if( pRight->pPhrase && pRight->pPhrase->doclist.aAll ){
Fts3Doclist *pDl = &pRight->pPhrase->doclist;
while( *pRc==SQLITE_OK && pRight->bEof==0 ){
memset(pDl->pList, 0, pDl->nList);
@@ -5206,7 +5167,7 @@ static void fts3EvalNextRow(
if( pRight->bEof || (pLeft->bEof==0 && iCmp<0) ){
fts3EvalNextRow(pCsr, pLeft, pRc);
}else if( pLeft->bEof || iCmp>0 ){
}else if( pLeft->bEof || (pRight->bEof==0 && iCmp>0) ){
fts3EvalNextRow(pCsr, pRight, pRc);
}else{
fts3EvalNextRow(pCsr, pLeft, pRc);
@@ -5298,6 +5259,7 @@ static int fts3EvalNearTest(Fts3Expr *pExpr, int *pRc){
*/
if( *pRc==SQLITE_OK
&& pExpr->eType==FTSQUERY_NEAR
&& pExpr->bEof==0
&& (pExpr->pParent==0 || pExpr->pParent->eType!=FTSQUERY_NEAR)
){
Fts3Expr *p;
@@ -5306,39 +5268,42 @@ static int fts3EvalNearTest(Fts3Expr *pExpr, int *pRc){
/* Allocate temporary working space. */
for(p=pExpr; p->pLeft; p=p->pLeft){
assert( p->pRight->pPhrase->doclist.nList>0 );
nTmp += p->pRight->pPhrase->doclist.nList;
}
nTmp += p->pPhrase->doclist.nList;
aTmp = sqlite3_malloc(nTmp*2);
if( !aTmp ){
*pRc = SQLITE_NOMEM;
if( nTmp==0 ){
res = 0;
}else{
char *aPoslist = p->pPhrase->doclist.pList;
int nToken = p->pPhrase->nToken;
aTmp = sqlite3_malloc(nTmp*2);
if( !aTmp ){
*pRc = SQLITE_NOMEM;
res = 0;
}else{
char *aPoslist = p->pPhrase->doclist.pList;
int nToken = p->pPhrase->nToken;
for(p=p->pParent;res && p && p->eType==FTSQUERY_NEAR; p=p->pParent){
Fts3Phrase *pPhrase = p->pRight->pPhrase;
int nNear = p->nNear;
res = fts3EvalNearTrim(nNear, aTmp, &aPoslist, &nToken, pPhrase);
for(p=p->pParent;res && p && p->eType==FTSQUERY_NEAR; p=p->pParent){
Fts3Phrase *pPhrase = p->pRight->pPhrase;
int nNear = p->nNear;
res = fts3EvalNearTrim(nNear, aTmp, &aPoslist, &nToken, pPhrase);
}
aPoslist = pExpr->pRight->pPhrase->doclist.pList;
nToken = pExpr->pRight->pPhrase->nToken;
for(p=pExpr->pLeft; p && res; p=p->pLeft){
int nNear;
Fts3Phrase *pPhrase;
assert( p->pParent && p->pParent->pLeft==p );
nNear = p->pParent->nNear;
pPhrase = (
p->eType==FTSQUERY_NEAR ? p->pRight->pPhrase : p->pPhrase
);
res = fts3EvalNearTrim(nNear, aTmp, &aPoslist, &nToken, pPhrase);
}
}
aPoslist = pExpr->pRight->pPhrase->doclist.pList;
nToken = pExpr->pRight->pPhrase->nToken;
for(p=pExpr->pLeft; p && res; p=p->pLeft){
int nNear;
Fts3Phrase *pPhrase;
assert( p->pParent && p->pParent->pLeft==p );
nNear = p->pParent->nNear;
pPhrase = (
p->eType==FTSQUERY_NEAR ? p->pRight->pPhrase : p->pPhrase
);
res = fts3EvalNearTrim(nNear, aTmp, &aPoslist, &nToken, pPhrase);
}
sqlite3_free(aTmp);
}
sqlite3_free(aTmp);
}
return res;
+1 -3
View File
@@ -230,7 +230,6 @@ struct Fts3Table {
** statements is run and reset within a single virtual table API call.
*/
sqlite3_stmt *aStmt[40];
sqlite3_stmt *pSeekStmt; /* Cache for fts3CursorSeekStmt() */
char *zReadExprlist;
char *zWriteExprlist;
@@ -300,7 +299,6 @@ struct Fts3Cursor {
i16 eSearch; /* Search strategy (see below) */
u8 isEof; /* True if at End Of Results */
u8 isRequireSeek; /* True if must seek pStmt to %_content row */
u8 bSeekStmt; /* True if pStmt is a seek */
sqlite3_stmt *pStmt; /* Prepared statement in use by the cursor */
Fts3Expr *pExpr; /* Parsed MATCH query string */
int iLangid; /* Language being queried for */
@@ -584,7 +582,7 @@ int sqlite3Fts3ExprParse(sqlite3_tokenizer *, int,
);
void sqlite3Fts3ExprFree(Fts3Expr *);
#ifdef SQLITE_TEST
int sqlite3Fts3ExprInitTestInterface(sqlite3 *db, Fts3Hash*);
int sqlite3Fts3ExprInitTestInterface(sqlite3 *db);
int sqlite3Fts3InitTerm(sqlite3 *db);
#endif
+53 -36
View File
@@ -1108,6 +1108,34 @@ void sqlite3Fts3ExprFree(Fts3Expr *pDel){
#include <stdio.h>
/*
** Function to query the hash-table of tokenizers (see README.tokenizers).
*/
static int queryTestTokenizer(
sqlite3 *db,
const char *zName,
const sqlite3_tokenizer_module **pp
){
int rc;
sqlite3_stmt *pStmt;
const char zSql[] = "SELECT fts3_tokenizer(?)";
*pp = 0;
rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
if( rc!=SQLITE_OK ){
return rc;
}
sqlite3_bind_text(pStmt, 1, zName, -1, SQLITE_STATIC);
if( SQLITE_ROW==sqlite3_step(pStmt) ){
if( sqlite3_column_type(pStmt, 0)==SQLITE_BLOB ){
memcpy((void *)pp, sqlite3_column_blob(pStmt, 0), sizeof(*pp));
}
}
return sqlite3_finalize(pStmt);
}
/*
** Return a pointer to a buffer containing a text representation of the
** expression passed as the first argument. The buffer is obtained from
@@ -1175,12 +1203,12 @@ static char *exprToString(Fts3Expr *pExpr, char *zBuf){
**
** SELECT fts3_exprtest('simple', 'Bill col2:Bloggs', 'col1', 'col2');
*/
static void fts3ExprTestCommon(
int bRebalance,
static void fts3ExprTest(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
sqlite3_tokenizer_module const *pModule = 0;
sqlite3_tokenizer *pTokenizer = 0;
int rc;
char **azCol = 0;
@@ -1190,9 +1218,7 @@ static void fts3ExprTestCommon(
int ii;
Fts3Expr *pExpr;
char *zBuf = 0;
Fts3Hash *pHash = (Fts3Hash*)sqlite3_user_data(context);
const char *zTokenizer = 0;
char *zErr = 0;
sqlite3 *db = sqlite3_context_db_handle(context);
if( argc<3 ){
sqlite3_result_error(context,
@@ -1201,18 +1227,24 @@ static void fts3ExprTestCommon(
return;
}
zTokenizer = (const char*)sqlite3_value_text(argv[0]);
rc = sqlite3Fts3InitTokenizer(pHash, zTokenizer, &pTokenizer, &zErr);
if( rc!=SQLITE_OK ){
if( rc==SQLITE_NOMEM ){
sqlite3_result_error_nomem(context);
}else{
sqlite3_result_error(context, zErr, -1);
}
sqlite3_free(zErr);
return;
rc = queryTestTokenizer(db,
(const char *)sqlite3_value_text(argv[0]), &pModule);
if( rc==SQLITE_NOMEM ){
sqlite3_result_error_nomem(context);
goto exprtest_out;
}else if( !pModule ){
sqlite3_result_error(context, "No such tokenizer module", -1);
goto exprtest_out;
}
rc = pModule->xCreate(0, 0, &pTokenizer);
assert( rc==SQLITE_NOMEM || rc==SQLITE_OK );
if( rc==SQLITE_NOMEM ){
sqlite3_result_error_nomem(context);
goto exprtest_out;
}
pTokenizer->pModule = pModule;
zExpr = (const char *)sqlite3_value_text(argv[1]);
nExpr = sqlite3_value_bytes(argv[1]);
nCol = argc-2;
@@ -1225,7 +1257,7 @@ static void fts3ExprTestCommon(
azCol[ii] = (char *)sqlite3_value_text(argv[ii+2]);
}
if( bRebalance ){
if( sqlite3_user_data(context) ){
char *zDummy = 0;
rc = sqlite3Fts3ExprParse(
pTokenizer, 0, azCol, 0, nCol, nCol, zExpr, nExpr, &pExpr, &zDummy
@@ -1251,38 +1283,23 @@ static void fts3ExprTestCommon(
sqlite3Fts3ExprFree(pExpr);
exprtest_out:
if( pTokenizer ){
rc = pTokenizer->pModule->xDestroy(pTokenizer);
if( pModule && pTokenizer ){
rc = pModule->xDestroy(pTokenizer);
}
sqlite3_free(azCol);
}
static void fts3ExprTest(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
fts3ExprTestCommon(0, context, argc, argv);
}
static void fts3ExprTestRebalance(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
fts3ExprTestCommon(1, context, argc, argv);
}
/*
** Register the query expression parser test function fts3_exprtest()
** with database connection db.
*/
int sqlite3Fts3ExprInitTestInterface(sqlite3 *db, Fts3Hash *pHash){
int sqlite3Fts3ExprInitTestInterface(sqlite3* db){
int rc = sqlite3_create_function(
db, "fts3_exprtest", -1, SQLITE_UTF8, (void*)pHash, fts3ExprTest, 0, 0
db, "fts3_exprtest", -1, SQLITE_UTF8, 0, fts3ExprTest, 0, 0
);
if( rc==SQLITE_OK ){
rc = sqlite3_create_function(db, "fts3_exprtest_rebalance",
-1, SQLITE_UTF8, (void*)pHash, fts3ExprTestRebalance, 0, 0
-1, SQLITE_UTF8, (void *)1, fts3ExprTest, 0, 0
);
}
return rc;
+5 -12
View File
@@ -18,14 +18,7 @@
** that the sqlite3_tokenizer_module.xLanguage() method is invoked correctly.
*/
#if defined(INCLUDE_SQLITE_TCL_H)
# include "sqlite_tcl.h"
#else
# include "tcl.h"
# ifndef SQLITE_TCLAPI
# define SQLITE_TCLAPI
# endif
#endif
#include <tcl.h>
#include <string.h>
#include <assert.h>
@@ -150,7 +143,7 @@ static int nm_match_count(
/*
** Tclcmd: fts3_near_match DOCUMENT EXPR ?OPTIONS?
*/
static int SQLITE_TCLAPI fts3_near_match_cmd(
static int fts3_near_match_cmd(
ClientData clientData,
Tcl_Interp *interp,
int objc,
@@ -285,7 +278,7 @@ static int SQLITE_TCLAPI fts3_near_match_cmd(
** # Restore initial incr-load settings:
** eval fts3_configure_incr_load $cfg
*/
static int SQLITE_TCLAPI fts3_configure_incr_load_cmd(
static int fts3_configure_incr_load_cmd(
ClientData clientData,
Tcl_Interp *interp,
int objc,
@@ -495,7 +488,7 @@ static int testTokenizerLanguage(
}
#endif
static int SQLITE_TCLAPI fts3_test_tokenizer_cmd(
static int fts3_test_tokenizer_cmd(
ClientData clientData,
Tcl_Interp *interp,
int objc,
@@ -524,7 +517,7 @@ static int SQLITE_TCLAPI fts3_test_tokenizer_cmd(
return TCL_OK;
}
static int SQLITE_TCLAPI fts3_test_varint_cmd(
static int fts3_test_varint_cmd(
ClientData clientData,
Tcl_Interp *interp,
int objc,
+1 -5
View File
@@ -224,11 +224,7 @@ int sqlite3Fts3InitTokenizer(
#ifdef SQLITE_TEST
#if defined(INCLUDE_SQLITE_TCL_H)
# include "sqlite_tcl.h"
#else
# include "tcl.h"
#endif
#include <tcl.h>
#include <string.h>
/*
+13 -13
View File
@@ -136,16 +136,16 @@ static int unicodeAddExceptions(
){
const unsigned char *z = (const unsigned char *)zIn;
const unsigned char *zTerm = &z[nIn];
unsigned int iCode;
int iCode;
int nEntry = 0;
assert( bAlnum==0 || bAlnum==1 );
while( z<zTerm ){
READ_UTF8(z, zTerm, iCode);
assert( (sqlite3FtsUnicodeIsalnum((int)iCode) & 0xFFFFFFFE)==0 );
if( sqlite3FtsUnicodeIsalnum((int)iCode)!=bAlnum
&& sqlite3FtsUnicodeIsdiacritic((int)iCode)==0
assert( (sqlite3FtsUnicodeIsalnum(iCode) & 0xFFFFFFFE)==0 );
if( sqlite3FtsUnicodeIsalnum(iCode)!=bAlnum
&& sqlite3FtsUnicodeIsdiacritic(iCode)==0
){
nEntry++;
}
@@ -162,13 +162,13 @@ static int unicodeAddExceptions(
z = (const unsigned char *)zIn;
while( z<zTerm ){
READ_UTF8(z, zTerm, iCode);
if( sqlite3FtsUnicodeIsalnum((int)iCode)!=bAlnum
&& sqlite3FtsUnicodeIsdiacritic((int)iCode)==0
if( sqlite3FtsUnicodeIsalnum(iCode)!=bAlnum
&& sqlite3FtsUnicodeIsdiacritic(iCode)==0
){
int i, j;
for(i=0; i<nNew && aNew[i]<(int)iCode; i++);
for(i=0; i<nNew && aNew[i]<iCode; i++);
for(j=nNew; j>i; j--) aNew[j] = aNew[j-1];
aNew[i] = (int)iCode;
aNew[i] = iCode;
nNew++;
}
}
@@ -318,7 +318,7 @@ static int unicodeNext(
){
unicode_cursor *pCsr = (unicode_cursor *)pC;
unicode_tokenizer *p = ((unicode_tokenizer *)pCsr->base.pTokenizer);
unsigned int iCode = 0;
int iCode = 0;
char *zOut;
const unsigned char *z = &pCsr->aInput[pCsr->iOff];
const unsigned char *zStart = z;
@@ -330,7 +330,7 @@ static int unicodeNext(
** the input. */
while( z<zTerm ){
READ_UTF8(z, zTerm, iCode);
if( unicodeIsAlnum(p, (int)iCode) ) break;
if( unicodeIsAlnum(p, iCode) ) break;
zStart = z;
}
if( zStart>=zTerm ) return SQLITE_DONE;
@@ -350,7 +350,7 @@ static int unicodeNext(
/* Write the folded case of the last character read to the output */
zEnd = z;
iOut = sqlite3FtsUnicodeFold((int)iCode, p->bRemoveDiacritic);
iOut = sqlite3FtsUnicodeFold(iCode, p->bRemoveDiacritic);
if( iOut ){
WRITE_UTF8(zOut, iOut);
}
@@ -358,8 +358,8 @@ static int unicodeNext(
/* If the cursor is not at EOF, read the next character */
if( z>=zTerm ) break;
READ_UTF8(z, zTerm, iCode);
}while( unicodeIsAlnum(p, (int)iCode)
|| sqlite3FtsUnicodeIsdiacritic((int)iCode)
}while( unicodeIsAlnum(p, iCode)
|| sqlite3FtsUnicodeIsdiacritic(iCode)
);
/* Set the output variables and return. */
+11 -10
View File
@@ -127,9 +127,9 @@ int sqlite3FtsUnicodeIsalnum(int c){
0xFFFFFFFF, 0xFC00FFFF, 0xF8000001, 0xF8000001,
};
if( (unsigned int)c<128 ){
return ( (aAscii[c >> 5] & ((unsigned int)1 << (c & 0x001F)))==0 );
}else if( (unsigned int)c<(1<<22) ){
if( c<128 ){
return ( (aAscii[c >> 5] & (1 << (c & 0x001F)))==0 );
}else if( c<(1<<22) ){
unsigned int key = (((unsigned int)c)<<10) | 0x000003FF;
int iRes = 0;
int iHi = sizeof(aEntry)/sizeof(aEntry[0]) - 1;
@@ -322,17 +322,16 @@ int sqlite3FtsUnicodeFold(int c, int bRemoveDiacritic){
int ret = c;
assert( c>=0 );
assert( sizeof(unsigned short)==2 && sizeof(unsigned char)==1 );
if( c<128 ){
if( c>='A' && c<='Z' ) ret = c + ('a' - 'A');
}else if( c<65536 ){
const struct TableEntry *p;
int iHi = sizeof(aEntry)/sizeof(aEntry[0]) - 1;
int iLo = 0;
int iRes = -1;
assert( c>aEntry[0].iCode );
while( iHi>=iLo ){
int iTest = (iHi + iLo) / 2;
int cmp = (c - aEntry[iTest].iCode);
@@ -343,12 +342,14 @@ int sqlite3FtsUnicodeFold(int c, int bRemoveDiacritic){
iHi = iTest-1;
}
}
assert( iRes<0 || c>=aEntry[iRes].iCode );
assert( iRes>=0 && c>=aEntry[iRes].iCode );
p = &aEntry[iRes];
if( c<(p->iCode + p->nRange) && 0==(0x01 & p->flags & (p->iCode ^ c)) ){
ret = (c + (aiOff[p->flags>>1])) & 0x0000FFFF;
assert( ret>0 );
if( iRes>=0 ){
const struct TableEntry *p = &aEntry[iRes];
if( c<(p->iCode + p->nRange) && 0==(0x01 & p->flags & (p->iCode ^ c)) ){
ret = (c + (aiOff[p->flags>>1])) & 0x0000FFFF;
assert( ret>0 );
}
}
if( bRemoveDiacritic ) ret = remove_diacritic(ret);
+5 -12
View File
@@ -407,8 +407,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_v2(p->db, zSql, -1, &pStmt, NULL);
sqlite3_free(zSql);
assert( rc==SQLITE_OK || pStmt==0 );
p->aStmt[eStmt] = pStmt;
@@ -1908,7 +1907,6 @@ static int fts3WriteSegment(
sqlite3_bind_blob(pStmt, 2, z, n, SQLITE_STATIC);
sqlite3_step(pStmt);
rc = sqlite3_reset(pStmt);
sqlite3_bind_null(pStmt, 2);
}
return rc;
}
@@ -1965,7 +1963,6 @@ static int fts3WriteSegdir(
sqlite3_bind_blob(pStmt, 6, zRoot, nRoot, SQLITE_STATIC);
sqlite3_step(pStmt);
rc = sqlite3_reset(pStmt);
sqlite3_bind_null(pStmt, 6);
}
return rc;
}
@@ -3445,7 +3442,6 @@ static void fts3UpdateDocTotals(
sqlite3_bind_blob(pStmt, 2, pBlob, nBlob, SQLITE_STATIC);
sqlite3_step(pStmt);
*pRC = sqlite3_reset(pStmt);
sqlite3_bind_null(pStmt, 2);
sqlite3_free(a);
}
@@ -4634,7 +4630,6 @@ static int fts3TruncateSegment(
sqlite3_bind_int(pChomp, 4, iIdx);
sqlite3_step(pChomp);
rc = sqlite3_reset(pChomp);
sqlite3_bind_null(pChomp, 2);
}
}
@@ -4714,7 +4709,6 @@ static int fts3IncrmergeHintStore(Fts3Table *p, Blob *pHint){
sqlite3_bind_blob(pReplace, 2, pHint->a, pHint->n, SQLITE_STATIC);
sqlite3_step(pReplace);
rc = sqlite3_reset(pReplace);
sqlite3_bind_null(pReplace, 2);
}
return rc;
@@ -4962,14 +4956,11 @@ int sqlite3Fts3Incrmerge(Fts3Table *p, int nMerge, int nMin){
** Convert the text beginning at *pz into an integer and return
** its value. Advance *pz to point to the first character past
** the integer.
**
** This function used for parameters to merge= and incrmerge=
** commands.
*/
static int fts3Getint(const char **pz){
const char *z = *pz;
int i = 0;
while( (*z)>='0' && (*z)<='9' && i<214748363 ) i = 10*i + *(z++) - '0';
while( (*z)>='0' && (*z)<='9' ) i = 10*i + *(z++) - '0';
*pz = z;
return i;
}
@@ -5529,6 +5520,7 @@ int sqlite3Fts3UpdateMethod(
){
Fts3Table *p = (Fts3Table *)pVtab;
int rc = SQLITE_OK; /* Return Code */
int isRemove = 0; /* True for an UPDATE or DELETE */
u32 *aSzIns = 0; /* Sizes of inserted documents */
u32 *aSzDel = 0; /* Sizes of deleted documents */
int nChng = 0; /* Net change in number of documents */
@@ -5626,6 +5618,7 @@ int sqlite3Fts3UpdateMethod(
if( sqlite3_value_type(apVal[0])!=SQLITE_NULL ){
assert( sqlite3_value_type(apVal[0])==SQLITE_INTEGER );
rc = fts3DeleteByRowid(p, apVal[0], &nChng, aSzDel);
isRemove = 1;
}
/* If this is an INSERT or UPDATE operation, insert the new record. */
@@ -5637,7 +5630,7 @@ int sqlite3Fts3UpdateMethod(
rc = FTS_CORRUPT_VTAB;
}
}
if( rc==SQLITE_OK ){
if( rc==SQLITE_OK && (!isRemove || *pRowid!=p->iPrevDocid ) ){
rc = fts3PendingTermsDocid(p, 0, iLangid, *pRowid);
}
if( rc==SQLITE_OK ){
-16
View File
@@ -1,16 +0,0 @@
#!/bin/sh
set -e
srcdir=`dirname $(dirname $(dirname $(dirname $0)))`
./testfixture $srcdir/test/fts3.test --output=fts3cov-out.txt
echo ""
for f in `ls $srcdir/ext/fts3/*.c`
do
f=`basename $f`
echo -ne "$f: "
gcov -b $f | grep Taken | sed 's/Taken at least once://'
done
+1 -1
View File
@@ -227,7 +227,7 @@ proc print_isalnum {zFunc lRange} {
an_print_ascii_bitmap $lRange
puts {
if( (unsigned int)c<128 ){
return ( (aAscii[c >> 5] & ((unsigned int)1 << (c & 0x001F)))==0 );
return ( (aAscii[c >> 5] & (1 << (c & 0x001F)))==0 );
}else if( (unsigned int)c<(1<<22) ){
unsigned int key = (((unsigned int)c)<<10) | 0x000003FF;
int iRes = 0;
+2 -1
View File
@@ -318,7 +318,7 @@ struct Fts5ExtensionApi {
** behaviour. The structure methods are expected to function as follows:
**
** xCreate:
** This function is used to allocate and initialize a tokenizer instance.
** This function is used to allocate and inititalize a tokenizer instance.
** A tokenizer instance is required to actually tokenize text.
**
** The first argument passed to this function is a copy of the (void*)
@@ -577,3 +577,4 @@ struct fts5_api {
#endif
#endif /* _FTS5_H */
+5 -11
View File
@@ -30,9 +30,7 @@ typedef short i16;
typedef sqlite3_int64 i64;
typedef sqlite3_uint64 u64;
#ifndef ArraySize
# define ArraySize(x) ((int)(sizeof(x) / sizeof(x[0])))
#endif
#define ArraySize(x) ((int)(sizeof(x) / sizeof(x[0])))
#define testcase(x)
#define ALWAYS(x) 1
@@ -446,9 +444,9 @@ int sqlite3Fts5IndexBeginWrite(
/*
** Flush any data stored in the in-memory hash tables to the database.
** Also close any open blob handles.
** If the bCommit flag is true, also close any open blob handles.
*/
int sqlite3Fts5IndexSync(Fts5Index *p);
int sqlite3Fts5IndexSync(Fts5Index *p, int bCommit);
/*
** Discard any data stored in the in-memory hash tables. Do not write it
@@ -618,7 +616,7 @@ int sqlite3Fts5StorageDocsize(Fts5Storage *p, i64 iRowid, int *aCol);
int sqlite3Fts5StorageSize(Fts5Storage *p, int iCol, i64 *pnAvg);
int sqlite3Fts5StorageRowCount(Fts5Storage *p, i64 *pnRow);
int sqlite3Fts5StorageSync(Fts5Storage *p);
int sqlite3Fts5StorageSync(Fts5Storage *p, int bCommit);
int sqlite3Fts5StorageRollback(Fts5Storage *p);
int sqlite3Fts5StorageConfigValue(
@@ -654,7 +652,6 @@ struct Fts5Token {
/* Parse a MATCH expression. */
int sqlite3Fts5ExprNew(
Fts5Config *pConfig,
int iCol, /* Column on LHS of MATCH operator */
const char *zExpr,
Fts5Expr **ppNew,
char **pzErr
@@ -722,8 +719,6 @@ Fts5ExprPhrase *sqlite3Fts5ParseTerm(
int bPrefix
);
void sqlite3Fts5ParseSetCaret(Fts5ExprPhrase*);
Fts5ExprNearset *sqlite3Fts5ParseNearset(
Fts5Parse*,
Fts5ExprNearset*,
@@ -741,8 +736,7 @@ void sqlite3Fts5ParseNearsetFree(Fts5ExprNearset*);
void sqlite3Fts5ParseNodeFree(Fts5ExprNode*);
void sqlite3Fts5ParseSetDistance(Fts5Parse*, Fts5ExprNearset*, Fts5Token*);
void sqlite3Fts5ParseSetColset(Fts5Parse*, Fts5ExprNode*, Fts5Colset*);
Fts5Colset *sqlite3Fts5ParseColsetInvert(Fts5Parse*, Fts5Colset*);
void sqlite3Fts5ParseSetColset(Fts5Parse*, Fts5ExprNearset*, Fts5Colset*);
void sqlite3Fts5ParseFinished(Fts5Parse *pParse, Fts5ExprNode *p);
void sqlite3Fts5ParseNear(Fts5Parse *pParse, Fts5Token*);
+48 -200
View File
@@ -189,7 +189,7 @@ static int fts5HighlightCb(
if( p->iRangeEnd>0 && iPos==p->iRangeEnd ){
fts5HighlightAppend(&rc, p, &p->zIn[p->iOff], iEndOff - p->iOff);
p->iOff = iEndOff;
if( iPos>=p->iter.iStart && iPos<p->iter.iEnd ){
if( iPos<p->iter.iEnd ){
fts5HighlightAppend(&rc, p, p->zClose, -1);
}
}
@@ -246,128 +246,6 @@ static void fts5HighlightFunction(
** End of highlight() implementation.
**************************************************************************/
/*
** Context object passed to the fts5SentenceFinderCb() function.
*/
typedef struct Fts5SFinder Fts5SFinder;
struct Fts5SFinder {
int iPos; /* Current token position */
int nFirstAlloc; /* Allocated size of aFirst[] */
int nFirst; /* Number of entries in aFirst[] */
int *aFirst; /* Array of first token in each sentence */
const char *zDoc; /* Document being tokenized */
};
/*
** Add an entry to the Fts5SFinder.aFirst[] array. Grow the array if
** necessary. Return SQLITE_OK if successful, or SQLITE_NOMEM if an
** error occurs.
*/
static int fts5SentenceFinderAdd(Fts5SFinder *p, int iAdd){
if( p->nFirstAlloc==p->nFirst ){
int nNew = p->nFirstAlloc ? p->nFirstAlloc*2 : 64;
int *aNew;
aNew = (int*)sqlite3_realloc(p->aFirst, nNew*sizeof(int));
if( aNew==0 ) return SQLITE_NOMEM;
p->aFirst = aNew;
p->nFirstAlloc = nNew;
}
p->aFirst[p->nFirst++] = iAdd;
return SQLITE_OK;
}
/*
** This function is an xTokenize() callback used by the auxiliary snippet()
** function. Its job is to identify tokens that are the first in a sentence.
** For each such token, an entry is added to the SFinder.aFirst[] array.
*/
static int fts5SentenceFinderCb(
void *pContext, /* Pointer to HighlightContext object */
int tflags, /* Mask of FTS5_TOKEN_* flags */
const char *pToken, /* Buffer containing token */
int nToken, /* Size of token in bytes */
int iStartOff, /* Start offset of token */
int iEndOff /* End offset of token */
){
int rc = SQLITE_OK;
UNUSED_PARAM2(pToken, nToken);
UNUSED_PARAM(iEndOff);
if( (tflags & FTS5_TOKEN_COLOCATED)==0 ){
Fts5SFinder *p = (Fts5SFinder*)pContext;
if( p->iPos>0 ){
int i;
char c = 0;
for(i=iStartOff-1; i>=0; i--){
c = p->zDoc[i];
if( c!=' ' && c!='\t' && c!='\n' && c!='\r' ) break;
}
if( i!=iStartOff-1 && (c=='.' || c==':') ){
rc = fts5SentenceFinderAdd(p, p->iPos);
}
}else{
rc = fts5SentenceFinderAdd(p, 0);
}
p->iPos++;
}
return rc;
}
static int fts5SnippetScore(
const Fts5ExtensionApi *pApi, /* API offered by current FTS version */
Fts5Context *pFts, /* First arg to pass to pApi functions */
int nDocsize, /* Size of column in tokens */
unsigned char *aSeen, /* Array with one element per query phrase */
int iCol, /* Column to score */
int iPos, /* Starting offset to score */
int nToken, /* Max tokens per snippet */
int *pnScore, /* OUT: Score */
int *piPos /* OUT: Adjusted offset */
){
int rc;
int i;
int ip = 0;
int ic = 0;
int iOff = 0;
int iFirst = -1;
int nInst;
int nScore = 0;
int iLast = 0;
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) ){
nScore += (aSeen[ip] ? 1 : 1000);
aSeen[ip] = 1;
if( iFirst<0 ) iFirst = iOff;
iLast = iOff + pApi->xPhraseSize(pFts, ip);
}
}
*pnScore = nScore;
if( piPos ){
int iAdj = iFirst - (nToken - (iLast-iFirst)) / 2;
if( (iAdj+nToken)>nDocsize ) iAdj = nDocsize - nToken;
if( iAdj<0 ) iAdj = 0;
*piPos = iAdj;
}
return rc;
}
/*
** Return the value in pVal interpreted as utf-8 text. Except, if pVal
** contains a NULL value, return a pointer to a static string zero
** bytes in length instead of a NULL pointer.
*/
static const char *fts5ValueToText(sqlite3_value *pVal){
const char *zRet = (const char*)sqlite3_value_text(pVal);
return zRet ? zRet : "";
}
/*
** Implementation of snippet() function.
*/
@@ -389,10 +267,9 @@ static void fts5SnippetFunction(
unsigned char *aSeen; /* Array of "seen instance" flags */
int iBestCol; /* Column containing best snippet */
int iBestStart = 0; /* First token of best snippet */
int iBestLast; /* Last token of best snippet */
int nBestScore = 0; /* Score of best snippet */
int nColSize = 0; /* Total size of iBestCol in tokens */
Fts5SFinder sFinder; /* Used to find the beginnings of sentences */
int nCol;
if( nVal!=5 ){
const char *zErr = "wrong number of arguments to function snippet()";
@@ -400,13 +277,13 @@ static void fts5SnippetFunction(
return;
}
nCol = pApi->xColumnCount(pFts);
memset(&ctx, 0, sizeof(HighlightContext));
iCol = sqlite3_value_int(apVal[0]);
ctx.zOpen = fts5ValueToText(apVal[1]);
ctx.zClose = fts5ValueToText(apVal[2]);
zEllips = fts5ValueToText(apVal[3]);
ctx.zOpen = (const char*)sqlite3_value_text(apVal[1]);
ctx.zClose = (const char*)sqlite3_value_text(apVal[2]);
zEllips = (const char*)sqlite3_value_text(apVal[3]);
nToken = sqlite3_value_int(apVal[4]);
iBestLast = nToken-1;
iBestCol = (iCol>=0 ? iCol : 0);
nPhrase = pApi->xPhraseCount(pFts);
@@ -414,94 +291,65 @@ static void fts5SnippetFunction(
if( aSeen==0 ){
rc = SQLITE_NOMEM;
}
if( rc==SQLITE_OK ){
rc = pApi->xInstCount(pFts, &nInst);
}
for(i=0; rc==SQLITE_OK && i<nInst; i++){
int ip, iSnippetCol, iStart;
memset(aSeen, 0, nPhrase);
rc = pApi->xInst(pFts, i, &ip, &iSnippetCol, &iStart);
if( rc==SQLITE_OK && (iCol<0 || iSnippetCol==iCol) ){
int nScore = 1000;
int iLast = iStart - 1 + pApi->xPhraseSize(pFts, ip);
int j;
aSeen[ip] = 1;
memset(&sFinder, 0, sizeof(Fts5SFinder));
for(i=0; i<nCol; i++){
if( iCol<0 || iCol==i ){
int nDoc;
int nDocsize;
int ii;
sFinder.iPos = 0;
sFinder.nFirst = 0;
rc = pApi->xColumnText(pFts, i, &sFinder.zDoc, &nDoc);
if( rc!=SQLITE_OK ) break;
rc = pApi->xTokenize(pFts,
sFinder.zDoc, nDoc, (void*)&sFinder,fts5SentenceFinderCb
);
if( rc!=SQLITE_OK ) break;
rc = pApi->xColumnSize(pFts, i, &nDocsize);
if( rc!=SQLITE_OK ) break;
for(ii=0; rc==SQLITE_OK && ii<nInst; ii++){
int ip, ic, io;
int iAdj;
int nScore;
int jj;
rc = pApi->xInst(pFts, ii, &ip, &ic, &io);
if( ic!=i || rc!=SQLITE_OK ) continue;
memset(aSeen, 0, nPhrase);
rc = fts5SnippetScore(pApi, pFts, nDocsize, aSeen, i,
io, nToken, &nScore, &iAdj
);
if( rc==SQLITE_OK && nScore>nBestScore ){
nBestScore = nScore;
iBestCol = i;
iBestStart = iAdj;
nColSize = nDocsize;
for(j=i+1; rc==SQLITE_OK && j<nInst; j++){
int ic; int io; int iFinal;
rc = pApi->xInst(pFts, j, &ip, &ic, &io);
iFinal = io + pApi->xPhraseSize(pFts, ip) - 1;
if( rc==SQLITE_OK && ic==iSnippetCol && iLast<iStart+nToken ){
nScore += aSeen[ip] ? 1000 : 1;
aSeen[ip] = 1;
if( iFinal>iLast ) iLast = iFinal;
}
}
if( rc==SQLITE_OK && sFinder.nFirst && nDocsize>nToken ){
for(jj=0; jj<(sFinder.nFirst-1); jj++){
if( sFinder.aFirst[jj+1]>io ) break;
}
if( sFinder.aFirst[jj]<io ){
memset(aSeen, 0, nPhrase);
rc = fts5SnippetScore(pApi, pFts, nDocsize, aSeen, i,
sFinder.aFirst[jj], nToken, &nScore, 0
);
nScore += (sFinder.aFirst[jj]==0 ? 120 : 100);
if( rc==SQLITE_OK && nScore>nBestScore ){
nBestScore = nScore;
iBestCol = i;
iBestStart = sFinder.aFirst[jj];
nColSize = nDocsize;
}
}
}
if( rc==SQLITE_OK && nScore>nBestScore ){
iBestCol = iSnippetCol;
iBestStart = iStart;
iBestLast = iLast;
nBestScore = nScore;
}
}
}
if( rc==SQLITE_OK ){
rc = pApi->xColumnText(pFts, iBestCol, &ctx.zIn, &ctx.nIn);
}
if( rc==SQLITE_OK && nColSize==0 ){
rc = pApi->xColumnSize(pFts, iBestCol, &nColSize);
}
if( rc==SQLITE_OK ){
rc = pApi->xColumnText(pFts, iBestCol, &ctx.zIn, &ctx.nIn);
}
if( ctx.zIn ){
if( rc==SQLITE_OK ){
rc = fts5CInstIterInit(pApi, pFts, iBestCol, &ctx.iter);
}
if( (iBestStart+nToken-1)>iBestLast ){
iBestStart -= (iBestStart+nToken-1-iBestLast) / 2;
}
if( iBestStart+nToken>nColSize ){
iBestStart = nColSize - nToken;
}
if( iBestStart<0 ) iBestStart = 0;
ctx.iRangeStart = iBestStart;
ctx.iRangeEnd = iBestStart + nToken - 1;
if( iBestStart>0 ){
fts5HighlightAppend(&rc, &ctx, zEllips, -1);
}
/* Advance iterator ctx.iter so that it points to the first coalesced
** phrase instance at or following position iBestStart. */
while( ctx.iter.iStart>=0 && ctx.iter.iStart<iBestStart && rc==SQLITE_OK ){
rc = fts5CInstIterNext(&ctx.iter);
}
if( rc==SQLITE_OK ){
rc = pApi->xTokenize(pFts, ctx.zIn, ctx.nIn, (void*)&ctx,fts5HighlightCb);
}
@@ -510,15 +358,15 @@ static void fts5SnippetFunction(
}else{
fts5HighlightAppend(&rc, &ctx, zEllips, -1);
}
if( rc==SQLITE_OK ){
sqlite3_result_text(pCtx, (const char*)ctx.zOut, -1, SQLITE_TRANSIENT);
}else{
sqlite3_result_error_code(pCtx, rc);
}
sqlite3_free(ctx.zOut);
}
if( rc==SQLITE_OK ){
sqlite3_result_text(pCtx, (const char*)ctx.zOut, -1, SQLITE_TRANSIENT);
}else{
sqlite3_result_error_code(pCtx, rc);
}
sqlite3_free(ctx.zOut);
sqlite3_free(aSeen);
sqlite3_free(sFinder.aFirst);
}
/************************************************************************/
+5 -7
View File
@@ -67,11 +67,9 @@ void sqlite3Fts5BufferAppendBlob(
const u8 *pData
){
assert_nc( *pRc || nData>=0 );
if( nData ){
if( fts5BufferGrow(pRc, pBuf, nData) ) return;
memcpy(&pBuf->p[pBuf->n], pData, nData);
pBuf->n += nData;
}
if( fts5BufferGrow(pRc, pBuf, nData) ) return;
memcpy(&pBuf->p[pBuf->n], pData, nData);
pBuf->n += nData;
}
/*
@@ -248,8 +246,8 @@ void *sqlite3Fts5MallocZero(int *pRc, int nByte){
void *pRet = 0;
if( *pRc==SQLITE_OK ){
pRet = sqlite3_malloc(nByte);
if( pRet==0 ){
if( nByte>0 ) *pRc = SQLITE_NOMEM;
if( pRet==0 && nByte>0 ){
*pRc = SQLITE_NOMEM;
}else{
memset(pRet, 0, nByte);
}
+74 -259
View File
@@ -87,8 +87,7 @@ struct Fts5ExprNode {
** or term prefix.
*/
struct Fts5ExprTerm {
u8 bPrefix; /* True for a prefix term */
u8 bFirst; /* True if token must be first in column */
int bPrefix; /* True for a prefix term */
char *zTerm; /* nul-terminated term */
Fts5IndexIter *pIter; /* Iterator for this term */
Fts5ExprTerm *pSynonym; /* Pointer to first in list of synonyms */
@@ -168,8 +167,6 @@ static int fts5ExprGetToken(
case ',': tok = FTS5_COMMA; break;
case '+': tok = FTS5_PLUS; break;
case '*': tok = FTS5_STAR; break;
case '-': tok = FTS5_MINUS; break;
case '^': tok = FTS5_CARET; break;
case '\0': tok = FTS5_EOF; break;
case '"': {
@@ -215,7 +212,6 @@ static void fts5ParseFree(void *p){ sqlite3_free(p); }
int sqlite3Fts5ExprNew(
Fts5Config *pConfig, /* FTS5 Configuration */
int iCol,
const char *zExpr, /* Expression text */
Fts5Expr **ppNew,
char **pzErr
@@ -240,18 +236,6 @@ int sqlite3Fts5ExprNew(
}while( sParse.rc==SQLITE_OK && t!=FTS5_EOF );
sqlite3Fts5ParserFree(pEngine, fts5ParseFree);
/* If the LHS of the MATCH expression was a user column, apply the
** implicit column-filter. */
if( iCol<pConfig->nCol && sParse.pExpr && sParse.rc==SQLITE_OK ){
int n = sizeof(Fts5Colset);
Fts5Colset *pColset = (Fts5Colset*)sqlite3Fts5MallocZero(&sParse.rc, n);
if( pColset ){
pColset->nCol = 1;
pColset->aiCol[0] = iCol;
sqlite3Fts5ParseSetColset(&sParse, sParse.pExpr, pColset);
}
}
assert( sParse.rc!=SQLITE_OK || sParse.zErr==0 );
if( sParse.rc==SQLITE_OK ){
*ppNew = pNew = sqlite3_malloc(sizeof(Fts5Expr));
@@ -429,7 +413,6 @@ static int fts5ExprPhraseIsMatch(
Fts5PoslistReader *aIter = aStatic;
int i;
int rc = SQLITE_OK;
int bFirst = pPhrase->aTerm[0].bFirst;
fts5BufferZero(&pPhrase->poslist);
@@ -484,10 +467,8 @@ static int fts5ExprPhraseIsMatch(
}while( bMatch==0 );
/* Append position iPos to the output */
if( bFirst==0 || FTS5_POS2OFFSET(iPos)==0 ){
rc = sqlite3Fts5PoslistWriterAppend(&pPhrase->poslist, &writer, iPos);
if( rc!=SQLITE_OK ) goto ismatch_out;
}
rc = sqlite3Fts5PoslistWriterAppend(&pPhrase->poslist, &writer, iPos);
if( rc!=SQLITE_OK ) goto ismatch_out;
for(i=0; i<pPhrase->nTerm; i++){
if( sqlite3Fts5PoslistReaderNext(&aIter[i]) ) goto ismatch_out;
@@ -741,9 +722,7 @@ static int fts5ExprNearTest(
** phrase is not a match, break out of the loop early. */
for(i=0; rc==SQLITE_OK && i<pNear->nPhrase; i++){
Fts5ExprPhrase *pPhrase = pNear->apPhrase[i];
if( pPhrase->nTerm>1 || pPhrase->aTerm[0].pSynonym
|| pNear->pColset || pPhrase->aTerm[0].bFirst
){
if( pPhrase->nTerm>1 || pPhrase->aTerm[0].pSynonym || pNear->pColset ){
int bMatch = 0;
rc = fts5ExprPhraseIsMatch(pNode, pPhrase, &bMatch);
if( bMatch==0 ) break;
@@ -766,61 +745,49 @@ static int fts5ExprNearTest(
** Initialize all term iterators in the pNear object. If any term is found
** to match no documents at all, return immediately without initializing any
** further iterators.
**
** If an error occurs, return an SQLite error code. Otherwise, return
** SQLITE_OK. It is not considered an error if some term matches zero
** documents.
*/
static int fts5ExprNearInitAll(
Fts5Expr *pExpr,
Fts5ExprNode *pNode
){
Fts5ExprNearset *pNear = pNode->pNear;
int i;
int i, j;
int rc = SQLITE_OK;
assert( pNode->bNomatch==0 );
for(i=0; i<pNear->nPhrase; i++){
for(i=0; rc==SQLITE_OK && i<pNear->nPhrase; i++){
Fts5ExprPhrase *pPhrase = pNear->apPhrase[i];
if( pPhrase->nTerm==0 ){
pNode->bEof = 1;
return SQLITE_OK;
}else{
int j;
for(j=0; j<pPhrase->nTerm; j++){
Fts5ExprTerm *pTerm = &pPhrase->aTerm[j];
Fts5ExprTerm *p;
int bHit = 0;
for(j=0; j<pPhrase->nTerm; j++){
Fts5ExprTerm *pTerm = &pPhrase->aTerm[j];
Fts5ExprTerm *p;
int bEof = 1;
for(p=pTerm; p; p=p->pSynonym){
int rc;
if( p->pIter ){
sqlite3Fts5IterClose(p->pIter);
p->pIter = 0;
}
rc = sqlite3Fts5IndexQuery(
pExpr->pIndex, p->zTerm, (int)strlen(p->zTerm),
(pTerm->bPrefix ? FTS5INDEX_QUERY_PREFIX : 0) |
(pExpr->bDesc ? FTS5INDEX_QUERY_DESC : 0),
pNear->pColset,
&p->pIter
);
assert( (rc==SQLITE_OK)==(p->pIter!=0) );
if( rc!=SQLITE_OK ) return rc;
if( 0==sqlite3Fts5IterEof(p->pIter) ){
bHit = 1;
}
for(p=pTerm; p && rc==SQLITE_OK; p=p->pSynonym){
if( p->pIter ){
sqlite3Fts5IterClose(p->pIter);
p->pIter = 0;
}
rc = sqlite3Fts5IndexQuery(
pExpr->pIndex, p->zTerm, (int)strlen(p->zTerm),
(pTerm->bPrefix ? FTS5INDEX_QUERY_PREFIX : 0) |
(pExpr->bDesc ? FTS5INDEX_QUERY_DESC : 0),
pNear->pColset,
&p->pIter
);
assert( rc==SQLITE_OK || p->pIter==0 );
if( p->pIter && 0==sqlite3Fts5IterEof(p->pIter) ){
bEof = 0;
}
}
if( bHit==0 ){
pNode->bEof = 1;
return SQLITE_OK;
}
if( bEof ){
pNode->bEof = 1;
return rc;
}
}
}
pNode->bEof = 0;
return SQLITE_OK;
return rc;
}
/*
@@ -924,7 +891,6 @@ static int fts5ExprNodeTest_STRING(
assert( pNear->nPhrase>1
|| pNear->apPhrase[0]->nTerm>1
|| pNear->apPhrase[0]->aTerm[0].pSynonym
|| pNear->apPhrase[0]->aTerm[0].bFirst
);
/* Initialize iLast, the "lastest" rowid any iterator points to. If the
@@ -954,7 +920,7 @@ static int fts5ExprNodeTest_STRING(
}
}else{
Fts5IndexIter *pIter = pPhrase->aTerm[j].pIter;
if( pIter->iRowid==iLast || pIter->bEof ) continue;
if( pIter->iRowid==iLast ) continue;
bMatch = 0;
if( fts5ExprAdvanceto(pIter, bDesc, &iLast, &rc, &pNode->bEof) ){
return rc;
@@ -1131,10 +1097,7 @@ static int fts5ExprNodeNext_OR(
|| (bFromValid && fts5RowidCmp(pExpr, p1->iRowid, iFrom)<0)
){
int rc = fts5ExprNodeNext(pExpr, p1, bFromValid, iFrom);
if( rc!=SQLITE_OK ){
pNode->bNomatch = 0;
return rc;
}
if( rc!=SQLITE_OK ) return rc;
}
}
}
@@ -1165,10 +1128,7 @@ static int fts5ExprNodeTest_AND(
if( cmp>0 ){
/* Advance pChild until it points to iLast or laster */
rc = fts5ExprNodeNext(pExpr, pChild, 1, iLast);
if( rc!=SQLITE_OK ){
pAnd->bNomatch = 0;
return rc;
}
if( rc!=SQLITE_OK ) return rc;
}
/* If the child node is now at EOF, so is the parent AND node. Otherwise,
@@ -1207,8 +1167,6 @@ static int fts5ExprNodeNext_AND(
int rc = fts5ExprNodeNext(pExpr, pNode->apChild[0], bFromValid, iFrom);
if( rc==SQLITE_OK ){
rc = fts5ExprNodeTest_AND(pExpr, pNode);
}else{
pNode->bNomatch = 0;
}
return rc;
}
@@ -1251,9 +1209,6 @@ static int fts5ExprNodeNext_NOT(
if( rc==SQLITE_OK ){
rc = fts5ExprNodeTest_NOT(pExpr, pNode);
}
if( rc!=SQLITE_OK ){
pNode->bNomatch = 0;
}
return rc;
}
@@ -1376,10 +1331,7 @@ int sqlite3Fts5ExprFirst(Fts5Expr *p, Fts5Index *pIdx, i64 iFirst, int bDesc){
/* If not at EOF but the current rowid occurs earlier than iFirst in
** the iteration order, move to document iFirst or later. */
if( rc==SQLITE_OK
&& 0==pRoot->bEof
&& fts5RowidCmp(p, pRoot->iRowid, iFirst)<0
){
if( pRoot->bEof==0 && fts5RowidCmp(p, pRoot->iRowid, iFirst)<0 ){
rc = fts5ExprNodeNext(p, pRoot, 1, iFirst);
}
@@ -1449,16 +1401,6 @@ static void fts5ExprPhraseFree(Fts5ExprPhrase *pPhrase){
}
}
/*
** Set the "bFirst" flag on the first token of the phrase passed as the
** only argument.
*/
void sqlite3Fts5ParseSetCaret(Fts5ExprPhrase *pPhrase){
if( pPhrase && pPhrase->nTerm ){
pPhrase->aTerm[0].bFirst = 1;
}
}
/*
** If argument pNear is NULL, then a new Fts5ExprNearset object is allocated
** and populated with pPhrase. Or, if pNear is not NULL, phrase pPhrase is
@@ -1643,7 +1585,7 @@ Fts5ExprPhrase *sqlite3Fts5ParseTerm(
rc = fts5ParseStringFromToken(pToken, &z);
if( rc==SQLITE_OK ){
int flags = FTS5_TOKENIZE_QUERY | (bPrefix ? FTS5_TOKENIZE_PREFIX : 0);
int flags = FTS5_TOKENIZE_QUERY | (bPrefix ? FTS5_TOKENIZE_QUERY : 0);
int n;
sqlite3Fts5Dequote(z);
n = (int)strlen(z);
@@ -1676,7 +1618,7 @@ Fts5ExprPhrase *sqlite3Fts5ParseTerm(
** no token characters at all. (e.g ... MATCH '""'). */
sCtx.pPhrase = sqlite3Fts5MallocZero(&pParse->rc, sizeof(Fts5ExprPhrase));
}else if( sCtx.pPhrase->nTerm ){
sCtx.pPhrase->aTerm[sCtx.pPhrase->nTerm-1].bPrefix = (u8)bPrefix;
sCtx.pPhrase->aTerm[sCtx.pPhrase->nTerm-1].bPrefix = bPrefix;
}
pParse->apPhrase[pParse->nPhrase-1] = sCtx.pPhrase;
}
@@ -1695,6 +1637,7 @@ int sqlite3Fts5ExprClonePhrase(
){
int rc = SQLITE_OK; /* Return code */
Fts5ExprPhrase *pOrig; /* The phrase extracted from pExpr */
int i; /* Used to iterate through phrase terms */
Fts5Expr *pNew = 0; /* Expression to return via *ppNew */
TokenCtx sCtx = {0,0}; /* Context object for fts5ParseTokenize */
@@ -1715,7 +1658,7 @@ int sqlite3Fts5ExprClonePhrase(
if( rc==SQLITE_OK ){
Fts5Colset *pColsetOrig = pOrig->pNode->pNear->pColset;
if( pColsetOrig ){
int nByte = sizeof(Fts5Colset) + (pColsetOrig->nCol-1) * sizeof(int);
int nByte = sizeof(Fts5Colset) + pColsetOrig->nCol * sizeof(int);
Fts5Colset *pColset = (Fts5Colset*)sqlite3Fts5MallocZero(&rc, nByte);
if( pColset ){
memcpy(pColset, pColsetOrig, nByte);
@@ -1724,26 +1667,18 @@ int sqlite3Fts5ExprClonePhrase(
}
}
if( pOrig->nTerm ){
int i; /* Used to iterate through phrase terms */
for(i=0; rc==SQLITE_OK && i<pOrig->nTerm; i++){
int tflags = 0;
Fts5ExprTerm *p;
for(p=&pOrig->aTerm[i]; p && rc==SQLITE_OK; p=p->pSynonym){
const char *zTerm = p->zTerm;
rc = fts5ParseTokenize((void*)&sCtx, tflags, zTerm, (int)strlen(zTerm),
0, 0);
tflags = FTS5_TOKEN_COLOCATED;
}
if( rc==SQLITE_OK ){
sCtx.pPhrase->aTerm[i].bPrefix = pOrig->aTerm[i].bPrefix;
sCtx.pPhrase->aTerm[i].bFirst = pOrig->aTerm[i].bFirst;
}
for(i=0; rc==SQLITE_OK && i<pOrig->nTerm; i++){
int tflags = 0;
Fts5ExprTerm *p;
for(p=&pOrig->aTerm[i]; p && rc==SQLITE_OK; p=p->pSynonym){
const char *zTerm = p->zTerm;
rc = fts5ParseTokenize((void*)&sCtx, tflags, zTerm, (int)strlen(zTerm),
0, 0);
tflags = FTS5_TOKEN_COLOCATED;
}
if( rc==SQLITE_OK ){
sCtx.pPhrase->aTerm[i].bPrefix = pOrig->aTerm[i].bPrefix;
}
}else{
/* This happens when parsing a token or quoted phrase that contains
** no token characters at all. (e.g ... MATCH '""'). */
sCtx.pPhrase = sqlite3Fts5MallocZero(&rc, sizeof(Fts5ExprPhrase));
}
if( rc==SQLITE_OK ){
@@ -1756,10 +1691,7 @@ int sqlite3Fts5ExprClonePhrase(
pNew->pRoot->pNear->nPhrase = 1;
sCtx.pPhrase->pNode = pNew->pRoot;
if( pOrig->nTerm==1
&& pOrig->aTerm[0].pSynonym==0
&& pOrig->aTerm[0].bFirst==0
){
if( pOrig->nTerm==1 && pOrig->aTerm[0].pSynonym==0 ){
pNew->pRoot->eType = FTS5_TERM;
pNew->pRoot->xNext = fts5ExprNodeNext_TERM;
}else{
@@ -1861,34 +1793,6 @@ static Fts5Colset *fts5ParseColset(
return pNew;
}
/*
** Allocate and return an Fts5Colset object specifying the inverse of
** the colset passed as the second argument. Free the colset passed
** as the second argument before returning.
*/
Fts5Colset *sqlite3Fts5ParseColsetInvert(Fts5Parse *pParse, Fts5Colset *p){
Fts5Colset *pRet;
int nCol = pParse->pConfig->nCol;
pRet = (Fts5Colset*)sqlite3Fts5MallocZero(&pParse->rc,
sizeof(Fts5Colset) + sizeof(int)*nCol
);
if( pRet ){
int i;
int iOld = 0;
for(i=0; i<nCol; i++){
if( iOld>=p->nCol || p->aiCol[iOld]!=i ){
pRet->aiCol[pRet->nCol++] = i;
}else{
iOld++;
}
}
}
sqlite3_free(p);
return pRet;
}
Fts5Colset *sqlite3Fts5ParseColset(
Fts5Parse *pParse, /* Store SQLITE_NOMEM here if required */
Fts5Colset *pColset, /* Existing colset object */
@@ -1921,110 +1825,25 @@ Fts5Colset *sqlite3Fts5ParseColset(
return pRet;
}
/*
** If argument pOrig is NULL, or if (*pRc) is set to anything other than
** SQLITE_OK when this function is called, NULL is returned.
**
** Otherwise, a copy of (*pOrig) is made into memory obtained from
** sqlite3Fts5MallocZero() and a pointer to it returned. If the allocation
** fails, (*pRc) is set to SQLITE_NOMEM and NULL is returned.
*/
static Fts5Colset *fts5CloneColset(int *pRc, Fts5Colset *pOrig){
Fts5Colset *pRet;
if( pOrig ){
int nByte = sizeof(Fts5Colset) + (pOrig->nCol-1) * sizeof(int);
pRet = (Fts5Colset*)sqlite3Fts5MallocZero(pRc, nByte);
if( pRet ){
memcpy(pRet, pOrig, nByte);
}
}else{
pRet = 0;
}
return pRet;
}
/*
** Remove from colset pColset any columns that are not also in colset pMerge.
*/
static void fts5MergeColset(Fts5Colset *pColset, Fts5Colset *pMerge){
int iIn = 0; /* Next input in pColset */
int iMerge = 0; /* Next input in pMerge */
int iOut = 0; /* Next output slot in pColset */
while( iIn<pColset->nCol && iMerge<pMerge->nCol ){
int iDiff = pColset->aiCol[iIn] - pMerge->aiCol[iMerge];
if( iDiff==0 ){
pColset->aiCol[iOut++] = pMerge->aiCol[iMerge];
iMerge++;
iIn++;
}else if( iDiff>0 ){
iMerge++;
}else{
iIn++;
}
}
pColset->nCol = iOut;
}
/*
** Recursively apply colset pColset to expression node pNode and all of
** its decendents. If (*ppFree) is not NULL, it contains a spare copy
** of pColset. This function may use the spare copy and set (*ppFree) to
** zero, or it may create copies of pColset using fts5CloneColset().
*/
static void fts5ParseSetColset(
Fts5Parse *pParse,
Fts5ExprNode *pNode,
Fts5Colset *pColset,
Fts5Colset **ppFree
){
if( pParse->rc==SQLITE_OK ){
assert( pNode->eType==FTS5_TERM || pNode->eType==FTS5_STRING
|| pNode->eType==FTS5_AND || pNode->eType==FTS5_OR
|| pNode->eType==FTS5_NOT || pNode->eType==FTS5_EOF
);
if( pNode->eType==FTS5_STRING || pNode->eType==FTS5_TERM ){
Fts5ExprNearset *pNear = pNode->pNear;
if( pNear->pColset ){
fts5MergeColset(pNear->pColset, pColset);
if( pNear->pColset->nCol==0 ){
pNode->eType = FTS5_EOF;
pNode->xNext = 0;
}
}else if( *ppFree ){
pNear->pColset = pColset;
*ppFree = 0;
}else{
pNear->pColset = fts5CloneColset(&pParse->rc, pColset);
}
}else{
int i;
assert( pNode->eType!=FTS5_EOF || pNode->nChild==0 );
for(i=0; i<pNode->nChild; i++){
fts5ParseSetColset(pParse, pNode->apChild[i], pColset, ppFree);
}
}
}
}
/*
** Apply colset pColset to expression node pExpr and all of its descendents.
*/
void sqlite3Fts5ParseSetColset(
Fts5Parse *pParse,
Fts5ExprNode *pExpr,
Fts5ExprNearset *pNear,
Fts5Colset *pColset
){
Fts5Colset *pFree = pColset;
if( pParse->pConfig->eDetail==FTS5_DETAIL_NONE ){
pParse->rc = SQLITE_ERROR;
pParse->zErr = sqlite3_mprintf(
"fts5: column queries are not supported (detail=none)"
);
}else{
fts5ParseSetColset(pParse, pExpr, pColset, &pFree);
sqlite3_free(pColset);
return;
}
if( pNear ){
pNear->pColset = pColset;
}else{
sqlite3_free(pColset);
}
sqlite3_free(pFree);
}
static void fts5ExprAssignXNext(Fts5ExprNode *pNode){
@@ -2033,7 +1852,6 @@ static void fts5ExprAssignXNext(Fts5ExprNode *pNode){
Fts5ExprNearset *pNear = pNode->pNear;
if( pNear->nPhrase==1 && pNear->apPhrase[0]->nTerm==1
&& pNear->apPhrase[0]->aTerm[0].pSynonym==0
&& pNear->apPhrase[0]->aTerm[0].bFirst==0
){
pNode->eType = FTS5_TERM;
pNode->xNext = fts5ExprNodeNext_TERM;
@@ -2120,23 +1938,20 @@ Fts5ExprNode *sqlite3Fts5ParseNode(
}
}
if( pParse->pConfig->eDetail!=FTS5_DETAIL_FULL ){
Fts5ExprPhrase *pPhrase = pNear->apPhrase[0];
if( pNear->nPhrase!=1
|| pPhrase->nTerm>1
|| (pPhrase->nTerm>0 && pPhrase->aTerm[0].bFirst)
){
assert( pParse->rc==SQLITE_OK );
pParse->rc = SQLITE_ERROR;
assert( pParse->zErr==0 );
pParse->zErr = sqlite3_mprintf(
"fts5: %s queries are not supported (detail!=full)",
pNear->nPhrase==1 ? "phrase": "NEAR"
);
sqlite3_free(pRet);
pRet = 0;
}
if( pParse->pConfig->eDetail!=FTS5_DETAIL_FULL
&& (pNear->nPhrase!=1 || pNear->apPhrase[0]->nTerm>1)
){
assert( pParse->rc==SQLITE_OK );
pParse->rc = SQLITE_ERROR;
assert( pParse->zErr==0 );
pParse->zErr = sqlite3_mprintf(
"fts5: %s queries are not supported (detail!=full)",
pNear->nPhrase==1 ? "phrase": "NEAR"
);
sqlite3_free(pRet);
pRet = 0;
}
}else{
fts5ExprAddChildren(pRet, pLeft);
fts5ExprAddChildren(pRet, pRight);
@@ -2482,7 +2297,7 @@ static void fts5ExprFunction(
rc = sqlite3Fts5ConfigParse(pGlobal, db, nConfig, azConfig, &pConfig, &zErr);
if( rc==SQLITE_OK ){
rc = sqlite3Fts5ExprNew(pConfig, pConfig->nCol, zExpr, &pExpr, &zErr);
rc = sqlite3Fts5ExprNew(pConfig, zExpr, &pExpr, &zErr);
}
if( rc==SQLITE_OK ){
char *zText;
+29 -39
View File
@@ -36,10 +36,9 @@ struct Fts5Hash {
/*
** Each entry in the hash table is represented by an object of the
** following type. Each object, its key (a nul-terminated string) and
** its current data are stored in a single memory allocation. The
** key immediately follows the object in memory. The position list
** data immediately follows the key data in memory.
** following type. Each object, its key (zKey[]) and its current data
** are stored in a single memory allocation. The position list data
** immediately follows the key data in memory.
**
** The data that follows the key is in a similar, but not identical format
** to the doclist data stored in the database. It is:
@@ -63,20 +62,20 @@ struct Fts5HashEntry {
int nAlloc; /* Total size of allocation */
int iSzPoslist; /* Offset of space for 4-byte poslist size */
int nData; /* Total bytes of data (incl. structure) */
int nKey; /* Length of key in bytes */
int nKey; /* Length of zKey[] in bytes */
u8 bDel; /* Set delete-flag @ iSzPoslist */
u8 bContent; /* Set content-flag (detail=none mode) */
i16 iCol; /* Column of last value written */
int iPos; /* Position of last value written */
i64 iRowid; /* Rowid of last value written */
char zKey[8]; /* Nul-terminated entry key */
};
/*
** Eqivalent to:
**
** char *fts5EntryKey(Fts5HashEntry *pEntry){ return zKey; }
** Size of Fts5HashEntry without the zKey[] array.
*/
#define fts5EntryKey(p) ( ((char *)(&(p)[1])) )
#define FTS5_HASHENTRYSIZE (sizeof(Fts5HashEntry)-8)
/*
@@ -171,11 +170,10 @@ static int fts5HashResize(Fts5Hash *pHash){
for(i=0; i<pHash->nSlot; i++){
while( apOld[i] ){
unsigned int iHash;
int iHash;
Fts5HashEntry *p = apOld[i];
apOld[i] = p->pHashNext;
iHash = fts5HashKey(nNew, (u8*)fts5EntryKey(p),
(int)strlen(fts5EntryKey(p)));
iHash = fts5HashKey(nNew, (u8*)p->zKey, (int)strlen(p->zKey));
p->pHashNext = apNew[iHash];
apNew[iHash] = p;
}
@@ -246,10 +244,9 @@ int sqlite3Fts5HashWrite(
/* Attempt to locate an existing hash entry */
iHash = fts5HashKey2(pHash->nSlot, (u8)bByte, (const u8*)pToken, nToken);
for(p=pHash->aSlot[iHash]; p; p=p->pHashNext){
char *zKey = fts5EntryKey(p);
if( zKey[0]==bByte
if( p->zKey[0]==bByte
&& p->nKey==nToken
&& memcmp(&zKey[1], pToken, nToken)==0
&& memcmp(&p->zKey[1], pToken, nToken)==0
){
break;
}
@@ -258,8 +255,7 @@ int sqlite3Fts5HashWrite(
/* If an existing hash entry cannot be found, create a new one. */
if( p==0 ){
/* Figure out how much space to allocate */
char *zKey;
int nByte = sizeof(Fts5HashEntry) + (nToken+1) + 1 + 64;
int nByte = FTS5_HASHENTRYSIZE + (nToken+1) + 1 + 64;
if( nByte<128 ) nByte = 128;
/* Grow the Fts5Hash.aSlot[] array if necessary. */
@@ -272,15 +268,14 @@ int sqlite3Fts5HashWrite(
/* Allocate new Fts5HashEntry and add it to the hash table. */
p = (Fts5HashEntry*)sqlite3_malloc(nByte);
if( !p ) return SQLITE_NOMEM;
memset(p, 0, sizeof(Fts5HashEntry));
memset(p, 0, FTS5_HASHENTRYSIZE);
p->nAlloc = nByte;
zKey = fts5EntryKey(p);
zKey[0] = bByte;
memcpy(&zKey[1], pToken, nToken);
assert( iHash==fts5HashKey(pHash->nSlot, (u8*)zKey, nToken+1) );
p->zKey[0] = bByte;
memcpy(&p->zKey[1], pToken, nToken);
assert( iHash==fts5HashKey(pHash->nSlot, (u8*)p->zKey, nToken+1) );
p->nKey = nToken;
zKey[nToken+1] = '\0';
p->nData = nToken+1 + 1 + sizeof(Fts5HashEntry);
p->zKey[nToken+1] = '\0';
p->nData = nToken+1 + 1 + FTS5_HASHENTRYSIZE;
p->pHashNext = pHash->aSlot[iHash];
pHash->aSlot[iHash] = p;
pHash->nEntry++;
@@ -398,11 +393,9 @@ static Fts5HashEntry *fts5HashEntryMerge(
p1 = 0;
}else{
int i = 0;
char *zKey1 = fts5EntryKey(p1);
char *zKey2 = fts5EntryKey(p2);
while( zKey1[i]==zKey2[i] ) i++;
while( p1->zKey[i]==p2->zKey[i] ) i++;
if( ((u8)zKey1[i])>((u8)zKey2[i]) ){
if( ((u8)p1->zKey[i])>((u8)p2->zKey[i]) ){
/* p2 is smaller */
*ppOut = p2;
ppOut = &p2->pScanNext;
@@ -445,7 +438,7 @@ static int fts5HashEntrySort(
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 || 0==memcmp(pIter->zKey, pTerm, nTerm) ){
Fts5HashEntry *pEntry = pIter;
pEntry->pScanNext = 0;
for(i=0; ap[i]; i++){
@@ -478,18 +471,16 @@ int sqlite3Fts5HashQuery(
int *pnDoclist /* OUT: Size of doclist in bytes */
){
unsigned int iHash = fts5HashKey(pHash->nSlot, (const u8*)pTerm, nTerm);
char *zKey = 0;
Fts5HashEntry *p;
for(p=pHash->aSlot[iHash]; p; p=p->pHashNext){
zKey = fts5EntryKey(p);
if( memcmp(zKey, pTerm, nTerm)==0 && zKey[nTerm]==0 ) break;
if( memcmp(p->zKey, pTerm, nTerm)==0 && p->zKey[nTerm]==0 ) break;
}
if( p ){
fts5HashAddPoslistSize(pHash, p);
*ppDoclist = (const u8*)&zKey[nTerm+1];
*pnDoclist = p->nData - (sizeof(Fts5HashEntry) + nTerm + 1);
*ppDoclist = (const u8*)&p->zKey[nTerm+1];
*pnDoclist = p->nData - (FTS5_HASHENTRYSIZE + nTerm + 1);
}else{
*ppDoclist = 0;
*pnDoclist = 0;
@@ -522,12 +513,11 @@ void sqlite3Fts5HashScanEntry(
){
Fts5HashEntry *p;
if( (p = pHash->pScan) ){
char *zKey = fts5EntryKey(p);
int nTerm = (int)strlen(zKey);
int nTerm = (int)strlen(p->zKey);
fts5HashAddPoslistSize(pHash, p);
*pzTerm = zKey;
*ppDoclist = (const u8*)&zKey[nTerm+1];
*pnDoclist = p->nData - (sizeof(Fts5HashEntry) + nTerm + 1);
*pzTerm = p->zKey;
*ppDoclist = (const u8*)&p->zKey[nTerm+1];
*pnDoclist = p->nData - (FTS5_HASHENTRYSIZE + nTerm + 1);
}else{
*pzTerm = 0;
*ppDoclist = 0;
+38 -82
View File
@@ -628,6 +628,7 @@ static void fts5CloseReader(Fts5Index *p){
}
}
/*
** Retrieve a record from the %_data table.
**
@@ -701,6 +702,7 @@ static Fts5Data *fts5DataRead(Fts5Index *p, i64 iRowid){
return pRet;
}
/*
** Release a reference to data record returned by an earlier call to
** fts5DataRead().
@@ -709,18 +711,6 @@ static void fts5DataRelease(Fts5Data *pData){
sqlite3_free(pData);
}
static Fts5Data *fts5LeafRead(Fts5Index *p, i64 iRowid){
Fts5Data *pRet = fts5DataRead(p, iRowid);
if( pRet ){
if( pRet->szLeaf>pRet->nn ){
p->rc = FTS5_CORRUPT;
fts5DataRelease(pRet);
pRet = 0;
}
}
return pRet;
}
static int fts5IndexPrepareStmt(
Fts5Index *p,
sqlite3_stmt **ppStmt,
@@ -728,8 +718,7 @@ 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);
p->rc = sqlite3_prepare_v2(p->pConfig->db, zSql, -1, ppStmt, 0);
}else{
p->rc = SQLITE_NOMEM;
}
@@ -758,7 +747,6 @@ static void fts5DataWrite(Fts5Index *p, i64 iRowid, const u8 *pData, int nData){
sqlite3_bind_blob(p->pWriter, 2, pData, nData, SQLITE_STATIC);
sqlite3_step(p->pWriter);
p->rc = sqlite3_reset(p->pWriter);
sqlite3_bind_null(p->pWriter, 2);
}
/*
@@ -779,8 +767,7 @@ static void fts5DataDelete(Fts5Index *p, i64 iFirst, i64 iLast){
if( zSql==0 ){
rc = SQLITE_NOMEM;
}else{
rc = sqlite3_prepare_v3(pConfig->db, zSql, -1,
SQLITE_PREPARE_PERSISTENT, &p->pDeleter, 0);
rc = sqlite3_prepare_v2(pConfig->db, zSql, -1, &p->pDeleter, 0);
sqlite3_free(zSql);
}
if( rc!=SQLITE_OK ){
@@ -1532,7 +1519,7 @@ static void fts5SegIterNextPage(
pIter->pLeaf = pIter->pNextLeaf;
pIter->pNextLeaf = 0;
}else if( pIter->iLeafPgno<=pSeg->pgnoLast ){
pIter->pLeaf = fts5LeafRead(p,
pIter->pLeaf = fts5DataRead(p,
FTS5_SEGMENT_ROWID(pSeg->iSegid, pIter->iLeafPgno)
);
}else{
@@ -2035,13 +2022,14 @@ static void fts5SegIterNext(
if( pLeaf->nn>pLeaf->szLeaf ){
pIter->iPgidxOff = pLeaf->szLeaf + fts5GetVarint32(
&pLeaf->p[pLeaf->szLeaf], pIter->iEndofDoclist
);
);
}
}
else if( pLeaf->nn>pLeaf->szLeaf ){
pIter->iPgidxOff = pLeaf->szLeaf + fts5GetVarint32(
&pLeaf->p[pLeaf->szLeaf], iOff
);
);
pIter->iLeafOffset = iOff;
pIter->iEndofDoclist = iOff;
bNewTerm = 1;
@@ -2075,7 +2063,6 @@ static void fts5SegIterNext(
*/
int nSz;
assert( p->rc==SQLITE_OK );
assert( pIter->iLeafOffset<=pIter->pLeaf->nn );
fts5FastGetVarint32(pIter->pLeaf->p, pIter->iLeafOffset, nSz);
pIter->bDel = (nSz & 0x0001);
pIter->nPos = nSz>>1;
@@ -2282,11 +2269,6 @@ static void fts5LeafSeek(
iTermOff += nKeep;
iOff = iTermOff;
if( iOff>=n ){
p->rc = FTS5_CORRUPT;
return;
}
/* Read the nKeep field of the next term. */
fts5FastGetVarint32(a, iOff, nKeep);
}
@@ -2387,7 +2369,6 @@ static void fts5SegIterSeekInit(
bDlidx = (val & 0x0001);
}
p->rc = sqlite3_reset(pIdxSelect);
sqlite3_bind_null(pIdxSelect, 2);
if( iPg<pSeg->pgnoFirst ){
iPg = pSeg->pgnoFirst;
@@ -2844,7 +2825,6 @@ static void fts5MultiIterNext(
i64 iFrom /* Advance at least as far as this */
){
int bUseFrom = bFrom;
assert( pIter->base.bEof==0 );
while( p->rc==SQLITE_OK ){
int iFirst = pIter->aFirst[1].iFirst;
int bNewTerm = 0;
@@ -2882,8 +2862,7 @@ static void fts5MultiIterNext2(
){
assert( pIter->bSkipEmpty );
if( p->rc==SQLITE_OK ){
*pbNewTerm = 0;
do{
do {
int iFirst = pIter->aFirst[1].iFirst;
Fts5SegIter *pSeg = &pIter->aSeg[iFirst];
int bNewTerm = 0;
@@ -2896,6 +2875,8 @@ static void fts5MultiIterNext2(
fts5MultiIterAdvanced(p, pIter, iFirst, 1);
fts5MultiIterSetEof(pIter);
*pbNewTerm = 1;
}else{
*pbNewTerm = 0;
}
fts5AssertMultiIterSetup(p, pIter);
@@ -3070,7 +3051,7 @@ static void fts5ChunkIterate(
break;
}else{
pgno++;
pData = fts5LeafRead(p, FTS5_SEGMENT_ROWID(pSeg->pSeg->iSegid, pgno));
pData = fts5DataRead(p, FTS5_SEGMENT_ROWID(pSeg->pSeg->iSegid, pgno));
if( pData==0 ) break;
pChunk = &pData->p[4];
nChunk = MIN(nRem, pData->szLeaf - 4);
@@ -3161,23 +3142,23 @@ static int fts5IndexExtractCol(
return p - (*pa);
}
static void fts5IndexExtractColset(
int *pRc,
static int fts5IndexExtractColset (
Fts5Colset *pColset, /* Colset to filter on */
const u8 *pPos, int nPos, /* Position list */
Fts5Buffer *pBuf /* Output buffer */
){
if( *pRc==SQLITE_OK ){
int i;
fts5BufferZero(pBuf);
for(i=0; i<pColset->nCol; i++){
const u8 *pSub = pPos;
int nSub = fts5IndexExtractCol(&pSub, nPos, pColset->aiCol[i]);
if( nSub ){
fts5BufferAppendBlob(pRc, pBuf, nSub, pSub);
}
int rc = SQLITE_OK;
int i;
fts5BufferZero(pBuf);
for(i=0; i<pColset->nCol; i++){
const u8 *pSub = pPos;
int nSub = fts5IndexExtractCol(&pSub, nPos, pColset->aiCol[i]);
if( nSub ){
fts5BufferAppendBlob(&rc, pBuf, nSub, pSub);
}
}
return rc;
}
/*
@@ -3214,15 +3195,6 @@ static void fts5IterSetOutputs_Nocolset(Fts5Iter *pIter, Fts5SegIter *pSeg){
}
}
/*
** xSetOutputs callback used when the Fts5Colset object has nCol==0 (match
** against no columns at all).
*/
static void fts5IterSetOutputs_ZeroColset(Fts5Iter *pIter, Fts5SegIter *pSeg){
UNUSED_PARAM(pSeg);
pIter->base.nData = 0;
}
/*
** xSetOutputs callback used by detail=col when there is a column filter
** and there are 100 or more columns. Also called as a fallback from
@@ -3301,9 +3273,8 @@ static void fts5IterSetOutputs_Full(Fts5Iter *pIter, Fts5SegIter *pSeg){
pIter->base.nData = fts5IndexExtractCol(&a, pSeg->nPos,pColset->aiCol[0]);
pIter->base.pData = a;
}else{
int *pRc = &pIter->pIndex->rc;
fts5BufferZero(&pIter->poslist);
fts5IndexExtractColset(pRc, pColset, a, pSeg->nPos, &pIter->poslist);
fts5IndexExtractColset(pColset, a, pSeg->nPos, &pIter->poslist);
pIter->base.pData = pIter->poslist.p;
pIter->base.nData = pIter->poslist.n;
}
@@ -3329,10 +3300,6 @@ static void fts5IterSetOutputCb(int *pRc, Fts5Iter *pIter){
pIter->xSetOutputs = fts5IterSetOutputs_Nocolset;
}
else if( pIter->pColset->nCol==0 ){
pIter->xSetOutputs = fts5IterSetOutputs_ZeroColset;
}
else if( pConfig->eDetail==FTS5_DETAIL_FULL ){
pIter->xSetOutputs = fts5IterSetOutputs_Full;
}
@@ -3600,7 +3567,6 @@ static int fts5AllocateSegid(Fts5Index *p, Fts5Structure *pStruct){
sqlite3_bind_blob(pIdxSelect, 2, aBlob, 2, SQLITE_STATIC);
assert( sqlite3_step(pIdxSelect)!=SQLITE_ROW );
p->rc = sqlite3_reset(pIdxSelect);
sqlite3_bind_null(pIdxSelect, 2);
}
}
#endif
@@ -3727,7 +3693,6 @@ static void fts5WriteFlushBtree(Fts5Index *p, Fts5SegWriter *pWriter){
sqlite3_bind_int64(p->pIdxWriter, 3, bFlag + ((i64)pWriter->iBtPage<<1));
sqlite3_step(p->pIdxWriter);
p->rc = sqlite3_reset(p->pIdxWriter);
sqlite3_bind_null(p->pIdxWriter, 2);
}
pWriter->iBtPage = 0;
}
@@ -3850,6 +3815,9 @@ static void fts5WriteFlushLeaf(Fts5Index *p, Fts5SegWriter *pWriter){
Fts5PageWriter *pPage = &pWriter->writer;
i64 iRowid;
static int nCall = 0;
nCall++;
assert( (pPage->pgidx.n==0)==(pWriter->bFirstTermInPage) );
/* Set the szLeaf header field. */
@@ -4198,7 +4166,6 @@ static void fts5IndexMergeLevel(
int bOldest; /* True if the output segment is the oldest */
int eDetail = p->pConfig->eDetail;
const int flags = FTS5INDEX_QUERY_NOOUTPUT;
int bTermWritten = 0; /* True if current term already output */
assert( iLvl<pStruct->nLevel );
assert( pLvl->nMerge<=pLvl->nSeg );
@@ -4252,22 +4219,18 @@ static void fts5IndexMergeLevel(
int nTerm;
const u8 *pTerm;
/* Check for key annihilation. */
if( pSegIter->nPos==0 && (bOldest || pSegIter->bDel==0) ) continue;
pTerm = fts5MultiIterTerm(pIter, &nTerm);
if( nTerm!=term.n || memcmp(pTerm, term.p, nTerm) ){
if( pnRem && writer.nLeafWritten>nRem ){
break;
}
fts5BufferSet(&p->rc, &term, nTerm, pTerm);
bTermWritten =0;
}
/* Check for key annihilation. */
if( pSegIter->nPos==0 && (bOldest || pSegIter->bDel==0) ) continue;
if( p->rc==SQLITE_OK && bTermWritten==0 ){
/* This is a new term. Append a term to the output segment. */
fts5WriteAppendTerm(p, &writer, nTerm, pTerm);
bTermWritten = 1;
fts5BufferSet(&p->rc, &term, nTerm, pTerm);
}
/* Append the rowid to the output */
@@ -4913,13 +4876,7 @@ static void fts5MergePrefixLists(
Fts5Buffer out = {0, 0, 0};
Fts5Buffer tmp = {0, 0, 0};
/* The maximum size of the output is equal to the sum of the two
** input sizes + 1 varint (9 bytes). The extra varint is because if the
** first rowid in one input is a large negative number, and the first in
** the other a non-negative number, the delta for the non-negative
** number will be larger on disk than the literal integer value
** was. */
if( sqlite3Fts5BufferSize(&p->rc, &out, p1->n + p2->n + 9) ) return;
if( sqlite3Fts5BufferSize(&p->rc, &out, p1->n + p2->n) ) return;
fts5DoclistIterInit(p1, &i1);
fts5DoclistIterInit(p2, &i2);
@@ -5013,7 +4970,6 @@ static void fts5MergePrefixLists(
fts5MergeAppendDocid(&out, iLastRowid, i2.iRowid);
fts5BufferSafeAppendBlob(&out, i2.aPoslist, i2.aEof - i2.aPoslist);
}
assert( out.n<=(p1->n+p2->n+9) );
fts5BufferSet(&p->rc, p1, out.n, out.p);
fts5BufferFree(&tmp);
@@ -5106,7 +5062,7 @@ static void fts5SetupPrefixIter(
if( pData ){
pData->p = (u8*)&pData[1];
pData->nn = pData->szLeaf = doclist.n;
if( doclist.n ) memcpy(pData->p, doclist.p, doclist.n);
memcpy(pData->p, doclist.p, doclist.n);
fts5MultiIterNew2(p, pData, bDesc, ppIter);
}
fts5BufferFree(&doclist);
@@ -5145,10 +5101,10 @@ int sqlite3Fts5IndexBeginWrite(Fts5Index *p, int bDelete, i64 iRowid){
/*
** Commit data to disk.
*/
int sqlite3Fts5IndexSync(Fts5Index *p){
int sqlite3Fts5IndexSync(Fts5Index *p, int bCommit){
assert( p->rc==SQLITE_OK );
fts5IndexFlush(p);
fts5CloseReader(p);
if( bCommit ) fts5CloseReader(p);
return fts5IndexReturn(p);
}
@@ -5345,7 +5301,7 @@ int sqlite3Fts5IndexQuery(
if( sqlite3Fts5BufferSize(&p->rc, &buf, nToken+1)==0 ){
int iIdx = 0; /* Index to search */
if( nToken ) memcpy(&buf.p[1], pToken, nToken);
memcpy(&buf.p[1], pToken, nToken);
/* Figure out which index to search and set iIdx accordingly. If this
** is a prefix query for which there is no prefix index, set iIdx to
@@ -5394,7 +5350,7 @@ int sqlite3Fts5IndexQuery(
}
if( p->rc ){
sqlite3Fts5IterClose((Fts5IndexIter*)pRet);
sqlite3Fts5IterClose(&pRet->base);
pRet = 0;
fts5CloseReader(p);
}
@@ -5844,7 +5800,7 @@ static void fts5IndexIntegrityCheckSegment(
** ignore this b-tree entry. Otherwise, load it into memory. */
if( iIdxLeaf<pSeg->pgnoFirst ) continue;
iRow = FTS5_SEGMENT_ROWID(pSeg->iSegid, iIdxLeaf);
pLeaf = fts5LeafRead(p, iRow);
pLeaf = fts5DataRead(p, iRow);
if( pLeaf==0 ) break;
/* Check that the leaf contains at least one term, and that it is equal
+26 -47
View File
@@ -506,7 +506,6 @@ static void fts5SetUniqueFlag(sqlite3_index_info *pIdxInfo){
static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
Fts5Table *pTab = (Fts5Table*)pVTab;
Fts5Config *pConfig = pTab->pConfig;
const int nCol = pConfig->nCol;
int idxFlags = 0; /* Parameter passed through to xFilter() */
int bHasMatch;
int iNext;
@@ -532,40 +531,24 @@ static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
int aColMap[3];
aColMap[0] = -1;
aColMap[1] = nCol;
aColMap[2] = nCol+1;
assert( SQLITE_INDEX_CONSTRAINT_EQ<SQLITE_INDEX_CONSTRAINT_MATCH );
assert( SQLITE_INDEX_CONSTRAINT_GT<SQLITE_INDEX_CONSTRAINT_MATCH );
assert( SQLITE_INDEX_CONSTRAINT_LE<SQLITE_INDEX_CONSTRAINT_MATCH );
assert( SQLITE_INDEX_CONSTRAINT_GE<SQLITE_INDEX_CONSTRAINT_MATCH );
assert( SQLITE_INDEX_CONSTRAINT_LE<SQLITE_INDEX_CONSTRAINT_MATCH );
aColMap[1] = pConfig->nCol;
aColMap[2] = pConfig->nCol+1;
/* Set idxFlags flags for all WHERE clause terms that will be used. */
for(i=0; i<pInfo->nConstraint; i++){
struct sqlite3_index_constraint *p = &pInfo->aConstraint[i];
int iCol = p->iColumn;
if( (p->op==SQLITE_INDEX_CONSTRAINT_MATCH && iCol>=0 && iCol<=nCol)
|| (p->op==SQLITE_INDEX_CONSTRAINT_EQ && iCol==nCol)
){
/* A MATCH operator or equivalent */
if( p->usable ){
idxFlags = (idxFlags & 0xFFFF) | FTS5_BI_MATCH | (iCol << 16);
aConstraint[0].iConsIndex = i;
}else{
/* As there exists an unusable MATCH constraint this is an
** unusable plan. Set a prohibitively high cost. */
pInfo->estimatedCost = 1e50;
return SQLITE_OK;
}
}else if( p->op<=SQLITE_INDEX_CONSTRAINT_MATCH ){
int j;
for(j=1; j<ArraySize(aConstraint); j++){
struct Constraint *pC = &aConstraint[j];
if( iCol==aColMap[pC->iCol] && (p->op & pC->op) && p->usable ){
int j;
for(j=0; j<ArraySize(aConstraint); j++){
struct Constraint *pC = &aConstraint[j];
if( p->iColumn==aColMap[pC->iCol] && p->op & pC->op ){
if( p->usable ){
pC->iConsIndex = i;
idxFlags |= pC->fts5op;
}else if( j==0 ){
/* As there exists an unusable MATCH constraint this is an
** unusable plan. Set a prohibitively high cost. */
pInfo->estimatedCost = 1e50;
return SQLITE_OK;
}
}
}
@@ -889,8 +872,7 @@ static int fts5PrepareStatement(
if( zSql==0 ){
rc = SQLITE_NOMEM;
}else{
rc = sqlite3_prepare_v3(pConfig->db, zSql, -1,
SQLITE_PREPARE_PERSISTENT, &pRet, 0);
rc = sqlite3_prepare_v2(pConfig->db, zSql, -1, &pRet, 0);
if( rc!=SQLITE_OK ){
*pConfig->pzErrmsg = sqlite3_mprintf("%s", sqlite3_errmsg(pConfig->db));
}
@@ -1026,8 +1008,7 @@ static int fts5FindRankFunction(Fts5Cursor *pCsr){
char *zSql = sqlite3Fts5Mprintf(&rc, "SELECT %s", zRankArgs);
if( zSql ){
sqlite3_stmt *pStmt = 0;
rc = sqlite3_prepare_v3(pConfig->db, zSql, -1,
SQLITE_PREPARE_PERSISTENT, &pStmt, 0);
rc = sqlite3_prepare_v2(pConfig->db, zSql, -1, &pStmt, 0);
sqlite3_free(zSql);
assert( rc==SQLITE_OK || pCsr->pRankArgStmt==0 );
if( rc==SQLITE_OK ){
@@ -1142,7 +1123,6 @@ static int fts5FilterMethod(
sqlite3_value *pRowidEq = 0; /* rowid = ? expression (or NULL) */
sqlite3_value *pRowidLe = 0; /* rowid <= ? expression (or NULL) */
sqlite3_value *pRowidGe = 0; /* rowid >= ? expression (or NULL) */
int iCol; /* Column on LHS of MATCH operator */
char **pzErrmsg = pConfig->pzErrmsg;
UNUSED_PARAM(zUnused);
@@ -1173,8 +1153,6 @@ static int fts5FilterMethod(
if( BitFlagTest(idxNum, FTS5_BI_ROWID_EQ) ) pRowidEq = apVal[iVal++];
if( BitFlagTest(idxNum, FTS5_BI_ROWID_LE) ) pRowidLe = apVal[iVal++];
if( BitFlagTest(idxNum, FTS5_BI_ROWID_GE) ) pRowidGe = apVal[iVal++];
iCol = (idxNum>>16);
assert( iCol>=0 && iCol<=pConfig->nCol );
assert( iVal==nVal );
bOrderByRank = ((idxNum & FTS5_BI_ORDER_RANK) ? 1 : 0);
pCsr->bDesc = bDesc = ((idxNum & FTS5_BI_ORDER_DESC) ? 1 : 0);
@@ -1221,7 +1199,7 @@ static int fts5FilterMethod(
rc = fts5SpecialMatch(pTab, pCsr, &zExpr[1]);
}else{
char **pzErr = &pTab->base.zErrMsg;
rc = sqlite3Fts5ExprNew(pConfig, iCol, zExpr, &pCsr->pExpr, pzErr);
rc = sqlite3Fts5ExprNew(pConfig, zExpr, &pCsr->pExpr, pzErr);
if( rc==SQLITE_OK ){
if( bOrderByRank ){
pCsr->ePlan = FTS5_PLAN_SORTED_MATCH;
@@ -1601,7 +1579,7 @@ static int fts5SyncMethod(sqlite3_vtab *pVtab){
fts5CheckTransactionState(pTab, FTS5_SYNC, 0);
pTab->pConfig->pzErrmsg = &pTab->base.zErrMsg;
fts5TripCursors(pTab);
rc = sqlite3Fts5StorageSync(pTab->pStorage);
rc = sqlite3Fts5StorageSync(pTab->pStorage, 1);
pTab->pConfig->pzErrmsg = 0;
return rc;
}
@@ -2412,7 +2390,7 @@ static int fts5SavepointMethod(sqlite3_vtab *pVtab, int iSavepoint){
UNUSED_PARAM(iSavepoint); /* Call below is a no-op for NDEBUG builds */
fts5CheckTransactionState(pTab, FTS5_SAVEPOINT, iSavepoint);
fts5TripCursors(pTab);
return sqlite3Fts5StorageSync(pTab->pStorage);
return sqlite3Fts5StorageSync(pTab->pStorage, 0);
}
/*
@@ -2425,7 +2403,7 @@ static int fts5ReleaseMethod(sqlite3_vtab *pVtab, int iSavepoint){
UNUSED_PARAM(iSavepoint); /* Call below is a no-op for NDEBUG builds */
fts5CheckTransactionState(pTab, FTS5_RELEASE, iSavepoint);
fts5TripCursors(pTab);
return sqlite3Fts5StorageSync(pTab->pStorage);
return sqlite3Fts5StorageSync(pTab->pStorage, 0);
}
/*
@@ -2615,14 +2593,15 @@ static void fts5ModuleDestroy(void *pCtx){
static void fts5Fts5Func(
sqlite3_context *pCtx, /* Function call context */
int nArg, /* Number of args */
sqlite3_value **apArg /* Function arguments */
sqlite3_value **apUnused /* Function arguments */
){
Fts5Global *pGlobal = (Fts5Global*)sqlite3_user_data(pCtx);
fts5_api **ppApi;
UNUSED_PARAM(nArg);
assert( nArg==1 );
ppApi = (fts5_api**)sqlite3_value_pointer(apArg[0], "fts5_api_ptr");
if( ppApi ) *ppApi = &pGlobal->api;
char buf[8];
UNUSED_PARAM2(nArg, apUnused);
assert( nArg==0 );
assert( sizeof(buf)>=sizeof(pGlobal) );
memcpy(buf, (void*)&pGlobal, sizeof(pGlobal));
sqlite3_result_blob(pCtx, buf, sizeof(pGlobal), SQLITE_TRANSIENT);
}
/*
@@ -2687,7 +2666,7 @@ static int fts5Init(sqlite3 *db){
if( rc==SQLITE_OK ) rc = sqlite3Fts5VocabInit(pGlobal, db);
if( rc==SQLITE_OK ){
rc = sqlite3_create_function(
db, "fts5", 1, SQLITE_UTF8, p, fts5Fts5Func, 0, 0
db, "fts5", 0, SQLITE_UTF8, p, fts5Fts5Func, 0, 0
);
}
if( rc==SQLITE_OK ){
+17 -15
View File
@@ -136,8 +136,7 @@ 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);
rc = sqlite3_prepare_v2(pC->db, zSql, -1, &p->aStmt[eStmt], 0);
sqlite3_free(zSql);
if( rc!=SQLITE_OK && pzErrMsg ){
*pzErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(pC->db));
@@ -219,7 +218,7 @@ static void fts5StorageRenameOne(
int sqlite3Fts5StorageRename(Fts5Storage *pStorage, const char *zName){
Fts5Config *pConfig = pStorage->pConfig;
int rc = sqlite3Fts5StorageSync(pStorage);
int rc = sqlite3Fts5StorageSync(pStorage, 1);
fts5StorageRenameOne(pConfig, &rc, "data", zName);
fts5StorageRenameOne(pConfig, &rc, "idx", zName);
@@ -458,7 +457,6 @@ static int fts5StorageInsertDocsize(
sqlite3_bind_blob(pReplace, 2, pBuf->p, pBuf->n, SQLITE_STATIC);
sqlite3_step(pReplace);
rc = sqlite3_reset(pReplace);
sqlite3_bind_null(pReplace, 2);
}
}
return rc;
@@ -547,6 +545,11 @@ int sqlite3Fts5StorageDelete(Fts5Storage *p, i64 iDel, sqlite3_value **apVal){
}
}
/* Write the averages record */
if( rc==SQLITE_OK ){
rc = fts5StorageSaveTotals(p);
}
return rc;
}
@@ -750,6 +753,11 @@ int sqlite3Fts5StorageIndexInsert(
}
sqlite3_free(buf.p);
/* Write the averages record */
if( rc==SQLITE_OK ){
rc = fts5StorageSaveTotals(p);
}
return rc;
}
@@ -1083,18 +1091,13 @@ int sqlite3Fts5StorageRowCount(Fts5Storage *p, i64 *pnRow){
/*
** Flush any data currently held in-memory to disk.
*/
int sqlite3Fts5StorageSync(Fts5Storage *p){
int rc = SQLITE_OK;
i64 iLastRowid = sqlite3_last_insert_rowid(p->pConfig->db);
if( p->bTotalsValid ){
rc = fts5StorageSaveTotals(p);
int sqlite3Fts5StorageSync(Fts5Storage *p, int bCommit){
if( bCommit && p->bTotalsValid ){
int rc = fts5StorageSaveTotals(p);
p->bTotalsValid = 0;
if( rc!=SQLITE_OK ) return rc;
}
if( rc==SQLITE_OK ){
rc = sqlite3Fts5IndexSync(p->pIndex);
}
sqlite3_set_last_insert_rowid(p->pConfig->db, iLastRowid);
return rc;
return sqlite3Fts5IndexSync(p->pIndex, bCommit);
}
int sqlite3Fts5StorageRollback(Fts5Storage *p){
@@ -1119,7 +1122,6 @@ int sqlite3Fts5StorageConfigValue(
}
sqlite3_step(pReplace);
rc = sqlite3_reset(pReplace);
sqlite3_bind_null(pReplace, 1);
}
if( rc==SQLITE_OK && pVal ){
int iNew = p->pConfig->iCookie + 1;
+22 -26
View File
@@ -14,14 +14,7 @@
#ifdef SQLITE_TEST
#if defined(INCLUDE_SQLITE_TCL_H)
# include "sqlite_tcl.h"
#else
# include "tcl.h"
# ifndef SQLITE_TCLAPI
# define SQLITE_TCLAPI
# endif
#endif
#include <tcl.h>
#ifdef SQLITE_ENABLE_FTS5
@@ -85,7 +78,7 @@ static int f5tResultToErrorCode(const char *zRes){
return SQLITE_ERROR;
}
static int SQLITE_TCLAPI f5tDbAndApi(
static int f5tDbAndApi(
Tcl_Interp *interp,
Tcl_Obj *pObj,
sqlite3 **ppDb,
@@ -99,13 +92,16 @@ static int SQLITE_TCLAPI f5tDbAndApi(
sqlite3_stmt *pStmt = 0;
fts5_api *pApi = 0;
rc = sqlite3_prepare_v2(db, "SELECT fts5(?1)", -1, &pStmt, 0);
rc = sqlite3_prepare_v2(db, "SELECT fts5()", -1, &pStmt, 0);
if( rc!=SQLITE_OK ){
Tcl_AppendResult(interp, "error: ", sqlite3_errmsg(db), 0);
return TCL_ERROR;
}
sqlite3_bind_pointer(pStmt, 1, (void*)&pApi, "fts5_api_ptr", 0);
sqlite3_step(pStmt);
if( SQLITE_ROW==sqlite3_step(pStmt) ){
const void *pPtr = sqlite3_column_blob(pStmt, 0);
memcpy((void*)&pApi, pPtr, sizeof(pApi));
}
if( sqlite3_finalize(pStmt)!=SQLITE_OK ){
Tcl_AppendResult(interp, "error: ", sqlite3_errmsg(db), 0);
@@ -168,7 +164,7 @@ static int xTokenizeCb(
return rc;
}
static int SQLITE_TCLAPI xF5tApi(void*, Tcl_Interp*, int, Tcl_Obj *CONST []);
static int xF5tApi(void*, Tcl_Interp*, int, Tcl_Obj *CONST []);
static int xQueryPhraseCb(
const Fts5ExtensionApi *pApi,
@@ -213,7 +209,7 @@ static void xSetAuxdataDestructor(void *p){
**
** Description...
*/
static int SQLITE_TCLAPI xF5tApi(
static int xF5tApi(
void * clientData,
Tcl_Interp *interp,
int objc,
@@ -433,7 +429,7 @@ static int SQLITE_TCLAPI xF5tApi(
int iVal;
int bClear;
if( Tcl_GetBooleanFromObj(interp, objv[2], &bClear) ) return TCL_ERROR;
iVal = (int)((char*)p->pApi->xGetAuxdata(p->pFts, bClear) - (char*)0);
iVal = ((char*)p->pApi->xGetAuxdata(p->pFts, bClear) - (char*)0);
Tcl_SetObjResult(interp, Tcl_NewIntObj(iVal));
break;
}
@@ -482,7 +478,7 @@ static int SQLITE_TCLAPI xF5tApi(
rc = p->pApi->xPhraseFirstColumn(p->pFts, iPhrase, &iter, &iCol);
if( rc!=SQLITE_OK ){
Tcl_SetResult(interp, (char*)sqlite3ErrName(rc), TCL_VOLATILE);
Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
return TCL_ERROR;
}
for( ; iCol>=0; p->pApi->xPhraseNextColumn(p->pFts, &iter, &iCol)){
@@ -606,7 +602,7 @@ static void xF5tDestroy(void *pCtx){
**
** Description...
*/
static int SQLITE_TCLAPI f5tCreateFunction(
static int f5tCreateFunction(
void * clientData,
Tcl_Interp *interp,
int objc,
@@ -676,7 +672,7 @@ static int xTokenizeCb2(
**
** Description...
*/
static int SQLITE_TCLAPI f5tTokenize(
static int f5tTokenize(
void * clientData,
Tcl_Interp *interp,
int objc,
@@ -882,7 +878,7 @@ static int f5tTokenizerTokenize(
/*
** sqlite3_fts5_token ?-colocated? TEXT START END
*/
static int SQLITE_TCLAPI f5tTokenizerReturn(
static int f5tTokenizerReturn(
void * clientData,
Tcl_Interp *interp,
int objc,
@@ -924,7 +920,7 @@ static int SQLITE_TCLAPI f5tTokenizerReturn(
rc = p->xToken(p->pCtx, tflags, zToken, nToken, iStart, iEnd);
Tcl_SetResult(interp, (char*)sqlite3ErrName(rc), TCL_VOLATILE);
return rc==SQLITE_OK ? TCL_OK : TCL_ERROR;
return TCL_OK;
usage:
Tcl_WrongNumArgs(interp, 1, objv, "?-colocated? TEXT START END");
@@ -953,7 +949,7 @@ static void f5tDelTokenizer(void *pCtx){
** SCRIPT2 should invoke the [sqlite3_fts5_token] command once for each
** token within the tokenized text.
*/
static int SQLITE_TCLAPI f5tCreateTokenizer(
static int f5tCreateTokenizer(
ClientData clientData,
Tcl_Interp *interp,
int objc,
@@ -996,7 +992,7 @@ static int SQLITE_TCLAPI f5tCreateTokenizer(
return TCL_OK;
}
static void SQLITE_TCLAPI xF5tFree(ClientData clientData){
static void xF5tFree(ClientData clientData){
ckfree(clientData);
}
@@ -1005,7 +1001,7 @@ static void SQLITE_TCLAPI xF5tFree(ClientData clientData){
**
** Set or clear the global "may-be-corrupt" flag. Return the old value.
*/
static int SQLITE_TCLAPI f5tMayBeCorrupt(
static int f5tMayBeCorrupt(
void * clientData,
Tcl_Interp *interp,
int objc,
@@ -1037,7 +1033,7 @@ static unsigned int f5t_fts5HashKey(int nSlot, const char *p, int n){
return (h % nSlot);
}
static int SQLITE_TCLAPI f5tTokenHash(
static int f5tTokenHash(
void * clientData,
Tcl_Interp *interp,
int objc,
@@ -1062,7 +1058,7 @@ static int SQLITE_TCLAPI f5tTokenHash(
return TCL_OK;
}
static int SQLITE_TCLAPI f5tRegisterMatchinfo(
static int f5tRegisterMatchinfo(
void * clientData,
Tcl_Interp *interp,
int objc,
@@ -1087,7 +1083,7 @@ static int SQLITE_TCLAPI f5tRegisterMatchinfo(
return TCL_OK;
}
static int SQLITE_TCLAPI f5tRegisterTok(
static int f5tRegisterTok(
void * clientData,
Tcl_Interp *interp,
int objc,
+7 -3
View File
@@ -73,10 +73,13 @@ static int fts5_api_from_db(sqlite3 *db, fts5_api **ppApi){
int rc;
*ppApi = 0;
rc = sqlite3_prepare(db, "SELECT fts5(?1)", -1, &pStmt, 0);
rc = sqlite3_prepare(db, "SELECT fts5()", -1, &pStmt, 0);
if( rc==SQLITE_OK ){
sqlite3_bind_pointer(pStmt, 1, (void*)ppApi, "fts5_api_ptr", 0);
(void)sqlite3_step(pStmt);
if( SQLITE_ROW==sqlite3_step(pStmt)
&& sizeof(fts5_api*)==sqlite3_column_bytes(pStmt, 0)
){
memcpy(ppApi, sqlite3_column_blob(pStmt, 0), sizeof(fts5_api*));
}
rc = sqlite3_finalize(pStmt);
}
@@ -419,3 +422,4 @@ int sqlite3Fts5TestRegisterMatchinfo(sqlite3 *db){
}
#endif /* SQLITE_ENABLE_FTS5 */
+2 -2
View File
@@ -40,7 +40,7 @@
*/
#if defined(SQLITE_TEST) && defined(SQLITE_ENABLE_FTS5)
#include "fts5.h"
#include <fts5.h>
#include <string.h>
#include <assert.h>
@@ -182,7 +182,7 @@ static int fts5tokConnectMethod(
Fts5tokTable *pTab = 0;
int rc;
char **azDequote = 0;
int nDequote = 0;
int nDequote;
rc = sqlite3_declare_vtab(db,
"CREATE TABLE x(input HIDDEN, token, start, end, position)"
+27 -150
View File
@@ -29,11 +29,6 @@
** the number of fts5 rows that contain at least one instance of term
** $term. Field $cnt is set to the total number of instances of term
** $term in the database.
**
** instance:
** CREATE TABLE vocab(term, doc, col, offset, PRIMARY KEY(<all-fields>));
**
** One row for each term instance in the database.
*/
@@ -49,7 +44,7 @@ struct Fts5VocabTable {
char *zFts5Db; /* Db containing fts5 table */
sqlite3 *db; /* Database handle */
Fts5Global *pGlobal; /* FTS5 global object for this database */
int eType; /* FTS5_VOCAB_COL, ROW or INSTANCE */
int eType; /* FTS5_VOCAB_COL or ROW */
};
struct Fts5VocabCursor {
@@ -69,22 +64,16 @@ struct Fts5VocabCursor {
i64 *aCnt;
i64 *aDoc;
/* Output values used by all tables. */
/* Output values used by 'row' and 'col' tables */
i64 rowid; /* This table's current rowid value */
Fts5Buffer term; /* Current value of 'term' column */
/* Output values Used by 'instance' tables only */
i64 iInstPos;
int iInstOff;
};
#define FTS5_VOCAB_COL 0
#define FTS5_VOCAB_ROW 1
#define FTS5_VOCAB_INSTANCE 2
#define FTS5_VOCAB_COL 0
#define FTS5_VOCAB_ROW 1
#define FTS5_VOCAB_COL_SCHEMA "term, col, doc, cnt"
#define FTS5_VOCAB_ROW_SCHEMA "term, doc, cnt"
#define FTS5_VOCAB_INST_SCHEMA "term, doc, col, offset"
/*
** Bits for the mask used as the idxNum value by xBestIndex/xFilter.
@@ -112,9 +101,6 @@ static int fts5VocabTableType(const char *zType, char **pzErr, int *peType){
if( sqlite3_stricmp(zCopy, "row")==0 ){
*peType = FTS5_VOCAB_ROW;
}else
if( sqlite3_stricmp(zCopy, "instance")==0 ){
*peType = FTS5_VOCAB_INSTANCE;
}else
{
*pzErr = sqlite3_mprintf("fts5vocab: unknown table type: %Q", zCopy);
rc = SQLITE_ERROR;
@@ -175,8 +161,7 @@ static int fts5VocabInitVtab(
){
const char *azSchema[] = {
"CREATE TABlE vocab(" FTS5_VOCAB_COL_SCHEMA ")",
"CREATE TABlE vocab(" FTS5_VOCAB_ROW_SCHEMA ")",
"CREATE TABlE vocab(" FTS5_VOCAB_INST_SCHEMA ")"
"CREATE TABlE vocab(" FTS5_VOCAB_ROW_SCHEMA ")"
};
Fts5VocabTable *pRet = 0;
@@ -250,15 +235,6 @@ static int fts5VocabCreateMethod(
/*
** Implementation of the xBestIndex method.
**
** Only constraints of the form:
**
** term <= ?
** term == ?
** term >= ?
**
** are interpreted. Less-than and less-than-or-equal are treated
** identically, as are greater-than and greater-than-or-equal.
*/
static int fts5VocabBestIndexMethod(
sqlite3_vtab *pUnused,
@@ -303,19 +279,8 @@ static int fts5VocabBestIndexMethod(
}
}
/* This virtual table always delivers results in ascending order of
** the "term" column (column 0). So if the user has requested this
** specifically - "ORDER BY term" or "ORDER BY term ASC" - set the
** sqlite3_index_info.orderByConsumed flag to tell the core the results
** are already in sorted order. */
if( pInfo->nOrderBy==1
&& pInfo->aOrderBy[0].iColumn==0
&& pInfo->aOrderBy[0].desc==0
){
pInfo->orderByConsumed = 1;
}
pInfo->idxNum = idxNum;
return SQLITE_OK;
}
@@ -402,54 +367,6 @@ static int fts5VocabCloseMethod(sqlite3_vtab_cursor *pCursor){
return SQLITE_OK;
}
static int fts5VocabInstanceNewTerm(Fts5VocabCursor *pCsr){
int rc = SQLITE_OK;
if( sqlite3Fts5IterEof(pCsr->pIter) ){
pCsr->bEof = 1;
}else{
const char *zTerm;
int nTerm;
zTerm = sqlite3Fts5IterTerm(pCsr->pIter, &nTerm);
if( pCsr->nLeTerm>=0 ){
int nCmp = MIN(nTerm, pCsr->nLeTerm);
int bCmp = memcmp(pCsr->zLeTerm, zTerm, nCmp);
if( bCmp<0 || (bCmp==0 && pCsr->nLeTerm<nTerm) ){
pCsr->bEof = 1;
}
}
sqlite3Fts5BufferSet(&rc, &pCsr->term, nTerm, (const u8*)zTerm);
}
return rc;
}
static int fts5VocabInstanceNext(Fts5VocabCursor *pCsr){
int eDetail = pCsr->pConfig->eDetail;
int rc = SQLITE_OK;
Fts5IndexIter *pIter = pCsr->pIter;
i64 *pp = &pCsr->iInstPos;
int *po = &pCsr->iInstOff;
while( eDetail==FTS5_DETAIL_NONE
|| sqlite3Fts5PoslistNext64(pIter->pData, pIter->nData, po, pp)
){
pCsr->iInstPos = 0;
pCsr->iInstOff = 0;
rc = sqlite3Fts5IterNextScan(pCsr->pIter);
if( rc==SQLITE_OK ){
rc = fts5VocabInstanceNewTerm(pCsr);
if( eDetail==FTS5_DETAIL_NONE ) break;
}
if( rc ){
pCsr->bEof = 1;
break;
}
}
return rc;
}
/*
** Advance the cursor to the next row in the table.
@@ -462,17 +379,13 @@ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){
pCsr->rowid++;
if( pTab->eType==FTS5_VOCAB_INSTANCE ){
return fts5VocabInstanceNext(pCsr);
}
if( pTab->eType==FTS5_VOCAB_COL ){
for(pCsr->iCol++; pCsr->iCol<nCol; pCsr->iCol++){
if( pCsr->aDoc[pCsr->iCol] ) break;
}
}
if( pTab->eType!=FTS5_VOCAB_COL || pCsr->iCol>=nCol ){
if( pTab->eType==FTS5_VOCAB_ROW || pCsr->iCol>=nCol ){
if( sqlite3Fts5IterEof(pCsr->pIter) ){
pCsr->bEof = 1;
}else{
@@ -496,26 +409,22 @@ 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;
const u8 *pPos; int nPos; /* Position list */
i64 iPos = 0; /* 64-bit position read from poslist */
int iOff = 0; /* Current offset within position list */
pPos = pCsr->pIter->pData;
nPos = pCsr->pIter->nData;
switch( pTab->eType ){
case FTS5_VOCAB_ROW:
if( eDetail==FTS5_DETAIL_FULL ){
switch( pCsr->pConfig->eDetail ){
case FTS5_DETAIL_FULL:
pPos = pCsr->pIter->pData;
nPos = pCsr->pIter->nData;
if( pTab->eType==FTS5_VOCAB_ROW ){
while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff, &iPos) ){
pCsr->aCnt[0]++;
}
}
pCsr->aDoc[0]++;
break;
case FTS5_VOCAB_COL:
if( eDetail==FTS5_DETAIL_FULL ){
pCsr->aDoc[0]++;
}else{
int iCol = -1;
while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff, &iPos) ){
int ii = FTS5_POS2COLUMN(iPos);
@@ -529,7 +438,13 @@ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){
iCol = ii;
}
}
}else if( eDetail==FTS5_DETAIL_COLUMNS ){
}
break;
case FTS5_DETAIL_COLUMNS:
if( pTab->eType==FTS5_VOCAB_ROW ){
pCsr->aDoc[0]++;
}else{
while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff,&iPos) ){
assert_nc( iPos>=0 && iPos<nCol );
if( iPos>=nCol ){
@@ -538,21 +453,18 @@ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){
}
pCsr->aDoc[iPos]++;
}
}else{
assert( eDetail==FTS5_DETAIL_NONE );
pCsr->aDoc[0]++;
}
break;
default:
assert( pTab->eType==FTS5_VOCAB_INSTANCE );
default:
assert( pCsr->pConfig->eDetail==FTS5_DETAIL_NONE );
pCsr->aDoc[0]++;
break;
}
if( rc==SQLITE_OK ){
rc = sqlite3Fts5IterNextScan(pCsr->pIter);
}
if( pTab->eType==FTS5_VOCAB_INSTANCE ) break;
if( rc==SQLITE_OK ){
zTerm = sqlite3Fts5IterTerm(pCsr->pIter, &nTerm);
@@ -582,9 +494,7 @@ static int fts5VocabFilterMethod(
int nUnused, /* Number of elements in apVal */
sqlite3_value **apVal /* Arguments for the indexing scheme */
){
Fts5VocabTable *pTab = (Fts5VocabTable*)pCursor->pVtab;
Fts5VocabCursor *pCsr = (Fts5VocabCursor*)pCursor;
int eType = pTab->eType;
int rc = SQLITE_OK;
int iVal = 0;
@@ -624,16 +534,11 @@ static int fts5VocabFilterMethod(
}
}
if( rc==SQLITE_OK ){
rc = sqlite3Fts5IndexQuery(pCsr->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 ){
rc = fts5VocabNextMethod(pCursor);
}
@@ -675,41 +580,13 @@ static int fts5VocabColumnMethod(
}else{
iVal = pCsr->aCnt[pCsr->iCol];
}
}else if( eType==FTS5_VOCAB_ROW ){
}else{
assert( iCol==1 || iCol==2 );
if( iCol==1 ){
iVal = pCsr->aDoc[0];
}else{
iVal = pCsr->aCnt[0];
}
}else{
assert( eType==FTS5_VOCAB_INSTANCE );
switch( iCol ){
case 1:
sqlite3_result_int64(pCtx, pCsr->pIter->iRowid);
break;
case 2: {
int ii = -1;
if( eDetail==FTS5_DETAIL_FULL ){
ii = FTS5_POS2COLUMN(pCsr->iInstPos);
}else if( eDetail==FTS5_DETAIL_COLUMNS ){
ii = (int)pCsr->iInstPos;
}
if( ii>=0 && ii<pCsr->pConfig->nCol ){
const char *z = pCsr->pConfig->azCol[ii];
sqlite3_result_text(pCtx, z, -1, SQLITE_STATIC);
}
break;
}
default: {
assert( iCol==3 );
if( eDetail==FTS5_DETAIL_FULL ){
int ii = FTS5_POS2OFFSET(pCsr->iInstPos);
sqlite3_result_int(pCtx, ii);
}
break;
}
}
}
if( iVal>0 ) sqlite3_result_int64(pCtx, iVal);
+19 -33
View File
@@ -89,29 +89,6 @@ input ::= expr(X). { sqlite3Fts5ParseFinished(pParse, X); }
%destructor expr { sqlite3Fts5ParseNodeFree($$); }
%destructor exprlist { sqlite3Fts5ParseNodeFree($$); }
%type colset {Fts5Colset*}
%destructor colset { sqlite3_free($$); }
%type colsetlist {Fts5Colset*}
%destructor colsetlist { sqlite3_free($$); }
colset(A) ::= MINUS LCP colsetlist(X) RCP. {
A = sqlite3Fts5ParseColsetInvert(pParse, X);
}
colset(A) ::= LCP colsetlist(X) RCP. { A = X; }
colset(A) ::= STRING(X). {
A = sqlite3Fts5ParseColset(pParse, 0, &X);
}
colset(A) ::= MINUS STRING(X). {
A = sqlite3Fts5ParseColset(pParse, 0, &X);
A = sqlite3Fts5ParseColsetInvert(pParse, A);
}
colsetlist(A) ::= colsetlist(Y) STRING(X). {
A = sqlite3Fts5ParseColset(pParse, Y, &X); }
colsetlist(A) ::= STRING(X). {
A = sqlite3Fts5ParseColset(pParse, 0, &X);
}
expr(A) ::= expr(X) AND expr(Y). {
A = sqlite3Fts5ParseNode(pParse, FTS5_AND, X, Y, 0);
}
@@ -122,10 +99,6 @@ expr(A) ::= expr(X) NOT expr(Y). {
A = sqlite3Fts5ParseNode(pParse, FTS5_NOT, X, Y, 0);
}
expr(A) ::= colset(X) COLON LP expr(Y) RP. {
sqlite3Fts5ParseSetColset(pParse, Y, X);
A = Y;
}
expr(A) ::= LP expr(X) RP. {A = X;}
expr(A) ::= exprlist(X). {A = X;}
@@ -138,8 +111,24 @@ cnearset(A) ::= nearset(X). {
A = sqlite3Fts5ParseNode(pParse, FTS5_STRING, 0, 0, X);
}
cnearset(A) ::= colset(X) COLON nearset(Y). {
sqlite3Fts5ParseSetColset(pParse, Y, X);
A = sqlite3Fts5ParseNode(pParse, FTS5_STRING, 0, 0, Y);
sqlite3Fts5ParseSetColset(pParse, A, X);
}
%type colset {Fts5Colset*}
%destructor colset { sqlite3_free($$); }
%type colsetlist {Fts5Colset*}
%destructor colsetlist { sqlite3_free($$); }
colset(A) ::= LCP colsetlist(X) RCP. { A = X; }
colset(A) ::= STRING(X). {
A = sqlite3Fts5ParseColset(pParse, 0, &X);
}
colsetlist(A) ::= colsetlist(Y) STRING(X). {
A = sqlite3Fts5ParseColset(pParse, Y, &X); }
colsetlist(A) ::= STRING(X). {
A = sqlite3Fts5ParseColset(pParse, 0, &X);
}
@@ -148,11 +137,7 @@ cnearset(A) ::= colset(X) COLON nearset(Y). {
%destructor nearset { sqlite3Fts5ParseNearsetFree($$); }
%destructor nearphrases { sqlite3Fts5ParseNearsetFree($$); }
nearset(A) ::= phrase(Y). { A = sqlite3Fts5ParseNearset(pParse, 0, Y); }
nearset(A) ::= CARET phrase(Y). {
sqlite3Fts5ParseSetCaret(Y);
A = sqlite3Fts5ParseNearset(pParse, 0, Y);
}
nearset(A) ::= phrase(X). { A = sqlite3Fts5ParseNearset(pParse, 0, X); }
nearset(A) ::= STRING(X) LP nearphrases(Y) neardist_opt(Z) RP. {
sqlite3Fts5ParseNear(pParse, &X);
sqlite3Fts5ParseSetDistance(pParse, Y, &Z);
@@ -193,5 +178,6 @@ phrase(A) ::= STRING(Y) star_opt(Z). {
** Optional "*" character.
*/
%type star_opt {int}
star_opt(A) ::= STAR. { A = 1; }
star_opt(A) ::= . { A = 0; }
+3 -43
View File
@@ -441,7 +441,7 @@ db func funk funk
do_catchsql_test 16.2 {
SELECT funk(), bm25(n1), funk() FROM n1 WHERE n1 MATCH 'a+b+c+d'
} {0 {{} -1e-06 {}}}
# {1 {SQL logic error}}
# {1 {SQL logic error or missing database}}
#-------------------------------------------------------------------------
#
@@ -561,49 +561,9 @@ do_test 20.1 {
execsql { SELECT rowid FROM tmp WHERE tmp MATCH 'y' }
} $::ids
#--------------------------------------------------------------------
# Test that a DROP TABLE may be executed within a transaction that
# writes to an FTS5 table.
#
do_execsql_test 21.0 {
CREATE TEMP TABLE t8(a, b);
CREATE VIRTUAL TABLE ft USING fts5(x, detail=%DETAIL%);
}
do_execsql_test 21.1 {
BEGIN;
INSERT INTO ft VALUES('a b c');
DROP TABLE t8;
COMMIT;
}
do_execsql_test 22.0 {
CREATE VIRTUAL TABLE t9 USING fts5(x, detail=%DETAIL%);
INSERT INTO t9(rowid, x) VALUES(2, 'bbb');
BEGIN;
INSERT INTO t9(rowid, x) VALUES(1, 'aaa');
DELETE FROM t9 WHERE rowid = 2;
INSERT INTO t9(rowid, x) VALUES(3, 'bbb');
COMMIT;
}
do_execsql_test 22.1 {
SELECT rowid FROM t9('a*')
} {1}
#-------------------------------------------------------------------------
do_execsql_test 23.0 {
CREATE VIRTUAL TABLE t10 USING fts5(x, detail=%DETAIL%);
CREATE TABLE t11(x);
}
do_execsql_test 23.1 {
SELECT * FROM t11, t10 WHERE t11.x = t10.x AND t10.rowid IS NULL;
}
do_execsql_test 23.2 {
SELECT * FROM t11, t10 WHERE t10.rowid IS NULL;
}
}
expand_all_sql db
finish_test
+1
View File
@@ -294,3 +294,4 @@ do_execsql_test 7.0 {
finish_test
+1
View File
@@ -276,3 +276,4 @@ foreach {tn expr tclexpr} {
}
finish_test
+2
View File
@@ -231,6 +231,7 @@ foreach {T create} {
set res [lsort -integer -increasing $res]
}
set n [llength $res]
if {$T==5} breakpoint
do_execsql_test $T.$bAsc.$tn.$n $sql $res
}
}
@@ -241,3 +242,4 @@ foreach {T create} {
}
finish_test
+1
View File
@@ -309,3 +309,4 @@ foreach {tn q cnt} {
}
finish_test
+30 -72
View File
@@ -72,56 +72,42 @@ foreach {tn doc res} {
2.2 {o X o o o o o o} {o [X] o o o o o...}
2.3 {o o X o o o o o} {o o [X] o o o o...}
2.4 {o o o X o o o o} {o o o [X] o o o...}
2.5 {o o o o X o o o} {o o o o [X] o o...}
2.6 {o o o o o X o o} {o o o o o [X] o...}
2.7 {o o o o o o X o} {o o o o o o [X]...}
2.5 {o o o o X o o o} {...o o o [X] o o o}
2.6 {o o o o o X o o} {...o o o o [X] o o}
2.7 {o o o o o o X o} {...o o o o o [X] o}
2.8 {o o o o o o o X} {...o o o o o o [X]}
2.9 {o o o o o o o X o} {...o o o o o [X] o}
2.10 {o o o o o o o X o o} {...o o o o [X] o o}
2.11 {o o o o o o o X o o o} {...o o o [X] o o o}
2.12 {o o o o o o o X o o o o} {...o o o [X] o o o...}
3.1 {X o o o o o o o o} {[X] o o o o o o...}
3.2 {o X o o o o o o o} {o [X] o o o o o...}
3.3 {o o X o o o o o o} {o o [X] o o o o...}
3.4 {o o o X o o o o o} {o o o [X] o o o...}
3.5 {o o o o o o o X o o o o} {...o o o [X] o o o...}
3.6 {o o o o o o o o X o o o} {...o o o [X] o o o}
3.7 {o o o o o o o o o X o o} {...o o o o [X] o o}
3.8 {o o o o o o o o o o X o} {...o o o o o [X] o}
3.9 {o o o o o o o o o o o X} {...o o o o o o [X]}
3.5 {o o o o X o o o o} {...o o o [X] o o o...}
3.6 {o o o o o X o o o} {...o o o [X] o o o}
3.7 {o o o o o o X o o} {...o o o o [X] o o}
3.8 {o o o o o o o X o} {...o o o o o [X] o}
3.9 {o o o o o o o o X} {...o o o o o o [X]}
4.1 {X o o o o o X o o} {[X] o o o o o [X]...}
4.2 {o o o o o o o X o o o o o X o} {...[X] o o o o o [X]...}
4.3 {o o o o o o o o X o o o o o X} {...[X] o o o o o [X]}
4.2 {o X o o o o o X o} {...[X] o o o o o [X]...}
4.3 {o o X o o o o o X} {...[X] o o o o o [X]}
5.1 {X o o o o X o o o} {[X] o o o o [X] o...}
5.2 {o o o o o o o X o o o o X o o} {...[X] o o o o [X] o...}
5.3 {o o o o o o o o X o o o o X o} {...[X] o o o o [X] o}
5.4 {o o o o o o o o o X o o o o X} {...o [X] o o o o [X]}
5.2 {o X o o o o X o o} {...[X] o o o o [X] o...}
5.3 {o o X o o o o X o} {...[X] o o o o [X] o}
5.4 {o o o X o o o o X} {...o [X] o o o o [X]}
6.1 {X o o o X o o o} {[X] o o o [X] o o...}
6.2 {o X o o o X o o o} {o [X] o o o [X] o...}
6.3 {o o o o o o o X o o o X o o} {...o [X] o o o [X] o...}
6.4 {o o o o o o o o X o o o X o} {...o [X] o o o [X] o}
6.5 {o o o o o o o o o X o o o X} {...o o [X] o o o [X]}
6.3 {o o X o o o X o o} {...o [X] o o o [X] o...}
6.4 {o o o X o o o X o} {...o [X] o o o [X] o}
6.5 {o o o o X o o o X} {...o o [X] o o o [X]}
7.1 {X o o X o o o o o} {[X] o o [X] o o o...}
7.2 {o X o o X o o o o} {o [X] o o [X] o o...}
7.3 {o o o o o o o X o o X o o o} {...o [X] o o [X] o o...}
7.4 {o o o o o o o o X o o X o o} {...o [X] o o [X] o o}
7.5 {o o o o o o o o o X o o X o} {...o o [X] o o [X] o}
7.6 {o o o o o o o o o o X o o X} {...o o o [X] o o [X]}
8.1 {o o o o o o o o o X o o o o o o o o o o o o o o o o X X X o o o}
{...o o [X] [X] [X] o o...}
8.2 {o o o o o o o. o o X o o o o o o o o o o o o o o o o X X X o o o}
{...o o [X] o o o o...}
8.3 {o o o o X o o o o o o o o o o o o o o o o o o o o o X X X o o o}
{o o o o [X] o o...}
7.3 {o o X o o X o o o} {...o [X] o o [X] o o...}
7.4 {o o o X o o X o o} {...o [X] o o [X] o o}
7.5 {o o o o X o o X o} {...o o [X] o o [X] o}
7.6 {o o o o o X o o X} {...o o o [X] o o [X]}
} {
do_snippet_test 1.$tn $doc X $res
}
@@ -138,53 +124,25 @@ if {[detail_is_full]} {
2.1 {X Y o o o o o o} {[X Y] o o o o o...}
2.2 {o X Y o o o o o} {o [X Y] o o o o...}
2.3 {o o X Y o o o o} {o o [X Y] o o o...}
2.4 {o o o o o o o X Y o o o} {...o o [X Y] o o o}
2.5 {o o o o o o o o X Y o o} {...o o o [X Y] o o}
2.6 {o o o o o o o o o X Y o} {...o o o o [X Y] o}
2.7 {o o o o o o o o o o X Y} {...o o o o o [X Y]}
2.4 {o o o X Y o o o} {...o o [X Y] o o o}
2.5 {o o o o X Y o o} {...o o o [X Y] o o}
2.6 {o o o o o X Y o} {...o o o o [X Y] o}
2.7 {o o o o o o X Y} {...o o o o o [X Y]}
3.1 {X Y o o o o o o o} {[X Y] o o o o o...}
3.2 {o X Y o o o o o o} {o [X Y] o o o o...}
3.3 {o o X Y o o o o o} {o o [X Y] o o o...}
3.4 {o o o o o o o X Y o o o o} {...o o [X Y] o o o...}
3.5 {o o o o o o o o X Y o o o} {...o o [X Y] o o o}
3.6 {o o o o o o o o o X Y o o} {...o o o [X Y] o o}
3.7 {o o o o o o o o o o X Y o} {...o o o o [X Y] o}
3.8 {o o o o o o o o o o o X Y} {...o o o o o [X Y]}
3.4 {o o o X Y o o o o} {...o o [X Y] o o o...}
3.5 {o o o o X Y o o o} {...o o [X Y] o o o}
3.6 {o o o o o X Y o o} {...o o o [X Y] o o}
3.7 {o o o o o o X Y o} {...o o o o [X Y] o}
3.8 {o o o o o o o X Y} {...o o o o o [X Y]}
} {
do_snippet_test 2.$tn $doc "X + Y" $res
}
}
do_execsql_test 4.0 {
CREATE VIRTUAL TABLE x1 USING fts5(a, b);
INSERT INTO x1 VALUES('xyz', '1 2 3 4 5 6 7 8 9 10 11 12 13');
SELECT snippet(x1, 1, '[', ']', '...', 5) FROM x1('xyz');
} {
{1 2 3 4 5...}
}
do_execsql_test 5.0 {
CREATE VIRTUAL TABLE p1 USING fts5(a, b);
INSERT INTO p1 VALUES(
'x a a a a a a a a a a',
'a a a a a a a a a a a a a a a a a a a x'
);
}
do_execsql_test 5.1 {
SELECT snippet(p1, 0, '[', ']', '...', 6) FROM p1('x');
} {{[x] a a a a a...}}
do_execsql_test 5.2 {
SELECT snippet(p1, 0, '[', ']', NULL, 6) FROM p1('x');
} {{[x] a a a a a}}
do_execsql_test 5.3 {
SELECT snippet(p1, 0, NULL, ']', '...', 6) FROM p1('x');
} {{x] a a a a a...}}
do_execsql_test 5.4 {
SELECT snippet(p1, 0, '[', NULL, '...', 6) FROM p1('x');
} {{[x a a a a a...}}
} ;# foreach_detail_mode
finish_test
+1
View File
@@ -142,3 +142,4 @@ if {[detail_is_full]} {
finish_test
+1
View File
@@ -167,3 +167,4 @@ do_execsql_test 1.8.2 {
#db eval {SELECT rowid, fts5_decode(rowid, block) aS r FROM t1_data} {puts $r}
finish_test
+1
View File
@@ -55,3 +55,4 @@ do_execsql_test 1.2 {
finish_test
+1
View File
@@ -66,3 +66,4 @@ do_execsql_test 2.0 { INSERT INTO t1(t1) VALUES('integrity-check') }
finish_test
+1
View File
@@ -147,3 +147,4 @@ do_execsql_test 3.1 {
}
finish_test
+2 -1
View File
@@ -77,7 +77,7 @@ foreach {tn defn} {
} {
do_test 2.2.$tn {
catchsql { INSERT INTO ft1(ft1, rank) VALUES('rank', $defn) }
} {1 {SQL logic error}}
} {1 {SQL logic error or missing database}}
}
#-------------------------------------------------------------------------
@@ -297,3 +297,4 @@ do_catchsql_test 4.4.4 {
finish_test
+2
View File
@@ -89,6 +89,7 @@ do_execsql_test 3.1 {
BEGIN;
INSERT INTO abc(rowid, a) VALUES(2, 'a');
}
breakpoint
do_execsql_test 3.2 {
SELECT rowid FROM abc WHERE abc MATCH 'a';
} {1 2}
@@ -99,3 +100,4 @@ do_execsql_test 3.3 {
} {1 2}
finish_test
+1
View File
@@ -342,3 +342,4 @@ foreach {tn expr} {
finish_test
+2
View File
@@ -240,6 +240,7 @@ foreach {tn lRow res} {
} {
execsql { DELETE FROM x1 }
foreach row $lRow { execsql { INSERT INTO x1 VALUES($row) } }
breakpoint
do_execsql_test 8.$tn {
SELECT highlight(x1, 0, '[', ']') FROM x1 WHERE x1 MATCH 'a OR (b AND d)';
} $res
@@ -278,3 +279,4 @@ do_execsql_test 9.3 {
finish_test
+1
View File
@@ -112,3 +112,4 @@ db eval {
}
finish_test
+1
View File
@@ -61,3 +61,4 @@ do_test 2.1...slow {
} {}
finish_test
+2
View File
@@ -64,3 +64,5 @@ foreach_detail_mode $::testprefix {
}
finish_test
-86
View File
@@ -1,86 +0,0 @@
# 2016 August 10
#
# 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 fts5colset
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
ifcapable !fts5 {
finish_test
return
}
foreach_detail_mode $::testprefix {
if {[detail_is_none]} continue
do_execsql_test 1.0 {
CREATE VIRTUAL TABLE t1 USING fts5(a, b, c, d, detail=%DETAIL%);
INSERT INTO t1 VALUES('a', 'b', 'c', 'd'); -- 1
INSERT INTO t1 VALUES('d', 'a', 'b', 'c'); -- 2
INSERT INTO t1 VALUES('c', 'd', 'a', 'b'); -- 3
INSERT INTO t1 VALUES('b', 'c', 'd', 'a'); -- 4
}
foreach {tn q res} {
1 "a" {1 2 3 4}
2 "{a} : a" {1}
3 "-{a} : a" {2 3 4}
4 "- {a c} : a" {2 4}
5 " - {d d c} : a" {1 2}
6 "- {d c b a} : a" {}
7 "-{\"a\"} : b" {1 2 3}
8 "- c : a" {1 2 4}
9 "-c : a" {1 2 4}
10 "-\"c\" : a" {1 2 4}
} {
do_execsql_test 1.$tn {
SELECT rowid FROM t1($q)
} $res
}
foreach {tn q res} {
0 {{a} : (a AND ":")} {}
1 "{a b c} : (a AND d)" {2 3}
2 "{a b c} : (a AND b:d)" {3}
3 "{a b c} : (a AND d:d)" {}
4 "{b} : ( {b a} : ( {c b a} : ( {d b c a} : ( d OR c ) ) ) )" {3 4}
5 "{a} : ( {b a} : ( {c b a} : ( {d b c a} : ( d OR c ) ) ) )" {2 3}
6 "{a} : ( {b a} : ( {c b} : ( {d b c a} : ( d OR c ) ) ) )" {}
7 "{a b c} : (b:a AND c:b)" {2}
} {
do_execsql_test 2.$tn {
SELECT rowid FROM t1($q)
} $res
}
foreach {tn w res} {
0 "a MATCH 'a'" {1}
1 "b MATCH 'a'" {2}
2 "b MATCH '{a b c} : a'" {2}
3 "b MATCH 'a OR b'" {1 2}
4 "b MATCH 'a OR a:b'" {2}
5 "b MATCH 'a OR b:b'" {1 2}
} {
do_execsql_test 3.$tn "
SELECT rowid FROM t1 WHERE $w
" $res
}
do_catchsql_test 4.1 {
SELECT * FROM t1 WHERE rowid MATCH 'a'
} {1 {unable to use function MATCH in the requested context}}
}
finish_test
+1
View File
@@ -143,6 +143,7 @@ do_execsql_test 4.1.1 {
INSERT INTO t5 VALUES('2 4 6 8');
}
breakpoint
do_execsql_test 4.1.2 {
INSERT INTO t5(t5) VALUES('integrity-check');
}
+16 -14
View File
@@ -66,7 +66,7 @@ foreach {tn val} {
} {
do_catchsql_test 3.$tn {
INSERT INTO t1(t1, rank) VALUES('rank', $val);
} {1 {SQL logic error}}
} {1 {SQL logic error or missing database}}
}
#-------------------------------------------------------------------------
@@ -110,6 +110,7 @@ do_catchsql_test 5.1 {
CREATE VIRTUAL TABLE xx USING fts5(x, tokenize="porter 'ascii");
} {1 {parse error in tokenize directive}}
breakpoint
do_catchsql_test 5.2 {
CREATE VIRTUAL TABLE xx USING fts5(x, [y[]);
} {0 {}}
@@ -168,33 +169,33 @@ do_execsql_test 9.0 {
} {}
do_catchsql_test 9.1.1 {
INSERT INTO abc(abc, rank) VALUES('pgsz', -5);
} {1 {SQL logic error}}
} {1 {SQL logic error or missing database}}
do_catchsql_test 9.1.2 {
INSERT INTO abc(abc, rank) VALUES('pgsz', 50000000);
} {1 {SQL logic error}}
} {1 {SQL logic error or missing database}}
do_catchsql_test 9.1.3 {
INSERT INTO abc(abc, rank) VALUES('pgsz', 66.67);
} {1 {SQL logic error}}
} {1 {SQL logic error or missing database}}
do_catchsql_test 9.2.1 {
INSERT INTO abc(abc, rank) VALUES('automerge', -5);
} {1 {SQL logic error}}
} {1 {SQL logic error or missing database}}
do_catchsql_test 9.2.2 {
INSERT INTO abc(abc, rank) VALUES('automerge', 50000000);
} {1 {SQL logic error}}
} {1 {SQL logic error or missing database}}
do_catchsql_test 9.2.3 {
INSERT INTO abc(abc, rank) VALUES('automerge', 66.67);
} {1 {SQL logic error}}
} {1 {SQL logic error or missing database}}
do_execsql_test 9.2.4 {
INSERT INTO abc(abc, rank) VALUES('automerge', 1);
} {}
do_catchsql_test 9.3.1 {
INSERT INTO abc(abc, rank) VALUES('crisismerge', -5);
} {1 {SQL logic error}}
} {1 {SQL logic error or missing database}}
do_catchsql_test 9.3.2 {
INSERT INTO abc(abc, rank) VALUES('crisismerge', 66.67);
} {1 {SQL logic error}}
} {1 {SQL logic error or missing database}}
do_execsql_test 9.3.3 {
INSERT INTO abc(abc, rank) VALUES('crisismerge', 1);
} {}
@@ -204,14 +205,14 @@ do_execsql_test 9.3.4 {
do_catchsql_test 9.4.1 {
INSERT INTO abc(abc, rank) VALUES('nosuchoption', 1);
} {1 {SQL logic error}}
} {1 {SQL logic error or missing database}}
do_catchsql_test 9.5.1 {
INSERT INTO abc(abc, rank) VALUES('hashsize', 'not an integer');
} {1 {SQL logic error}}
} {1 {SQL logic error or missing database}}
do_catchsql_test 9.5.2 {
INSERT INTO abc(abc, rank) VALUES('hashsize', -500000);
} {1 {SQL logic error}}
} {1 {SQL logic error or missing database}}
do_catchsql_test 9.5.3 {
INSERT INTO abc(abc, rank) VALUES('hashsize', 500000);
} {0 {}}
@@ -244,7 +245,7 @@ foreach {tn opt} {
do_catchsql_test 12.1 {
INSERT INTO t1(t1, rank) VALUES('rank', NULL);;
} {1 {SQL logic error}}
} {1 {SQL logic error or missing database}}
#-------------------------------------------------------------------------
# errors in the 'usermerge' option
@@ -259,7 +260,8 @@ foreach {tn val} {
4 1
} {
set sql "INSERT INTO tt(tt, rank) VALUES('usermerge', $val)"
do_catchsql_test 13.$tn $sql {1 {SQL logic error}}
do_catchsql_test 13.$tn $sql {1 {SQL logic error or missing database}}
}
finish_test
+2
View File
@@ -66,3 +66,5 @@ do_execsql_test 2.1 {
}
finish_test
-247
View File
@@ -1,247 +0,0 @@
# 2017 August 17
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#*************************************************************************
#
source [file join [file dirname [info script]] fts5_common.tcl]
set testprefix fts5connect
ifcapable !fts5 {
finish_test
return
}
#-------------------------------------------------------------------------
# The tests in this file test the outcome of a schema-reset happening
# within the xConnect() method of an FTS5 table. At one point this
# was causing a problem in SQLite. Each test proceeds as follows:
#
# 1. Connection [db] opens the db and reads from some unrelated, non-FTS5
# table causing SQLite to load the db schema into memory.
#
# 2. Connection [db2] opens the db and modifies the db schema.
#
# 3. Connection [db] reads or writes an existing fts5 table. That the
# schema has been modified is detected inside the fts5 xConnect()
# callback that is invoked by sqlite3_prepare().
#
# 4. Verify that the statement in 3 has worked. SQLite should detect
# that the schema has changed and successfully prepare the
# statement against the new schema.
#
# Test plan:
#
# 1.*: Trigger the xConnect()/schema-reset using statements executed
# directly against an FTS5 table.
#
# 2.*: Using various statements executed by various BEFORE triggers.
#
# 3.*: Using various statements executed by various AFTER triggers.
#
# 4.*: Using various statements executed by various INSTEAD OF triggers.
#
do_execsql_test 1.0 {
CREATE VIRTUAL TABLE ft1 USING fts5(a, b);
CREATE TABLE abc(x INTEGER PRIMARY KEY);
CREATE TABLE t1(i INTEGER PRIMARY KEY, a, b);
INSERT INTO ft1 VALUES('one', 'two');
INSERT INTO ft1 VALUES('three', 'four');
}
foreach {tn sql res} {
1 "SELECT * FROM ft1" {one two three four}
2 "REPLACE INTO ft1(rowid, a, b) VALUES(1, 'five', 'six')" {}
3 "SELECT * FROM ft1" {five six three four}
4 "INSERT INTO ft1 VALUES('seven', 'eight')" {}
5 "SELECT * FROM ft1" {five six three four seven eight}
6 "DELETE FROM ft1 WHERE rowid=2" {}
7 "UPDATE ft1 SET b='nine' WHERE rowid=1" {}
8 "SELECT * FROM ft1" {five nine seven eight}
} {
catch { db close }
catch { db2 close }
sqlite3 db test.db
sqlite3 db2 test.db
do_test 1.$tn.1 {
db eval { INSERT INTO abc DEFAULT VALUES }
db2 eval { CREATE TABLE newtable(x,y); DROP TABLE newtable }
} {}
do_execsql_test 1.$tn.2 $sql $res
do_execsql_test 1.$tn.3 {
INSERT INTO ft1(ft1) VALUES('integrity-check');
}
}
do_execsql_test 2.0 {
CREATE VIRTUAL TABLE ft2 USING fts5(a, b);
CREATE TABLE t2(a, b);
CREATE TABLE log(txt);
CREATE TRIGGER t2_ai AFTER INSERT ON t2 BEGIN
INSERT INTO ft2(rowid, a, b) VALUES(new.rowid, new.a, new.b);
INSERT INTO log VALUES('insert');
END;
CREATE TRIGGER t2_ad AFTER DELETE ON t2 BEGIN
DELETE FROM ft2 WHERE rowid = old.rowid;
INSERT INTO log VALUES('delete');
END;
CREATE TRIGGER t2_au AFTER UPDATE ON t2 BEGIN
UPDATE ft2 SET a=new.a, b=new.b WHERE rowid=new.rowid;
INSERT INTO log VALUES('update');
END;
INSERT INTO t2 VALUES('one', 'two');
INSERT INTO t2 VALUES('three', 'four');
}
foreach {tn sql res} {
1 "SELECT * FROM t2" {one two three four}
2 "REPLACE INTO t2(rowid, a, b) VALUES(1, 'five', 'six')" {}
3 "SELECT * FROM ft2" {five six three four}
4 "INSERT INTO t2 VALUES('seven', 'eight')" {}
5 "SELECT * FROM ft2" {five six three four seven eight}
6 "DELETE FROM t2 WHERE rowid=2" {}
7 "UPDATE t2 SET b='nine' WHERE rowid=1" {}
8 "SELECT * FROM ft2" {five nine seven eight}
} {
catch { db close }
catch { db2 close }
sqlite3 db test.db
sqlite3 db2 test.db
do_test 2.$tn.1 {
db eval { INSERT INTO abc DEFAULT VALUES }
db2 eval { CREATE TABLE newtable(x,y); DROP TABLE newtable }
} {}
do_execsql_test 2.$tn.2 $sql $res
do_execsql_test 2.$tn.3 {
INSERT INTO ft2(ft2) VALUES('integrity-check');
}
}
do_execsql_test 3.0 {
CREATE VIRTUAL TABLE ft3 USING fts5(a, b);
CREATE TABLE t3(a, b);
CREATE TRIGGER t3_ai BEFORE INSERT ON t3 BEGIN
INSERT INTO ft3(rowid, a, b) VALUES(new.rowid, new.a, new.b);
INSERT INTO log VALUES('insert');
END;
CREATE TRIGGER t3_ad BEFORE DELETE ON t3 BEGIN
DELETE FROM ft3 WHERE rowid = old.rowid;
INSERT INTO log VALUES('delete');
END;
CREATE TRIGGER t3_au BEFORE UPDATE ON t3 BEGIN
UPDATE ft3 SET a=new.a, b=new.b WHERE rowid=new.rowid;
INSERT INTO log VALUES('update');
END;
INSERT INTO t3(rowid, a, b) VALUES(1, 'one', 'two');
INSERT INTO t3(rowid, a, b) VALUES(2, 'three', 'four');
}
foreach {tn sql res} {
1 "SELECT * FROM t3" {one two three four}
2 "REPLACE INTO t3(rowid, a, b) VALUES(1, 'five', 'six')" {}
3 "SELECT * FROM ft3" {five six three four}
4 "INSERT INTO t3(rowid, a, b) VALUES(3, 'seven', 'eight')" {}
5 "SELECT * FROM ft3" {five six three four seven eight}
6 "DELETE FROM t3 WHERE rowid=2" {}
7 "UPDATE t3 SET b='nine' WHERE rowid=1" {}
8 "SELECT * FROM ft3" {five nine seven eight}
} {
catch { db close }
catch { db2 close }
sqlite3 db test.db
sqlite3 db2 test.db
do_test 3.$tn.1 {
db eval { INSERT INTO abc DEFAULT VALUES }
db2 eval { CREATE TABLE newtable(x,y); DROP TABLE newtable }
} {}
do_execsql_test 3.$tn.2 $sql $res
do_execsql_test 3.$tn.3 {
INSERT INTO ft3(ft3) VALUES('integrity-check');
}
}
do_execsql_test 4.0 {
CREATE VIRTUAL TABLE ft4 USING fts5(a, b);
CREATE VIEW v4 AS SELECT rowid, * FROM ft4;
CREATE TRIGGER t4_ai INSTEAD OF INSERT ON v4 BEGIN
INSERT INTO ft4(rowid, a, b) VALUES(new.rowid, new.a, new.b);
INSERT INTO log VALUES('insert');
END;
CREATE TRIGGER t4_ad INSTEAD OF DELETE ON v4 BEGIN
DELETE FROM ft4 WHERE rowid = old.rowid;
INSERT INTO log VALUES('delete');
END;
CREATE TRIGGER t4_au INSTEAD OF UPDATE ON v4 BEGIN
UPDATE ft4 SET a=new.a, b=new.b WHERE rowid=new.rowid;
INSERT INTO log VALUES('update');
END;
INSERT INTO ft4(rowid, a, b) VALUES(1, 'one', 'two');
INSERT INTO ft4(rowid, a, b) VALUES(2, 'three', 'four');
}
foreach {tn sql res} {
1 "SELECT * FROM ft4" {one two three four}
2 "REPLACE INTO v4(rowid, a, b) VALUES(1, 'five', 'six')" {}
3 "SELECT * FROM ft4" {five six three four}
4 "INSERT INTO v4(rowid, a, b) VALUES(3, 'seven', 'eight')" {}
5 "SELECT * FROM ft4" {five six three four seven eight}
6 "DELETE FROM v4 WHERE rowid=2" {}
7 "UPDATE v4 SET b='nine' WHERE rowid=1" {}
8 "SELECT * FROM ft4" {five nine seven eight}
} {
catch { db close }
catch { db2 close }
sqlite3 db test.db
sqlite3 db2 test.db
do_test 4.$tn.1 {
db eval { INSERT INTO abc DEFAULT VALUES }
db2 eval { CREATE TABLE newtable(x,y); DROP TABLE newtable }
} {}
do_execsql_test 4.$tn.2 $sql $res
do_execsql_test 4.$tn.3 {
INSERT INTO ft3(ft3) VALUES('integrity-check');
}
}
finish_test
+1
View File
@@ -255,3 +255,4 @@ do_execsql_test 6.2 {
finish_test
+1
View File
@@ -96,3 +96,4 @@ do_catchsql_test 3.1 {
} {1 {database disk image is malformed}}
finish_test
+4 -3
View File
@@ -37,7 +37,7 @@ do_execsql_test 1.0 {
}
set mask [expr 31 << 31]
if 0 {
if 1 {
# Test 1:
#
@@ -84,8 +84,6 @@ foreach {tno stmt} {
}
}
}
# Using the same database as the 1.* tests.
#
# Run N-1 tests, where N is the number of bytes in the rightmost leaf page
@@ -214,6 +212,8 @@ foreach {tn nCut} {
# do_test 4.$tn.x { expr $nCorrupt>0 } 1
}
}
set doc [string repeat "A B C " 1000]
do_execsql_test 5.0 {
CREATE VIRTUAL TABLE x5 USING fts5(tt);
@@ -269,3 +269,4 @@ do_catchsql_test 6.2 {
sqlite3_fts5_may_be_corrupt 0
finish_test
+1
View File
@@ -409,3 +409,4 @@ do_catchsql_test 9.2.2 {
sqlite3_fts5_may_be_corrupt 0
finish_test
-53
View File
@@ -1,53 +0,0 @@
# 2017 May 12
#
# 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 fts5delete
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
ifcapable !fts5 {
finish_test
return
}
fts5_aux_test_functions db
do_execsql_test 1.0 {
CREATE VIRTUAL TABLE t1 USING fts5(x);
WITH s(i) AS (
SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<5000
)
INSERT INTO t1(rowid, x) SELECT i, (i/2)*2 FROM s;
}
do_test 1.1 {
execsql BEGIN
for {set i 1} {$i<=5000} {incr i} {
if {$i % 2} {
execsql { INSERT INTO t1 VALUES($i) }
} else {
execsql { DELETE FROM t1 WHERE rowid = $i }
}
}
execsql COMMIT
} {}
do_test 1.2 {
execsql { INSERT INTO t1(t1, rank) VALUES('usermerge', 2); }
for {set i 0} {$i < 5} {incr i} {
execsql { INSERT INTO t1(t1, rank) VALUES('merge', 1) }
execsql { INSERT INTO t1(t1) VALUES('integrity-check') }
}
} {}
finish_test
+1
View File
@@ -241,3 +241,4 @@ do_execsql_test 5.3 {
finish_test
+2
View File
@@ -63,3 +63,5 @@ foreach_detail_mode $::testprefix {
finish_test
+3
View File
@@ -66,6 +66,7 @@ proc do_dlidx_test1 {tn spc1 spc2 nEntry iFirst nStep} {
}
execsql COMMIT
breakpoint
do_test $tn.1 {
execsql { INSERT INTO t1(t1) VALUES('integrity-check') }
} {}
@@ -123,6 +124,7 @@ proc do_dlidx_test2 {tn nEntry iFirst nStep} {
do_execsql_test $tn.1 {
SELECT rowid FROM t1 WHERE t1 MATCH 'b AND a'
} {1}
breakpoint
do_execsql_test $tn.2 {
SELECT rowid FROM t1 WHERE t1 MATCH 'b AND a' ORDER BY rowid DESC
} {1}
@@ -195,3 +197,4 @@ foreach v $vocab {
finish_test
+1
View File
@@ -44,3 +44,4 @@ do_execsql_test 1.2 {
finish_test
+3 -17
View File
@@ -63,21 +63,7 @@ do_catchsql_test 2.1 {
SELECT fts5_expr_tcl()
} {1 {wrong number of arguments to function fts5_expr_tcl}}
do_execsql_test 3.0 {
CREATE VIRTUAL TABLE e1 USING fts5(text, tokenize = 'porter unicode61');
INSERT INTO e1 VALUES ("just a few words with a / inside");
}
do_execsql_test 3.1 {
SELECT rowid, bm25(e1) FROM e1 WHERE e1 MATCH '"just"' ORDER BY rank;
} {1 -1e-06}
do_execsql_test 3.2 {
SELECT rowid FROM e1 WHERE e1 MATCH '"/" OR "just"'
} 1
do_execsql_test 3.3 {
SELECT rowid, bm25(e1) FROM e1 WHERE e1 MATCH '"/" OR "just"' ORDER BY rank;
} {1 -1e-06}
finish_test
+1
View File
@@ -351,3 +351,4 @@ do_faultsim_test 9.1 -faults oom-* -prep {
finish_test
+1
View File
@@ -137,3 +137,4 @@ do_faultsim_test 5.0 -faults oom-* -prep {
}
finish_test
+1
View File
@@ -110,3 +110,4 @@ do_faultsim_test 3.2 -faults oom-* -prep {
finish_test
+1
View File
@@ -395,3 +395,4 @@ do_faultsim_test 14.1 -faults oom-t* -prep {
}
finish_test
+2
View File
@@ -105,6 +105,7 @@ do_faultsim_test 3.2 -faults oom-t* -body {
faultsim_test_result {0 {1 10 11 12 13 14 15 16 17 18 19 2}}
}
breakpoint
do_execsql_test 3.3.0 {
SELECT * FROM tv2;
} {
@@ -129,3 +130,4 @@ do_faultsim_test 3.3 -faults oom-t* -body {
finish_test
+5 -3
View File
@@ -253,7 +253,7 @@ do_faultsim_test 5.2 -faults oom* -prep {
SELECT rowid, mit(matchinfo(t1, 'x')) FROM t1 WHERE t1 MATCH 'a AND c'
}
} -test {
faultsim_test_result [list 0 $::res] {1 {SQL logic error}}
faultsim_test_result [list 0 $::res]
}
do_faultsim_test 5.3 -faults oom* -prep {
@@ -264,7 +264,7 @@ do_faultsim_test 5.3 -faults oom* -prep {
SELECT count(*) FROM t1 WHERE t1 MATCH 'd AND e AND f'
}
} -test {
faultsim_test_result {0 29} {1 {SQL logic error}}
faultsim_test_result {0 29}
}
do_faultsim_test 5.4 -faults oom* -prep {
@@ -275,11 +275,12 @@ do_faultsim_test 5.4 -faults oom* -prep {
SELECT count(*) FROM t1 WHERE t1 MATCH 'x + e'
}
} -test {
faultsim_test_result {0 1} {1 {SQL logic error}}
faultsim_test_result {0 1}
}
#-------------------------------------------------------------------------
catch { db close }
breakpoint
do_faultsim_test 6 -faults oom* -prep {
sqlite_orig db test.db
sqlite3_db_config_lookaside db 0 0 0
@@ -291,3 +292,4 @@ do_faultsim_test 6 -faults oom* -prep {
db close
}
finish_test
+1
View File
@@ -116,3 +116,4 @@ do_faultsim_test 2.2 -faults oom-* -body {
}
finish_test
+1
View File
@@ -82,3 +82,4 @@ do_faultsim_test 4 -faults oom-* -prep {
finish_test
+3 -6
View File
@@ -24,8 +24,6 @@ ifcapable !fts5 {
foreach_detail_mode $testprefix {
if {"%DETAIL%" != "none"} continue
fts5_aux_test_functions db
do_execsql_test 1.0 {
@@ -100,16 +98,14 @@ do_faultsim_test 4.1 -faults oom-t* -body {
execsql { SELECT rowid, fts5_test_collist(t4) FROM t4('2') }
} -test {
faultsim_test_result \
{0 {1 {0.0 0.1 0.2} 2 {0.0 0.1 0.2} 3 {0.0 0.1 0.2}}} \
{1 SQLITE_NOMEM} {1 SQLITE_ERROR} {1 {SQL logic error}}
{0 {1 {0.0 0.1 0.2} 2 {0.0 0.1 0.2} 3 {0.0 0.1 0.2}}} {1 SQLITE_NOMEM}
}
do_faultsim_test 4.2 -faults oom-t* -body {
execsql { SELECT rowid, fts5_test_collist(t4) FROM t4('a5 OR b5 OR c5') }
} -test {
faultsim_test_result \
{0 {4 {0.0 0.1 0.2} 5 {1.0 1.1 1.2} 6 {2.0 2.1 2.2}}} \
{1 SQLITE_NOMEM} {1 SQLITE_ERROR} {1 {SQL logic error}}
{0 {4 {0.0 0.1 0.2} 5 {1.0 1.1 1.2} 6 {2.0 2.1 2.2}}} {1 SQLITE_NOMEM}
}
@@ -157,3 +153,4 @@ do_faultsim_test 6 -faults oom-* -body {
} ;# foreach_detail_mode...
finish_test
+1
View File
@@ -61,3 +61,4 @@ do_faultsim_test 2 -faults oom* -prep {
faultsim_test_result {0 {1 2}}
}
finish_test
+1 -69
View File
@@ -78,74 +78,6 @@ do_faultsim_test 2.4 -faults oom* -body {
faultsim_test_result {0 {{3 2} {2 3}}}
}
#-------------------------------------------------------------------------
#
reset_db
do_execsql_test 3.0 {
CREATE VIRTUAL TABLE x1 USING fts5(z);
}
do_faultsim_test 3.1 -faults oom* -body {
execsql {
SELECT rowid FROM x1('c') WHERE rowid>1;
}
} -test {
faultsim_test_result {0 {}}
}
do_execsql_test 3.2 {
INSERT INTO x1 VALUES('a b c');
INSERT INTO x1 VALUES('b c d');
INSERT INTO x1 VALUES('c d e');
INSERT INTO x1 VALUES('d e f');
}
do_faultsim_test 3.3 -faults oom* -body {
execsql {
SELECT rowid FROM x1('c') WHERE rowid>1;
}
} -test {
faultsim_test_result {0 {2 3}}
}
#-------------------------------------------------------------------------
# Test OOM injection with nested colsets.
#
reset_db
do_execsql_test 4.0 {
CREATE VIRTUAL TABLE t1 USING fts5(a, b, c, d);
INSERT INTO t1 VALUES('a', 'b', 'c', 'd'); -- 1
INSERT INTO t1 VALUES('d', 'a', 'b', 'c'); -- 2
INSERT INTO t1 VALUES('c', 'd', 'a', 'b'); -- 3
INSERT INTO t1 VALUES('b', 'c', 'd', 'a'); -- 4
}
do_faultsim_test 4.1 -faults oom* -body {
execsql { SELECT rowid FROM t1('{a b c} : (b:a AND c:b)'); }
} -test {
faultsim_test_result {0 2}
}
do_faultsim_test 4.2 -faults oom* -body {
execsql { SELECT rowid FROM t1('{a b c} : (a AND d)') }
} -test {
faultsim_test_result {0 {2 3}}
}
#-------------------------------------------------------------------------
# Test OOM injection while parsing a CARET expression
#
reset_db
do_execsql_test 5.0 {
CREATE VIRTUAL TABLE t1 USING fts5(a);
INSERT INTO t1 VALUES('a b c d'); -- 1
INSERT INTO t1 VALUES('d a b c'); -- 2
INSERT INTO t1 VALUES('c d a b'); -- 3
INSERT INTO t1 VALUES('b c d a'); -- 4
}
do_faultsim_test 5.1 -faults oom* -body {
execsql { SELECT rowid FROM t1('^a OR ^b') }
} -test {
faultsim_test_result {0 {1 4}}
}
finish_test
-87
View File
@@ -1,87 +0,0 @@
# 2016 February 2
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#*************************************************************************
#
# This file is focused on OOM errors.
#
source [file join [file dirname [info script]] fts5_common.tcl]
source $testdir/malloc_common.tcl
set testprefix fts5faultA
# If SQLITE_ENABLE_FTS3 is defined, omit this file.
ifcapable !fts5 {
finish_test
return
}
foreach_detail_mode $testprefix {
if {"%DETAIL%"=="none"} continue
do_execsql_test 1.0 {
CREATE VIRTUAL TABLE o1 USING fts5(a, b, c, detail=%DETAIL%);
INSERT INTO o1(o1, rank) VALUES('pgsz', 32);
WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<60 )
INSERT INTO o1 SELECT 'A', 'B', 'C' FROM s;
WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<60 )
INSERT INTO o1 SELECT 'C', 'A', 'B' FROM s;
WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<60 )
INSERT INTO o1 SELECT 'B', 'C', 'A' FROM s;
}
do_faultsim_test 1 -faults int* -prep {
sqlite3 db test.db
} -body {
execsql { SELECT count(*) FROM o1('a') }
} -test {
faultsim_test_result {0 180} {1 {vtable constructor failed: o1}}
}
do_faultsim_test 2 -faults int* -prep {
sqlite3 db test.db
} -body {
execsql { SELECT * FROM o1('a:a AND {b c}:b') ORDER BY rank }
expr 1
} -test {
faultsim_test_result {0 1} {1 {vtable constructor failed: o1}}
}
do_faultsim_test 3 -faults int* -prep {
sqlite3 db test.db
} -body {
execsql { SELECT * FROM o1('{b c}:b NOT a:a') ORDER BY rank }
expr 1
} -test {
faultsim_test_result {0 1} {1 {vtable constructor failed: o1}}
}
do_faultsim_test 4 -faults int* -prep {
sqlite3 db test.db
} -body {
execsql { SELECT * FROM o1('b:b OR a:a') }
expr 1
} -test {
faultsim_test_result {0 1} {1 {vtable constructor failed: o1}}
}
do_faultsim_test 5 -faults int* -prep {
sqlite3 db test.db
} -body {
execsql { SELECT count(*) FROM o1('c:b') }
expr 1
} -test {
faultsim_test_result {0 1} {1 {vtable constructor failed: o1}}
}
}
finish_test
-96
View File
@@ -1,96 +0,0 @@
# 2017 November 25
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
source [file join [file dirname [info script]] fts5_common.tcl]
set testprefix fts5first
ifcapable !fts5 {
finish_test
return
}
do_execsql_test 1.0 {
CREATE VIRTUAL TABLE x1 USING fts5(a, b);
}
foreach {tn expr ok} {
1 {^abc} 1
2 {^abc + def} 1
3 {^ "abc def"} 1
4 {^"abc def"} 1
5 {abc ^def} 1
6 {abc + ^def} 0
7 {abc ^+ def} 0
8 {"^abc"} 1
9 {NEAR(^abc def)} 0
} {
set res(0) {/1 {fts5: syntax error near .*}/}
set res(1) {0 {}}
do_catchsql_test 1.$tn { SELECT * FROM x1($expr) } $res($ok)
}
#-------------------------------------------------------------------------
#
do_execsql_test 2.0 {
INSERT INTO x1 VALUES('a b c', 'b c a');
}
foreach {tn expr match} {
1 {^a} 1
2 {^b} 1
3 {^c} 0
4 {^a + b} 1
5 {^b + c} 1
6 {^c + a} 0
7 {^"c a"} 0
8 {a:^a} 1
9 {a:^b} 0
10 {a:^"a b"} 1
} {
do_execsql_test 2.$tn { SELECT EXISTS (SELECT rowid FROM x1($expr)) } $match
}
#-------------------------------------------------------------------------
#
do_execsql_test 3.0 {
DELETE FROM x1;
INSERT INTO x1 VALUES('b a', 'c a');
INSERT INTO x1 VALUES('a a', 'c c');
INSERT INTO x1 VALUES('a b', 'a a');
}
fts5_aux_test_functions db
foreach {tn expr expect} {
1 {^a} {{2 1}}
2 {^c AND ^b} {{0 2} {1 0}}
} {
do_execsql_test 3.$tn {
SELECT fts5_test_queryphrase(x1) FROM x1($expr) LIMIT 1
} [list $expect]
}
#-------------------------------------------------------------------------
#
do_execsql_test 3.1 {
CREATE VIRTUAL TABLE x2 USING fts5(a, b, c, detail=column);
}
do_catchsql_test 3.2 {
SELECT * FROM x2('a + b');
} {1 {fts5: phrase queries are not supported (detail!=full)}}
do_catchsql_test 3.3 {
SELECT * FROM x2('^a');
} {1 {fts5: phrase queries are not supported (detail!=full)}}
finish_test
+1
View File
@@ -40,3 +40,4 @@ do_test 1.1 {
finish_test
+1
View File
@@ -90,3 +90,4 @@ do_catchsql_test 4.1 {
} {1 {fts5: syntax error near "`"}}
finish_test
+2
View File
@@ -121,6 +121,7 @@ foreach_detail_mode $testprefix {
}
execsql { CREATE VIRTUAL TABLE t2 USING fts5(x, detail=%DETAIL%) }
breakpoint
execsql {
INSERT INTO t2 VALUES($small || ' ' || $big);
}
@@ -129,3 +130,4 @@ foreach_detail_mode $testprefix {
} ;# foreach_detail_mode
finish_test
+1
View File
@@ -210,3 +210,4 @@ foreach {tn pgsz} {
}
finish_test
-72
View File
@@ -1,72 +0,0 @@
# 2017 Feb 27
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
#
# Tests of the last_insert_rowid functionality with fts5.
#
source [file join [file dirname [info script]] fts5_common.tcl]
set testprefix fts5lastrowid
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
ifcapable !fts5 {
finish_test
return
}
do_execsql_test 1.0 {
CREATE VIRTUAL TABLE t1 USING fts5(str);
}
do_execsql_test 1.1 {
INSERT INTO t1 VALUES('one string');
INSERT INTO t1 VALUES('two string');
INSERT INTO t1 VALUES('three string');
SELECT last_insert_rowid();
} {3}
do_execsql_test 1.2 {
BEGIN;
INSERT INTO t1 VALUES('one string');
INSERT INTO t1 VALUES('two string');
INSERT INTO t1 VALUES('three string');
COMMIT;
SELECT last_insert_rowid();
} {6}
do_execsql_test 1.3 {
INSERT INTO t1(rowid, str) VALUES(-22, 'some more text');
SELECT last_insert_rowid();
} {-22}
do_execsql_test 1.4 {
BEGIN;
INSERT INTO t1(rowid, str) VALUES(45, 'some more text');
INSERT INTO t1(rowid, str) VALUES(46, 'some more text');
INSERT INTO t1(rowid, str) VALUES(222, 'some more text');
SELECT last_insert_rowid();
COMMIT;
SELECT last_insert_rowid();
} {222 222}
do_execsql_test 1.5 {
CREATE TABLE x1(x);
INSERT INTO x1 VALUES('john'), ('paul'), ('george'), ('ringo');
INSERT INTO t1 SELECT x FROM x1;
SELECT last_insert_rowid();
} {226}
do_execsql_test 1.6 {
INSERT INTO t1(rowid, str) SELECT rowid+10, x FROM x1;
SELECT last_insert_rowid();
} {14}
finish_test
-43
View File
@@ -1,43 +0,0 @@
# 2014 June 17
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#*************************************************************************
# This file implements 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 fts5leftjoin
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
ifcapable !fts5 {
finish_test
return
}
do_execsql_test 1.0 {
CREATE VIRTUAL TABLE vt USING fts5(x);
INSERT INTO vt VALUES('abc');
INSERT INTO vt VALUES('xyz');
CREATE TABLE t1(a INTEGER PRIMARY KEY);
INSERT INTO t1 VALUES(1), (2);
}
do_execsql_test 1.1 {
SELECT * FROM t1 LEFT JOIN (
SELECT rowid AS rrr, * FROM vt WHERE vt MATCH 'abc'
) ON t1.a = rrr
} {1 1 abc 2 {} {}}
do_execsql_test 1.2 {
SELECT * FROM t1 LEFT JOIN vt ON (vt MATCH 'abc')
} {1 abc 2 abc}
finish_test
+2 -1
View File
@@ -472,7 +472,7 @@ do_execsql_test 12.1 {
#
reset_db
proc xyz {} {}
db func fts5 -argcount 1 xyz
db func fts5 -argcount 0 xyz
do_test 13.1 {
list [catch { sqlite3_fts5_register_matchinfo db } msg] $msg
} {1 SQLITE_ERROR}
@@ -492,3 +492,4 @@ do_catchsql_test 14.2 {
} {1 {unrecognized matchinfo flag: d}}
finish_test
+1
View File
@@ -241,3 +241,4 @@ do_execsql_test 6.3 {
finish_test

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