Compare commits

...

88 Commits

Author SHA1 Message Date
drh 91694dbdd2 Test cases for sqlite3_normalize().
FossilOrigin-Name: 658f42257d56a3562dfa8e55023c6e497f55c565cd751d942de3a9e0cb2fa708
2018-01-08 20:04:57 +00:00
drh d19866bb98 Special handling of the NULL keyword. Sometimes it is a literal, and sometimes
it is a keyword.

FossilOrigin-Name: db5d138e97f22ad4d4d11dbef96df93696ba0e557809066bc263ca3c3898f349
2018-01-08 19:29:28 +00:00
drh ef42481224 Add IN-operator normalizating and the SQLITE_NORMALIZE_CLI compile-time
option for generating a stand-alone program.

FossilOrigin-Name: d77dbb398afa80c1b3373c55f278491e83d5c80ddc22dbc303876bdcbc127df9
2018-01-08 19:18:27 +00:00
drh a41f2855e9 First code for an auxiliary function that will normalize an SQL statement.
FossilOrigin-Name: 84814aac81e54f03430f180926156ab0fc01e22bbce2bb228b698ea0d4a588ea
2018-01-08 16:54:26 +00:00
drh a5da4ef4ad Avoid the use of utimensat() on older unix platforms.
FossilOrigin-Name: 90cb01d8d6ac12d0b88f2952a75aeefa81ba66f5e4a5377fdd8b9f86aec8e927
2018-01-07 23:28:10 +00:00
drh 03491a1a1a Remove the dependency on test_windirent.h from the generated shell.c file.
FossilOrigin-Name: 0a50c9e3bb0dbdaaec819ac6453276ba287b475ea322918ddda1ab3a1ec4b58b
2018-01-07 21:58:17 +00:00
drh 8682e12190 Modify the sqltclsh startup script to look for a properly formatted
SQLAR at the end of the executable.  Fix the CLI so that it automatically
links against appendvfs and so that the --append command-line option works.

FossilOrigin-Name: 67c4a8c6881e33b830aa27c80e7e3d697a4222939edd77cd5ca77ece16471ea4
2018-01-07 20:38:10 +00:00
drh acd6fdee98 Improved comments on the sqlar.c and compress.c extensions that describe
the differences between the "zlib format" used by SQLAR, the raw deflate
format used by ZIP, and the custom format used by compress.c.  No changes
to code.

FossilOrigin-Name: c13415c5caf06eaa73086c500907451dfcdfd1354ac4a9ab63edb7255edbfa1b
2018-01-07 19:52:28 +00:00
drh 1fa6d9f96f The shell detects and opens ZIP archives using the zipfile extension.
FossilOrigin-Name: 05c99eb8cefbb3366b6d4ae91e10aa0c82bdf5ea361f4b3375413783af9167ac
2018-01-06 21:46:01 +00:00
drh e37c0e1ce7 In the shell, include the ".archive" command only if compiling with
SQLITE_HAVE_ZLIB.  Add ".archive" to the ".help" output.

FossilOrigin-Name: 366469f5603367fabcadfc9ffe8cd1e23c649fea49a560178ca0858a16a7e4d1
2018-01-06 19:19:50 +00:00
drh afba1802a0 Better whitespace in the "CREATE TABLE sqlar()" statement for the ".ar"
command.

FossilOrigin-Name: 252ee55a7fc0b068b707af27bd912e684c28320996e78f0675217046b8c2fb49
2018-01-06 15:49:57 +00:00
drh 11be81d413 Improved output from ".schema --indent" when a column definition is followed
by a comment.

FossilOrigin-Name: 87da7efff07327278b1437f862ed8683c2d5d6ada7ea7461601a58f9762646b4
2018-01-06 15:46:20 +00:00
mistachkin 5e6f782f11 Remove a trailing tab from the Makefile for MSVC.
FossilOrigin-Name: 00cc26e34d2b81f140b031aa2f9ae0e2a4835cdd261d68f94b3e18a1388ca73d
2018-01-06 14:44:29 +00:00
mistachkin 0476b95c43 Minor tweaks to the Makefile for MSVC.
FossilOrigin-Name: 2f6cc5d8a0d9d961d1daf46e8725f7373f740afa788cf99ede9689f49d3a54ec
2018-01-06 14:43:33 +00:00
drh 4574db78a4 Add the appendvfs extension and code for the sqltclsh.exe executable.
FossilOrigin-Name: b0a43e325c53ec0df50fd41acffbbee65eac47b9318868e6959cd39da66fa8d6
2018-01-06 13:42:27 +00:00
drh 6b9986e84a Fix the appendvfs so that it leaves sqlite3_file->pMethods as NULL if it
fails to open.

FossilOrigin-Name: 46b341e3ad11b807ae50f001b970299de7ea0d523dbb639ee10f1d5aca5d958b
2018-01-06 13:33:21 +00:00
drh 9dea173154 Add sqltclsh.exe to the windows makefile.
FossilOrigin-Name: a6d5c7c2aabd70b4fb2bd8f6278f70272a5bd166adf2f7225ea582e10a46fafa
2018-01-06 04:34:05 +00:00
drh 1e506b5527 Make sure i64 and u64 typedefs are available throughout shell.c.
FossilOrigin-Name: 656fb5aab32f40412389e43de209867cedee1589533949cc8c01ba24218ea434
2018-01-05 21:01:37 +00:00
drh f5c75626ff Fix the shell.c.in amalgamator script so that it avoids generating
redundant typedef statements.

FossilOrigin-Name: 6c53c740cb4f62305689ea0a73beca83e71ed86707094e850bed975965c8c9f2
2018-01-05 20:30:54 +00:00
mistachkin 2f74b3c3ab MinGW does not define the S_ISLNK macro; therefore, define it in the shell when needed.
FossilOrigin-Name: 73023febbe57495a22db05904bd6ddff439d6c25970cbe87e0ba4a923f3e8a29
2018-01-05 20:26:06 +00:00
mistachkin f2e8aa637e Skip running the 'zipfile' test if the necessary static package cannot be loaded.
FossilOrigin-Name: 5bc816ec4010c20407396a1051e9f9b0a360ca27c0a99dafa867225cf974e306
2018-01-05 20:13:33 +00:00
mistachkin acae8c3e5d Fix shell compilation with MinGW by including the 'dirent.h' header.
FossilOrigin-Name: dfe510b51046a53c7f5c54fe73ec9de3364923eabd4b909c11984552e6bea406
2018-01-05 20:08:46 +00:00
drh 411dfd4e6d Fix the autoconf makefile so that it builds testfixture correctly.
FossilOrigin-Name: fbfe04c0b4f261789cbda3d2e98d12508181c283eab0bb757b081f0383e891bd
2018-01-05 19:49:54 +00:00
mistachkin b3ec2e1f4a Sync up the autoconf Makefile for MSVC.
FossilOrigin-Name: da8712bdb8f69dee9efb42b74d0b2ec10043f281c5f93e2724078bdf1370ecb1
2018-01-05 19:28:16 +00:00
mistachkin 992fdfc5d8 The 'releasetest' tool should pass the TCLDIR macro for MSVC to nmake.
FossilOrigin-Name: eaa9c0dda73808f1458f9968be59947636fbd4781c9fc535eb50bcaf790093c1
2018-01-05 19:27:19 +00:00
mistachkin 370732a83a For the MSVC Makefile, the 'sqlite3_checker.exe' target requires the Tcl library.
FossilOrigin-Name: 38109a47ffa977f1f962af2e183285d4e5db6fac2344868c5f1de64779dd0839
2018-01-05 19:25:52 +00:00
drh b2b7274e10 Add the ".ar" command to the command-line shell.
FossilOrigin-Name: 148b8aee78e40cab9a758a920589bd3ca8fc1c45cc93598bc50d96b85cd17e6c
2018-01-05 19:01:05 +00:00
drh 7ee8836e08 Fix a bug introduced by efforts to reduce compiler warnings in
check-in [364ac333b030f0]

FossilOrigin-Name: 1d6cee9ad448b10e69f351ef9dbec09110c5b189cba8734e637f41abe8f35bf8
2018-01-05 18:51:25 +00:00
mistachkin af23899318 In the Makefile for MSVC, the default target should not include binaries that link against the Tcl library.
FossilOrigin-Name: 5c6d0a1d58533feb4ea6926f4d3611664a275ad216492b424056276da38e84a2
2018-01-05 17:40:38 +00:00
mistachkin 5d7503a789 More adjustments to MSVC Makefile dependencies for zlib.
FossilOrigin-Name: bb650e5d14642b925c5ea65ba7991b35c4e941405d2557d542b99c66ca4bc130
2018-01-05 17:12:13 +00:00
mistachkin 9a5efdec70 Fix compiler warnings.
FossilOrigin-Name: 19aabccfe34c956599f33cd3ddc846816adc06784c2496838f1ef53059e038e5
2018-01-05 17:10:49 +00:00
drh c932033630 Fix missing dependencies for shell.c in all makefiles.
FossilOrigin-Name: 45495d3e256fef4d0669754726878ed17248fc781397ebb0421149ee9492f977
2018-01-05 16:23:43 +00:00
mistachkin 590522c18e In the Makefile for MSVC, only attempt to link against Tcl when it is needed. Also, only compile 'zipfile.c' when use of zlib is enabled.
FossilOrigin-Name: a33ad33cf031edee273afa4735c8564870465be22962a9c277e4ac43a307ff2c
2018-01-05 16:05:51 +00:00
mistachkin 91f7211caa Add some missing #ifdefs for building without zlib.
FossilOrigin-Name: c63fb1700c0f67d90857b1f3859c203880d0939f356a64d8ae7cafc814ea72bf
2018-01-05 16:03:52 +00:00
drh af2770f842 Fix compiler warnings.
FossilOrigin-Name: 364ac333b030f0e3372937df723f1098183da87913ba0e8ae162864ee24a50d3
2018-01-05 14:55:43 +00:00
dan 303b02cc0b Fix an LSM problem causing the wrong amount of "auto-work" to be performed
under fairly obscure circumstances.

FossilOrigin-Name: a4876672edea4e96103efd2463ce9a34a0b994a8744c941660940578aafbd454
2018-01-05 11:34:18 +00:00
dan 8503d6451b Fix an LSM crash that could occur if LSM_CONFIG_AUTOFLUSH was set to 0.
FossilOrigin-Name: 05346f83d587e6049da0e8ec5f62c749daa9e80359cf48f8c37e333e6a1e7d2a
2018-01-05 07:57:54 +00:00
mistachkin 47be3b23e9 Revise detection of 'tclsh.exe' in the Makefile for MSVC.
FossilOrigin-Name: 45fabd868dc690894f5a911d373a3d6410ba2d95d177307a42009afc8ae296cc
2018-01-05 01:22:37 +00:00
mistachkin 1152250b44 Enhance the 'zlib' build target for MSVC.
FossilOrigin-Name: 0bc3b76ec9b83f3034e282ea0369a53673e2cb64dde42e8cf5e800f6d642d527
2018-01-05 01:00:17 +00:00
mistachkin 3acaf4c07a Add missing #ifdef.
FossilOrigin-Name: a0e18aea0950f5ebdf4112f826ff64d24e8660b341031132dcb65bb15579ef1c
2018-01-05 00:53:03 +00:00
mistachkin 104958cab0 In the 'fileio' extension code for Win32, use the FILE_FLAG_BACKUP_SEMANTICS flag when setting the file times, just in case the file is actually a directory.
FossilOrigin-Name: 4f3444060057127bce81787ed83cb5225cdbdd577596bc3fb06a40be2208f238
2018-01-04 23:49:08 +00:00
mistachkin e55988074f Remove 'timespec' related code from the shell that has no effect and a (now) superfluous 'timespec' typedef from the Win32 dirent header file.
FossilOrigin-Name: 57dac995dd028e4b7c8ce6806f5769831715c1bb9b886318fceb3fa50563d537
2018-01-04 22:50:52 +00:00
mistachkin dfdfd8c7f2 Get the shell enhancements compiling with MSVC.
FossilOrigin-Name: 335387f9e0d4569097d34cd99cd332b38a282e9b7ae25f088eb47df5c25837ef
2018-01-04 22:46:08 +00:00
drh c76ed3d57d Merge in all recent trunk enhancements.
FossilOrigin-Name: 406f79183736b6ad360169b837172afef2c82a4312f5787db08c54167a44b15e
2018-01-04 19:54:55 +00:00
drh 35100fb194 Remove the snarky "_supported_" qualifier from the name of the
sqlite_offset() SQL function.

FossilOrigin-Name: a6eee0fcd89d3958f8720ebdb5f0a8558b4795d747128091dae283eb81c4f74f
2018-01-04 19:20:37 +00:00
drh 64c1990c00 Fix a broken documentation hyperlink. No code changes.
FossilOrigin-Name: d91e3f3d343d281af374dd23eea333e61228539023ad5c5aea622085e5863bc7
2018-01-04 16:40:44 +00:00
drh 9eb8dbad4d Add another test case (found by OSSFuzz) for the problem fixed in
check-in [2846458a] and described by ticket [dc3f932f5a147771].
No changes to code.

FossilOrigin-Name: 4165fae920a1176c68bfaa1f2cfe17df7f8dd8793519d458b71e3e63670b5495
2018-01-03 01:47:30 +00:00
drh d9620b8555 Fix code indentation. No logic changes.
FossilOrigin-Name: e115f2583499df0c7ee991d372bed4b89aa717b10a4e4b10977864390cb4fc11
2018-01-02 21:29:42 +00:00
drh 4d795ef7e4 In the constraint resolution logic, be careful not to cache column values
in registers whose initialization might be bypassed by an OP_NoConflict opcode.
Fix for ticket [dc3f932f5a147771] reported by OSSFuzz.

FossilOrigin-Name: 2846458af5d029a8e4fdcc8f50873a44e57897bbfe6aee8a23a01ffc34c5579f
2018-01-02 18:11:11 +00:00
drh 595a0e2a4a Enhance the memvfs extension so that it can be read/write.
FossilOrigin-Name: 04c9197d589666299aef86ee6a56df63448c050274c9fba4af94f932752be237
2018-01-02 16:02:50 +00:00
drh 9199ac1048 Updates to the sqlite3_file_control() documentation. No changes to code.
FossilOrigin-Name: 240e32ab1f2a18e3c9b92f577b1cc8f8ecb4c68c44eac863d859491e042cb72a
2018-01-02 13:48:48 +00:00
drh cde7b77932 Do not attempt to use pragma_module_list in the command-line shell unless
it has been compiled with -DSQLITE_INTROSPECTION_PRAGMAS.

FossilOrigin-Name: 39ca5fcd31c902cbade4da05125b0dbf2bc5e2b8901af1645f113c9d3dbc8209
2018-01-02 12:50:40 +00:00
drh 667a2a25ba The ".schema" command in the command-line shell now shows the structure of
table-valued functions and eponymous virtual tables if they are named on the
".schema" command line.  Example:  ".schema sql%" shows the structure of
the "sqlite_dbstat" and "sqlite_stmt" virtual tables.

FossilOrigin-Name: f80f6651df0b2843c6c9619a8f3e05c56cd50363402800a2e166e6eb664f7768
2018-01-02 00:04:37 +00:00
drh 1d315cf7b8 Improved name quoting and escaping in the auxiliary column info section
of the ".schema" output for views and virtual tables.

FossilOrigin-Name: d64b14e37d9624bf5d86059ddd091170d8e6d341a8043f84548b9b3dbb96a908
2018-01-01 21:49:43 +00:00
drh ceba792a2f In the output of ".schema", show the column names of virtual tables and
views in a separate comment.

FossilOrigin-Name: 2234a87fa905312b23f46d52e06cff7cacbf23b187e16c4398a42e6bdae0ee9f
2018-01-01 21:28:25 +00:00
drh c22b716e31 Minor simplification to the ".schema" logic in the command-line shell.
FossilOrigin-Name: add45c47288248ca3745e0fceb5e0d9062a852d173d93ff2ff1a0f8fdf3237dc
2018-01-01 20:11:23 +00:00
drh 470fc9ddaa Enable the introspection pragmas for command-line shell builds.
FossilOrigin-Name: 0b04223f256f5c1e06fa6e899727815ebf650f2dfcf8f36d6cbfb6cb62d4ead8
2018-01-01 19:33:12 +00:00
dan 0cde0c62b1 Have zipfile support DELETE commands.
FossilOrigin-Name: 01d4e866fb7b01aeada537d41c4a47747c7810e2028f51077ee5b8b78c348954
2017-12-30 18:32:27 +00:00
dan db0cb303ad Rearrange things a bit so that writing to a zipfile does not invert the order
of objects it contains.

FossilOrigin-Name: f69e8194bfa7de436c96028730ebd57f186d2e6207792e172e1aa38c7f4211c9
2017-12-30 14:26:29 +00:00
dan 373dc3bb3f Update ext/misc/zipfile.c to support creating and adding entries to existing
zip archives.

FossilOrigin-Name: 2dec2dec592c0726ebe87b841b9c8d493dea7074a99f278eb1bf0b744d658a9d
2017-12-29 20:19:03 +00:00
drh c64487b9c8 Add support for the sqlite_unsupported_offset() SQL function if and only
if compiled using -DSQLITE_ENABLE_OFFSET_SQL_FUNC.  Use that definition
when compiling the command-line shell.

FossilOrigin-Name: 4f1f1f521ae6da96b899e10bfeff6bc1ab7a45de0705076febaae20b441f48c6
2017-12-29 17:21:21 +00:00
dan b5090e4897 Improve the shell tool ".ar --list --verbose" command.
FossilOrigin-Name: b64681a644c419bb98d00980a6cb56ef5a0aff5ef5321955631f0b4c88aac283
2017-12-27 21:13:21 +00:00
dan 5a78b81b1b Have the shell tool ".ar --list" and ".ar --extract" commands support zip
files. Currently the "-zip" switch is required.

FossilOrigin-Name: a532a0f6fd59e81086d46f09151ba7fb26725198231d902c71d0f95cb01dbe91
2017-12-27 18:54:11 +00:00
dan 9ebfaad25d Add new file ext/misc/zipfile.c, containing a virtual table for read-only
access to simple zip archives.

FossilOrigin-Name: 8e366b99b13d765d8bf000a7ec5919e582702e51dc07c27a746b6002898a2302
2017-12-26 20:39:58 +00:00
drh 844cf56bc6 Merge recent enhancements from trunk.
FossilOrigin-Name: edceaccd66a65d6b36e53ce33d760a7bd9c2261a592d12189f5f55417b5d5d74
2017-12-23 18:40:39 +00:00
drh 60ba57d9c5 Merge enhancements from trunk.
FossilOrigin-Name: 150f07fec1e6d1fc0601820d717d8712fc513fe0d4bed67c8679eb51bca30d53
2017-12-23 18:34:49 +00:00
dan d1b51d4955 Do not use the compress() and uncompress() functions in ext/misc/compress.c -
they are not quite compatible with the spec. Instead use new functions in
ext/misc/sqlar.c.

FossilOrigin-Name: 7652b3c2374084047b6c1da3e525e0cac34fe220597f81e793bc4fd9f33358da
2017-12-16 19:11:26 +00:00
drh dd2a43a225 Fixes to the appendvfs.c extension. Add the "sqltclsh" application that
uses appendvfs.c to find its scripts.

FossilOrigin-Name: ee248b529c2396c5480fb99b0a1dc31032627ec8241eca4a8c0fff257bb4a088
2017-12-14 19:24:00 +00:00
dan ac15e2d7cc Have the writefile() function optionally set the modification-time of the
files it writes or creates. And many small fixes to the new code on this
branch.

FossilOrigin-Name: 7b51269caebe1492885fe9b965892f49a3f8bdb1d666b0203d594c30f9e83938
2017-12-14 19:15:07 +00:00
drh 233ff96ec5 The "apndvfs" VFS shim now appears to be working for both reads and writes.
FossilOrigin-Name: 7f7b72d83633922e2b5dbf0d3455d0fea72cc6b8925ffcb78dfbad7b3c4b26e9
2017-12-14 16:57:11 +00:00
drh e483d349ab Add the ability to write to an appended database. This check-in compiles
but is otherwise untested.

FossilOrigin-Name: e343c63cbd754f37c33c939cd0b6f1ecc6202e60c6e66cd65c23cc8d571a994e
2017-12-14 16:28:27 +00:00
dan 0d0547fec6 Improve error and usage messages output by the shell ".ar" command.
FossilOrigin-Name: b9d2d5d97291bf3d1392232e3705cca89dc7b918db2b08067b2b013ea39320e0
2017-12-14 15:40:42 +00:00
drh 32b5fdcaea Bring in the latest trunk changes.
FossilOrigin-Name: 75d8517703f7efa33437079108e2c4ef0de1a118bbe1f4a86afdc34da09d3008
2017-12-14 14:50:49 +00:00
dan 7d935ab46d Merge latest trunk changes into this branch.
FossilOrigin-Name: 803156cba8b056a1cb8d1bb186a57454afe72341abe7de1dfe529234c3415cd2
2017-12-14 13:55:01 +00:00
dan 06741a3c9b Add the shell tool ".ar --update" command.
FossilOrigin-Name: 825e3c037b03fc09d581aeda0193ff1d4062404414c7354cb649f99aa9022d25
2017-12-13 20:17:18 +00:00
dan 3f67ddf8f2 Add support for the "--list" command. And for arguments to the "--extract"
command.

FossilOrigin-Name: 32c4fa2552bb0fa7d7d143108457efae7a756d6cb14b1d59312e56efac3b2656
2017-12-13 20:04:53 +00:00
dan ece4b0c172 Add tests and fixes for the shell ".ar" command -f option.
FossilOrigin-Name: 1a9867973c9d6675fa5254fdd74f36004707a98a91593a188033cf5a49cc7a0b
2017-12-12 20:28:36 +00:00
dan d4b56e5901 Add support for parsing options in non-traditional tar form to the ".ar"
command. Have writefile() attempt to create any missing path components. And
not to throw an exception if it is called to create a directory that already
exists.

FossilOrigin-Name: 38dbeb1e777aa7ec742aa27002ad4dcee28af520dc43de96e5c56c39f16574ff
2017-12-12 20:04:59 +00:00
dan 1ad3f61b81 Enhance virtual table "fsdir" in ext/misc/fileio.c. Add support for "-C" to
the shell command's ".ar c" command.

FossilOrigin-Name: 0394889afed2479773af594e2d9659cf58b8959004ebcdeaff8e08e5dae684ef
2017-12-11 20:22:02 +00:00
dan 2ad0949db4 Add support for -C to ".ar x".
FossilOrigin-Name: 8cd70960c5ddf0d0b2c40b8b6af4ce6b0277ffdaf04f33fcb33227d2b99ad515
2017-12-09 18:28:22 +00:00
dan 88be020916 Improve parsing of ".ar" commands. Add new test file for the same.
FossilOrigin-Name: 840401cc8ce3a09e0663b46973ecd2856d9607be71d2d1e9b21f7df7a82dcbe5
2017-12-09 17:58:02 +00:00
dan 25c1218e73 Add the ".ar x" command to the shell. For extracting the contents of sqlar
archives.

FossilOrigin-Name: 0cc699d14adfe8c7b7be50c180186562861806c47425c80c935bce43ee5c5c12
2017-12-07 21:03:33 +00:00
dan fd0245d771 Begin adding support for the sqlar archive format to shell.c. There is no
"extract" command so far, only "create".

FossilOrigin-Name: c9827a01a6e107f38f85c2b2c1c7a599e443067b106217e965b6936441ca619d
2017-12-07 15:44:29 +00:00
mistachkin a0fcafe762 For MSVC, simplify default locations for Tcl and ICU by using directories inside 'compat'.
FossilOrigin-Name: 8155b5ac850327ea76aba2adf624132f3e05024c973afd218b12f186fc7630e8
2017-12-05 19:07:30 +00:00
mistachkin cb6acda902 Add support for including zlib in the shell when compiling with MSVC.
FossilOrigin-Name: e1838cee3847301ef491467dc75d9c4e1e3b12599596c058bdb14319a52fd8a0
2017-12-05 18:54:12 +00:00
dan 72afc3c5de If SQLITE_HAVE_ZLIB is defined at build-time, include the functions in
ext/misc/compress.c in the shell.

FossilOrigin-Name: 0296286a9963bbaab60ee30d8700703f5ccb382380c9bfc0eb12c4bcb6f2accd
2017-12-05 18:32:40 +00:00
drh 7e8cf76c8a Merge all the latest changes from trunk.
FossilOrigin-Name: 1a1a73b821eb1a22ca335f582a0aea31c71ca9f5b09d54f26409691c90e38c4a
2017-11-15 16:29:02 +00:00
drh 3be8b1a4f7 Initial implementation of the appendvfs extension. Untested.
FossilOrigin-Name: 063a03a3779e8c032dd006712facaaa6d60964425701ea10c753ff981a8f2bd9
2017-10-21 12:59:27 +00:00
42 changed files with 5545 additions and 271 deletions
+1
View File
@@ -0,0 +1 @@
compat
+1
View File
@@ -0,0 +1 @@
compat/*
+19 -3
View File
@@ -440,6 +440,7 @@ TESTSRC += \
$(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 \
@@ -447,7 +448,8 @@ TESTSRC += \
$(TOP)/ext/misc/spellfix.c \
$(TOP)/ext/misc/totype.c \
$(TOP)/ext/misc/unionvtab.c \
$(TOP)/ext/misc/wholenumber.c
$(TOP)/ext/misc/wholenumber.c \
$(TOP)/ext/misc/zipfile.c
# Source code to the library files needed by the test fixture
#
@@ -558,7 +560,8 @@ TESTPROGS = \
sqlite3$(TEXE) \
sqlite3_analyzer$(TEXE) \
sqldiff$(TEXE) \
dbhash$(TEXE)
dbhash$(TEXE) \
sqltclsh$(TEXE)
# Databases containing fuzzer test cases
#
@@ -583,6 +586,7 @@ 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
@@ -991,9 +995,15 @@ keywordhash.h: $(TOP)/tool/mkkeywordhash.c
# 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/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
@@ -1193,6 +1203,12 @@ sqlite3_analyzer.c: sqlite3.c $(TOP)/src/tclsqlite.c $(TOP)/tool/spaceanal.tcl $
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)
+138 -16
View File
@@ -92,6 +92,29 @@ 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
@@ -612,6 +635,15 @@ 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
@@ -802,12 +834,16 @@ 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 = c:\tcl\include
TCLINCDIR = $(TCLDIR)\include
!ENDIF
!IFNDEF TCLLIBDIR
TCLLIBDIR = c:\tcl\lib
TCLLIBDIR = $(TCLDIR)\lib
!ENDIF
!IFNDEF LIBTCL
@@ -819,7 +855,32 @@ LIBTCLSTUB = tclstub86.lib
!ENDIF
!IFNDEF LIBTCLPATH
LIBTCLPATH = c:\tcl\bin
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
!ENDIF
# The locations of the ICU header and library files. These variables
@@ -827,12 +888,16 @@ LIBTCLPATH = c:\tcl\bin
# 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 = c:\icu\include
ICUINCDIR = $(ICUDIR)\include
!ENDIF
!IFNDEF ICULIBDIR
ICULIBDIR = c:\icu\lib
ICULIBDIR = $(ICUDIR)\lib
!ENDIF
!IFNDEF LIBICU
@@ -845,7 +910,11 @@ 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
!ENDIF
# <</mark>>
@@ -951,6 +1020,15 @@ 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
@@ -1071,8 +1149,15 @@ LDFLAGS = $(LDOPTS)
# Start with the Tcl related linker options.
#
!IF $(NO_TCL)==0
LTLIBPATHS = /LIBPATH:$(TCLLIBDIR)
LTLIBS = $(LTLIBS) $(LIBTCL)
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)
!ENDIF
# If ICU support is enabled, add the linker options for it.
@@ -1415,6 +1500,7 @@ TESTEXT = \
$(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 \
@@ -1424,6 +1510,12 @@ TESTEXT = \
$(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)
#
@@ -1495,7 +1587,8 @@ TESTPROGS = \
sqlite3_analyzer.exe \
sqlite3_checker.exe \
sqldiff.exe \
dbhash.exe
dbhash.exe \
sqltclsh.exe
# Databases containing fuzzer test cases
#
@@ -1513,7 +1606,7 @@ FUZZDATA = \
!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
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_OFFSET_SQL_FUNC -DSQLITE_INTROSPECTION_PRAGMAS
!ENDIF
# <<mark>>
@@ -1545,7 +1638,15 @@ 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.
#
all: dll libsqlite3.lib shell $(ALL_TCL_TARGETS)
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
# Dynamic link library section.
#
@@ -1940,7 +2041,7 @@ tclsqlite-shell.lo: $(TOP)\src\tclsqlite.c $(HDR) $(SQLITE_TCL_DEP)
$(LTCOMPILE) $(NO_WARN) -DTCLSH -DBUILD_sqlite -I$(TCLINCDIR) -c $(TOP)\src\tclsqlite.c
tclsqlite3.exe: tclsqlite-shell.lo $(SQLITE3C) $(SQLITE3H) $(LIBRESOBJS)
$(LTLINK) $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) /OUT:$@ tclsqlite-shell.lo $(LIBRESOBJS) $(LTLIBS) $(TLIBS)
$(LTLINK) $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS) $(TCLLIBPATHS) $(LTLIBPATHS) /OUT:$@ tclsqlite-shell.lo $(LIBRESOBJS) $(TCLLIBS) $(LTLIBS) $(TLIBS)
# Rules to build opcodes.c and opcodes.h
#
@@ -1983,13 +2084,26 @@ keywordhash.h: $(TOP)\tool\mkkeywordhash.c mkkeywordhash.exe
# 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\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.
#
@@ -2167,11 +2281,11 @@ sqlite_tcl.h:
| $(TCLSH_CMD) $(TOP)\tool\replace.tcl exact "Tcl_HashEntry *(*createProc)" "Tcl_HashEntry *(SQLITE_TCLAPI *createProc)" >> $(SQLITETCLH)
!ENDIF
testfixture.exe: $(TESTFIXTURE_SRC) $(SQLITE3H) $(LIBRESOBJS) $(HDR) $(SQLITE_TCL_DEP)
testfixture.exe: $(TESTFIXTURE_SRC) $(TESTFIXTURE_DEP) $(SQLITE3H) $(LIBRESOBJS) $(HDR) $(SQLITE_TCL_DEP)
$(LTLINK) -DSQLITE_NO_SYNC=1 $(TESTFIXTURE_FLAGS) \
-DBUILD_sqlite -I$(TCLINCDIR) \
$(TESTFIXTURE_SRC) \
/link $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LTLIBS) $(TLIBS)
/link $(LDFLAGS) $(LTLINKOPTS) $(TCLLIBPATHS) $(LTLIBPATHS) $(LIBRESOBJS) $(TCLLIBS) $(LTLIBS) $(TLIBS)
extensiontest: testfixture.exe testloadext.dll
@set PATH=$(LIBTCLPATH);$(PATH)
@@ -2221,7 +2335,14 @@ sqlite3_analyzer.c: $(SQLITE3C) $(SQLITE3H) $(TOP)\src\tclsqlite.c $(TOP)\tool\s
sqlite3_analyzer.exe: sqlite3_analyzer.c $(LIBRESOBJS)
$(LTLINK) $(NO_WARN) -DBUILD_sqlite -I$(TCLINCDIR) sqlite3_analyzer.c \
/link $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LTLIBS) $(TLIBS)
/link $(LDFLAGS) $(LTLINKOPTS) $(TCLLIBPATHS) $(LTLIBPATHS) $(LIBRESOBJS) $(TCLLIBS) $(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
$(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)
@@ -2241,7 +2362,7 @@ sqlite3_checker.c: $(CHECKER_DEPS)
sqlite3_checker.exe: sqlite3_checker.c $(LIBRESOBJS)
$(LTLINK) $(NO_WARN) -DBUILD_sqlite -I$(TCLINCDIR) sqlite3_checker.c \
/link $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LTLIBS) $(TLIBS)
/link $(LDFLAGS) $(LTLINKOPTS) $(TCLLIBPATHS) $(LTLIBPATHS) $(LIBRESOBJS) $(TCLLIBS) $(LTLIBS) $(TLIBS)
dbdump.exe: $(TOP)\ext\misc\dbdump.c $(SQLITE3C) $(SQLITE3H)
$(LTLINK) $(NO_WARN) -DDBDUMP_STANDALONE $(TOP)\ext\misc\dbdump.c $(SQLITE3C) \
@@ -2342,6 +2463,7 @@ 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.exe 2>NUL
del /Q fts5.* fts5parse.* 2>NUL
del /Q lsm.h lsm1.c 2>NUL
# <</mark>>
+11 -1
View File
@@ -561,6 +561,7 @@ SHELL_CORE_DEP =
!ENDIF
!ENDIF
# This is the core library that the shell executable should link with.
#
!IFNDEF SHELL_CORE_LIB
@@ -929,13 +930,22 @@ LIBRESOBJS =
!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
!ENDIF
# This is the default Makefile target. The objects listed here
# are what get build when you type just "make" with no arguments.
#
all: dll shell
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
# Dynamic link library section.
#
+1 -1
View File
@@ -433,7 +433,7 @@ static int SQLITE_TCLAPI xF5tApi(
int iVal;
int bClear;
if( Tcl_GetBooleanFromObj(interp, objv[2], &bClear) ) return TCL_ERROR;
iVal = ((char*)p->pApi->xGetAuxdata(p->pFts, bClear) - (char*)0);
iVal = (int)((char*)p->pApi->xGetAuxdata(p->pFts, bClear) - (char*)0);
Tcl_SetObjResult(interp, Tcl_NewIntObj(iVal));
break;
}
+1
View File
@@ -121,6 +121,7 @@ int test_mdb_scan(TestDb *, void *, int, void *, int, void *, int,
*/
int test_lsm_open(const char*, const char *zFile, int bClear, TestDb **ppDb);
int test_lsm_lomem_open(const char*, const char*, int bClear, TestDb **ppDb);
int test_lsm_lomem2_open(const char*, const char*, int bClear, TestDb **ppDb);
int test_lsm_zip_open(const char*, const char*, int bClear, TestDb **ppDb);
int test_lsm_small_open(const char*, const char*, int bClear, TestDb **ppDb);
int test_lsm_mt2(const char*, const char *zFile, int bClear, TestDb **ppDb);
+1
View File
@@ -721,6 +721,7 @@ static struct Lib {
{ "sqlite3", "testdb.sqlite", sql_open },
{ "lsm_small", "testdb.lsm_small", test_lsm_small_open },
{ "lsm_lomem", "testdb.lsm_lomem", test_lsm_lomem_open },
{ "lsm_lomem2", "testdb.lsm_lomem2", test_lsm_lomem2_open },
#ifdef HAVE_ZLIB
{ "lsm_zip", "testdb.lsm_zip", test_lsm_zip_open },
#endif
+13
View File
@@ -1033,6 +1033,19 @@ int test_lsm_lomem_open(
return testLsmOpen(zCfg, zFilename, bClear, ppDb);
}
int test_lsm_lomem2_open(
const char *zSpec,
const char *zFilename,
int bClear,
TestDb **ppDb
){
/* "max_freelist=4 autocheckpoint=32" */
const char *zCfg =
"page_size=512 block_size=64 autoflush=0 mmap=0 "
;
return testLsmOpen(zCfg, zFilename, bClear, ppDb);
}
int test_lsm_zip_open(
const char *zSpec,
const char *zFilename,
+1 -1
View File
@@ -683,7 +683,7 @@ static int doWriteOp(
int nDiff;
if( nQuant>pDb->nTreeLimit ){
nQuant = pDb->nTreeLimit;
nQuant = LSM_MAX(pDb->nTreeLimit, pgsz);
}
nBefore = lsmTreeSize(pDb);
+2 -3
View File
@@ -5252,16 +5252,15 @@ static int doLsmSingleWork(
/* If the in-memory part of the free-list is too large, write a new
** top-level containing just the in-memory free-list entries to disk. */
if( rc==LSM_OK && pDb->pWorker->freelist.nEntry > pDb->nMaxFreelist ){
int nPg = 0;
while( rc==LSM_OK && lsmDatabaseFull(pDb) ){
int nPg = 0;
rc = sortedWork(pDb, 16, nMerge, 1, &nPg);
nRem -= nPg;
}
if( rc==LSM_OK ){
rc = sortedNewFreelistOnly(pDb);
}
nRem -= nPg;
if( nPg ) bDirty = 1;
bDirty = 1;
}
if( rc==LSM_OK ){
+563
View File
@@ -0,0 +1,563 @@
/*
** 2017-10-20
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
******************************************************************************
**
** This file implements a VFS shim that allows an SQLite database to be
** appended onto the end of some other file, such as an executable.
**
** A special record must appear at the end of the file that identifies the
** file as an appended database and provides an offset to page 1. For
** best performance page 1 should be located at a disk page boundary, though
** that is not required.
**
** When opening a database using this VFS, the connection might treat
** the file as an ordinary SQLite database, or it might treat is as a
** database appended onto some other file. Here are the rules:
**
** (1) When opening a new empty file, that file is treated as an ordinary
** database.
**
** (2) When opening a file that begins with the standard SQLite prefix
** string "SQLite format 3", that file is treated as an ordinary
** database.
**
** (3) When opening a file that ends with the appendvfs trailer string
** "Start-Of-SQLite3-NNNNNNNN" that file is treated as an appended
** database.
**
** (4) If none of the above apply and the SQLITE_OPEN_CREATE flag is
** set, then a new database is appended to the already existing file.
**
** (5) Otherwise, SQLITE_CANTOPEN is returned.
**
** To avoid unnecessary complications with the PENDING_BYTE, the size of
** the file containing the database is limited to 1GB. This VFS will refuse
** to read or write past the 1GB mark. This restriction might be lifted in
** future versions. For now, if you need a large database, then keep the
** database in a separate file.
**
** If the file being opened is not an appended database, then this shim is
** a pass-through into the default underlying VFS.
**/
#include "sqlite3ext.h"
SQLITE_EXTENSION_INIT1
#include <string.h>
#include <assert.h>
/* The append mark at the end of the database is:
**
** Start-Of-SQLite3-NNNNNNNN
** 123456789 123456789 12345
**
** The NNNNNNNN represents a 64-bit big-endian unsigned integer which is
** the offset to page 1.
*/
#define APND_MARK_PREFIX "Start-Of-SQLite3-"
#define APND_MARK_PREFIX_SZ 17
#define APND_MARK_SIZE 25
/*
** Maximum size of the combined prefix + database + append-mark. This
** must be less than 0x40000000 to avoid locking issues on Windows.
*/
#define APND_MAX_SIZE (65536*15259)
/*
** Forward declaration of objects used by this utility
*/
typedef struct sqlite3_vfs ApndVfs;
typedef struct ApndFile ApndFile;
/* Access to a lower-level VFS that (might) implement dynamic loading,
** access to randomness, etc.
*/
#define ORIGVFS(p) ((sqlite3_vfs*)((p)->pAppData))
#define ORIGFILE(p) ((sqlite3_file*)(((ApndFile*)(p))+1))
/* An open file */
struct ApndFile {
sqlite3_file base; /* IO methods */
sqlite3_int64 iPgOne; /* File offset to page 1 */
sqlite3_int64 iMark; /* Start of the append-mark */
};
/*
** Methods for ApndFile
*/
static int apndClose(sqlite3_file*);
static int apndRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
static int apndWrite(sqlite3_file*,const void*,int iAmt, sqlite3_int64 iOfst);
static int apndTruncate(sqlite3_file*, sqlite3_int64 size);
static int apndSync(sqlite3_file*, int flags);
static int apndFileSize(sqlite3_file*, sqlite3_int64 *pSize);
static int apndLock(sqlite3_file*, int);
static int apndUnlock(sqlite3_file*, int);
static int apndCheckReservedLock(sqlite3_file*, int *pResOut);
static int apndFileControl(sqlite3_file*, int op, void *pArg);
static int apndSectorSize(sqlite3_file*);
static int apndDeviceCharacteristics(sqlite3_file*);
static int apndShmMap(sqlite3_file*, int iPg, int pgsz, int, void volatile**);
static int apndShmLock(sqlite3_file*, int offset, int n, int flags);
static void apndShmBarrier(sqlite3_file*);
static int apndShmUnmap(sqlite3_file*, int deleteFlag);
static int apndFetch(sqlite3_file*, sqlite3_int64 iOfst, int iAmt, void **pp);
static int apndUnfetch(sqlite3_file*, sqlite3_int64 iOfst, void *p);
/*
** Methods for ApndVfs
*/
static int apndOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *);
static int apndDelete(sqlite3_vfs*, const char *zName, int syncDir);
static int apndAccess(sqlite3_vfs*, const char *zName, int flags, int *);
static int apndFullPathname(sqlite3_vfs*, const char *zName, int, char *zOut);
static void *apndDlOpen(sqlite3_vfs*, const char *zFilename);
static void apndDlError(sqlite3_vfs*, int nByte, char *zErrMsg);
static void (*apndDlSym(sqlite3_vfs *pVfs, void *p, const char*zSym))(void);
static void apndDlClose(sqlite3_vfs*, void*);
static int apndRandomness(sqlite3_vfs*, int nByte, char *zOut);
static int apndSleep(sqlite3_vfs*, int microseconds);
static int apndCurrentTime(sqlite3_vfs*, double*);
static int apndGetLastError(sqlite3_vfs*, int, char *);
static int apndCurrentTimeInt64(sqlite3_vfs*, sqlite3_int64*);
static int apndSetSystemCall(sqlite3_vfs*, const char*,sqlite3_syscall_ptr);
static sqlite3_syscall_ptr apndGetSystemCall(sqlite3_vfs*, const char *z);
static const char *apndNextSystemCall(sqlite3_vfs*, const char *zName);
static sqlite3_vfs apnd_vfs = {
3, /* iVersion (set when registered) */
0, /* szOsFile (set when registered) */
1024, /* mxPathname */
0, /* pNext */
"apndvfs", /* zName */
0, /* pAppData (set when registered) */
apndOpen, /* xOpen */
apndDelete, /* xDelete */
apndAccess, /* xAccess */
apndFullPathname, /* xFullPathname */
apndDlOpen, /* xDlOpen */
apndDlError, /* xDlError */
apndDlSym, /* xDlSym */
apndDlClose, /* xDlClose */
apndRandomness, /* xRandomness */
apndSleep, /* xSleep */
apndCurrentTime, /* xCurrentTime */
apndGetLastError, /* xGetLastError */
apndCurrentTimeInt64, /* xCurrentTimeInt64 */
apndSetSystemCall, /* xSetSystemCall */
apndGetSystemCall, /* xGetSystemCall */
apndNextSystemCall /* xNextSystemCall */
};
static const sqlite3_io_methods apnd_io_methods = {
3, /* iVersion */
apndClose, /* xClose */
apndRead, /* xRead */
apndWrite, /* xWrite */
apndTruncate, /* xTruncate */
apndSync, /* xSync */
apndFileSize, /* xFileSize */
apndLock, /* xLock */
apndUnlock, /* xUnlock */
apndCheckReservedLock, /* xCheckReservedLock */
apndFileControl, /* xFileControl */
apndSectorSize, /* xSectorSize */
apndDeviceCharacteristics, /* xDeviceCharacteristics */
apndShmMap, /* xShmMap */
apndShmLock, /* xShmLock */
apndShmBarrier, /* xShmBarrier */
apndShmUnmap, /* xShmUnmap */
apndFetch, /* xFetch */
apndUnfetch /* xUnfetch */
};
/*
** Close an apnd-file.
*/
static int apndClose(sqlite3_file *pFile){
pFile = ORIGFILE(pFile);
return pFile->pMethods->xClose(pFile);
}
/*
** Read data from an apnd-file.
*/
static int apndRead(
sqlite3_file *pFile,
void *zBuf,
int iAmt,
sqlite_int64 iOfst
){
ApndFile *p = (ApndFile *)pFile;
pFile = ORIGFILE(pFile);
return pFile->pMethods->xRead(pFile, zBuf, iAmt, iOfst+p->iPgOne);
}
/*
** Add the append-mark onto the end of the file.
*/
static int apndWriteMark(ApndFile *p, sqlite3_file *pFile){
int i;
unsigned char a[APND_MARK_SIZE];
memcpy(a, APND_MARK_PREFIX, APND_MARK_PREFIX_SZ);
for(i=0; i<8; i++){
a[APND_MARK_PREFIX_SZ+i] = (p->iPgOne >> (56 - i*8)) & 0xff;
}
return pFile->pMethods->xWrite(pFile, a, APND_MARK_SIZE, p->iMark);
}
/*
** Write data to an apnd-file.
*/
static int apndWrite(
sqlite3_file *pFile,
const void *zBuf,
int iAmt,
sqlite_int64 iOfst
){
int rc;
ApndFile *p = (ApndFile *)pFile;
pFile = ORIGFILE(pFile);
if( iOfst+iAmt>=APND_MAX_SIZE ) return SQLITE_FULL;
rc = pFile->pMethods->xWrite(pFile, zBuf, iAmt, iOfst+p->iPgOne);
if( rc==SQLITE_OK && iOfst + iAmt + p->iPgOne > p->iMark ){
sqlite3_int64 sz = 0;
rc = pFile->pMethods->xFileSize(pFile, &sz);
if( rc==SQLITE_OK ){
p->iMark = sz - APND_MARK_SIZE;
if( iOfst + iAmt + p->iPgOne > p->iMark ){
p->iMark = p->iPgOne + iOfst + iAmt;
rc = apndWriteMark(p, pFile);
}
}
}
return rc;
}
/*
** Truncate an apnd-file.
*/
static int apndTruncate(sqlite3_file *pFile, sqlite_int64 size){
int rc;
ApndFile *p = (ApndFile *)pFile;
pFile = ORIGFILE(pFile);
rc = pFile->pMethods->xTruncate(pFile, size+p->iPgOne+APND_MARK_SIZE);
if( rc==SQLITE_OK ){
p->iMark = p->iPgOne+size;
rc = apndWriteMark(p, pFile);
}
return rc;
}
/*
** Sync an apnd-file.
*/
static int apndSync(sqlite3_file *pFile, int flags){
pFile = ORIGFILE(pFile);
return pFile->pMethods->xSync(pFile, flags);
}
/*
** Return the current file-size of an apnd-file.
*/
static int apndFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
ApndFile *p = (ApndFile *)pFile;
int rc;
pFile = ORIGFILE(p);
rc = pFile->pMethods->xFileSize(pFile, pSize);
if( rc==SQLITE_OK && p->iPgOne ){
*pSize -= p->iPgOne + APND_MARK_SIZE;
}
return rc;
}
/*
** Lock an apnd-file.
*/
static int apndLock(sqlite3_file *pFile, int eLock){
pFile = ORIGFILE(pFile);
return pFile->pMethods->xLock(pFile, eLock);
}
/*
** Unlock an apnd-file.
*/
static int apndUnlock(sqlite3_file *pFile, int eLock){
pFile = ORIGFILE(pFile);
return pFile->pMethods->xUnlock(pFile, eLock);
}
/*
** Check if another file-handle holds a RESERVED lock on an apnd-file.
*/
static int apndCheckReservedLock(sqlite3_file *pFile, int *pResOut){
pFile = ORIGFILE(pFile);
return pFile->pMethods->xCheckReservedLock(pFile, pResOut);
}
/*
** File control method. For custom operations on an apnd-file.
*/
static int apndFileControl(sqlite3_file *pFile, int op, void *pArg){
ApndFile *p = (ApndFile *)pFile;
int rc;
pFile = ORIGFILE(pFile);
rc = pFile->pMethods->xFileControl(pFile, op, pArg);
if( rc==SQLITE_OK && op==SQLITE_FCNTL_VFSNAME ){
*(char**)pArg = sqlite3_mprintf("apnd(%lld)/%z", p->iPgOne, *(char**)pArg);
}
return rc;
}
/*
** Return the sector-size in bytes for an apnd-file.
*/
static int apndSectorSize(sqlite3_file *pFile){
pFile = ORIGFILE(pFile);
return pFile->pMethods->xSectorSize(pFile);
}
/*
** Return the device characteristic flags supported by an apnd-file.
*/
static int apndDeviceCharacteristics(sqlite3_file *pFile){
pFile = ORIGFILE(pFile);
return pFile->pMethods->xDeviceCharacteristics(pFile);
}
/* Create a shared memory file mapping */
static int apndShmMap(
sqlite3_file *pFile,
int iPg,
int pgsz,
int bExtend,
void volatile **pp
){
pFile = ORIGFILE(pFile);
return pFile->pMethods->xShmMap(pFile,iPg,pgsz,bExtend,pp);
}
/* Perform locking on a shared-memory segment */
static int apndShmLock(sqlite3_file *pFile, int offset, int n, int flags){
pFile = ORIGFILE(pFile);
return pFile->pMethods->xShmLock(pFile,offset,n,flags);
}
/* Memory barrier operation on shared memory */
static void apndShmBarrier(sqlite3_file *pFile){
pFile = ORIGFILE(pFile);
pFile->pMethods->xShmBarrier(pFile);
}
/* Unmap a shared memory segment */
static int apndShmUnmap(sqlite3_file *pFile, int deleteFlag){
pFile = ORIGFILE(pFile);
return pFile->pMethods->xShmUnmap(pFile,deleteFlag);
}
/* Fetch a page of a memory-mapped file */
static int apndFetch(
sqlite3_file *pFile,
sqlite3_int64 iOfst,
int iAmt,
void **pp
){
ApndFile *p = (ApndFile *)pFile;
pFile = ORIGFILE(pFile);
return pFile->pMethods->xFetch(pFile, iOfst+p->iPgOne, iAmt, pp);
}
/* Release a memory-mapped page */
static int apndUnfetch(sqlite3_file *pFile, sqlite3_int64 iOfst, void *pPage){
ApndFile *p = (ApndFile *)pFile;
pFile = ORIGFILE(pFile);
return pFile->pMethods->xUnfetch(pFile, iOfst+p->iPgOne, pPage);
}
/*
** Check to see if the file is an ordinary SQLite database file.
*/
static int apndIsOrdinaryDatabaseFile(sqlite3_int64 sz, sqlite3_file *pFile){
int rc;
char zHdr[16];
static const char aSqliteHdr[] = "SQLite format 3";
if( sz<512 ) return 0;
rc = pFile->pMethods->xRead(pFile, zHdr, sizeof(zHdr), 0);
if( rc ) return 0;
return memcmp(zHdr, aSqliteHdr, sizeof(zHdr))==0;
}
/*
** Try to read the append-mark off the end of a file. Return the
** start of the appended database if the append-mark is present. If
** there is no append-mark, return -1;
*/
static sqlite3_int64 apndReadMark(sqlite3_int64 sz, sqlite3_file *pFile){
int rc, i;
sqlite3_int64 iMark;
unsigned char a[APND_MARK_SIZE];
if( sz<=APND_MARK_SIZE ) return -1;
rc = pFile->pMethods->xRead(pFile, a, APND_MARK_SIZE, sz-APND_MARK_SIZE);
if( rc ) return -1;
if( memcmp(a, APND_MARK_PREFIX, APND_MARK_PREFIX_SZ)!=0 ) return -1;
iMark = ((sqlite3_int64)(a[APND_MARK_PREFIX_SZ]&0x7f))<<56;
for(i=1; i<8; i++){
iMark += (sqlite3_int64)a[APND_MARK_PREFIX_SZ+i]<<(56-8*i);
}
return iMark;
}
/*
** Open an apnd file handle.
*/
static int apndOpen(
sqlite3_vfs *pVfs,
const char *zName,
sqlite3_file *pFile,
int flags,
int *pOutFlags
){
ApndFile *p;
sqlite3_file *pSubFile;
sqlite3_vfs *pSubVfs;
int rc;
sqlite3_int64 sz;
pSubVfs = ORIGVFS(pVfs);
if( (flags & SQLITE_OPEN_MAIN_DB)==0 ){
return pSubVfs->xOpen(pSubVfs, zName, pFile, flags, pOutFlags);
}
p = (ApndFile*)pFile;
memset(p, 0, sizeof(*p));
pSubFile = ORIGFILE(pFile);
p->base.pMethods = &apnd_io_methods;
rc = pSubVfs->xOpen(pSubVfs, zName, pSubFile, flags, pOutFlags);
if( rc ) goto apnd_open_done;
rc = pSubFile->pMethods->xFileSize(pSubFile, &sz);
if( rc ){
pSubFile->pMethods->xClose(pSubFile);
goto apnd_open_done;
}
if( apndIsOrdinaryDatabaseFile(sz, pSubFile) ){
memmove(pFile, pSubFile, pSubVfs->szOsFile);
return SQLITE_OK;
}
p->iMark = 0;
p->iPgOne = apndReadMark(sz, pFile);
if( p->iPgOne>0 ){
return SQLITE_OK;
}
if( (flags & SQLITE_OPEN_CREATE)==0 ){
pSubFile->pMethods->xClose(pSubFile);
rc = SQLITE_CANTOPEN;
}
p->iPgOne = (sz+0xfff) & ~(sqlite3_int64)0xfff;
apnd_open_done:
if( rc ) pFile->pMethods = 0;
return rc;
}
/*
** All other VFS methods are pass-thrus.
*/
static int apndDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
return ORIGVFS(pVfs)->xDelete(ORIGVFS(pVfs), zPath, dirSync);
}
static int apndAccess(
sqlite3_vfs *pVfs,
const char *zPath,
int flags,
int *pResOut
){
return ORIGVFS(pVfs)->xAccess(ORIGVFS(pVfs), zPath, flags, pResOut);
}
static int apndFullPathname(
sqlite3_vfs *pVfs,
const char *zPath,
int nOut,
char *zOut
){
return ORIGVFS(pVfs)->xFullPathname(ORIGVFS(pVfs),zPath,nOut,zOut);
}
static void *apndDlOpen(sqlite3_vfs *pVfs, const char *zPath){
return ORIGVFS(pVfs)->xDlOpen(ORIGVFS(pVfs), zPath);
}
static void apndDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){
ORIGVFS(pVfs)->xDlError(ORIGVFS(pVfs), nByte, zErrMsg);
}
static void (*apndDlSym(sqlite3_vfs *pVfs, void *p, const char *zSym))(void){
return ORIGVFS(pVfs)->xDlSym(ORIGVFS(pVfs), p, zSym);
}
static void apndDlClose(sqlite3_vfs *pVfs, void *pHandle){
ORIGVFS(pVfs)->xDlClose(ORIGVFS(pVfs), pHandle);
}
static int apndRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
return ORIGVFS(pVfs)->xRandomness(ORIGVFS(pVfs), nByte, zBufOut);
}
static int apndSleep(sqlite3_vfs *pVfs, int nMicro){
return ORIGVFS(pVfs)->xSleep(ORIGVFS(pVfs), nMicro);
}
static int apndCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
return ORIGVFS(pVfs)->xCurrentTime(ORIGVFS(pVfs), pTimeOut);
}
static int apndGetLastError(sqlite3_vfs *pVfs, int a, char *b){
return ORIGVFS(pVfs)->xGetLastError(ORIGVFS(pVfs), a, b);
}
static int apndCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *p){
return ORIGVFS(pVfs)->xCurrentTimeInt64(ORIGVFS(pVfs), p);
}
static int apndSetSystemCall(
sqlite3_vfs *pVfs,
const char *zName,
sqlite3_syscall_ptr pCall
){
return ORIGVFS(pVfs)->xSetSystemCall(ORIGVFS(pVfs),zName,pCall);
}
static sqlite3_syscall_ptr apndGetSystemCall(
sqlite3_vfs *pVfs,
const char *zName
){
return ORIGVFS(pVfs)->xGetSystemCall(ORIGVFS(pVfs),zName);
}
static const char *apndNextSystemCall(sqlite3_vfs *pVfs, const char *zName){
return ORIGVFS(pVfs)->xNextSystemCall(ORIGVFS(pVfs), zName);
}
#ifdef _WIN32
__declspec(dllexport)
#endif
/*
** This routine is called when the extension is loaded.
** Register the new VFS.
*/
int sqlite3_appendvfs_init(
sqlite3 *db,
char **pzErrMsg,
const sqlite3_api_routines *pApi
){
int rc = SQLITE_OK;
sqlite3_vfs *pOrig;
SQLITE_EXTENSION_INIT2(pApi);
pOrig = sqlite3_vfs_find(0);
apnd_vfs.iVersion = pOrig->iVersion;
apnd_vfs.pAppData = pOrig;
apnd_vfs.szOsFile = pOrig->szOsFile + sizeof(ApndFile);
rc = sqlite3_vfs_register(&apnd_vfs, 0);
#ifdef APPENDVFS_TEST
if( rc==SQLITE_OK ){
rc = sqlite3_auto_extension((void(*)(void))apndvfsRegister);
}
#endif
if( rc==SQLITE_OK ) rc = SQLITE_OK_LOAD_PERMANENTLY;
return rc;
}
+15
View File
@@ -27,6 +27,21 @@ SQLITE_EXTENSION_INIT1
** seven bits per integer stored in the lower seven bits of each byte.
** More significant bits occur first. The most significant bit (0x80)
** is a flag to indicate the end of the integer.
**
** This function, SQLAR, and ZIP all use the same "deflate" compression
** algorithm, but each is subtly different:
**
** * ZIP uses raw deflate.
**
** * SQLAR uses the "zlib format" which is raw deflate with a two-byte
** algorithm-identification header and a four-byte checksum at the end.
**
** * This utility uses the "zlib format" like SQLAR, but adds the variable-
** length integer uncompressed size value at the beginning.
**
** This function might be extended in the future to support compression
** formats other than deflate, by providing a different algorithm-id
** mark following the variable-length integer size parameter.
*/
static void compressFunc(
sqlite3_context *context,
+707 -35
View File
@@ -11,11 +11,120 @@
******************************************************************************
**
** This SQLite extension implements SQL functions readfile() and
** writefile().
** writefile(), and eponymous virtual type "fsdir".
**
** WRITEFILE(FILE, DATA [, MODE [, MTIME]]):
**
** If neither of the optional arguments is present, then this UDF
** function writes blob DATA to file FILE. If successful, the number
** of bytes written is returned. If an error occurs, NULL is returned.
**
** If the first option argument - MODE - is present, then it must
** be passed an integer value that corresponds to a POSIX mode
** value (file type + permissions, as returned in the stat.st_mode
** field by the stat() system call). Three types of files may
** be written/created:
**
** regular files: (mode & 0170000)==0100000
** symbolic links: (mode & 0170000)==0120000
** directories: (mode & 0170000)==0040000
**
** For a directory, the DATA is ignored. For a symbolic link, it is
** interpreted as text and used as the target of the link. For a
** regular file, it is interpreted as a blob and written into the
** named file. Regardless of the type of file, its permissions are
** set to (mode & 0777) before returning.
**
** If the optional MTIME argument is present, then it is interpreted
** as an integer - the number of seconds since the unix epoch. The
** modification-time of the target file is set to this value before
** returning.
**
** If three or more arguments are passed to this function and an
** error is encountered, an exception is raised.
**
** READFILE(FILE):
**
** Read and return the contents of file FILE (type blob) from disk.
**
** FSDIR:
**
** Used as follows:
**
** SELECT * FROM fsdir($path [, $dir]);
**
** Parameter $path is an absolute or relative pathname. If the file that it
** refers to does not exist, it is an error. If the path refers to a regular
** file or symbolic link, it returns a single row. Or, if the path refers
** to a directory, it returns one row for the directory, and one row for each
** file within the hierarchy rooted at $path.
**
** Each row has the following columns:
**
** name: Path to file or directory (text value).
** mode: Value of stat.st_mode for directory entry (an integer).
** mtime: Value of stat.st_mtime for directory entry (an integer).
** data: For a regular file, a blob containing the file data. For a
** symlink, a text value containing the text of the link. For a
** directory, NULL.
**
** If a non-NULL value is specified for the optional $dir parameter and
** $path is a relative path, then $path is interpreted relative to $dir.
** And the paths returned in the "name" column of the table are also
** relative to directory $dir.
*/
#include "sqlite3ext.h"
SQLITE_EXTENSION_INIT1
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#if !defined(_WIN32) && !defined(WIN32)
# include <unistd.h>
# include <dirent.h>
# include <utime.h>
#else
# include "windows.h"
# include <io.h>
# include <direct.h>
# include "test_windirent.h"
# define dirent DIRENT
# define timespec TIMESPEC
# define stat _stat
# define mkdir(path,mode) _mkdir(path)
# define lstat(path,buf) _stat(path,buf)
#endif
#include <time.h>
#include <errno.h>
#define FSDIR_SCHEMA "(name,mode,mtime,data,path HIDDEN,dir HIDDEN)"
/*
** Set the result stored by context ctx to a blob containing the
** contents of file zName.
*/
static void readFileContents(sqlite3_context *ctx, const char *zName){
FILE *in;
long nIn;
void *pBuf;
in = fopen(zName, "rb");
if( in==0 ) return;
fseek(in, 0, SEEK_END);
nIn = ftell(in);
rewind(in);
pBuf = sqlite3_malloc( nIn );
if( pBuf && 1==fread(pBuf, nIn, 1, in) ){
sqlite3_result_blob(ctx, pBuf, nIn, sqlite3_free);
}else{
sqlite3_free(pBuf);
}
fclose(in);
}
/*
** Implementation of the "readfile(X)" SQL function. The entire content
@@ -28,58 +137,618 @@ static void readfileFunc(
sqlite3_value **argv
){
const char *zName;
FILE *in;
long nIn;
void *pBuf;
(void)(argc); /* Unused parameter */
zName = (const char*)sqlite3_value_text(argv[0]);
if( zName==0 ) return;
in = fopen(zName, "rb");
if( in==0 ) return;
fseek(in, 0, SEEK_END);
nIn = ftell(in);
rewind(in);
pBuf = sqlite3_malloc( nIn );
if( pBuf && 1==fread(pBuf, nIn, 1, in) ){
sqlite3_result_blob(context, pBuf, nIn, sqlite3_free);
}else{
sqlite3_free(pBuf);
}
fclose(in);
readFileContents(context, zName);
}
/*
** Implementation of the "writefile(X,Y)" SQL function. The argument Y
** is written into file X. The number of bytes written is returned. Or
** NULL is returned if something goes wrong, such as being unable to open
** file X for writing.
** Set the error message contained in context ctx to the results of
** vprintf(zFmt, ...).
*/
static void ctxErrorMsg(sqlite3_context *ctx, const char *zFmt, ...){
char *zMsg = 0;
va_list ap;
va_start(ap, zFmt);
zMsg = sqlite3_vmprintf(zFmt, ap);
sqlite3_result_error(ctx, zMsg, -1);
sqlite3_free(zMsg);
va_end(ap);
}
/*
** Argument zFile is the name of a file that will be created and/or written
** by SQL function writefile(). This function ensures that the directory
** zFile will be written to exists, creating it if required. The permissions
** for any path components created by this function are set to (mode&0777).
**
** If an OOM condition is encountered, SQLITE_NOMEM is returned. Otherwise,
** SQLITE_OK is returned if the directory is successfully created, or
** SQLITE_ERROR otherwise.
*/
static int makeDirectory(
const char *zFile,
mode_t mode
){
char *zCopy = sqlite3_mprintf("%s", zFile);
int rc = SQLITE_OK;
if( zCopy==0 ){
rc = SQLITE_NOMEM;
}else{
int nCopy = (int)strlen(zCopy);
int i = 1;
while( rc==SQLITE_OK ){
struct stat sStat;
int rc2;
for(; zCopy[i]!='/' && i<nCopy; i++);
if( i==nCopy ) break;
zCopy[i] = '\0';
rc2 = stat(zCopy, &sStat);
if( rc2!=0 ){
if( mkdir(zCopy, mode & 0777) ) rc = SQLITE_ERROR;
}else{
if( !S_ISDIR(sStat.st_mode) ) rc = SQLITE_ERROR;
}
zCopy[i] = '/';
i++;
}
sqlite3_free(zCopy);
}
return rc;
}
/*
** This function does the work for the writefile() UDF. Refer to
** header comments at the top of this file for details.
*/
static int writeFile(
sqlite3_context *pCtx, /* Context to return bytes written in */
const char *zFile, /* File to write */
sqlite3_value *pData, /* Data to write */
mode_t mode, /* MODE parameter passed to writefile() */
sqlite3_int64 mtime /* MTIME parameter (or -1 to not set time) */
){
#if !defined(_WIN32) && !defined(WIN32)
if( S_ISLNK(mode) ){
const char *zTo = (const char*)sqlite3_value_text(pData);
if( symlink(zTo, zFile)<0 ) return 1;
}else
#endif
{
if( S_ISDIR(mode) ){
if( mkdir(zFile, mode) ){
/* The mkdir() call to create the directory failed. This might not
** be an error though - if there is already a directory at the same
** path and either the permissions already match or can be changed
** to do so using chmod(), it is not an error. */
struct stat sStat;
if( errno!=EEXIST
|| 0!=stat(zFile, &sStat)
|| !S_ISDIR(sStat.st_mode)
|| ((sStat.st_mode&0777)!=(mode&0777) && 0!=chmod(zFile, mode&0777))
){
return 1;
}
}
}else{
sqlite3_int64 nWrite = 0;
const char *z;
int rc = 0;
FILE *out = fopen(zFile, "wb");
if( out==0 ) return 1;
z = (const char*)sqlite3_value_blob(pData);
if( z ){
sqlite3_int64 n = fwrite(z, 1, sqlite3_value_bytes(pData), out);
nWrite = sqlite3_value_bytes(pData);
if( nWrite!=n ){
rc = 1;
}
}
fclose(out);
if( rc==0 && mode && chmod(zFile, mode & 0777) ){
rc = 1;
}
if( rc ) return 2;
sqlite3_result_int64(pCtx, nWrite);
}
}
if( mtime>=0 ){
#if defined(_WIN32)
/* Windows */
FILETIME lastAccess;
FILETIME lastWrite;
SYSTEMTIME currentTime;
LONGLONG intervals;
HANDLE hFile;
GetSystemTime(&currentTime);
SystemTimeToFileTime(&currentTime, &lastAccess);
intervals = Int32x32To64(mtime, 10000000) + 116444736000000000;
lastWrite.dwLowDateTime = (DWORD)intervals;
lastWrite.dwHighDateTime = intervals >> 32;
hFile = CreateFile(
zFile, FILE_WRITE_ATTRIBUTES, 0, NULL, OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS, NULL
);
if( hFile!=INVALID_HANDLE_VALUE ){
BOOL bResult = SetFileTime(hFile, NULL, &lastAccess, &lastWrite);
CloseHandle(hFile);
return !bResult;
}else{
return 1;
}
#elif defined(AT_FDCWD)
/* Recent unix */
struct timespec times[2];
times[0].tv_nsec = times[1].tv_nsec = 0;
times[0].tv_sec = time(0);
times[1].tv_sec = mtime;
if( utimensat(AT_FDCWD, zFile, times, AT_SYMLINK_NOFOLLOW) ){
return 1;
}
#else
/* Legacy unix */
struct timeval times[2];
times[0].tv_usec = times[1].tv_usec = 0;
times[0].tv_sec = time(0);
times[1].tv_sec = mtime;
if( utimes(zFile, times) ){
return 1;
}
#endif
}
return 0;
}
/*
** Implementation of the "writefile(W,X[,Y[,Z]]])" SQL function.
** Refer to header comments at the top of this file for details.
*/
static void writefileFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
FILE *out;
const char *z;
sqlite3_int64 rc;
const char *zFile;
mode_t mode = 0;
int res;
sqlite3_int64 mtime = -1;
if( argc<2 || argc>4 ){
sqlite3_result_error(context,
"wrong number of arguments to function writefile()", -1
);
return;
}
(void)(argc); /* Unused parameter */
zFile = (const char*)sqlite3_value_text(argv[0]);
if( zFile==0 ) return;
out = fopen(zFile, "wb");
if( out==0 ) return;
z = (const char*)sqlite3_value_blob(argv[1]);
if( z==0 ){
rc = 0;
}else{
rc = fwrite(z, 1, sqlite3_value_bytes(argv[1]), out);
if( argc>=3 ){
mode = (mode_t)sqlite3_value_int(argv[2]);
}
if( argc==4 ){
mtime = sqlite3_value_int64(argv[3]);
}
res = writeFile(context, zFile, argv[1], mode, mtime);
if( res==1 && errno==ENOENT ){
if( makeDirectory(zFile, mode)==SQLITE_OK ){
res = writeFile(context, zFile, argv[1], mode, mtime);
}
}
if( argc>2 && res!=0 ){
if( S_ISLNK(mode) ){
ctxErrorMsg(context, "failed to create symlink: %s", zFile);
}else if( S_ISDIR(mode) ){
ctxErrorMsg(context, "failed to create directory: %s", zFile);
}else{
ctxErrorMsg(context, "failed to write file: %s", zFile);
}
}
fclose(out);
sqlite3_result_int64(context, rc);
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
/*
** Cursor type for recursively iterating through a directory structure.
*/
typedef struct fsdir_cursor fsdir_cursor;
typedef struct FsdirLevel FsdirLevel;
struct FsdirLevel {
DIR *pDir; /* From opendir() */
char *zDir; /* Name of directory (nul-terminated) */
};
struct fsdir_cursor {
sqlite3_vtab_cursor base; /* Base class - must be first */
int nLvl; /* Number of entries in aLvl[] array */
int iLvl; /* Index of current entry */
FsdirLevel *aLvl; /* Hierarchy of directories being traversed */
const char *zBase;
int nBase;
struct stat sStat; /* Current lstat() results */
char *zPath; /* Path to current entry */
sqlite3_int64 iRowid; /* Current rowid */
};
typedef struct fsdir_tab fsdir_tab;
struct fsdir_tab {
sqlite3_vtab base; /* Base class - must be first */
};
/*
** Construct a new fsdir virtual table object.
*/
static int fsdirConnect(
sqlite3 *db,
void *pAux,
int argc, const char *const*argv,
sqlite3_vtab **ppVtab,
char **pzErr
){
fsdir_tab *pNew = 0;
int rc;
rc = sqlite3_declare_vtab(db, "CREATE TABLE x" FSDIR_SCHEMA);
if( rc==SQLITE_OK ){
pNew = (fsdir_tab*)sqlite3_malloc( sizeof(*pNew) );
if( pNew==0 ) return SQLITE_NOMEM;
memset(pNew, 0, sizeof(*pNew));
}
*ppVtab = (sqlite3_vtab*)pNew;
return rc;
}
/*
** This method is the destructor for fsdir vtab objects.
*/
static int fsdirDisconnect(sqlite3_vtab *pVtab){
sqlite3_free(pVtab);
return SQLITE_OK;
}
/*
** Constructor for a new fsdir_cursor object.
*/
static int fsdirOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
fsdir_cursor *pCur;
pCur = sqlite3_malloc( sizeof(*pCur) );
if( pCur==0 ) return SQLITE_NOMEM;
memset(pCur, 0, sizeof(*pCur));
pCur->iLvl = -1;
*ppCursor = &pCur->base;
return SQLITE_OK;
}
/*
** Reset a cursor back to the state it was in when first returned
** by fsdirOpen().
*/
static void fsdirResetCursor(fsdir_cursor *pCur){
int i;
for(i=0; i<=pCur->iLvl; i++){
FsdirLevel *pLvl = &pCur->aLvl[i];
if( pLvl->pDir ) closedir(pLvl->pDir);
sqlite3_free(pLvl->zDir);
}
sqlite3_free(pCur->zPath);
pCur->aLvl = 0;
pCur->zPath = 0;
pCur->zBase = 0;
pCur->nBase = 0;
pCur->iLvl = -1;
pCur->iRowid = 1;
}
/*
** Destructor for an fsdir_cursor.
*/
static int fsdirClose(sqlite3_vtab_cursor *cur){
fsdir_cursor *pCur = (fsdir_cursor*)cur;
fsdirResetCursor(pCur);
sqlite3_free(pCur->aLvl);
sqlite3_free(pCur);
return SQLITE_OK;
}
/*
** Set the error message for the virtual table associated with cursor
** pCur to the results of vprintf(zFmt, ...).
*/
static void fsdirSetErrmsg(fsdir_cursor *pCur, const char *zFmt, ...){
va_list ap;
va_start(ap, zFmt);
pCur->base.pVtab->zErrMsg = sqlite3_vmprintf(zFmt, ap);
va_end(ap);
}
/*
** Advance an fsdir_cursor to its next row of output.
*/
static int fsdirNext(sqlite3_vtab_cursor *cur){
fsdir_cursor *pCur = (fsdir_cursor*)cur;
mode_t m = pCur->sStat.st_mode;
pCur->iRowid++;
if( S_ISDIR(m) ){
/* Descend into this directory */
int iNew = pCur->iLvl + 1;
FsdirLevel *pLvl;
if( iNew>=pCur->nLvl ){
int nNew = iNew+1;
int nByte = nNew*sizeof(FsdirLevel);
FsdirLevel *aNew = (FsdirLevel*)sqlite3_realloc(pCur->aLvl, nByte);
if( aNew==0 ) return SQLITE_NOMEM;
memset(&aNew[pCur->nLvl], 0, sizeof(FsdirLevel)*(nNew-pCur->nLvl));
pCur->aLvl = aNew;
pCur->nLvl = nNew;
}
pCur->iLvl = iNew;
pLvl = &pCur->aLvl[iNew];
pLvl->zDir = pCur->zPath;
pCur->zPath = 0;
pLvl->pDir = opendir(pLvl->zDir);
if( pLvl->pDir==0 ){
fsdirSetErrmsg(pCur, "cannot read directory: %s", pCur->zPath);
return SQLITE_ERROR;
}
}
while( pCur->iLvl>=0 ){
FsdirLevel *pLvl = &pCur->aLvl[pCur->iLvl];
struct dirent *pEntry = readdir(pLvl->pDir);
if( pEntry ){
if( pEntry->d_name[0]=='.' ){
if( pEntry->d_name[1]=='.' && pEntry->d_name[2]=='\0' ) continue;
if( pEntry->d_name[1]=='\0' ) continue;
}
sqlite3_free(pCur->zPath);
pCur->zPath = sqlite3_mprintf("%s/%s", pLvl->zDir, pEntry->d_name);
if( pCur->zPath==0 ) return SQLITE_NOMEM;
if( lstat(pCur->zPath, &pCur->sStat) ){
fsdirSetErrmsg(pCur, "cannot stat file: %s", pCur->zPath);
return SQLITE_ERROR;
}
return SQLITE_OK;
}
closedir(pLvl->pDir);
sqlite3_free(pLvl->zDir);
pLvl->pDir = 0;
pLvl->zDir = 0;
pCur->iLvl--;
}
/* EOF */
sqlite3_free(pCur->zPath);
pCur->zPath = 0;
return SQLITE_OK;
}
/*
** Return values of columns for the row at which the series_cursor
** is currently pointing.
*/
static int fsdirColumn(
sqlite3_vtab_cursor *cur, /* The cursor */
sqlite3_context *ctx, /* First argument to sqlite3_result_...() */
int i /* Which column to return */
){
fsdir_cursor *pCur = (fsdir_cursor*)cur;
switch( i ){
case 0: { /* name */
sqlite3_result_text(ctx, &pCur->zPath[pCur->nBase], -1, SQLITE_TRANSIENT);
break;
}
case 1: /* mode */
sqlite3_result_int64(ctx, pCur->sStat.st_mode);
break;
case 2: /* mtime */
sqlite3_result_int64(ctx, pCur->sStat.st_mtime);
break;
case 3: { /* data */
mode_t m = pCur->sStat.st_mode;
if( S_ISDIR(m) ){
sqlite3_result_null(ctx);
#if !defined(_WIN32) && !defined(WIN32)
}else if( S_ISLNK(m) ){
char aStatic[64];
char *aBuf = aStatic;
int nBuf = 64;
int n;
while( 1 ){
n = readlink(pCur->zPath, aBuf, nBuf);
if( n<nBuf ) break;
if( aBuf!=aStatic ) sqlite3_free(aBuf);
nBuf = nBuf*2;
aBuf = sqlite3_malloc(nBuf);
if( aBuf==0 ){
sqlite3_result_error_nomem(ctx);
return SQLITE_NOMEM;
}
}
sqlite3_result_text(ctx, aBuf, n, SQLITE_TRANSIENT);
if( aBuf!=aStatic ) sqlite3_free(aBuf);
#endif
}else{
readFileContents(ctx, pCur->zPath);
}
}
}
return SQLITE_OK;
}
/*
** Return the rowid for the current row. In this implementation, the
** first row returned is assigned rowid value 1, and each subsequent
** row a value 1 more than that of the previous.
*/
static int fsdirRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
fsdir_cursor *pCur = (fsdir_cursor*)cur;
*pRowid = pCur->iRowid;
return SQLITE_OK;
}
/*
** Return TRUE if the cursor has been moved off of the last
** row of output.
*/
static int fsdirEof(sqlite3_vtab_cursor *cur){
fsdir_cursor *pCur = (fsdir_cursor*)cur;
return (pCur->zPath==0);
}
/*
** xFilter callback.
*/
static int fsdirFilter(
sqlite3_vtab_cursor *cur,
int idxNum, const char *idxStr,
int argc, sqlite3_value **argv
){
const char *zDir = 0;
fsdir_cursor *pCur = (fsdir_cursor*)cur;
fsdirResetCursor(pCur);
if( idxNum==0 ){
fsdirSetErrmsg(pCur, "table function fsdir requires an argument");
return SQLITE_ERROR;
}
assert( argc==idxNum && (argc==1 || argc==2) );
zDir = (const char*)sqlite3_value_text(argv[0]);
if( zDir==0 ){
fsdirSetErrmsg(pCur, "table function fsdir requires a non-NULL argument");
return SQLITE_ERROR;
}
if( argc==2 ){
pCur->zBase = (const char*)sqlite3_value_text(argv[1]);
}
if( pCur->zBase ){
pCur->nBase = (int)strlen(pCur->zBase)+1;
pCur->zPath = sqlite3_mprintf("%s/%s", pCur->zBase, zDir);
}else{
pCur->zPath = sqlite3_mprintf("%s", zDir);
}
if( pCur->zPath==0 ){
return SQLITE_NOMEM;
}
if( lstat(pCur->zPath, &pCur->sStat) ){
fsdirSetErrmsg(pCur, "cannot stat file: %s", pCur->zPath);
return SQLITE_ERROR;
}
return SQLITE_OK;
}
/*
** SQLite will invoke this method one or more times while planning a query
** that uses the generate_series virtual table. This routine needs to create
** a query plan for each invocation and compute an estimated cost for that
** plan.
**
** In this implementation idxNum is used to represent the
** query plan. idxStr is unused.
**
** The query plan is represented by bits in idxNum:
**
** (1) start = $value -- constraint exists
** (2) stop = $value -- constraint exists
** (4) step = $value -- constraint exists
** (8) output in descending order
*/
static int fsdirBestIndex(
sqlite3_vtab *tab,
sqlite3_index_info *pIdxInfo
){
int i; /* Loop over constraints */
int idx4 = -1;
int idx5 = -1;
const struct sqlite3_index_constraint *pConstraint;
pConstraint = pIdxInfo->aConstraint;
for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
if( pConstraint->usable==0 ) continue;
if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
if( pConstraint->iColumn==4 ) idx4 = i;
if( pConstraint->iColumn==5 ) idx5 = i;
}
if( idx4<0 ){
pIdxInfo->idxNum = 0;
pIdxInfo->estimatedCost = (double)(((sqlite3_int64)1) << 50);
}else{
pIdxInfo->aConstraintUsage[idx4].omit = 1;
pIdxInfo->aConstraintUsage[idx4].argvIndex = 1;
if( idx5>=0 ){
pIdxInfo->aConstraintUsage[idx5].omit = 1;
pIdxInfo->aConstraintUsage[idx5].argvIndex = 2;
pIdxInfo->idxNum = 2;
pIdxInfo->estimatedCost = 10.0;
}else{
pIdxInfo->idxNum = 1;
pIdxInfo->estimatedCost = 100.0;
}
}
return SQLITE_OK;
}
/*
** Register the "fsdir" virtual table.
*/
static int fsdirRegister(sqlite3 *db){
static sqlite3_module fsdirModule = {
0, /* iVersion */
0, /* xCreate */
fsdirConnect, /* xConnect */
fsdirBestIndex, /* xBestIndex */
fsdirDisconnect, /* xDisconnect */
0, /* xDestroy */
fsdirOpen, /* xOpen - open a cursor */
fsdirClose, /* xClose - close a cursor */
fsdirFilter, /* xFilter - configure scan constraints */
fsdirNext, /* xNext - advance a cursor */
fsdirEof, /* xEof - check for end of scan */
fsdirColumn, /* xColumn - read data */
fsdirRowid, /* xRowid - read data */
0, /* xUpdate */
0, /* xBegin */
0, /* xSync */
0, /* xCommit */
0, /* xRollback */
0, /* xFindMethod */
0, /* xRename */
};
int rc = sqlite3_create_module(db, "fsdir", &fsdirModule, 0);
return rc;
}
#else /* SQLITE_OMIT_VIRTUALTABLE */
# define fsdirRegister(x) SQLITE_OK
#endif
#ifdef _WIN32
__declspec(dllexport)
@@ -95,8 +764,11 @@ int sqlite3_fileio_init(
rc = sqlite3_create_function(db, "readfile", 1, SQLITE_UTF8, 0,
readfileFunc, 0, 0);
if( rc==SQLITE_OK ){
rc = sqlite3_create_function(db, "writefile", 2, SQLITE_UTF8, 0,
rc = sqlite3_create_function(db, "writefile", -1, SQLITE_UTF8, 0,
writefileFunc, 0, 0);
}
if( rc==SQLITE_OK ){
rc = fsdirRegister(db);
}
return rc;
}
+122 -39
View File
@@ -10,23 +10,33 @@
**
******************************************************************************
**
** This is an in-memory read-only VFS implementation. The application
** supplies a block of memory which is the database file, and this VFS
** uses that block of memory.
** This is an in-memory VFS implementation. The application supplies
** a chunk of memory to hold the database file.
**
** Because there is no place to store journals and no good way to lock
** the "file", this VFS is read-only.
** Because there is place to store a rollback or wal journal, the database
** must use one of journal_mode=MEMORY or journal_mode=NONE.
**
** USAGE:
**
** sqlite3_open_v2("file:/whatever?ptr=0xf05538&sz=14336", &db,
** SQLITE_OPEN_READONLY | SQLITE_OPEN_URI,
** sqlite3_open_v2("file:/whatever?ptr=0xf05538&sz=14336&max=65536", &db,
** SQLITE_OPEN_READWRITE | SQLITE_OPEN_URI,
** "memvfs");
**
** The ptr= and sz= query parameters are required or the open will fail.
** The ptr= parameter gives the memory address of the buffer holding the
** read-only database and sz= gives the size of the database. The parameter
** values may be in hexadecimal or decimal. The filename is ignored.
** These are the query parameters:
**
** ptr= The address of the memory buffer that holds the database.
**
** sz= The current size the database file
**
** maxsz= The maximum size of the database. In other words, the
** amount of space allocated for the ptr= buffer.
**
** freeonclose= If true, then sqlite3_free() is called on the ptr=
** value when the connection closes.
**
** The ptr= and sz= query parameters are required. If maxsz= is omitted,
** then it defaults to the sz= value. Parameter values can be in either
** decimal or hexadecimal. The filename in the URI is ignored.
*/
#include <sqlite3ext.h>
SQLITE_EXTENSION_INIT1
@@ -49,7 +59,9 @@ typedef struct MemFile MemFile;
struct MemFile {
sqlite3_file base; /* IO methods */
sqlite3_int64 sz; /* Size of the file */
sqlite3_int64 szMax; /* Space allocated to aData */
unsigned char *aData; /* content of the file */
int bFreeOnClose; /* Invoke sqlite3_free() on aData at close */
};
/*
@@ -144,6 +156,8 @@ static const sqlite3_io_methods mem_io_methods = {
** to free.
*/
static int memClose(sqlite3_file *pFile){
MemFile *p = (MemFile *)pFile;
if( p->bFreeOnClose ) sqlite3_free(p->aData);
return SQLITE_OK;
}
@@ -170,21 +184,34 @@ static int memWrite(
int iAmt,
sqlite_int64 iOfst
){
return SQLITE_READONLY;
MemFile *p = (MemFile *)pFile;
if( iOfst+iAmt>p->sz ){
if( iOfst+iAmt>p->szMax ) return SQLITE_FULL;
if( iOfst>p->sz ) memset(p->aData+p->sz, 0, iOfst-p->sz);
p->sz = iOfst+iAmt;
}
memcpy(p->aData+iOfst, z, iAmt);
return SQLITE_OK;
}
/*
** Truncate an mem-file.
*/
static int memTruncate(sqlite3_file *pFile, sqlite_int64 size){
return SQLITE_READONLY;
MemFile *p = (MemFile *)pFile;
if( size>p->sz ){
if( size>p->szMax ) return SQLITE_FULL;
memset(p->aData+p->sz, 0, size-p->sz);
}
p->sz = size;
return SQLITE_OK;
}
/*
** Sync an mem-file.
*/
static int memSync(sqlite3_file *pFile, int flags){
return SQLITE_READONLY;
return SQLITE_OK;
}
/*
@@ -200,7 +227,7 @@ static int memFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
** Lock an mem-file.
*/
static int memLock(sqlite3_file *pFile, int eLock){
return SQLITE_READONLY;
return SQLITE_OK;
}
/*
@@ -242,7 +269,10 @@ static int memSectorSize(sqlite3_file *pFile){
** Return the device characteristic flags supported by an mem-file.
*/
static int memDeviceCharacteristics(sqlite3_file *pFile){
return SQLITE_IOCAP_IMMUTABLE;
return SQLITE_IOCAP_ATOMIC |
SQLITE_IOCAP_POWERSAFE_OVERWRITE |
SQLITE_IOCAP_SAFE_APPEND |
SQLITE_IOCAP_SEQUENTIAL;
}
/* Create a shared memory file mapping */
@@ -253,12 +283,12 @@ static int memShmMap(
int bExtend,
void volatile **pp
){
return SQLITE_READONLY;
return SQLITE_IOERR_SHMMAP;
}
/* Perform locking on a shared-memory segment */
static int memShmLock(sqlite3_file *pFile, int offset, int n, int flags){
return SQLITE_READONLY;
return SQLITE_IOERR_SHMLOCK;
}
/* Memory barrier operation on shared memory */
@@ -305,6 +335,9 @@ static int memOpen(
if( p->aData==0 ) return SQLITE_CANTOPEN;
p->sz = sqlite3_uri_int64(zName,"sz",0);
if( p->sz<0 ) return SQLITE_CANTOPEN;
p->szMax = sqlite3_uri_int64(zName,"max",p->sz);
if( p->szMax<p->sz ) return SQLITE_CANTOPEN;
p->bFreeOnClose = sqlite3_uri_boolean(zName,"freeonclose",0);
pFile->pMethods = &mem_io_methods;
return SQLITE_OK;
}
@@ -315,7 +348,7 @@ static int memOpen(
** returning.
*/
static int memDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
return SQLITE_READONLY;
return SQLITE_IOERR_DELETE;
}
/*
@@ -328,14 +361,7 @@ static int memAccess(
int flags,
int *pResOut
){
/* The spec says there are three possible values for flags. But only
** two of them are actually used */
assert( flags==SQLITE_ACCESS_EXISTS || flags==SQLITE_ACCESS_READWRITE );
if( flags==SQLITE_ACCESS_READWRITE ){
*pResOut = 0;
}else{
*pResOut = 1;
}
*pResOut = 0;
return SQLITE_OK;
}
@@ -416,31 +442,43 @@ static int memCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *p){
#ifdef MEMVFS_TEST
/*
** memload(FILENAME)
** memvfs_from_file(FILENAME, MAXSIZE)
**
** This an SQL function used to help in testing the memvfs VFS. The
** function reads the content of a file into memory and then returns
** a string that gives the locate and size of the in-memory buffer.
** a URI that can be handed to ATTACH to attach the memory buffer as
** a database. Example:
**
** ATTACH memvfs_from_file('test.db',1048576) AS inmem;
**
** The optional MAXSIZE argument gives the size of the memory allocation
** used to hold the database. If omitted, it defaults to the size of the
** file on disk.
*/
#include <stdio.h>
static void memvfsMemloadFunc(
static void memvfsFromFileFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
unsigned char *p;
sqlite3_int64 sz;
sqlite3_int64 szMax;
FILE *in;
const char *zFilename = (const char*)sqlite3_value_text(argv[0]);
char zReturn[100];
char *zUri;
if( zFilename==0 ) return;
in = fopen(zFilename, "rb");
if( in==0 ) return;
fseek(in, 0, SEEK_END);
sz = ftell(in);
szMax = sz = ftell(in);
rewind(in);
p = sqlite3_malloc( sz );
if( argc>=2 ){
szMax = sqlite3_value_int64(argv[1]);
if( szMax<sz ) szMax = sz;
}
p = sqlite3_malloc64( szMax );
if( p==0 ){
fclose(in);
sqlite3_result_error_nomem(context);
@@ -448,18 +486,60 @@ static void memvfsMemloadFunc(
}
fread(p, sz, 1, in);
fclose(in);
sqlite3_snprintf(sizeof(zReturn),zReturn,"ptr=%lld&sz=%lld",
(sqlite3_int64)p, sz);
sqlite3_result_text(context, zReturn, -1, SQLITE_TRANSIENT);
zUri = sqlite3_mprintf(
"file:/mem?vfs=memvfs&ptr=%lld&sz=%lld&max=%lld&freeonclose=1",
(sqlite3_int64)p, sz, szMax);
sqlite3_result_text(context, zUri, -1, sqlite3_free);
}
#endif /* MEMVFS_TEST */
#ifdef MEMVFS_TEST
/*
** memvfs_to_file(SCHEMA, FILENAME)
**
** The schema identified by SCHEMA must be a memvfs database. Write
** the content of this database into FILENAME.
*/
static void memvfsToFileFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
MemFile *p = 0;
FILE *out;
int rc;
sqlite3 *db = sqlite3_context_db_handle(context);
sqlite3_vfs *pVfs = 0;
const char *zSchema = (const char*)sqlite3_value_text(argv[0]);
const char *zFilename = (const char*)sqlite3_value_text(argv[1]);
if( zFilename==0 ) return;
out = fopen(zFilename, "wb");
if( out==0 ) return;
rc = sqlite3_file_control(db, zSchema, SQLITE_FCNTL_VFS_POINTER, &pVfs);
if( rc || pVfs==0 ) return;
if( strcmp(pVfs->zName,"memvfs")!=0 ) return;
rc = sqlite3_file_control(db, zSchema, SQLITE_FCNTL_FILE_POINTER, &p);
if( rc ) return;
fwrite(p->aData, 1, (size_t)p->sz, out);
fclose(out);
}
#endif /* MEMVFS_TEST */
#ifdef MEMVFS_TEST
/* Called for each new database connection */
static int memvfsRegister(
sqlite3 *db,
const char **pzErrMsg,
char **pzErrMsg,
const struct sqlite3_api_routines *pThunk
){
return sqlite3_create_function(db, "memload", 1, SQLITE_UTF8, 0,
memvfsMemloadFunc, 0, 0);
sqlite3_create_function(db, "memvfs_from_file", 1, SQLITE_UTF8, 0,
memvfsFromFileFunc, 0, 0);
sqlite3_create_function(db, "memvfs_from_file", 2, SQLITE_UTF8, 0,
memvfsFromFileFunc, 0, 0);
sqlite3_create_function(db, "memvfs_to_file", 2, SQLITE_UTF8, 0,
memvfsToFileFunc, 0, 0);
return SQLITE_OK;
}
#endif /* MEMVFS_TEST */
@@ -485,6 +565,9 @@ int sqlite3_memvfs_init(
if( rc==SQLITE_OK ){
rc = sqlite3_auto_extension((void(*)(void))memvfsRegister);
}
if( rc==SQLITE_OK ){
rc = memvfsRegister(db, pzErrMsg, pApi);
}
#endif
if( rc==SQLITE_OK ) rc = SQLITE_OK_LOAD_PERMANENTLY;
return rc;
+707
View File
@@ -0,0 +1,707 @@
/*
** 2018-01-08
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
******************************************************************************
**
** This file contains code to implement the sqlite3_normalize() function.
**
** char *sqlite3_normalize(const char *zSql);
**
** This function takes an SQL string as input and returns a "normalized"
** version of that string in memory obtained from sqlite3_malloc64(). The
** caller is responsible for ensuring that the returned memory is freed.
**
** If a memory allocation error occurs, this routine returns NULL.
**
** The normalization consists of the following transformations:
**
** (1) Convert every literal (string, blob literal, numeric constant,
** or "NULL" constant) into a ?
**
** (2) Remove all superfluous whitespace, including comments. Change
** all required whitespace to a single space character.
**
** (3) Lowercase all ASCII characters.
**
** (4) If an IN or NOT IN operator is followed by a list of 1 or more
** values, convert that list into "(?,?,?)".
**
** The purpose of normalization is two-fold:
**
** (1) Sanitize queries by removing potentially private or sensitive
** information contained in literals.
**
** (2) Identify structurally identical queries by comparing their
** normalized forms.
**
** Command-Line Utility
** --------------------
**
** This file also contains code for a command-line utility that converts
** SQL queries in text files into their normalized forms. To build the
** command-line program, compile this file with -DSQLITE_NORMALIZE_CLI
** and link it against the SQLite library.
*/
#include <sqlite3.h>
#include <string.h>
/*
** Implementation note:
**
** Much of the tokenizer logic is copied out of the tokenize.c source file
** of SQLite. That logic could be simplified for this particular application,
** but that would impose a risk of introducing subtle errors. It is best to
** keep the code as close to the original as possible.
**
** The tokenize code is in sync with the SQLite core as of 2018-01-08.
** Any future changes to the core tokenizer might require corresponding
** adjustments to the tokenizer logic in this module.
*/
/* Character classes for tokenizing
**
** In the sqlite3GetToken() function, a switch() on aiClass[c] is implemented
** using a lookup table, whereas a switch() directly on c uses a binary search.
** The lookup table is much faster. To maximize speed, and to ensure that
** a lookup table is used, all of the classes need to be small integers and
** all of them need to be used within the switch.
*/
#define CC_X 0 /* The letter 'x', or start of BLOB literal */
#define CC_KYWD 1 /* Alphabetics or '_'. Usable in a keyword */
#define CC_ID 2 /* unicode characters usable in IDs */
#define CC_DIGIT 3 /* Digits */
#define CC_DOLLAR 4 /* '$' */
#define CC_VARALPHA 5 /* '@', '#', ':'. Alphabetic SQL variables */
#define CC_VARNUM 6 /* '?'. Numeric SQL variables */
#define CC_SPACE 7 /* Space characters */
#define CC_QUOTE 8 /* '"', '\'', or '`'. String literals, quoted ids */
#define CC_QUOTE2 9 /* '['. [...] style quoted ids */
#define CC_PIPE 10 /* '|'. Bitwise OR or concatenate */
#define CC_MINUS 11 /* '-'. Minus or SQL-style comment */
#define CC_LT 12 /* '<'. Part of < or <= or <> */
#define CC_GT 13 /* '>'. Part of > or >= */
#define CC_EQ 14 /* '='. Part of = or == */
#define CC_BANG 15 /* '!'. Part of != */
#define CC_SLASH 16 /* '/'. / or c-style comment */
#define CC_LP 17 /* '(' */
#define CC_RP 18 /* ')' */
#define CC_SEMI 19 /* ';' */
#define CC_PLUS 20 /* '+' */
#define CC_STAR 21 /* '*' */
#define CC_PERCENT 22 /* '%' */
#define CC_COMMA 23 /* ',' */
#define CC_AND 24 /* '&' */
#define CC_TILDA 25 /* '~' */
#define CC_DOT 26 /* '.' */
#define CC_ILLEGAL 27 /* Illegal character */
static const unsigned char aiClass[] = {
/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xa xb xc xd xe xf */
/* 0x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 7, 7, 27, 7, 7, 27, 27,
/* 1x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
/* 2x */ 7, 15, 8, 5, 4, 22, 24, 8, 17, 18, 21, 20, 23, 11, 26, 16,
/* 3x */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 19, 12, 14, 13, 6,
/* 4x */ 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
/* 5x */ 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 9, 27, 27, 27, 1,
/* 6x */ 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
/* 7x */ 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 27, 10, 27, 25, 27,
/* 8x */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
/* 9x */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
/* Ax */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
/* Bx */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
/* Cx */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
/* Dx */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
/* Ex */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
/* Fx */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2
};
/* An array to map all upper-case characters into their corresponding
** lower-case character.
**
** SQLite only considers US-ASCII (or EBCDIC) characters. We do not
** handle case conversions for the UTF character set since the tables
** involved are nearly as big or bigger than SQLite itself.
*/
static const unsigned char sqlite3UpperToLower[] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 97, 98, 99,100,101,102,103,
104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,
122, 91, 92, 93, 94, 95, 96, 97, 98, 99,100,101,102,103,104,105,106,107,
108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,
126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,
162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,
180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,
198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,
216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,
234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,
252,253,254,255
};
/*
** The following 256 byte lookup table is used to support SQLites built-in
** equivalents to the following standard library functions:
**
** isspace() 0x01
** isalpha() 0x02
** isdigit() 0x04
** isalnum() 0x06
** isxdigit() 0x08
** toupper() 0x20
** SQLite identifier character 0x40
** Quote character 0x80
**
** Bit 0x20 is set if the mapped character requires translation to upper
** case. i.e. if the character is a lower-case ASCII character.
** If x is a lower-case ASCII character, then its upper-case equivalent
** is (x - 0x20). Therefore toupper() can be implemented as:
**
** (x & ~(map[x]&0x20))
**
** The equivalent of tolower() is implemented using the sqlite3UpperToLower[]
** array. tolower() is used more often than toupper() by SQLite.
**
** Bit 0x40 is set if the character is non-alphanumeric and can be used in an
** SQLite identifier. Identifiers are alphanumerics, "_", "$", and any
** non-ASCII UTF character. Hence the test for whether or not a character is
** part of an identifier is 0x46.
*/
static const unsigned char sqlite3CtypeMap[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 00..07 ........ */
0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, /* 08..0f ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 10..17 ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 18..1f ........ */
0x01, 0x00, 0x80, 0x00, 0x40, 0x00, 0x00, 0x80, /* 20..27 !"#$%&' */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 28..2f ()*+,-./ */
0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, /* 30..37 01234567 */
0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 38..3f 89:;<=>? */
0x00, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x02, /* 40..47 @ABCDEFG */
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, /* 48..4f HIJKLMNO */
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, /* 50..57 PQRSTUVW */
0x02, 0x02, 0x02, 0x80, 0x00, 0x00, 0x00, 0x40, /* 58..5f XYZ[\]^_ */
0x80, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x22, /* 60..67 `abcdefg */
0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, /* 68..6f hijklmno */
0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, /* 70..77 pqrstuvw */
0x22, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, /* 78..7f xyz{|}~. */
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* 80..87 ........ */
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* 88..8f ........ */
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* 90..97 ........ */
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* 98..9f ........ */
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* a0..a7 ........ */
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* a8..af ........ */
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* b0..b7 ........ */
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* b8..bf ........ */
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* c0..c7 ........ */
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* c8..cf ........ */
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* d0..d7 ........ */
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* d8..df ........ */
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* e0..e7 ........ */
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* e8..ef ........ */
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* f0..f7 ........ */
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40 /* f8..ff ........ */
};
#define sqlite3Toupper(x) ((x)&~(sqlite3CtypeMap[(unsigned char)(x)]&0x20))
#define sqlite3Isspace(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x01)
#define sqlite3Isalnum(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x06)
#define sqlite3Isalpha(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x02)
#define sqlite3Isdigit(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x04)
#define sqlite3Isxdigit(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x08)
#define sqlite3Tolower(x) (sqlite3UpperToLower[(unsigned char)(x)])
#define sqlite3Isquote(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x80)
/*
** If X is a character that can be used in an identifier then
** IdChar(X) will be true. Otherwise it is false.
**
** For ASCII, any character with the high-order bit set is
** allowed in an identifier. For 7-bit characters,
** sqlite3IsIdChar[X] must be 1.
**
** For EBCDIC, the rules are more complex but have the same
** end result.
**
** Ticket #1066. the SQL standard does not allow '$' in the
** middle of identifiers. But many SQL implementations do.
** SQLite will allow '$' in identifiers for compatibility.
** But the feature is undocumented.
*/
#define IdChar(C) ((sqlite3CtypeMap[(unsigned char)C]&0x46)!=0)
/*
** Ignore testcase() macros
*/
#define testcase(X)
/*
** Token values
*/
#define TK_SPACE 0
#define TK_NAME 1
#define TK_LITERAL 2
#define TK_PUNCT 3
#define TK_ERROR 4
#define TK_MINUS TK_PUNCT
#define TK_LP TK_PUNCT
#define TK_RP TK_PUNCT
#define TK_SEMI TK_PUNCT
#define TK_PLUS TK_PUNCT
#define TK_STAR TK_PUNCT
#define TK_SLASH TK_PUNCT
#define TK_REM TK_PUNCT
#define TK_EQ TK_PUNCT
#define TK_LE TK_PUNCT
#define TK_NE TK_PUNCT
#define TK_LSHIFT TK_PUNCT
#define TK_LT TK_PUNCT
#define TK_GE TK_PUNCT
#define TK_RSHIFT TK_PUNCT
#define TK_GT TK_PUNCT
#define TK_GE TK_PUNCT
#define TK_BITOR TK_PUNCT
#define TK_CONCAT TK_PUNCT
#define TK_COMMA TK_PUNCT
#define TK_BITAND TK_PUNCT
#define TK_BITNOT TK_PUNCT
#define TK_STRING TK_LITERAL
#define TK_ID TK_NAME
#define TK_ILLEGAL TK_ERROR
#define TK_DOT TK_PUNCT
#define TK_INTEGER TK_LITERAL
#define TK_FLOAT TK_LITERAL
#define TK_VARIABLE TK_LITERAL
#define TK_BLOB TK_LITERAL
/*
** Return the length (in bytes) of the token that begins at z[0].
** Store the token type in *tokenType before returning.
*/
static int sqlite3GetToken(const unsigned char *z, int *tokenType){
int i, c;
switch( aiClass[*z] ){ /* Switch on the character-class of the first byte
** of the token. See the comment on the CC_ defines
** above. */
case CC_SPACE: {
for(i=1; sqlite3Isspace(z[i]); i++){}
*tokenType = TK_SPACE;
return i;
}
case CC_MINUS: {
if( z[1]=='-' ){
for(i=2; (c=z[i])!=0 && c!='\n'; i++){}
*tokenType = TK_SPACE;
return i;
}
*tokenType = TK_MINUS;
return 1;
}
case CC_LP: {
*tokenType = TK_LP;
return 1;
}
case CC_RP: {
*tokenType = TK_RP;
return 1;
}
case CC_SEMI: {
*tokenType = TK_SEMI;
return 1;
}
case CC_PLUS: {
*tokenType = TK_PLUS;
return 1;
}
case CC_STAR: {
*tokenType = TK_STAR;
return 1;
}
case CC_SLASH: {
if( z[1]!='*' || z[2]==0 ){
*tokenType = TK_SLASH;
return 1;
}
for(i=3, c=z[2]; (c!='*' || z[i]!='/') && (c=z[i])!=0; i++){}
if( c ) i++;
*tokenType = TK_SPACE;
return i;
}
case CC_PERCENT: {
*tokenType = TK_REM;
return 1;
}
case CC_EQ: {
*tokenType = TK_EQ;
return 1 + (z[1]=='=');
}
case CC_LT: {
if( (c=z[1])=='=' ){
*tokenType = TK_LE;
return 2;
}else if( c=='>' ){
*tokenType = TK_NE;
return 2;
}else if( c=='<' ){
*tokenType = TK_LSHIFT;
return 2;
}else{
*tokenType = TK_LT;
return 1;
}
}
case CC_GT: {
if( (c=z[1])=='=' ){
*tokenType = TK_GE;
return 2;
}else if( c=='>' ){
*tokenType = TK_RSHIFT;
return 2;
}else{
*tokenType = TK_GT;
return 1;
}
}
case CC_BANG: {
if( z[1]!='=' ){
*tokenType = TK_ILLEGAL;
return 1;
}else{
*tokenType = TK_NE;
return 2;
}
}
case CC_PIPE: {
if( z[1]!='|' ){
*tokenType = TK_BITOR;
return 1;
}else{
*tokenType = TK_CONCAT;
return 2;
}
}
case CC_COMMA: {
*tokenType = TK_COMMA;
return 1;
}
case CC_AND: {
*tokenType = TK_BITAND;
return 1;
}
case CC_TILDA: {
*tokenType = TK_BITNOT;
return 1;
}
case CC_QUOTE: {
int delim = z[0];
testcase( delim=='`' );
testcase( delim=='\'' );
testcase( delim=='"' );
for(i=1; (c=z[i])!=0; i++){
if( c==delim ){
if( z[i+1]==delim ){
i++;
}else{
break;
}
}
}
if( c=='\'' ){
*tokenType = TK_STRING;
return i+1;
}else if( c!=0 ){
*tokenType = TK_ID;
return i+1;
}else{
*tokenType = TK_ILLEGAL;
return i;
}
}
case CC_DOT: {
if( !sqlite3Isdigit(z[1]) ){
*tokenType = TK_DOT;
return 1;
}
/* If the next character is a digit, this is a floating point
** number that begins with ".". Fall thru into the next case */
}
case CC_DIGIT: {
*tokenType = TK_INTEGER;
if( z[0]=='0' && (z[1]=='x' || z[1]=='X') && sqlite3Isxdigit(z[2]) ){
for(i=3; sqlite3Isxdigit(z[i]); i++){}
return i;
}
for(i=0; sqlite3Isdigit(z[i]); i++){}
if( z[i]=='.' ){
i++;
while( sqlite3Isdigit(z[i]) ){ i++; }
*tokenType = TK_FLOAT;
}
if( (z[i]=='e' || z[i]=='E') &&
( sqlite3Isdigit(z[i+1])
|| ((z[i+1]=='+' || z[i+1]=='-') && sqlite3Isdigit(z[i+2]))
)
){
i += 2;
while( sqlite3Isdigit(z[i]) ){ i++; }
*tokenType = TK_FLOAT;
}
while( IdChar(z[i]) ){
*tokenType = TK_ILLEGAL;
i++;
}
return i;
}
case CC_QUOTE2: {
for(i=1, c=z[0]; c!=']' && (c=z[i])!=0; i++){}
*tokenType = c==']' ? TK_ID : TK_ILLEGAL;
return i;
}
case CC_VARNUM: {
*tokenType = TK_VARIABLE;
for(i=1; sqlite3Isdigit(z[i]); i++){}
return i;
}
case CC_DOLLAR:
case CC_VARALPHA: {
int n = 0;
testcase( z[0]=='$' ); testcase( z[0]=='@' );
testcase( z[0]==':' ); testcase( z[0]=='#' );
*tokenType = TK_VARIABLE;
for(i=1; (c=z[i])!=0; i++){
if( IdChar(c) ){
n++;
}else if( c=='(' && n>0 ){
do{
i++;
}while( (c=z[i])!=0 && !sqlite3Isspace(c) && c!=')' );
if( c==')' ){
i++;
}else{
*tokenType = TK_ILLEGAL;
}
break;
}else if( c==':' && z[i+1]==':' ){
i++;
}else{
break;
}
}
if( n==0 ) *tokenType = TK_ILLEGAL;
return i;
}
case CC_KYWD: {
for(i=1; aiClass[z[i]]<=CC_KYWD; i++){}
if( IdChar(z[i]) ){
/* This token started out using characters that can appear in keywords,
** but z[i] is a character not allowed within keywords, so this must
** be an identifier instead */
i++;
break;
}
*tokenType = TK_ID;
return i;
}
case CC_X: {
testcase( z[0]=='x' ); testcase( z[0]=='X' );
if( z[1]=='\'' ){
*tokenType = TK_BLOB;
for(i=2; sqlite3Isxdigit(z[i]); i++){}
if( z[i]!='\'' || i%2 ){
*tokenType = TK_ILLEGAL;
while( z[i] && z[i]!='\'' ){ i++; }
}
if( z[i] ) i++;
return i;
}
/* If it is not a BLOB literal, then it must be an ID, since no
** SQL keywords start with the letter 'x'. Fall through */
}
case CC_ID: {
i = 1;
break;
}
default: {
*tokenType = TK_ILLEGAL;
return 1;
}
}
while( IdChar(z[i]) ){ i++; }
*tokenType = TK_ID;
return i;
}
char *sqlite3_normalize(const char *zSql){
char *z; /* The output string */
sqlite3_int64 nZ; /* Size of the output string in bytes */
sqlite3_int64 nSql; /* Size of the input string in bytes */
int i; /* Next character to read from zSql[] */
int j; /* Next slot to fill in on z[] */
int tokenType; /* Type of the next token */
int n; /* Size of the next token */
int k; /* Loop counter */
nSql = strlen(zSql);
nZ = nSql;
z = sqlite3_malloc64( nZ+2 );
if( z==0 ) return 0;
for(i=j=0; zSql[i]; i += n){
n = sqlite3GetToken((unsigned char*)zSql+i, &tokenType);
switch( tokenType ){
case TK_SPACE: {
break;
}
case TK_ERROR: {
sqlite3_free(z);
return 0;
}
case TK_LITERAL: {
z[j++] = '?';
break;
}
case TK_PUNCT:
case TK_NAME: {
if( n==4 && sqlite3_strnicmp(zSql+i,"NULL",4)==0 ){
if( (j>=3 && strncmp(z+j-2,"is",2)==0 && !IdChar(z[j-3]))
|| (j>=4 && strncmp(z+j-3,"not",3)==0 && !IdChar(z[j-4]))
){
/* NULL is a keyword in this case, not a literal value */
}else{
/* Here the NULL is a literal value */
z[j++] = '?';
break;
}
}
if( j>0 && IdChar(z[j-1]) && IdChar(zSql[i]) ) z[j++] = ' ';
for(k=0; k<n; k++){
z[j++] = sqlite3Tolower(zSql[i+k]);
}
break;
}
}
}
while( j>0 && z[j-1]==' ' ){ j--; }
if( i>0 && z[j-1]!=';' ){ z[j++] = ';'; }
z[j] = 0;
/* Make a second pass converting "in(...)" where the "..." is not a
** SELECT statement into "in(?,?,?)" */
for(i=0; i<j; i=n){
char *zIn = strstr(z+i, "in(");
int nParen;
if( zIn==0 ) break;
n = (int)(zIn-z)+3; /* Index of first char past "in(" */
if( n && IdChar(zIn[-1]) ) continue;
if( strncmp(zIn, "in(select",9)==0 && !IdChar(zIn[9]) ) continue;
if( strncmp(zIn, "in(with",7)==0 && !IdChar(zIn[7]) ) continue;
for(nParen=1, k=0; z[n+k]; k++){
if( z[n+k]=='(' ) nParen++;
if( z[n+k]==')' ){
nParen--;
if( nParen==0 ) break;
}
}
/* k is the number of bytes in the "..." within "in(...)" */
if( k<5 ){
z = sqlite3_realloc64(z, j+(5-k)+1);
if( z==0 ) return 0;
memmove(z+n+5, z+n+k, j-(n+k));
}else if( k>5 ){
memmove(z+n+5, z+n+k, j-(n+k));
}
j = j-k+5;
z[j] = 0;
memcpy(z+n, "?,?,?", 5);
}
return z;
}
/*
** For testing purposes, or to build a stand-alone SQL normalizer program,
** compile this one source file with the -DSQLITE_NORMALIZE_CLI and link
** it against any SQLite library. The resulting command-line program will
** run sqlite3_normalize() over the text of all files named on the command-
** line and show the result on standard output.
*/
#ifdef SQLITE_NORMALIZE_CLI
#include <stdio.h>
#include <stdlib.h>
/*
** Break zIn up into separate SQL statements and run sqlite3_normalize()
** on each one. Print the result of each run.
*/
static void normalizeFile(char *zIn){
int i;
if( zIn==0 ) return;
for(i=0; zIn[i]; i++){
char cSaved;
if( zIn[i]!=';' ) continue;
cSaved = zIn[i+1];
zIn[i+1] = 0;
if( sqlite3_complete(zIn) ){
char *zOut = sqlite3_normalize(zIn);
if( zOut ){
printf("%s\n", zOut);
sqlite3_free(zOut);
}else{
fprintf(stderr, "ERROR: %s\n", zIn);
}
zIn[i+1] = cSaved;
zIn += i+1;
i = -1;
}else{
zIn[i+1] = cSaved;
}
}
}
/*
** The main routine for "sql_normalize". Read files named on the
** command-line and run the text of each through sqlite3_normalize().
*/
int main(int argc, char **argv){
int i;
FILE *in;
char *zBuf = 0;
sqlite3_int64 sz, got;
for(i=1; i<argc; i++){
in = fopen(argv[i], "rb");
if( in==0 ){
fprintf(stderr, "cannot open \"%s\"\n", argv[i]);
continue;
}
fseek(in, 0, SEEK_END);
sz = ftell(in);
rewind(in);
zBuf = sqlite3_realloc64(zBuf, sz+1);
if( zBuf==0 ){
fprintf(stderr, "failed to malloc for %lld bytes\n", sz);
exit(1);
}
got = fread(zBuf, 1, sz, in);
fclose(in);
if( got!=sz ){
fprintf(stderr, "only able to read %lld of %lld bytes from \"%s\"\n",
got, sz, argv[i]);
}else{
zBuf[got] = 0;
normalizeFile(zBuf);
}
}
sqlite3_free(zBuf);
}
#endif /* SQLITE_NORMALIZE_CLI */
+121
View File
@@ -0,0 +1,121 @@
/*
** 2017-12-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.
**
******************************************************************************
**
** Utility functions sqlar_compress() and sqlar_uncompress(). Useful
** for working with sqlar archives and used by the shell tool's built-in
** sqlar support.
*/
#include "sqlite3ext.h"
SQLITE_EXTENSION_INIT1
#include <zlib.h>
/*
** Implementation of the "sqlar_compress(X)" SQL function.
**
** If the type of X is SQLITE_BLOB, and compressing that blob using
** zlib utility function compress() yields a smaller blob, return the
** compressed blob. Otherwise, return a copy of X.
**
** SQLar uses the "zlib format" for compressed content. The zlib format
** contains a two-byte identification header and a four-byte checksum at
** the end. This is different from ZIP which uses the raw deflate format.
**
** Future enhancements to SQLar might add support for new compression formats.
** If so, those new formats will be identified by alternative headers in the
** compressed data.
*/
static void sqlarCompressFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
assert( argc==1 );
if( sqlite3_value_type(argv[0])==SQLITE_BLOB ){
const Bytef *pData = sqlite3_value_blob(argv[0]);
uLong nData = sqlite3_value_bytes(argv[0]);
uLongf nOut = compressBound(nData);
Bytef *pOut;
pOut = (Bytef*)sqlite3_malloc(nOut);
if( pOut==0 ){
sqlite3_result_error_nomem(context);
return;
}else{
if( Z_OK!=compress(pOut, &nOut, pData, nData) ){
sqlite3_result_error(context, "error in compress()", -1);
}else if( nOut<nData ){
sqlite3_result_blob(context, pOut, nOut, SQLITE_TRANSIENT);
}else{
sqlite3_result_value(context, argv[0]);
}
sqlite3_free(pOut);
}
}else{
sqlite3_result_value(context, argv[0]);
}
}
/*
** Implementation of the "sqlar_uncompress(X,SZ)" SQL function
**
** Parameter SZ is interpreted as an integer. If it is less than or
** equal to zero, then this function returns a copy of X. Or, if
** SZ is equal to the size of X when interpreted as a blob, also
** return a copy of X. Otherwise, decompress blob X using zlib
** utility function uncompress() and return the results (another
** blob).
*/
static void sqlarUncompressFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
uLong nData;
uLongf sz;
assert( argc==2 );
sz = sqlite3_value_int(argv[1]);
if( sz<=0 || sz==(nData = sqlite3_value_bytes(argv[0])) ){
sqlite3_result_value(context, argv[0]);
}else{
const Bytef *pData= sqlite3_value_blob(argv[0]);
Bytef *pOut = sqlite3_malloc(sz);
if( Z_OK!=uncompress(pOut, &sz, pData, nData) ){
sqlite3_result_error(context, "error in uncompress()", -1);
}else{
sqlite3_result_blob(context, pOut, sz, SQLITE_TRANSIENT);
}
sqlite3_free(pOut);
}
}
#ifdef _WIN32
__declspec(dllexport)
#endif
int sqlite3_sqlar_init(
sqlite3 *db,
char **pzErrMsg,
const sqlite3_api_routines *pApi
){
int rc = SQLITE_OK;
SQLITE_EXTENSION_INIT2(pApi);
(void)pzErrMsg; /* Unused parameter */
rc = sqlite3_create_function(db, "sqlar_compress", 1, SQLITE_UTF8, 0,
sqlarCompressFunc, 0, 0);
if( rc==SQLITE_OK ){
rc = sqlite3_create_function(db, "sqlar_uncompress", 2, SQLITE_UTF8, 0,
sqlarUncompressFunc, 0, 0);
}
return rc;
}
+1 -1
View File
@@ -799,7 +799,7 @@ static void unionConfigureVtab(
zVal = zOpt;
if( *zVal==':' ) zVal++;
while( union_isidchar(*zVal) ) zVal++;
nOpt = zVal-zOpt;
nOpt = (int)(zVal-zOpt);
while( union_isspace(*zVal) ) zVal++;
if( *zVal=='=' ){
+1418
View File
File diff suppressed because it is too large Load Diff
+16 -2
View File
@@ -361,6 +361,7 @@ TESTSRC += \
$(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 \
@@ -370,6 +371,7 @@ TESTSRC += \
$(TOP)/ext/misc/unionvtab.c \
$(TOP)/ext/misc/wholenumber.c \
$(TOP)/ext/misc/vfslog.c \
$(TOP)/ext/misc/zipfile.c \
$(TOP)/ext/fts5/fts5_tcl.c \
$(TOP)/ext/fts5/fts5_test_mi.c \
$(TOP)/ext/fts5/fts5_test_tok.c
@@ -486,7 +488,8 @@ TESTPROGS = \
sqlite3_analyzer$(EXE) \
sqlite3_checker$(EXE) \
sqldiff$(EXE) \
dbhash$(EXE)
dbhash$(EXE) \
sqltclsh$(EXE)
# Databases containing fuzzer test cases
#
@@ -510,6 +513,7 @@ 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
FUZZCHECK_OPT += -DSQLITE_MAX_MEMORY=50000000
@@ -691,11 +695,15 @@ keywordhash.h: $(TOP)/tool/mkkeywordhash.c
# 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/expert/sqlite3expert.h \
$(TOP)/ext/misc/zipfile.c \
$(TOP)/src/test_windirent.c
shell.c: $(SHELL_SRC) $(TOP)/tool/mkshellc.tcl
tclsh $(TOP)/tool/mkshellc.tcl >shell.c
@@ -814,6 +822,12 @@ sqlite3_analyzer.c: sqlite3.c $(TOP)/src/tclsqlite.c $(TOP)/tool/spaceanal.tcl $
sqlite3_analyzer$(EXE): sqlite3_analyzer.c
$(TCCX) $(TCL_FLAGS) sqlite3_analyzer.c -o $@ $(LIBTCL) $(THREADLIB)
sqltclsh.c: sqlite3.c $(TOP)/src/tclsqlite.c $(TOP)/tool/sqltclsh.tcl $(TOP)/ext/misc/appendvfs.c $(TOP)/tool/mkccode.tcl
tclsh $(TOP)/tool/mkccode.tcl $(TOP)/tool/sqltclsh.c.in >sqltclsh.c
sqltclsh$(EXE): sqltclsh.c
$(TCCX) $(TCL_FLAGS) sqltclsh.c -o $@ $(LIBTCL) $(THREADLIB)
sqlite3_expert$(EXE): $(TOP)/ext/expert/sqlite3expert.h $(TOP)/ext/expert/sqlite3expert.c $(TOP)/ext/expert/expert.c sqlite3.c
$(TCCX) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION $(TOP)/ext/expert/sqlite3expert.c $(TOP)/ext/expert/expert.c sqlite3.c -o sqlite3_expert$(EXE) $(THREADLIB)
+45 -34
View File
@@ -1,8 +1,10 @@
C Stricter\stest\scases.
D 2017-12-29T16:37:33.070
F Makefile.in 804c347948b0ad5a962aea3e59413e897227e0173d0e76910f11f473e6c7ae9b
C Test\scases\sfor\ssqlite3_normalize().
D 2018-01-08T20:04:57.992
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F Makefile.in 822052988bbf6204ca2c3e2665618b5a48acec24105d5afa8c4ebb59cb941d3e
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
F Makefile.msc 57dcce0595d4a0c4b94b6f6ba732b8e33540358adf5fb8e1aa8389d34a9677e8
F Makefile.msc 0f2875c7d4cb93ae4dab661f58f9d68699d323cfb87ebd7d8dccbb9949979b83
F README.md eeae1e552f93ef72ef7c5b8f6647b368a001c28820ad1df179d3dae602bef681
F VERSION 0c10cdfed866fdd2d80434f64f042c3330f1daaed12e54287beb104f04b3faaf
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
@@ -11,7 +13,7 @@ F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90
F art/sqlite370.jpg d512473dae7e378a67e28ff96a34da7cb331def2
F autoconf/INSTALL 83e4a25da9fd053c7b3665eaaaf7919707915903
F autoconf/Makefile.am 66c0befa511f0d95ba229e180067cf0357a9ebf8b3201b06d683c5ba6220fb39
F autoconf/Makefile.msc b88a70dee8453cc353e5d6df172d60a11a0af905710a24b1e6be80f8fea6e96b
F autoconf/Makefile.msc 2c50a59319af7da4eaca8c13e3240881b1bc245fd175845a055faab7d03d6e67
F autoconf/README.first 6c4f34fe115ff55d4e8dbfa3cecf04a0188292f7
F autoconf/README.txt 4f04b0819303aabaa35fff5f7b257fb0c1ef95f1
F autoconf/configure.ac 8dd08ca564279fff091c9bfdd2599d8f992c9f1f70c5396de2126ad2bd1b3bed
@@ -114,7 +116,7 @@ F ext/fts5/fts5_hash.c 32be400cf761868c9db33efe81a06eb19a17c5402ad477ee9efb51301
F ext/fts5/fts5_index.c 5fe14375a29e8a7aa8f3e863babe180a19269206c254c8f47b216821d4ac1e15
F ext/fts5/fts5_main.c 24868f88ab2a865defbba7a92eebeb726cc991eb092b71b5f5508f180c72605b
F ext/fts5/fts5_storage.c fb5ef3c27073f67ade2e1bea08405f9e43f68f5f3676ed0ab7013bce5ba10be6
F ext/fts5/fts5_tcl.c a7df39442ae674dde877cf06fe02ebb7658e69c179a4d223241c90df4f14b54e
F ext/fts5/fts5_tcl.c b470467be4c5cab2d8b026992c05d86cd2293e7d8c4a10ba56d5f4f707981097
F ext/fts5/fts5_test_mi.c 65864ba1e5c34a61d409c4c587e0bbe0466eb4f8f478d85dc42a92caad1338e6
F ext/fts5/fts5_test_tok.c ffd657dd67e7fcdb31bf63fb60b6d867299a581d0f46e97086abacd66c2a9b26
F ext/fts5/fts5_tokenize.c 2ce7b44183538ec46b7907726262ee43ffdd39a8
@@ -221,7 +223,7 @@ F ext/icu/sqliteicu.h 728867a802baa5a96de7495e9689a8e01715ef37
F ext/lsm1/Makefile 98b0a24b45e248283d6bea4b6cb3e58d7b394edd8e96a0ac28c5fa5104813bad
F ext/lsm1/Makefile.msc f8c878b467232226de288da320e1ac71c131f5ec91e08b21f502303347260013
F ext/lsm1/lsm-test/README 87ea529d2abe615e856d4714bfe8bb185e6c2771b8612aa6298588b7b43e6f86
F ext/lsm1/lsm-test/lsmtest.h 5847594d4b43ec3412e1fd97104f7eb5fd770be55e691e6cb2e80929f86bebe3
F ext/lsm1/lsm-test/lsmtest.h cf58528ffe0cfe535e91b44584e2ec5fb1caacdabecef0d8dcf83bf83168bf28
F ext/lsm1/lsm-test/lsmtest1.c 33158978327f800e82b6a47c09b86ace809f56a9ff10b0162273ec1186cc3153
F ext/lsm1/lsm-test/lsmtest2.c 188b09aec776516aeedcfd13b9c6faf85ba16b3671a0897a2c740ee00a5dc4f8
F ext/lsm1/lsm-test/lsmtest3.c 9ab87528a36dbf4a61d7c8ad954f5ee368c0878c127b84b942b2e2abe522de26
@@ -237,10 +239,10 @@ F ext/lsm1/lsm-test/lsmtest_func.c 159aa401bc8032bfa3d8cf2977bd687abebab88025589
F ext/lsm1/lsm-test/lsmtest_io.c cf11b27b129c6bd5818fa1d440176502dc27229f0db892b4479118d61993ea20
F ext/lsm1/lsm-test/lsmtest_main.c a9bc647738c0dcaebf205d6d194b3ce4a6ef3925801cd2d919f0a4ea33a15aeb
F ext/lsm1/lsm-test/lsmtest_mem.c 4e63c764345ab1df59d4f13a77980c6f3643798210b10d6cdbd785b4b888fda5
F ext/lsm1/lsm-test/lsmtest_tdb.c 555fb101d2fe638abdd133e9294536c857fb38e0f227e049c00a67f51eaece06
F ext/lsm1/lsm-test/lsmtest_tdb.c 618a8619183fda4f5540fcde15f9068293c5e3180e1a246e34409b0c148758b3
F ext/lsm1/lsm-test/lsmtest_tdb.h 8733eee249b12956a9df8322994b43d19bd8c02ad2e8b0bb5164db4d6ccc1735
F ext/lsm1/lsm-test/lsmtest_tdb2.cc 99ea7f2dd9c7536c8fb9bdd329e4cfeb76899f3ddf6f48bdd3926e016922b715
F ext/lsm1/lsm-test/lsmtest_tdb3.c e44bf94e8bd724cd6ac161fd2cd44ffe43193932ad3a6bee1b07d80bb74012bb
F ext/lsm1/lsm-test/lsmtest_tdb3.c b4e46b1d2fec553fe4efb44e341b43abd20556fde610db0cfffdc2300b72defe
F ext/lsm1/lsm-test/lsmtest_tdb4.c 47e8bb5eba266472d690fb8264f1855ebdba0ae5a0e541e35fcda61ebf1d277f
F ext/lsm1/lsm-test/lsmtest_util.c 241622db5a332a09c8e6e7606b617d288a37b557f7d3bce0bb97809f67cc2806
F ext/lsm1/lsm-test/lsmtest_win32.c 0e0a224674c4d3170631c41b026b56c7e1672b151f5261e1b4cc19068641da2d
@@ -249,11 +251,11 @@ F ext/lsm1/lsmInt.h 5983690e05e83653cc01ba9d8fbf8455e534ddf8349ed9adedbf46a75497
F ext/lsm1/lsm_ckpt.c 0eabfaf812ddb4ea43add38f05e430694cd054eb622c3e35af4c43118a2d5321
F ext/lsm1/lsm_file.c 3c51841d5b3e7da162693cbac9a9f47eeedf6bcbbe2969a4d25e30c428c9fe36
F ext/lsm1/lsm_log.c a8bf334532109bba05b09a504ee45fc393828b0d034ca61ab45e3940709d9a7c
F ext/lsm1/lsm_main.c 801295038b548ae2e5fae93f08c3f945154f40848a03ff26b16eab5d04ba573a
F ext/lsm1/lsm_main.c b5703f8042e71d3a2d65e671f6832e077e79e89e9975818f67f969922618db63
F ext/lsm1/lsm_mem.c 4c51ea9fa285ee6e35301b33491642d071740a0a
F ext/lsm1/lsm_mutex.c 378edf0a2b142b4f7640ee982df06d50b98788ea
F ext/lsm1/lsm_shared.c 76adfc1ed9ffebaf92746dde4b370ccc48143ca8b05b563816eadd2aadf1c525
F ext/lsm1/lsm_sorted.c d07ff7c28758542b8b4da4b5a1fb67b22a4d33e50e7f684cffe1f6c45cf5182c
F ext/lsm1/lsm_sorted.c df7b393d9e4b85e6ad07181c6434d58a69a9145ee925d89c3ee1d2a210adaf9a
F ext/lsm1/lsm_str.c 65e361b488c87b10bf3e5c0070b14ffc602cf84f094880bece77bbf6678bca82
F ext/lsm1/lsm_tree.c 682679d7ef2b8b6f2fe77aeb532c8d29695bca671c220b0abac77069de5fb9fb
F ext/lsm1/lsm_unix.c 57361bcf5b1a1a028f5d66571ee490e9064d2cfb145a2cc9e5ddade467bb551b
@@ -266,21 +268,23 @@ F ext/lsm1/tool/mklsm1c.tcl f31561bbee5349f0a554d1ad7236ac1991fc09176626f529f607
F ext/misc/README.md 8e008c8d2b02e09096b31dfba033253ac27c6c06a18aa5826e299fa7601d90b2
F ext/misc/amatch.c 6db4607cb17c54b853a2d7c7c36046d004853f65b9b733e6f019d543d5dfae87
F ext/misc/anycollseq.c 5ffdfde9829eeac52219136ad6aa7cd9a4edb3b15f4f2532de52f4a22525eddb
F ext/misc/appendvfs.c 4c65f0b79686ae5a483134233d7fd912f0f2d4fd76023404f96f2290fff13b19
F ext/misc/btreeinfo.c d7fd9a2fe2fa33ba28488e2fce703ebecc759219ea9e0bb3b254784866c0a676
F ext/misc/carray.c ed96c218ea940b85c9a274c4d9c59fe9491c299147a38a8bba537687bd6c6005
F ext/misc/closure.c 0d2a038df8fbae7f19de42e7c7d71f2e4dc88704
F ext/misc/completion.c 52c3f01523e3e387eb321b4739a89d1fe47cbe6025aa1f2d8d3685e9e365df0f
F ext/misc/compress.c 122faa92d25033d6c3f07c39231de074ab3d2e83
F ext/misc/compress.c dd4f8a6d0baccff3c694757db5b430f3bbd821d8686d1fc24df55cf9f035b189
F ext/misc/csv.c 1a009b93650732e22334edc92459c4630b9fa703397cbb3c8ca279921a36ca11
F ext/misc/dbdump.c 3509fa6b8932d04e932d6b6b827b6a82ca362781b8e8f3c77336f416793e215e
F ext/misc/eval.c f971962e92ebb8b0a4e6b62949463ee454d88fa2
F ext/misc/fileio.c b1aa06c0f1dac277695d4529e5e976c65ab5678dcbb53a0304deaa8adc44b332
F ext/misc/fileio.c 672e89e125846848e07e025cbe601dc370a93433d571d9422541a9cefbd12b76
F ext/misc/fuzzer.c 7c64b8197bb77b7d64eff7cac7848870235d4c25
F ext/misc/ieee754.c f190d0cc5182529acb15babd177781be1ac1718c
F ext/misc/json1.c dbe086615b9546c156bf32b9378fc09383b58bd17513b866cfd24c1e15281984
F ext/misc/memvfs.c e5225bc22e79dde6b28380f3a068ddf600683a33
F ext/misc/memvfs.c ab36f49e02ebcdf85a1e08dc4d8599ea8f343e073ac9e0bca18a98b7e1ec9567
F ext/misc/mmapwarm.c 70b618f2d0bde43fae288ad0b7498a629f2b6f61b50a27e06fae3cd23c83af29
F ext/misc/nextchar.c 35c8b8baacb96d92abbb34a83a997b797075b342
F ext/misc/normalize.c 19262ef3ef29d4de2f281b423326865c8916c63d0cb09f1dc98d24d5c1e8ba64
F ext/misc/percentile.c 92699c8cd7d517ff610e6037e56506f8904dae2e
F ext/misc/regexp.c a68d25c659bd2d893cd1215667bbf75ecb9dc7d4
F ext/misc/remember.c add730f0f7e7436cd15ea3fd6a90fd83c3f706ab44169f7f048438b7d6baa69c
@@ -291,14 +295,16 @@ F ext/misc/sha1.c 0b9e9b855354910d3ca467bf39099d570e73db56
F ext/misc/shathree.c 9e960ba50483214c6a7a4b1517f8d8cef799e9db381195178c3fd3ad207e10c0
F ext/misc/showauth.c 732578f0fe4ce42d577e1c86dc89dd14a006ab52
F ext/misc/spellfix.c 41cf26c6b89fcaa8798ae10ae64d39c1f1d9d6995152e545bd491c13058b8fac
F ext/misc/sqlar.c 57d5bc45cd5492208e451f697404be88f8612527d64c9d42f96b325b64983d74
F ext/misc/stmt.c 6f16443abb3551e3f5813bb13ba19a30e7032830015b0f92fe0c0453045c0a11
F ext/misc/totype.c 4a167594e791abeed95e0a8db028822b5e8fe512
F ext/misc/unionvtab.c de36c2c45583d68f99e45b392311967066b02e2651d05697da783698b245b387
F ext/misc/unionvtab.c 2aa94902ea646e1aaf6c05eac944a14276cddd67735b2ad856030ffffbb6626c
F ext/misc/vfslog.c fe40fab5c077a40477f7e5eba994309ecac6cc95
F ext/misc/vfsstat.c bf10ef0bc51e1ad6756629e1edb142f7a8db1178
F ext/misc/vtablog.c 31d0d8f4406795679dcd3a67917c213d3a2a5fb3ea5de35f6e773491ed7e13c9
F ext/misc/vtshim.c 1976e6dd68dd0d64508c91a6dfab8e75f8aaf6cd
F ext/misc/wholenumber.c 784b12543d60702ebdd47da936e278aa03076212
F ext/misc/zipfile.c 8075df9296beeebc344567927d114c6d3201110a29110013388d233fa7d4fb2c
F ext/rbu/rbu.c ea7d1b7eb44c123a2a619332e19fe5313500705c4a58aaa1887905c0d83ffc2e
F ext/rbu/rbu1.test 43836fac8c7179a358eaf38a8a1ef3d6e6285842
F ext/rbu/rbu10.test 1846519a438697f45e9dcb246908af81b551c29e1078d0304fae83f1fed7e9ee
@@ -401,7 +407,7 @@ F ext/userauth/userauth.c 3410be31283abba70255d71fd24734e017a4497f
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60
F main.mk b5f569262e4f8111bb8cf6110784b8210fe14ea45f6c7ea50fb4230ebe7a4880
F main.mk c6b8ee2fa871e01ad6a460d750cd074010292464a60a37a2207930ae0df629dc
F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
@@ -434,13 +440,13 @@ F src/delete.c 74667ad914ac143731a444a1bacf29ceb18f6eded8a0dd17aafae80baa07f8bb
F src/expr.c ad6e7a9c34a4bab9d10cc857d647ae7ce370a633b5c0bfa71f1c29b81ae364b8
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
F src/fkey.c d617daf66b5515e2b42c1405b2b4984c30ca50fb705ab164271a9bf66c69e331
F src/func.c 697a3ee3b8c8481db497226e9e71935727d6a9fb3d3cc049e82a1c717a0a8342
F src/func.c bd528d5ed68ce5cbf78a762e3b735fa75009f7197ff07fab07fd771f35ebaa1b
F src/global.c ac3094f1dc59fbeb919aef7cc0cc827a8459d1fb1adb7972ef75bd9e0c10b75b
F src/hash.c a12580e143f10301ed5166ea4964ae2853d3905a511d4e0c44497245c7ce1f7a
F src/hash.h ab34c5c54a9e9de2e790b24349ba5aab3dbb4fd4
F src/hwtime.h 747c1bbe9df21a92e9c50f3bbec1de841dc5e5da
F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
F src/insert.c cb67cc56ef2ddd13e6944b2c0dd08a920bcd9503230adef8b9928d338097c722
F src/insert.c 14686083cedc198540b15a79586cdd4be2acf6d5fa97627e355f817ab07e9fee
F src/legacy.c 134ab3e3fae00a0f67a5187981d6935b24b337bcf0f4b3e5c9fa5763da95bf4e
F src/loadext.c 55bcc3c741059a1056859e8adaf133aa179e22be12215c0936b2f354ef71209b
F src/main.c 690c4134f944cbd5b71d59dd6e61ce4131f6a50ab774f38108e57d07d79cf876
@@ -465,7 +471,7 @@ F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586
F src/os_unix.c 7fc2735390a7809d5d893ed735d994ff12521224b89738226fff6f1a0aa1c932
F src/os_win.c 0a4afa35cc8e812000df3ea2f64b476131b39e29e75d8007d0504726e4761de4
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
F src/pager.c 07cf850241667874fcce9d7d924c814305e499b26c804322e2261247b5921903
F src/pager.c 9b9cb4e06c03d43d62480a7a685a012d645fcf3a39e7767ccb505fb41ee083ec
F src/pager.h 581698f2177e8bd4008fe4760898ce20b6133d1df22139b9101b5155f900df7a
F src/parse.y 44cbbc3e132ea128258eff7be7f6d5c5dfa25522f89ec8b5501276966511bd50
F src/pcache.c 7ae91a4557a43d77d449accbfdc68846e6516f8e2eda46e8bbe4536fb669b201
@@ -479,8 +485,8 @@ F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
F src/resolve.c bbee7e31d369a18a2f4836644769882e9c5d40ef4a3af911db06410b65cb3730
F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac
F src/select.c 8b22abe193e4d8243befa2038e4ae2405802fed1c446e5e502d11f652e09ba74
F src/shell.c.in f3ec8f90dd698ea98781a90642c91eacbc24f4e55bb551c7b2762000d3ef55dc
F src/sqlite.h.in b4dc75265ed04b98e2184011a7dd0054ce2137ff84867a6be8b4f3bdfbc03d30
F src/shell.c.in 0e20ac49a6c4458620084bf7715ad39cd9557d9116e447548d2282000e8ca361
F src/sqlite.h.in 1f1a2da222ec57465794e8984d77f32d0bd0da80cdc136beadda461a0be9d80c
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h c02d628cca67f3889c689d82d25c3eb45e2c155db08e4c6089b5840d64687d34
F src/sqliteInt.h fd8702c65994d7de3e2d8f7d85d958731da1ed29476571fdfa2290fd8ec0bf80
@@ -488,7 +494,7 @@ F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6
F src/status.c 9737ed017279a9e0c5da748701c3c7bf1e8ae0dae459aad20dd64fcff97a7e35
F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34
F src/tclsqlite.c 1833388c01e3b77f4c712185ee7250b9423ee0981ce6ae7e401e47db0319a696
F src/test1.c 8ef15f7a357f85dfc41c6c748ce9c947b4f676e01bb5ae6a45bee4923dff8b51
F src/test1.c 1ab7cbbb6693e08364c1a9241e2aee17f8c4925e4cc52396be77ae6845a05828
F src/test2.c 3efb99ab7f1fc8d154933e02ae1378bac9637da5
F src/test3.c b8434949dfb8aff8dfa082c8b592109e77844c2135ed3c492113839b6956255b
F src/test4.c 18ec393bb4d0ad1de729f0b94da7267270f3d8e6
@@ -536,8 +542,8 @@ F src/test_tclvar.c 33ff42149494a39c5fbb0df3d25d6fafb2f668888e41c0688d07273dcb26
F src/test_thread.c 911d15fb14e19c0c542bdc8aabf981c2f10a4858
F src/test_vfs.c f0186261a24de2671d080bcd8050732f0cb64f6e
F src/test_vfstrace.c bab9594adc976cbe696ff3970728830b4c5ed698
F src/test_windirent.c 17f91f5f2aa1bb7328abb49414c363b5d2a9d3ff
F src/test_windirent.h 5d67483a55442e31e1bde0f4a230e6e932ad5906
F src/test_windirent.c a895e2c068a06644eef91a7f0a32182445a893b9a0f33d0cdb4283dca2486ac1
F src/test_windirent.h 8782864172ba5ae52c5c313c70faeadb324ff74de9c3dcc6b56a557dccaa1de6
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
F src/tokenize.c 1003d6d90c6783206c711f0a9397656fa5b055209f4d092caa43bb3bf5215db5
@@ -547,7 +553,7 @@ F src/update.c 961bd1265d4d1e5cd65c9a54fa5122fb7aefcb003fcf2de0c092fceb7e58972c
F src/utf.c 810fbfebe12359f10bc2a011520a6e10879ab2a163bcb26c74768eab82ea62a5
F src/util.c 7315e97a8dc2c8e19ca64196c652cf0a65d13fd0a211b2cec082062372dc6261
F src/vacuum.c 90839322fd5f00df9617eb21b68beda9b6e2a2937576b0d65985e4aeb1c53739
F src/vdbe.c cb3b5035f337c9fed4a0170ca20325dc4500b832c57d00561310cbb78149a73c
F src/vdbe.c c70267613df80345ed9bbd9c249c365b53bb9cbbe9d3e78e6d5c049d00ef5501
F src/vdbe.h d50cadf12bcf9fb99117ef392ce1ea283aa429270481426b6e8b0280c101fd97
F src/vdbeInt.h 1fe00770144c12c4913128f35262d11527ef3284561baaab59b947a41c08d0d9
F src/vdbeapi.c 9c670ca0dcc1cd86373aa353b747b26fe531ca5cd4331690c611d1f03842e2a1
@@ -917,7 +923,7 @@ F test/func2.test 772d66227e4e6684b86053302e2d74a2500e1e0f
F test/func3.test d202a7606d23f90988a664e88e268aed1087c11c
F test/func4.test 6beacdfcb0e18c358e6c2dcacf1b65d1fa80955f
F test/func5.test cdd224400bc3e48d891827cc913a57051a426fa4
F test/func6.test 1a2bc511fedb779e2bd3154361385216c6d35080f36bfe896b8cdd1b1954294a
F test/func6.test a4281c8fcd42b56f7a60f28e8e4d444e8b2256f9e82658b7ab87699f8318f564
F test/fuzz-oss1.test e58330d01cbbd8215ee636b17a03fe220b37dbfa
F test/fuzz.test 96083052bf5765e4518c1ba686ce2bab785670d1
F test/fuzz2.test 76dc35b32b6d6f965259508508abce75a6c4d7e1
@@ -969,7 +975,7 @@ F test/index7.test 7feababe16f2091b229c22aff2bcc1d4d6b9d2bb
F test/index8.test bc2e3db70e8e62459aaa1bd7e4a9b39664f8f9d7
F test/index9.test 0aa3e509dddf81f93380396e40e9bb386904c1054924ba8fa9bcdfe85a8e7721
F test/indexedby.test faa585e315e868f09bce0eb39c41d6134649b13d2801638294d3ae616edf1609
F test/indexexpr1.test 84100e880154a4b645db9f4fc7642756d9a2b6011b68f73c8efda4d244816de9
F test/indexexpr1.test ace1ad489adc25325ad298434f13b1a515b36bf5dca9fe2a4b66cdf17aea3fa0
F test/indexexpr2.test 13247bac49143196556eb3f65e97ef301bd3e993f4511558b5db322ddc370ea6
F test/indexfault.test 31d4ab9a7d2f6e9616933eb079722362a883eb1d
F test/init.test 15c823093fdabbf7b531fe22cf037134d09587a7
@@ -1087,6 +1093,7 @@ F test/mutex2.test bfeaeac2e73095b2ac32285d2756e3a65e681660
F test/nan.test 437d40e6d0778b050d7750726c0cbd2c9936b81962926e8f8c48ca698f00f4d1
F test/nockpt.test 9a436a7213ba5ef7a32304998d386d3ea3f76c9d
F test/nolock.test f196cf8b8fbea4e2ca345140a2b3f3b0da45c76e
F test/normalize.test 501630ab49b0b26b65c74124bf03e3374c1b57fa97aae750f84803609141d167
F test/notify1.test 669b2b743618efdc18ca4b02f45423d5d2304abf
F test/notify2.test 2ecabaa1305083856b7c39cf32816b612740c161
F test/notify3.test 10ff25cde502e72a92053a2f215d64bece4ef934
@@ -1127,7 +1134,7 @@ F test/pragma.test 7c8cfc328a1717a95663cf8edb06c52ddfeaf97bb0aee69ae7457132e8d39
F test/pragma2.test e5d5c176360c321344249354c0c16aec46214c9f
F test/pragma3.test 14c12bc5352b1e100e0b6b44f371053a81ccf8ed
F test/pragma4.test 3046501bee2f652dc2a4f9c87781e2741361d6864439c8381aba6c3b774b335c
F test/pragma5.test fd517f42ee847e126afbbbd9fd0fb9e5a4a61a962496a350adb8a22583fbdc37
F test/pragma5.test 824ce6ced5d6b7ec71abe37fc6005ff836fe39d638273dc5192b39864b9ee983
F test/pragmafault.test 275edaf3161771d37de60e5c2b412627ac94cef11739236bec12ed1258b240f8
F test/printf.test b3ff34e73d59124140eaf89f7672e21bc2ca5fcc
F test/printf2.test 9e6db85f81c63f2367c34a9d7db384088bd374ad
@@ -1147,7 +1154,7 @@ F test/rdonly.test 64e2696c322e3538df0b1ed624e21f9a23ed9ff8
F test/regexp1.test 497ea812f264d12b6198d6e50a76be4a1973a9d8
F test/regexp2.test 40e894223b3d6672655481493f1be12012f2b33c
F test/reindex.test 44edd3966b474468b823d481eafef0c305022254
F test/releasetest.tcl 0b0b3d926e36822ff63b405d683544ce1014303b029f2678bbcf40c162b5f246 x
F test/releasetest.tcl 6aaa853f7a7bbdc458d4cb42c0425228729b0f3e5769e9b41088c08eee999a49 x
F test/resolver01.test f4022acafda7f4d40eca94dbf16bc5fc4ac30ceb
F test/rollback.test f580934279800d480a19176c6b44909df31ce7ad45267ea475a541daa522f3d3
F test/rollback2.test 8435d6ff0f13f51d2a4181c232e706005fa90fc5
@@ -1213,13 +1220,14 @@ F test/sharedA.test 0cdf1a76dfa00e6beee66af5b534b1e8df2720f5
F test/sharedB.test 16cc7178e20965d75278f410943109b77b2e645e
F test/shared_err.test 32634e404a3317eeb94abc7a099c556a346fdb8fb3858dbe222a4cbb8926a939
F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304
F test/shell1.test f78ea0e2637ae9f497cb41206f6346f983052ffc7a359e664aaf6847fc704ea7
F test/shell1.test 6d69e08039aea13f2c42749f162fe05eab7b5c93729f31d49d7d27cf36226e5a
F test/shell2.test e242a9912f44f4c23c3d1d802a83e934e84c853b
F test/shell3.test 9b95ba643eaa228376f06a898fb410ee9b6e57c1
F test/shell4.test 89ad573879a745974ff2df20ff97c5d6ffffbd5d
F test/shell5.test 23939a4c51f0421330ea61dbd3c74f9c215f5f8d3d1a94846da6ffc777a35458
F test/shell6.test 1ceb51b2678c472ba6cf1e5da96679ce8347889fe2c3bf93a0e0fa73f00b00d3
F test/shell7.test 115132f66d0463417f408562cc2cf534f6bbc6d83a6d50f0072a9eb171bae97f
F test/shell8.test 7585847402452d594f0e5f93430d34ed63b2f34ca7e956f63db157f9327c6896
F test/shortread1.test bb591ef20f0fd9ed26d0d12e80eee6d7ac8897a3
F test/show_speedtest1_rtree.tcl 32e6c5f073d7426148a6936a0408f4b5b169aba5
F test/shrink.test 1b4330b1fd9e818c04726d45cb28db73087535ce
@@ -1592,6 +1600,7 @@ F test/wordcount.c cb589cec469a1d90add05b1f8cee75c7210338d87a5afd65260ed5c0f4bbf
F test/writecrash.test f1da7f7adfe8d7f09ea79b42e5ca6dcc41102f27f8e334ad71539501ddd910cc
F test/zeroblob.test 3857870fe681b8185654414a9bccfde80b62a0fa
F test/zerodamage.test e59a56443d6298ecf7435f618f0b27654f0c849e
F test/zipfile.test a1dd0429294cb9487900fc2b29aa9921329f20a7314aa0921b668246172ac090
F tool/GetFile.cs a15e08acb5dd7539b75ba23501581d7c2b462cb5
F tool/GetTclKit.bat 8995df40c4209808b31f24de0b58f90930239a234f7591e3675d45bfbb990c5d
F tool/Replace.cs 02c67258801c2fb5f63231e0ac0f220b4b36ba91
@@ -1624,7 +1633,7 @@ F tool/mkopcodec.tcl d1b6362bd3aa80d5520d4d6f3765badf01f6c43c
F tool/mkopcodeh.tcl 4ee2a30ccbd900dc4d5cdb61bdab87cd2166cd2affcc78c9cc0b8d22a65b2eee
F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e
F tool/mkpragmatab.tcl 2144bc8550a6471a029db262a132d2df4b9e0db61b90398bf64f5b7b3f8d92cd
F tool/mkshellc.tcl 574307265b49d813301fba91ccd74e6a26d33f65f74b6891c320a0ffbee07895
F tool/mkshellc.tcl 1f45770aea226ac093a9c72f718efbb88a2a2833409ec2e1c4cecae4202626f5
F tool/mksourceid.c d458f9004c837bee87a6382228ac20d3eae3c49ea3b0a5aace936f8b60748d3b
F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97
F tool/mksqlite3c-noext.tcl fef88397668ae83166735c41af99d79f56afaabb
@@ -1657,6 +1666,8 @@ F tool/speedtest8inst1.c 7ce07da76b5e745783e703a834417d725b7d45fd
F tool/split-sqlite3c.tcl 3efcd4240b738f6bb2b5af0aea7e1e0ef9bc1c61654f645076cec883030b710c
F tool/sqldiff.c 30879bbc8de686df4624e86adce2d8981f500904c1cfb55b5d1eea2ffd9341eb
F tool/sqlite3_analyzer.c.in 7eeaae8b0d7577662acaabbb11107af0659d1b41bc1dfdd4d91422de27127968
F tool/sqltclsh.c.in 8b2529b6c3cdd8ad6aaff21e80eb58370c428cb207b4607d0da4def064dcec56
F tool/sqltclsh.tcl 862f4cf1418df5e1315b5db3b5ebe88969e2a784525af5fbf9596592f14ed848
F tool/srcck1.c 371de5363b70154012955544f86fdee8f6e5326f
F tool/stack_usage.tcl f8e71b92cdb099a147dad572375595eae55eca43
F tool/symbols-mingw.sh 4dbcea7e74768305384c9fd2ed2b41bbf9f0414d
@@ -1688,7 +1699,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P 89e5720a8d8d46d4e2f16f15678e91336117e64abc977174e2b345a30308d0d2
R 9cb794037b97521b258cb5fdbbf60d53
P db5d138e97f22ad4d4d11dbef96df93696ba0e557809066bc263ca3c3898f349
R 5585a6831c91176202d5e0f81c59c944
U drh
Z 8d1ee588df9bbfd069e3afd64819112f
Z ca698384a23dd84f9bb875fa9da10ba1
+1 -1
View File
@@ -1 +1 @@
9406c0a685fd5ff3516a66402b0514a1440652822a5eecf0b7af85929f3079e8
658f42257d56a3562dfa8e55023c6e497f55c565cd751d942de3a9e0cb2fa708
+1 -2
View File
@@ -1800,8 +1800,7 @@ void sqlite3RegisterBuiltinFunctions(void){
FUNCTION2(affinity, 1, 0, 0, noopFunc, SQLITE_FUNC_AFFINITY),
#endif
#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC
FUNCTION2(sqlite_unsupported_offset,
1, 0, 0, noopFunc, SQLITE_FUNC_OFFSET|
FUNCTION2(sqlite_offset, 1, 0, 0, noopFunc, SQLITE_FUNC_OFFSET|
SQLITE_FUNC_TYPEOF),
#endif
FUNCTION(ltrim, 1, 1, 0, trimFunc ),
+2
View File
@@ -1571,6 +1571,7 @@ void sqlite3GenerateConstraintChecks(
}
/* Check to see if the new index entry will be unique */
sqlite3ExprCachePush(pParse);
sqlite3VdbeAddOp4Int(v, OP_NoConflict, iThisCur, addrUniqueOk,
regIdx, pIdx->nKeyCol); VdbeCoverage(v);
@@ -1659,6 +1660,7 @@ void sqlite3GenerateConstraintChecks(
}
}
sqlite3VdbeResolveLabel(v, addrUniqueOk);
sqlite3ExprCachePop(pParse);
if( regR!=regIdx ) sqlite3ReleaseTempRange(pParse, regR, nPkField);
}
if( ipkTop ){
+1 -1
View File
@@ -5579,7 +5579,7 @@ static int getPageMMap(
}
if( pPg==0 ){
rc = pagerAcquireMapPage(pPager, pgno, pData, &pPg);
}else{
}else{
sqlite3OsUnfetch(pPager->fd, (i64)(pgno-1)*pPager->pageSize, pData);
}
if( pPg ){
+1054 -96
View File
File diff suppressed because it is too large Load Diff
+4 -4
View File
@@ -6971,9 +6971,9 @@ sqlite3_mutex *sqlite3_db_mutex(sqlite3*);
** the xFileControl method. ^The return value of the xFileControl
** method becomes the return value of this routine.
**
** ^The SQLITE_FCNTL_FILE_POINTER value for the op parameter causes
** ^The [SQLITE_FCNTL_FILE_POINTER] value for the op parameter causes
** a pointer to the underlying [sqlite3_file] object to be written into
** the space pointed to by the 4th parameter. ^The SQLITE_FCNTL_FILE_POINTER
** the space pointed to by the 4th parameter. ^The [SQLITE_FCNTL_FILE_POINTER]
** case is a short-circuit path which does not actually invoke the
** underlying sqlite3_io_methods.xFileControl method.
**
@@ -6985,7 +6985,7 @@ sqlite3_mutex *sqlite3_db_mutex(sqlite3*);
** an incorrect zDbName and an SQLITE_ERROR return from the underlying
** xFileControl method.
**
** See also: [SQLITE_FCNTL_LOCKSTATE]
** See also: [file control opcodes]
*/
int sqlite3_file_control(sqlite3*, const char *zDbName, int op, void*);
@@ -8301,7 +8301,7 @@ int sqlite3_vtab_on_conflict(sqlite3 *);
** CAPI3REF: Determine The Collation For a Virtual Table Constraint
**
** This function may only be called from within a call to the [xBestIndex]
** method of a [virtual table implementation].
** method of a [virtual table].
**
** The first argument must be the sqlite3_index_info object that is the
** first parameter to the xBestIndex() method. The second argument must be
+36
View File
@@ -4559,6 +4559,35 @@ static int SQLITE_TCLAPI test_complete16(
return TCL_OK;
}
/*
** Usage: sqlite3_normalize SQL
**
** Return the normalized value for an SQL statement.
*/
static int SQLITE_TCLAPI test_normalize(
void * clientData,
Tcl_Interp *interp,
int objc,
Tcl_Obj *CONST objv[]
){
char *zSql;
char *zNorm;
extern char *sqlite3_normalize(const char*);
if( objc!=2 ){
Tcl_WrongNumArgs(interp, 1, objv, "SQL");
return TCL_ERROR;
}
zSql = (char*)Tcl_GetString(objv[1]);
zNorm = sqlite3_normalize(zSql);
if( zNorm ){
Tcl_SetObjResult(interp, Tcl_NewStringObj(zNorm, -1));
sqlite3_free(zNorm);
}
return TCL_OK;
}
/*
** Usage: sqlite3_step STMT
**
@@ -6960,6 +6989,9 @@ static int SQLITE_TCLAPI tclLoadStaticExtensionCmd(
extern int sqlite3_totype_init(sqlite3*,char**,const sqlite3_api_routines*);
extern int sqlite3_wholenumber_init(sqlite3*,char**,const sqlite3_api_routines*);
extern int sqlite3_unionvtab_init(sqlite3*,char**,const sqlite3_api_routines*);
#ifdef SQLITE_HAVE_ZLIB
extern int sqlite3_zipfile_init(sqlite3*,char**,const sqlite3_api_routines*);
#endif
static const struct {
const char *zExtName;
int (*pInit)(sqlite3*,char**,const sqlite3_api_routines*);
@@ -6981,6 +7013,9 @@ static int SQLITE_TCLAPI tclLoadStaticExtensionCmd(
{ "totype", sqlite3_totype_init },
{ "unionvtab", sqlite3_unionvtab_init },
{ "wholenumber", sqlite3_wholenumber_init },
#ifdef SQLITE_HAVE_ZLIB
{ "zipfile", sqlite3_zipfile_init },
#endif
};
sqlite3 *db;
const char *zName;
@@ -7541,6 +7576,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
{ "sqlite3_open16", test_open16 ,0 },
{ "sqlite3_open_v2", test_open_v2 ,0 },
{ "sqlite3_complete16", test_complete16 ,0 },
{ "sqlite3_normalize", test_normalize ,0 },
{ "sqlite3_prepare", test_prepare ,0 },
{ "sqlite3_prepare16", test_prepare16 ,0 },
-1
View File
@@ -14,7 +14,6 @@
*/
#if defined(_WIN32) && defined(_MSC_VER)
#include "test_windirent.h"
/*
+37 -4
View File
@@ -13,7 +13,8 @@
** POSIX functions on Win32 using the MSVCRT.
*/
#if defined(_WIN32) && defined(_MSC_VER)
#if defined(_WIN32) && defined(_MSC_VER) && !defined(SQLITE_WINDIRENT_H)
#define SQLITE_WINDIRENT_H
/*
** We need several data types from the Windows SDK header.
@@ -37,6 +38,33 @@
#include <errno.h>
#include <io.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>
/*
** We may need several defines that should have been in "sys/stat.h".
*/
#ifndef S_ISREG
#define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
#endif
#ifndef S_ISDIR
#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
#endif
#ifndef S_ISLNK
#define S_ISLNK(mode) (0)
#endif
/*
** We may need to provide the "mode_t" type.
*/
#ifndef MODE_T_DEFINED
#define MODE_T_DEFINED
typedef unsigned short mode_t;
#endif
/*
** We may need to provide the "ino_t" type.
@@ -75,22 +103,27 @@
** We need to provide the necessary structures and related types.
*/
#ifndef DIRENT_DEFINED
#define DIRENT_DEFINED
typedef struct DIRENT DIRENT;
typedef struct DIR DIR;
typedef DIRENT *LPDIRENT;
typedef DIR *LPDIR;
struct DIRENT {
ino_t d_ino; /* Sequence number, do not use. */
unsigned d_attributes; /* Win32 file attributes. */
char d_name[NAME_MAX + 1]; /* Name within the directory. */
};
#endif
#ifndef DIR_DEFINED
#define DIR_DEFINED
typedef struct DIR DIR;
typedef DIR *LPDIR;
struct DIR {
intptr_t d_handle; /* Value returned by "_findfirst". */
DIRENT d_first; /* DIRENT constructed based on "_findfirst". */
DIRENT d_next; /* DIRENT constructed based on "_findnext". */
};
#endif
/*
** Provide a macro, for use by the implementation, to determine if a
+1 -1
View File
@@ -2370,7 +2370,7 @@ case OP_Offset: { /* out3 */
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
pC = p->apCsr[pOp->p1];
pOut = &p->aMem[pOp->p3];
if( pC==0 || pC->eCurType!=CURTYPE_BTREE ){
if( NEVER(pC==0) || pC->eCurType!=CURTYPE_BTREE ){
sqlite3VdbeMemSetNull(pOut);
}else{
sqlite3VdbeMemSetInt64(pOut, sqlite3BtreeOffset(pC->uc.pCursor));
+20 -20
View File
@@ -9,7 +9,7 @@
#
#*************************************************************************
#
# Test cases for the sqlite_unsupported_offset() function.
# Test cases for the sqlite_offset() function.
#
# Some of the tests in this file depend on the exact placement of content
# within b-tree pages. Such placement is at the implementations discretion,
@@ -34,51 +34,51 @@ do_execsql_test func6-100 {
INSERT INTO t2(x,y) SELECT a, b FROM t1;
}
do_execsql_test func6-110 {
SELECT a, sqlite_unsupported_offset(d)/4096 + 1,
sqlite_unsupported_offset(d)%4096 FROM t1
SELECT a, sqlite_offset(d)/4096 + 1,
sqlite_offset(d)%4096 FROM t1
ORDER BY rowid LIMIT 2;
} {abc001 2 4084 abc002 2 4069}
do_execsql_test func6-120 {
SELECT a, typeof(sqlite_unsupported_offset(+a)) FROM t1
SELECT a, typeof(sqlite_offset(+a)) FROM t1
ORDER BY rowid LIMIT 2;
} {abc001 null abc002 null}
do_execsql_test func6-130 {
SELECT a, sqlite_unsupported_offset(a)/4096+1,
sqlite_unsupported_offset(a)%4096
SELECT a, sqlite_offset(a)/4096+1,
sqlite_offset(a)%4096
FROM t1
ORDER BY a LIMIT 2;
} {abc001 3 4087 abc002 3 4076}
do_execsql_test func6-140 {
SELECT a, sqlite_unsupported_offset(d)/4096+1,
sqlite_unsupported_offset(d)%4096
SELECT a, sqlite_offset(d)/4096+1,
sqlite_offset(d)%4096
FROM t1
ORDER BY a LIMIT 2;
} {abc001 2 4084 abc002 2 4069}
do_execsql_test func6-150 {
SELECT a,
sqlite_unsupported_offset(a)/4096+1,
sqlite_unsupported_offset(a)%4096,
sqlite_unsupported_offset(d)/4096+1,
sqlite_unsupported_offset(d)%4096
sqlite_offset(a)/4096+1,
sqlite_offset(a)%4096,
sqlite_offset(d)/4096+1,
sqlite_offset(d)%4096
FROM t1
ORDER BY a LIMIT 2;
} {abc001 3 4087 2 4084 abc002 3 4076 2 4069}
do_execsql_test func6-160 {
SELECT b,
sqlite_unsupported_offset(b)/4096+1,
sqlite_unsupported_offset(b)%4096,
sqlite_unsupported_offset(c)/4096+1,
sqlite_unsupported_offset(c)%4096,
sqlite_unsupported_offset(d)/4096+1,
sqlite_unsupported_offset(d)%4096
sqlite_offset(b)/4096+1,
sqlite_offset(b)%4096,
sqlite_offset(c)/4096+1,
sqlite_offset(c)%4096,
sqlite_offset(d)/4096+1,
sqlite_offset(d)%4096
FROM t1
ORDER BY b LIMIT 2;
} {1 4 4090 4 4090 2 4084 2 4 4081 4 4081 2 4069}
do_execsql_test func6-200 {
SELECT y, sqlite_unsupported_offset(y)/4096+1,
sqlite_unsupported_offset(y)%4096
SELECT y, sqlite_offset(y)/4096+1,
sqlite_offset(y)%4096
FROM t2
ORDER BY x LIMIT 2;
} {1 5 4087 2 5 4076}
+23
View File
@@ -401,5 +401,28 @@ do_execsql_test indexexpr1-1430 {
SELECT abs(15+3) IN (SELECT 17 UNION ALL SELECT 18) FROM t1;
} {1 1}
# 2018-01-02 ticket https://sqlite.org/src/info/dc3f932f5a147771
# A REPLACE into a table that uses an index on an expression causes
# an assertion fault. Problem discovered by OSSFuzz.
#
do_execsql_test indexexpr1-1500 {
CREATE TABLE t1500(a INT PRIMARY KEY, b INT UNIQUE);
CREATE INDEX t1500ab ON t1500(a*b);
INSERT INTO t1500(a,b) VALUES(1,2);
REPLACE INTO t1500(a,b) VALUES(1,3); -- formerly caused assertion fault
SELECT * FROM t1500;
} {1 3}
# 2018-01-03 OSSFuzz discovers another test case for the same problem
# above.
#
do_execsql_test indexexpr-1510 {
DROP TABLE IF EXISTS t1;
CREATE TABLE t1(a PRIMARY KEY,b UNIQUE);
REPLACE INTO t1 VALUES(2, 1);
REPLACE INTO t1 SELECT 6,1;
CREATE INDEX t1aa ON t1(a-a);
REPLACE INTO t1 SELECT a, randomblob(a) FROM t1
} {}
finish_test
+72
View File
@@ -0,0 +1,72 @@
# 2018-01-08
#
# 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 for the sqlite3_normalize() extension function.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix normalize
foreach {tnum sql norm} {
100
{SELECT * FROM t1 WHERE a IN (1) AND b=51.42}
{select*from t1 where a in(?,?,?)and b=?;}
110
{SELECT a, b+15, c FROM t1 WHERE d NOT IN (SELECT x FROM t2);}
{select a,b+?,c from t1 where d not in(select x from t2);}
120
{ SELECT NULL, b FROM t1 -- comment text
WHERE d IN (WITH t(a) AS (VALUES(5)) /* CTE */
SELECT a FROM t)
OR e='hello';
}
{select?,b from t1 where d in(with t(a)as(values(?))select a from t)or e=?;}
121
{/*Initial comment*/
-- another comment line
SELECT NULL /* comment */ , b FROM t1 -- comment text
WHERE d IN (WITH t(a) AS (VALUES(5)) /* CTE */
SELECT a FROM t)
OR e='hello';
}
{select?,b from t1 where d in(with t(a)as(values(?))select a from t)or e=?;}
130
{/* Query containing parameters */
SELECT x,$::abc(15),y,@abc,z,?99,w FROM t1 /* Trailing comment */}
{select x,?,y,?,z,?,w from t1;}
140
{/* Long list on the RHS of IN */
SELECT 15 IN (1,2,3,(SELECT * FROM t1),'xyz',x'abcd',22*(x+5),null);}
{select?in(?,?,?);}
150
{SELECT x'abc'; -- illegal token}
{}
160
{SELECT a,NULL,b FROM t1 WHERE c IS NOT NULL or D is null or e=5}
{select a,?,b from t1 where c is not null or d is null or e=?;}
170
{/* IN list exactly 5 bytes long */
SELECT * FROM t1 WHERE x IN (1,2,3);}
{select*from t1 where x in(?,?,?);}
} {
do_test $tnum [list sqlite3_normalize $sql] $norm
}
finish_test
+1 -1
View File
@@ -34,7 +34,7 @@ do_execsql_test 1.0 {
1 builtin {} 0 {} 0
}
do_execsql_test 1.1 {
SELECT * FROM pragma_function_list WHERE name='upper'
SELECT * FROM pragma_function_list WHERE name='upper' AND builtin
} {upper 1}
do_execsql_test 1.2 {
SELECT * FROM pragma_function_list WHERE name LIKE 'exter%';
+3
View File
@@ -734,6 +734,9 @@ proc makeCommand { targets makeOpts cflags opts } {
set nmakeDir [file nativename $::SRCDIR]
set nmakeFile [file nativename [file join $nmakeDir Makefile.msc]]
lappend result nmake /f $nmakeFile TOP=$nmakeDir
set tclDir [file nativename [file normalize \
[file dirname [file dirname [info nameofexecutable]]]]]
lappend result "TCLDIR=$tclDir"
if {[regexp {USE_STDCALL=1} $cflags]} {
lappend result USE_STDCALL=1
}
+4 -2
View File
@@ -581,8 +581,10 @@ do_test shell1-3.21.4 {
}
catchcmd "test.db" ".schema"
} {0 {CREATE TABLE t1(x);
CREATE VIEW v2 AS SELECT x+1 AS y FROM t1;
CREATE VIEW v1 AS SELECT y+1 FROM v2;}}
CREATE VIEW v2 AS SELECT x+1 AS y FROM t1
/* v2(y) */;
CREATE VIEW v1 AS SELECT y+1 FROM v2
/* v1("y+1") */;}}
db eval {DROP VIEW v1; DROP VIEW v2; DROP TABLE t1;}
}
+168
View File
@@ -0,0 +1,168 @@
# 2017 December 9
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
#
# Test the shell tool ".ar" command.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix shell8
set CLI [test_find_cli]
proc populate_dir {dirname spec} {
# First delete the current tree, if one exists.
file delete -force $dirname
# Recreate the root of the new tree.
file mkdir $dirname
# Add each file to the new tree.
foreach {f d} $spec {
set path [file join $dirname $f]
file mkdir [file dirname $path]
set fd [open $path w]
puts -nonewline $fd $d
close $fd
}
}
proc dir_to_list {dirname {n -1}} {
if {$n<0} {set n [llength [file split $dirname]]}
set res [list]
foreach f [glob -nocomplain $dirname/*] {
set mtime [file mtime $f]
if {$::tcl_platform(platform)!="windows"} {
set perm [file attributes $f -perm]
} else {
set perm 0
}
set relpath [file join {*}[lrange [file split $f] $n end]]
lappend res
if {[file isdirectory $f]} {
lappend res [list $relpath / $mtime $perm]
lappend res {*}[dir_to_list $f]
} else {
set fd [open $f]
set data [read $fd]
close $fd
lappend res [list $relpath $data $mtime $perm]
}
}
lsort $res
}
proc dir_compare {d1 d2} {
set l1 [dir_to_list $d1]
set l2 [dir_to_list $d1]
string compare $l1 $l2
}
foreach {tn tcl} {
1 {
set c1 ".ar c ar1"
set x1 ".ar x"
set c2 ".ar cC ar1 ."
set x2 ".ar Cx ar3"
set c3 ".ar cCf ar1 test_xyz.db ."
set x3 ".ar Cfx ar3 test_xyz.db"
}
2 {
set c1 ".ar -c ar1"
set x1 ".ar -x"
set c2 ".ar -cC ar1 ."
set x2 ".ar -xC ar3"
set c3 ".ar -cCar1 -ftest_xyz.db ."
set x3 ".ar -x -C ar3 -f test_xyz.db"
}
3 {
set c1 ".ar --create ar1"
set x1 ".ar --extract"
set c2 ".ar --directory ar1 --create ."
set x2 ".ar --extract --dir ar3"
set c3 ".ar --creat --dir ar1 --file test_xyz.db ."
set x3 ".ar --e --d ar3 --f test_xyz.db"
}
4 {
set c1 ".ar --cr ar1"
set x1 ".ar --e"
set c2 ".ar -C ar1 -c ."
set x2 ".ar -x -C ar3"
set c3 ".ar -c --directory ar1 --file test_xyz.db ."
set x3 ".ar -x --directory ar3 --file test_xyz.db"
}
} {
eval $tcl
# Populate directory "ar1" with some files.
#
populate_dir ar1 {
file1 "abcd"
file2 "efgh"
dir1/file3 "ijkl"
}
set expected [dir_to_list ar1]
do_test 1.$tn.1 {
catchcmd test_ar.db $c1
file delete -force ar1
catchcmd test_ar.db $x1
dir_to_list ar1
} $expected
do_test 1.$tn.2 {
file delete -force ar3
catchcmd test_ar.db $c2
catchcmd test_ar.db $x2
dir_to_list ar3
} $expected
do_test 1.$tn.3 {
file delete -force ar3
file delete -force test_xyz.db
catchcmd ":memory:" $c3
catchcmd ":memory:" $x3
dir_to_list ar3
} $expected
# This is a repeat of test 1.$tn.1, except that there is a 2 second
# pause between creating the archive and extracting its contents.
# This is to test that timestamps are set correctly.
#
# Because it is slow, only do this for $tn==1.
if {$tn==1} {
do_test 1.$tn.1 {
catchcmd test_ar.db $c1
file delete -force ar1
after 2000
catchcmd test_ar.db $x1
dir_to_list ar1
} $expected
}
}
finish_test
finish_test
+80
View File
@@ -0,0 +1,80 @@
# 2017 December 9
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix zipfile
if {[catch {load_static_extension db zipfile} error]} {
puts "Skipping zipfile tests, hit load error: $error"
finish_test; return
}
forcedelete test.zip
do_execsql_test 1.0 {
CREATE VIRTUAL TABLE temp.zz USING zipfile('test.zip');
PRAGMA table_info(zz);
} {
0 name {} 0 {} 0
1 mode {} 0 {} 0
2 mtime {} 0 {} 0
3 sz {} 0 {} 0
4 data {} 0 {} 0
5 method {} 0 {} 0
}
do_execsql_test 1.1.1 {
INSERT INTO zz VALUES('f.txt', '-rw-r--r--', 1000000000, 5, 'abcde', 0);
}
do_execsql_test 1.1.2 {
INSERT INTO zz VALUES('g.txt', '-rw-r--r--', 1000000002, 5, '12345', 0);
}
do_execsql_test 1.2 {
SELECT name, mtime, data FROM zipfile('test.zip')
} {
f.txt 1000000000 abcde
g.txt 1000000002 12345
}
do_execsql_test 1.3 {
INSERT INTO zz VALUES('h.txt',
'-rw-r--r--', 1000000004, 20, 'aaaaaaaaaabbbbbbbbbb', NULL
);
}
do_execsql_test 1.4 {
SELECT name, mtime, zipfile_uncompress(data, sz, method), method
FROM zipfile('test.zip');
} {
f.txt 1000000000 abcde 0
g.txt 1000000002 12345 0
h.txt 1000000004 aaaaaaaaaabbbbbbbbbb 8
}
do_execsql_test 1.5.1 {
BEGIN;
INSERT INTO zz VALUES('i.txt', '-rw-r--r--', 1000000006, 5, 'zxcvb', 0);
SELECT name FROM zz;
COMMIT;
} {f.txt g.txt h.txt i.txt}
do_execsql_test 1.5.2 {
SELECT name FROM zz;
} {f.txt g.txt h.txt i.txt}
do_execsql_test 1.6.0 {
DELETE FROM zz WHERE name='g.txt';
SELECT name FROM zz;
} {f.txt h.txt i.txt}
finish_test
+15 -2
View File
@@ -30,16 +30,29 @@ puts $out {/* DO NOT EDIT!
** by "src/shell.c.in", then rerun the tool/mkshellc.tcl script.
*/}
set in [open $topdir/src/shell.c.in rb]
proc omit_redundant_typedefs {line} {
global typedef_seen
if {[regexp {^typedef .*;} $line]} {
if {[info exists typedef_seen($line)]} {
return "/* $line */"
}
set typedef_seen($line) 1
}
return $line
}
while {1} {
set lx [gets $in]
set lx [omit_redundant_typedefs [gets $in]]
if {[eof $in]} break;
if {[regexp {^INCLUDE } $lx]} {
set cfile [lindex $lx 1]
puts $out "/************************* Begin $cfile ******************/"
set in2 [open $topdir/src/$cfile rb]
while {![eof $in2]} {
set lx [gets $in2]
set lx [omit_redundant_typedefs [gets $in2]]
if {[regexp {^#include "sqlite} $lx]} continue
if {[regexp {^# *include "test_windirent.h"} $lx]} {
set lx "/* $lx */"
}
set lx [string map [list __declspec(dllexport) {}] $lx]
puts $out $lx
}
+47
View File
@@ -0,0 +1,47 @@
/*
** This is the source code to a "tclsh" that has SQLite built-in.
**
** The startup script is located as follows:
**
** (1) Open the executable as an appended SQLite database and try to
** read the startup script out of that database.
**
** (2) If the first argument is a readable file, try to open that file
** as an SQLite database and read the startup script out of that
** database.
**
** (3) If the first argument is a readable file with a ".tcl" extension,
** then try to run that script directly.
**
** If none of the above steps work, then the program runs as an interactive
** tclsh.
*/
#define TCLSH_INIT_PROC sqlite3_tclapp_init_proc
#define SQLITE_ENABLE_DBSTAT_VTAB 1
#undef SQLITE_THREADSAFE
#define SQLITE_THREADSAFE 0
#undef SQLITE_ENABLE_COLUMN_METADATA
#define SQLITE_OMIT_DECLTYPE 1
#define SQLITE_OMIT_DEPRECATED 1
#define SQLITE_OMIT_PROGRESS_CALLBACK 1
#define SQLITE_OMIT_SHARED_CACHE 1
#define SQLITE_DEFAULT_MEMSTATUS 0
#define SQLITE_MAX_EXPR_DEPTH 0
INCLUDE sqlite3.c
INCLUDE $ROOT/ext/misc/appendvfs.c
INCLUDE $ROOT/ext/misc/zipfile.c
INCLUDE $ROOT/ext/misc/sqlar.c
INCLUDE $ROOT/src/tclsqlite.c
const char *sqlite3_tclapp_init_proc(Tcl_Interp *interp){
(void)interp;
sqlite3_appendvfs_init(0,0,0);
sqlite3_auto_extension((void(*)(void))sqlite3_sqlar_init);
sqlite3_auto_extension((void(*)(void))sqlite3_zipfile_init);
return
BEGIN_STRING
INCLUDE $ROOT/tool/sqltclsh.tcl
END_STRING
;
}
+71
View File
@@ -0,0 +1,71 @@
# Try to open the executable as a database and read the "scripts.data"
# field where "scripts.name" is 'main.tcl'
#
catch {
if {![file exists $argv0] && [file exists $argv0.exe]} {
append argv0 .exe
}
sqlite3 db $argv0 -vfs apndvfs -create 0
set mainscript [db one {
SELECT sqlar_uncompress(data,sz) FROM sqlar WHERE name='main.tcl'
}]
}
if {[info exists mainscript]} {
eval $mainscript
return
} else {
catch {db close}
}
# Try to open file named in the first argument as a database and
# read the "scripts.data" field where "scripts.name" is 'main.tcl'
#
if {[llength $argv]>0 && [file readable [lindex $argv 0]]} {
catch {
sqlite3 db [lindex $argv 0] -vfs apndvfs -create 0
set mainscript [db one {SELECT data FROM scripts WHERE name='main.tcl'}]
set argv0 [lindex $argv 0]
set argv [lrange $argv 1 end]
}
if {[info exists mainscript]} {
eval $mainscript
return
} else {
catch {db close}
}
if {[string match *.tcl [lindex $argv 0]]} {
set fd [open [lindex $argv 0] rb]
set mainscript [read $fd]
close $fd
unset fd
set argv0 [lindex $argv 0]
set argv [lrange $argv 1 end]
}
if {[info exists mainscript]} {
eval $mainscript
return
}
}
# If all else fails, do an interactive loop
#
set line {}
while {![eof stdin]} {
if {$line!=""} {
puts -nonewline "> "
} else {
puts -nonewline "% "
}
flush stdout
append line [gets stdin]
if {[info complete $line]} {
if {[catch {uplevel #0 $line} result]} {
puts stderr "Error: $result"
} elseif {$result!=""} {
puts $result
}
set line {}
} else {
append line \\n"
}
}