Compare commits
571 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e8f850e7bd | |||
| 0a4af54a7e | |||
| 6cc36dfb16 | |||
| b2972b8c6f | |||
| 8f79342f6a | |||
| dadd0b4085 | |||
| 9dfc2c61ec | |||
| 3ea05b5b4f | |||
| a0d35d44e4 | |||
| 93df8109fc | |||
| 3efac4aa78 | |||
| 3bdebaeabb | |||
| b85b7f257d | |||
| 79d0aa6f56 | |||
| 63f4926524 | |||
| e108f97256 | |||
| 00bc96c05c | |||
| f858182689 | |||
| 3e06f2d79b | |||
| 5b0b8653b6 | |||
| 66172ceb89 | |||
| 9d90a3af2f | |||
| 03c65171b8 | |||
| 297a95bad5 | |||
| f62d053b49 | |||
| 7df570421c | |||
| 84b0f221f4 | |||
| 7fd936e5ed | |||
| 189a4a0bbb | |||
| ede1690cce | |||
| 7a7002143c | |||
| d8452a9517 | |||
| 4192a95d23 | |||
| 6b3010a134 | |||
| 038424727b | |||
| 65552a7ae1 | |||
| 01bfe2a531 | |||
| 3c013479c3 | |||
| 659bafd05d | |||
| 31c3599ed0 | |||
| 6c074e5dc4 | |||
| 97af1346f0 | |||
| b6859b6f2c | |||
| 802b042f6e | |||
| e85b2cac0f | |||
| 51dd67080a | |||
| 31615637f3 | |||
| 0d9f2a15f2 | |||
| 1c68deead7 | |||
| 589796cd89 | |||
| dbe48d3c8d | |||
| c2b446f16a | |||
| 6e5802fc74 | |||
| 9e639d2490 | |||
| c6281e4893 | |||
| 3cd34ab981 | |||
| d98689f4d3 | |||
| cf9f841c5e | |||
| 77586831ed | |||
| d256b56880 | |||
| 3cf467a3ec | |||
| 4170780a82 | |||
| f306ca5286 | |||
| c229f11817 | |||
| 14613b1b1d | |||
| c49bfdbbee | |||
| 4b99ec0b8c | |||
| 454a426e31 | |||
| 5c72a39cfb | |||
| de50617bcb | |||
| fdc17e0bc8 | |||
| 276d213b2a | |||
| 45b2669ad3 | |||
| 82f3052e61 | |||
| 8fbf400bb0 | |||
| f6ca35d88c | |||
| a033790303 | |||
| 32933278fd | |||
| efbf481541 | |||
| 824a5bfcf0 | |||
| 80cf9fa00b | |||
| e16b345243 | |||
| 0911f86abf | |||
| 49906e8e4b | |||
| 8bffd498ea | |||
| 000e39e9a8 | |||
| 8dacf71043 | |||
| 73dcf45a3d | |||
| 1392ff5533 | |||
| 00d6b7abfc | |||
| 4f8f1965f7 | |||
| 36279c256b | |||
| 9dcf3d08c9 | |||
| 0424f255ef | |||
| 8b62a82ae3 | |||
| b0c8b08874 | |||
| 50637ca5c5 | |||
| d8c37bbc54 | |||
| 44980e8169 | |||
| 5dcf5890ae | |||
| 7c727bb61b | |||
| e097db7210 | |||
| 2228567ad3 | |||
| fe54b7a1f4 | |||
| fb9e8e48fd | |||
| 0186ee1cd7 | |||
| dea434ea65 | |||
| bc7e41c03c | |||
| 77731d5ec0 | |||
| 079f840e47 | |||
| d37412b80c | |||
| f1c5830311 | |||
| 7ae051df2a | |||
| 299fe02393 | |||
| 7a16413a84 | |||
| 8bfb186728 | |||
| 4331e6bd1d | |||
| dfb5f32758 | |||
| c70631623c | |||
| 07a2e5d1ed | |||
| 1519675a1a | |||
| 02e81f72a0 | |||
| 726a047a47 | |||
| efafde5eb4 | |||
| 72543206e5 | |||
| c9bf7ed9ad | |||
| 83baa239e7 | |||
| f52ed5fd61 | |||
| c850c2be75 | |||
| 9489aefb83 | |||
| 255548562b | |||
| 8e7a16895c | |||
| a6b62a26d4 | |||
| 2e899ccaff | |||
| 631900291d | |||
| b80d01a182 | |||
| d0db5edf61 | |||
| 985b4bc157 | |||
| ae24e13bc7 | |||
| c69d537b93 | |||
| 467e20ad1d | |||
| e9763e4ed7 | |||
| 87cdd5926d | |||
| 17dca772e0 | |||
| 3640785453 | |||
| 2534bf4011 | |||
| c6a39debf9 | |||
| 815709dd00 | |||
| 6cd83aecb9 | |||
| 8291cd78f2 | |||
| 0f4de9bf9d | |||
| 50c4420030 | |||
| 1a1fe1d1da | |||
| e52cdadea7 | |||
| e432f2a316 | |||
| f462046cd1 | |||
| 0887b70286 | |||
| ada3470075 | |||
| e024421624 | |||
| d0c6c6586e | |||
| 1425bae1ab | |||
| 7edb0c3920 | |||
| c957673bf7 | |||
| bfa7218982 | |||
| 4a25b740f2 | |||
| ec50c5a2a4 | |||
| b6953280e7 | |||
| 3202b11f66 | |||
| c5dd908c89 | |||
| 65d0312c96 | |||
| 3ba9adc5c1 | |||
| c738052394 | |||
| d1047faad6 | |||
| 874b5e9fbb | |||
| 73d9eb1bb3 | |||
| 4ea86ac0e3 | |||
| 0609cf85fd | |||
| 290caec8e3 | |||
| 942c958769 | |||
| f1747f93e0 | |||
| 43afab28a0 | |||
| 14bc98d8e2 | |||
| 4b5e8c926a | |||
| 27661f24cd | |||
| c1f914dbc9 | |||
| 35ac4c8685 | |||
| b1cbae8bd6 | |||
| c1242d60d9 | |||
| ad460db7eb | |||
| af8af121ab | |||
| 45d19952c3 | |||
| 6962f3d814 | |||
| fd11e5c082 | |||
| ece1729958 | |||
| 4a83311370 | |||
| 311990d74e | |||
| 4717d573e4 | |||
| e53393250a | |||
| 4a6896379f | |||
| fbbe262820 | |||
| 885f546f97 | |||
| a5dbae3781 | |||
| cee8b04d33 | |||
| f19d7b4de1 | |||
| 15e388d910 | |||
| 85900c04b0 | |||
| 8b53358f8f | |||
| 1e03bd8a89 | |||
| 1c1b3a0f2d | |||
| 1388a71690 | |||
| 7a3d03b1fd | |||
| 4bf468e69d | |||
| 8272128211 | |||
| 8f1bdc0f73 | |||
| ded37f337b | |||
| 8d6e3f513c | |||
| 04364cb3cc | |||
| db258d8ff7 | |||
| 1426d2a264 | |||
| 52c87ac084 | |||
| 3835cf6ea1 | |||
| a683b055fb | |||
| e0b6ee5185 | |||
| 66985fb8ff | |||
| f7fcf7f910 | |||
| 95f6df5b8d | |||
| 71d6456f59 | |||
| 6b19c72f26 | |||
| 4112a63b8f | |||
| 8b68902128 | |||
| e0190a6984 | |||
| 9591d3fe93 | |||
| 142c5de4dd | |||
| ccfb50d55e | |||
| be2a40d489 | |||
| f2d422c528 | |||
| 166f4eb5cf | |||
| 019de3d553 | |||
| 543ee479eb | |||
| 2dcd4fad6b | |||
| b097ef29d1 | |||
| 47bc07d425 | |||
| 0c34eab477 | |||
| 2fb488d10a | |||
| 32dd04b41e | |||
| bd1a5932d9 | |||
| 276172e4a3 | |||
| bba1953426 | |||
| 9ee02515c4 | |||
| 35d302ccb1 | |||
| 6e53f67c63 | |||
| e57527c14f | |||
| e85e33d39c | |||
| c29bc733be | |||
| 54f96dc50e | |||
| 94ad4abc65 | |||
| 4f5ae3fc4e | |||
| a42db7ff40 | |||
| fd360c3943 | |||
| 29d1d91502 | |||
| 9f53d0c817 | |||
| 8703642803 | |||
| 92d252e06d | |||
| 4597870108 | |||
| 1a4b2117f1 | |||
| ef636cc3cd | |||
| c40329c9bf | |||
| 0448e00aaf | |||
| eed134c4d3 | |||
| 76412af157 | |||
| 33c120f9b7 | |||
| 4b491d8565 | |||
| c9ac238b92 | |||
| bfdeb1f6d5 | |||
| ed7fe45c7c | |||
| 3e1f302dbe | |||
| 224e356081 | |||
| d004268b27 | |||
| fd66549cb6 | |||
| a13a645cdf | |||
| 9bc351b3c7 | |||
| d6d9c54bb2 | |||
| c5b9da34f2 | |||
| 03e306b3a1 | |||
| 5c208f36a4 | |||
| 2aac896611 | |||
| 25e042c0b0 | |||
| 187c115a69 | |||
| fed5234fb3 | |||
| e8233f14bd | |||
| dc7b94e63f | |||
| 3ff6aa6e39 | |||
| bfb7f77a8c | |||
| 60ad526639 | |||
| 0bce1d6c9f | |||
| cf04895832 | |||
| 966a158831 | |||
| f12e5d1a0f | |||
| 3e4ccc3208 | |||
| e2a3c7232b | |||
| 19a6315ccf | |||
| 58cb5644bc | |||
| 04a556acf2 | |||
| 0dd542f79e | |||
| f2d56bc578 | |||
| b56f179e45 | |||
| 8ff67df7ac | |||
| 7398e279a7 | |||
| de7e2b178d | |||
| 5c945264b0 | |||
| dcaf03fccf | |||
| 7a13effa20 | |||
| 0cf7131555 | |||
| ed271dc7ea | |||
| 38fdb2a857 | |||
| f0a9af433a | |||
| 9edb535bdd | |||
| a8c68e551d | |||
| d204a83c9b | |||
| 2f70d5838a | |||
| 9bf5bea607 | |||
| 032bcf72fb | |||
| d02833bf05 | |||
| 914e32f24a | |||
| 2722e2e822 | |||
| d4a65cfc51 | |||
| 9566982328 | |||
| a34fbd1b9b | |||
| 18c9e2638e | |||
| 457d9384a2 | |||
| b81e11b25b | |||
| c73b85c156 | |||
| d3aaf963a9 | |||
| 5608fb36ec | |||
| 3cd93a0b67 | |||
| 5ef61df185 | |||
| fbd9de1830 | |||
| fefc7b1bf7 | |||
| ea206ad17b | |||
| 12599d566b | |||
| 5cad859f61 | |||
| 0df847cc77 | |||
| de8aa17eb5 | |||
| 9c8235b1bd | |||
| bbc6e5c9b7 | |||
| f6fdf32553 | |||
| 70d390134c | |||
| 18689b8fb2 | |||
| 50faa8d17e | |||
| f6c7cc606e | |||
| d8f6222bee | |||
| 4b24cb2a3a | |||
| d676227f2c | |||
| 178ce6287b | |||
| 1adf87592f | |||
| e69b4d757e | |||
| 48c8447574 | |||
| 2eb9605e81 | |||
| ece4bf60ff | |||
| aa85c8c854 | |||
| 75ed9f819f | |||
| f121ffbde3 | |||
| 009601d534 | |||
| 59c80e0533 | |||
| c096d6add6 | |||
| 17e7e16b3b | |||
| 98be43ed73 | |||
| ea13658566 | |||
| 752df4c49b | |||
| c87d7bede0 | |||
| f154cef8f2 | |||
| 3b56698541 | |||
| 104ab7e81f | |||
| 26c080a04b | |||
| 31c160ab8f | |||
| 1b37bc0e66 | |||
| 92e9fa6fe8 | |||
| 7b32f84ebf | |||
| 0cd2ffffb7 | |||
| be46f935dc | |||
| 074cad3026 | |||
| e4d4d73397 | |||
| d29a369fe2 | |||
| 45c2b1804f | |||
| a864ac1c5a | |||
| f1b88ec953 | |||
| e9b04e524b | |||
| 5c792a484d | |||
| 497f84885b | |||
| 4ddeccfc15 | |||
| 23cfa0138e | |||
| 4441897daa | |||
| a700db9387 | |||
| a4093dcc06 | |||
| 62801081f3 | |||
| 3b306aac6e | |||
| 6f95d95015 | |||
| d42855e404 | |||
| ee9950d09b | |||
| 6e6820148a | |||
| c7882b975e | |||
| c00d89d599 | |||
| 88e6a942ad | |||
| b4afb2fb2f | |||
| 4c3139d7ee | |||
| 00e863c48e | |||
| d9345f3312 | |||
| 197fa124d7 | |||
| 968dc2489a | |||
| 347e4833f9 | |||
| 19d87fa848 | |||
| 67a3914e65 | |||
| 8acaa6d039 | |||
| 61cf538d27 | |||
| 9243eb4ab8 | |||
| 7e3e031182 | |||
| 598d0d1498 | |||
| 6da414ef41 | |||
| ebb3e03b6d | |||
| 2e29bcd542 | |||
| 199925a352 | |||
| 4c2f7e57a2 | |||
| e957bd1ce7 | |||
| edf7efc61c | |||
| 19c4fa92dd | |||
| 2ad29f3611 | |||
| d2ac1c5b7c | |||
| 2139c35da0 | |||
| 6d443b0d74 | |||
| e69d98df22 | |||
| 3205eab2f2 | |||
| 63346a4bca | |||
| 2c8d251956 | |||
| 710d00aa6f | |||
| 1934310ebd | |||
| bf19927688 | |||
| c6a6f1507c | |||
| bc60d7bee9 | |||
| 4bf24c8830 | |||
| 88ef6be57d | |||
| 2fd38836dc | |||
| 21d90a1607 | |||
| f3d279595e | |||
| 7860052209 | |||
| 266685c7e7 | |||
| 05e279fa46 | |||
| eb83747441 | |||
| 88349483ef | |||
| a9b00b0fb7 | |||
| 97c709b5be | |||
| c6cdee8303 | |||
| 18d21497b2 | |||
| e595a83856 | |||
| 13f03afd17 | |||
| 090b8649be | |||
| f0e7f4c1f2 | |||
| dea749acc3 | |||
| 32b4979559 | |||
| afb8798580 | |||
| bce0d04c98 | |||
| 03cfce20c9 | |||
| d27f6d7881 | |||
| f5187de2fb | |||
| 583770af28 | |||
| 3764f632b8 | |||
| 6d3f22cdc1 | |||
| 98eb4ad6ee | |||
| ec04c41be6 | |||
| 7be78606ff | |||
| 07cdceed8e | |||
| cf758d23cd | |||
| 343fe033c0 | |||
| 0e07bc36d9 | |||
| c6cfc8e3ea | |||
| fe9baec645 | |||
| 7a55fe3a95 | |||
| 07a1e3eb91 | |||
| 1e563f4817 | |||
| 2d73547cdb | |||
| 26eccee741 | |||
| 4f0529e33e | |||
| 9bcb0a510f | |||
| 7d7e82c9b1 | |||
| 55865c47a7 | |||
| fe5f721de6 | |||
| 067f809402 | |||
| 49e7cfc9a3 | |||
| 5be33f7b3f | |||
| 691e7eceb6 | |||
| e034c18591 | |||
| ca698abb5a | |||
| 47f4bb3f2d | |||
| d3335a7970 | |||
| ffddcb725f | |||
| 02834a9a3d | |||
| 4cbc413a25 | |||
| 13e735a5b5 | |||
| e32a50a025 | |||
| 7097105bea | |||
| a94ca1d37c | |||
| 8b3ba8eb5a | |||
| 173c113c5f | |||
| 4824b9c664 | |||
| 51d5aa0915 | |||
| 54a282830f | |||
| bc4df6079c | |||
| fe5602ffd9 | |||
| e40c2699b7 | |||
| 19afe7ffd1 | |||
| 42516b2ef9 | |||
| 8625bd64c2 | |||
| 4b4b5ff1d8 | |||
| 1a466a386e | |||
| de4fc707b5 | |||
| dfa64c5542 | |||
| 5f05a7c3c7 | |||
| cd9b951e6b | |||
| ee0b5e9bed | |||
| 99438c843c | |||
| 5a6dc86df2 | |||
| 36cb4d03ac | |||
| 1682fedaa0 | |||
| e550d98bbf | |||
| 3a92a5c4b3 | |||
| 2005250d7f | |||
| 5be20f3927 | |||
| f6e86e38ac | |||
| 6bb44daae4 | |||
| 9905e7e22b | |||
| 6d05f9af81 | |||
| 346f1e0ed9 | |||
| b27a30c620 | |||
| 0064c43a88 | |||
| 5598a3f8da | |||
| 954c02b414 | |||
| 6c45a5d60e | |||
| b909f23581 | |||
| e2a4ec3921 | |||
| e34646b5dc | |||
| 68b0e8db05 | |||
| c9f16f6562 | |||
| ac1f151796 | |||
| 66fee051a6 | |||
| bad9725a29 | |||
| 1fa0ef3ae8 | |||
| 26068b7901 | |||
| ae50e509f5 | |||
| 784623d599 | |||
| 59b4f75e0f | |||
| 5ea8d1ed5a | |||
| 1c27c39396 | |||
| ccb1211b54 | |||
| 26d5652b56 | |||
| 8ee82c6202 | |||
| dac467890e | |||
| bf441f7575 | |||
| 56d46d9d38 | |||
| 65d83fa221 | |||
| a2d88f6a03 | |||
| d045b42854 | |||
| cbb182fef2 | |||
| 70188a66e0 | |||
| a2a875e3b8 | |||
| 895ad5f4af | |||
| ed959dba7d | |||
| 79d3714f24 | |||
| d2a88e961a | |||
| 7d56669bc4 | |||
| 2eff8f2252 | |||
| acfd1e2ba8 | |||
| e25a267e81 |
+2
-2
@@ -19,7 +19,7 @@ that are public domain include the following:
|
||||
* All of the SQLite extension source code and test cases in the
|
||||
[ext/ directory](https://sqlite.org/src/tree/ext?type=tree&expand)
|
||||
* All code that ends up in the "sqlite3.c" and "sqlite3.h" build products
|
||||
that actually implements the SQLite RDBMS.
|
||||
that actually implement the SQLite RDBMS.
|
||||
* All of the code used to compile the
|
||||
[command-line interface](https://sqlite.org/cli.html)
|
||||
* All of the code used to build various utility programs such as
|
||||
@@ -56,7 +56,7 @@ words, there are some non-public-domain files used to implement:
|
||||
In all cases, the non-public-domain files included with this
|
||||
repository have generous BSD-style licenses. So anyone is free to
|
||||
use any of the code in this source repository for any purpose, though
|
||||
attribution my be required to reuse or republish the configure and
|
||||
attribution may be required to reuse or republish the configure and
|
||||
build scripts. None of the non-public-domain code ever actually reaches
|
||||
the build products, such as "sqlite3.c", however, so no attribution is
|
||||
required to use SQLite itself. The non-public-domain code consists of
|
||||
|
||||
+108
-98
@@ -4,60 +4,28 @@
|
||||
# Makefile for SQLITE
|
||||
#
|
||||
# This makefile is intended to be configured automatically using the
|
||||
# configure script. Hand editing may not work as expected because
|
||||
# certain blocks are added or removed depending on configure-time
|
||||
# information.
|
||||
# configure script.
|
||||
#
|
||||
# The docs for many of its variables are in the primary static
|
||||
# makefile, main.mk (which this one includes at runtime).
|
||||
#
|
||||
all:
|
||||
clean:
|
||||
########################################################################
|
||||
#XX# Lines starting with #XX# are TODOs for the port to autosetup.
|
||||
#
|
||||
# Known TODOs/FIXMEs/TOIMPROVEs for the autosetup port, in no
|
||||
# particular order...
|
||||
#
|
||||
# - libreadline detection and handling of its -I, -L, and -l flags.
|
||||
# These can vary considerably across systems. e.g. some need -lncurses,
|
||||
# and some don't know what an -lncurses is.
|
||||
#
|
||||
# - TEA pieces.
|
||||
#
|
||||
# - Replace the autotools-specific distribution deliverable(s).
|
||||
#
|
||||
# - Provide Makefile.msc, Makefile.linux-gcc, and any required similar
|
||||
# makefile stubs for environments where the configure script will not
|
||||
# run. The core makefile rules in main.mk "should" apply as-is for
|
||||
# most platforms. We can potentially generate those makefiles, along
|
||||
# with main.mk, like we do in the Fossil project.
|
||||
#
|
||||
# - Confirm whether cross-compilation works and patch it
|
||||
# appropriately.
|
||||
#
|
||||
# - There are some lingering dependencies issues which cause a
|
||||
# re-configure to trigger more often than it should. This is
|
||||
# especially a problem in parallel builds, which may launch multiple
|
||||
# re-configures in parallel. GNU Make offers ways of controlling
|
||||
# that, but we're limited to POSIX Make compatibility here. The
|
||||
# automatic reconfigures are not too onerous, though, because they're
|
||||
# much, much faster than Autotools configure runs.
|
||||
#
|
||||
# - Add target(s) to dump out specific vars, e.g. SQLITE_OPT, as
|
||||
# requested at https://sqlite.org/forum/forumpost/75cb3179216f8d86.
|
||||
# This would also be useful for the ext/wasm build, which fishes
|
||||
# SHELL_OPT out of the makefile.
|
||||
#
|
||||
#
|
||||
# Maintenance reminders:
|
||||
#
|
||||
# - When using the X?=Y variable assignment formulation, please test
|
||||
# the build with both GNU make and a POSIX make (e.g. BSD make,
|
||||
# a.k.a. bmake). On at least one occassion, that formulation has led
|
||||
# to inconsistent behavior between the two major make flavors when
|
||||
# used with variable names which might sensibly be in the
|
||||
# developer's environment (namely CC).
|
||||
# - This makefile should remain as POSIX-make-compatible as possible:
|
||||
# https://pubs.opengroup.org/onlinepubs/9799919799/utilities/make.html
|
||||
#
|
||||
# - The naming convention of some vars, using periods instead of
|
||||
# underscores, though unconventional, was selected for a couple of
|
||||
@@ -73,33 +41,75 @@ clean:
|
||||
# that contains this "Makefile.in" and the "configure" script.
|
||||
#
|
||||
TOP = @abs_top_srcdir@
|
||||
|
||||
#
|
||||
# Some standard variables and programs
|
||||
# Autotools-conventional vars which are used by package installation
|
||||
# rules in main.mk. To get sane handling when a user overrides only
|
||||
# a subset of these, we perform some acrobatics with these vars
|
||||
# in the configure script: see [proj-remap-autoconf-dir-vars] for
|
||||
# full details.
|
||||
#
|
||||
prefix ?= @prefix@
|
||||
exec_prefix ?= @exec_prefix@
|
||||
libdir ?= @libdir@
|
||||
pkgconfigdir ?= $(libdir)/pkgconfig
|
||||
bindir ?= @bindir@
|
||||
includedir ?= @includedir@
|
||||
# For completeness's sake, the aforementioned conventional vars which
|
||||
# are relevant to our installation rules are:
|
||||
#
|
||||
# Just testing some default dir expansions...
|
||||
# srcdir = @srcdir@
|
||||
# builddir = @builddir@
|
||||
# top_srcdir = @top_srcdir@
|
||||
# abs_top_srcdir = @abs_top_srcdir@
|
||||
# abs_top_builddir = @abs_top_builddir@
|
||||
# datadir = $(prefix)/share
|
||||
# mandir = $(datadir)/man
|
||||
# includedir = $(prefix)/include
|
||||
# exec_prefix = $(prefix)
|
||||
# bindir = $(exec_prefix)/bin
|
||||
# libdir = $(exec_prefix)/lib
|
||||
#
|
||||
# Our builds do not require any of their relatives:
|
||||
#
|
||||
# sbindir = $(exec_prefix)/sbin
|
||||
# sysconfdir = /etc
|
||||
# sharedstatedir = $(prefix)/com
|
||||
# localstatedir = /var
|
||||
# runstatedir = /run
|
||||
# infodir = $(datadir)/info
|
||||
# libexecdir = $(exec_prefix)/libexec
|
||||
#
|
||||
prefix = @prefix@
|
||||
datadir = @datadir@
|
||||
mandir = @mandir@
|
||||
includedir = @includedir@
|
||||
exec_prefix = @exec_prefix@
|
||||
bindir = @bindir@
|
||||
libdir = @libdir@
|
||||
|
||||
INSTALL = @BIN_INSTALL@
|
||||
AR = @AR@
|
||||
AR.flags = cr # TODO? Add a configure test to determine this?
|
||||
CC = @CC@
|
||||
B.cc = @BUILD_CC@ @BUILD_CFLAGS@
|
||||
B.cc = @CC_FOR_BUILD@ @BUILD_CFLAGS@
|
||||
T.cc = $(CC)
|
||||
CFLAGS = @CFLAGS@ @SH_CFLAGS@
|
||||
#
|
||||
# $(CFLAGS) is problematic because it is frequently overridden when
|
||||
# invoking make, which loses things like -fPIC. So... we avoid using
|
||||
# it directly and instead add a level of indirection. We combine
|
||||
# $(CFLAGS) and $(CPPFLAGS) here because that's the way the legacy
|
||||
# build did it and many builds rely on that. See main.mk for more
|
||||
# details.
|
||||
#
|
||||
# Historical note: the pre-3.48 build only honored CPPFLAGS at
|
||||
# configure-time, and expanded them into the generated Makefile. There
|
||||
# are, in that build, no uses of CPPFLAGS in the configure-expanded
|
||||
# Makefile. Ergo: if a client configures with CPPFLAGS=... and then
|
||||
# explicitly passes CFLAGS=... to make, the CPPFLAGS will be
|
||||
# lost. That behavior is retained in 3.48+.
|
||||
#
|
||||
CFLAGS = @CFLAGS@ @CPPFLAGS@
|
||||
#
|
||||
# $(LDFLAGS.configure) represents any LDFLAGS=... the client passes to
|
||||
# configure. See main.mk.
|
||||
#
|
||||
LDFLAGS.configure = @LDFLAGS@
|
||||
|
||||
LDFLAGS.shobj = @SHOBJ_LDFLAGS@
|
||||
#
|
||||
# CFLAGS.core is documented in main.mk.
|
||||
#
|
||||
CFLAGS.core = @SH_CFLAGS@
|
||||
LDFLAGS.shlib = @SH_LDFLAGS@
|
||||
LDFLAGS.zlib = @LDFLAGS_ZLIB@
|
||||
LDFLAGS.math = @LDFLAGS_MATH@
|
||||
LDFLAGS.rpath = @LDFLAGS_RPATH@
|
||||
@@ -107,8 +117,16 @@ LDFLAGS.pthread = @LDFLAGS_PTHREAD@
|
||||
LDFLAGS.dlopen = @LDFLAGS_DLOPEN@
|
||||
LDFLAGS.readline = @LDFLAGS_READLINE@
|
||||
CFLAGS.readline = @CFLAGS_READLINE@
|
||||
|
||||
LDFLAGS.icu = @LDFLAGS_ICU@
|
||||
CFLAGS.icu = @CFLAGS_ICU@
|
||||
LDFLAGS.libsqlite3.soname = @LDFLAGS_LIBSQLITE3_SONAME@
|
||||
# soname: see https://sqlite.org/src/forumpost/5a3b44f510df8ded
|
||||
LDFLAGS.libsqlite3.os-specific = @LDFLAGS_MAC_CVERSION@ @LDFLAGS_OUT_IMPLIB@
|
||||
# os-specific: see
|
||||
# - https://sqlite.org/forum/forumpost/9dfd5b8fd525a5d7
|
||||
# - https://sqlite.org/forum/forumpost/0c7fc097b2
|
||||
ENABLE_SHARED = @ENABLE_SHARED@
|
||||
ENABLE_STATIC = @ENABLE_STATIC@
|
||||
HAVE_WASI_SDK = @HAVE_WASI_SDK@
|
||||
|
||||
T.cc.sqlite = $(T.cc) @TARGET_DEBUG@
|
||||
@@ -117,27 +135,17 @@ T.cc.sqlite = $(T.cc) @TARGET_DEBUG@
|
||||
# Define -D_HAVE_SQLITE_CONFIG_H so that the code knows it
|
||||
# can include the generated sqlite_cfg.h.
|
||||
#
|
||||
# main.mk will fill out T.cc.sqlite with additional flags common to
|
||||
# all builds.
|
||||
#
|
||||
T.cc.sqlite += -D_HAVE_SQLITE_CONFIG_H -DBUILD_sqlite
|
||||
#
|
||||
# main.mk will fill out T.cc.sqlite with some flags common to all builds.
|
||||
|
||||
#XX#CFLAGS.readline += -DHAVE_EDITLINE=@TARGET_HAVE_EDITLINE@
|
||||
#XX#CFLAGS.readline += -DHAVE_LINENOISE=@TARGET_HAVE_LINENOISE@
|
||||
#XX#
|
||||
#XX## The library that programs using readline() must link against.
|
||||
#XX##
|
||||
#XX#LIBREADLINE = @TARGET_READLINE_LIBS@
|
||||
#XX#
|
||||
#XX## Should the database engine be compiled threadsafe
|
||||
#XX##
|
||||
#XX#T.cc += -DSQLITE_THREADSAFE=@SQLITE_THREADSAFE@
|
||||
|
||||
#
|
||||
# $(JIMSH) and $(CFLAGS.JIMSH) are documented in main.mk. $(JIMSH)
|
||||
# $(JIMSH) and $(CFLAGS.jimsh) are documented in main.mk. $(JIMSH)
|
||||
# must start with a path component so that it can be invoked as a
|
||||
# shell command.
|
||||
#
|
||||
CFLAGS.JIMSH = @CFLAGS_JIMSH@
|
||||
CFLAGS.jimsh = @CFLAGS_JIMSH@
|
||||
JIMSH = ./jimsh$(TEXE)
|
||||
|
||||
#
|
||||
@@ -146,11 +154,6 @@ JIMSH = ./jimsh$(TEXE)
|
||||
B.tclsh = @BTCLSH@
|
||||
$(B.tclsh):
|
||||
|
||||
#
|
||||
# $(CFLAGS.libsqlite3) is documented in main.mk.
|
||||
#
|
||||
CFLAGS.libsqlite3 = -DSQLITE_TEMP_STORE=@TEMP_STORE@
|
||||
|
||||
#
|
||||
# $(OPT_FEATURE_FLAGS) is documented in main.mk.
|
||||
#
|
||||
@@ -161,11 +164,9 @@ CFLAGS.libsqlite3 = -DSQLITE_TEMP_STORE=@TEMP_STORE@
|
||||
OPT_FEATURE_FLAGS = @OPT_FEATURE_FLAGS@ $(OPTIONS)
|
||||
|
||||
#
|
||||
# Release (X.Y.Z) and version (X.Y) numbers for the SQLite being
|
||||
# compiled.
|
||||
# Version (X.Y.Z) number for the SQLite being compiled.
|
||||
#
|
||||
VERSION.XYZ = @VERSION_XYZ@
|
||||
# VERSION.XY = @VERSION_XY@ # we don't currently use this anywhere
|
||||
PACKAGE_VERSION = @PACKAGE_VERSION@
|
||||
|
||||
#
|
||||
# Filename extensions for binaries and libraries
|
||||
@@ -196,25 +197,31 @@ TCL_CONFIG_SH = @TCL_CONFIG_SH@
|
||||
#
|
||||
# TCL config info from tclConfig.sh
|
||||
#
|
||||
TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
|
||||
TCL_LIB_SPEC = @TCL_LIB_SPEC@
|
||||
TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
|
||||
TCL_EXEC_PREFIX = @TCL_EXEC_PREFIX@
|
||||
TCL_VERSION = @TCL_VERSION@
|
||||
TCLLIB_RPATH = @TCLLIB_RPATH@
|
||||
# We have to inject this differently in main.mk to accommodate static
|
||||
# makefiles, so we don't currently bother to export it here. This
|
||||
# block is retained in case we decide that we do indeed need to export
|
||||
# it at configure-time instead of calculate it at make-time.
|
||||
#
|
||||
#TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
|
||||
#TCL_LIB_SPEC = @TCL_LIB_SPEC@
|
||||
#TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
|
||||
#TCL_EXEC_PREFIX = @TCL_EXEC_PREFIX@
|
||||
#TCL_VERSION = @TCL_VERSION@
|
||||
#
|
||||
# $(TCLLIBDIR) = where to install the tcl plugin. If this is empty, it
|
||||
# is calculated at make-time by the targets which need it but we
|
||||
# export it here so that it can be set at configure-time, so that
|
||||
# clients are not required to pass it at make-time, or may set it in
|
||||
# their environment to override it.
|
||||
#
|
||||
TCLLIBDIR = @TCLLIBDIR@
|
||||
|
||||
#
|
||||
# Additional options when running tests using testrunner.tcl
|
||||
# This is usually either blank, or else --status
|
||||
# This is usually either blank or --status.
|
||||
#
|
||||
TSTRNNR_OPTS = @TSTRNNR_OPTS@
|
||||
|
||||
#
|
||||
# Where do we want to install the tcl plugin
|
||||
#
|
||||
TCLLIBDIR = @TCLLIBDIR@
|
||||
|
||||
#
|
||||
# If gcov support was enabled by the configure script, add the appropriate
|
||||
# flags here. It's not always as easy as just having the user add the right
|
||||
@@ -243,9 +250,10 @@ AS_AUTO_DEF = $(TOP)/auto.def
|
||||
# Shell commands to re-run $(TOP)/configure with the same args it was
|
||||
# invoked with to produce this makefile.
|
||||
#
|
||||
AS_AUTOREMAKE = @SQLITE_AUTOREMAKE@
|
||||
AS_AUTORECONFIG = @SQLITE_AUTORECONFIG@
|
||||
|
||||
USE_AMALGAMATION ?= @USE_AMALGAMATION@
|
||||
LINK_TOOLS_DYNAMICALLY ?= @LINK_TOOLS_DYNAMICALLY@
|
||||
AMALGAMATION_GEN_FLAGS ?= --linemacros=@AMALGAMATION_LINE_MACROS@
|
||||
|
||||
#
|
||||
@@ -254,16 +262,16 @@ AMALGAMATION_GEN_FLAGS ?= --linemacros=@AMALGAMATION_LINE_MACROS@
|
||||
SHELL_OPT ?= @OPT_SHELL@
|
||||
|
||||
Makefile: $(TOP)/Makefile.in $(AS_AUTO_DEF)
|
||||
$(AS_AUTOREMAKE)
|
||||
$(AS_AUTORECONFIG)
|
||||
@touch $@
|
||||
|
||||
sqlite3.pc: $(TOP)/sqlite3.pc.in $(AS_AUTO_DEF)
|
||||
$(AS_AUTOREMAKE)
|
||||
$(AS_AUTORECONFIG)
|
||||
@touch $@
|
||||
install: install-pc # defined in main.mk
|
||||
|
||||
sqlite_cfg.h: $(TOP)/sqlite_cfg.h.in $(AS_AUTO_DEF)
|
||||
$(AS_AUTOREMAKE)
|
||||
sqlite_cfg.h: $(AS_AUTO_DEF)
|
||||
$(AS_AUTORECONFIG)
|
||||
@touch $@
|
||||
|
||||
#
|
||||
@@ -308,16 +316,17 @@ misspell: ./custom.rws has_tclsh84
|
||||
# perform cleanup known to be relevant to (only) the autosetup-driven
|
||||
# build.
|
||||
#
|
||||
clean-autosetup:
|
||||
-gmake -C ext/wasm distclean 2>/dev/null; true
|
||||
clean: clean-autosetup
|
||||
#clean-autosetup:
|
||||
# -if [ -f ext/wasm/GNUmakefile ]; then \
|
||||
# gmake --no-print-directory --ignore-errors -C ext/wasm clean; \
|
||||
# fi >/dev/null 2>&1; true
|
||||
#clean: clean-autosetup
|
||||
|
||||
distclean-autosetup: clean
|
||||
rm -f sqlite_cfg.h config.log config.status config.defines.json Makefile sqlite3.pc
|
||||
rm -f sqlite_cfg.h config.log config.status config.defines.* Makefile sqlite3.pc
|
||||
rm -f $(TOP)/tool/emcc.sh
|
||||
rm -f libsqlite3*$(T.dll)
|
||||
rm -f jimsh0*
|
||||
-gmake -C ext/wasm distclean 2>/dev/null; true
|
||||
distclean: distclean-autosetup
|
||||
|
||||
#
|
||||
@@ -327,4 +336,5 @@ distclean: distclean-autosetup
|
||||
version-info$(T.exe): $(TOP)/tool/version-info.c Makefile sqlite3.h
|
||||
$(T.link) $(ST_OPT) -o $@ $(TOP)/tool/version-info.c
|
||||
|
||||
IS_CROSS_COMPILING = @IS_CROSS_COMPILING@
|
||||
include $(TOP)/main.mk
|
||||
|
||||
@@ -24,9 +24,14 @@ TOP ?= $(realpath $(dir $(lastword $(MAKEFILE_LIST))))
|
||||
|
||||
#
|
||||
# $(CFLAGS) will be used when compiling the library and most
|
||||
# utilities. It must normally contain -fPIC on Linux systems.
|
||||
# utilities. It must normally contain -fPIC on Linux systems,
|
||||
# but overriding CFLAGS is an easy way for users to inadvertently
|
||||
# remove -fPIC from their builds, so we generally expect to see
|
||||
# -fPIC in $(CFLAGS.core), which main.mk will integrate with
|
||||
# the CFLAGS where needed.
|
||||
#
|
||||
CFLAGS = -fPIC
|
||||
CFLAGS =
|
||||
CFLAGS.core = -fPIC
|
||||
|
||||
#
|
||||
# $(SHELL_OPT) contains CFLAGS for building the sqlite3 CLI shell.
|
||||
@@ -42,7 +47,7 @@ LDFLAGS.zlib = -lz
|
||||
#
|
||||
# Library's version number.
|
||||
#
|
||||
VERSION.XYZ ?= $(shell cat $(TOP)/VERSION 2>/dev/null)
|
||||
PACKAGE_VERSION ?= $(shell cat $(TOP)/VERSION 2>/dev/null)
|
||||
|
||||
# sqlite_cfg.h is typically created by the configure script. It's
|
||||
# commonly not needed but main.mk does not know that so we have to
|
||||
|
||||
+23
-21
@@ -19,7 +19,9 @@ USE_AMALGAMATION = 1
|
||||
# <</mark>>
|
||||
|
||||
# Optionally set EXTRA_SRC to a list of C files to append to
|
||||
# the generated sqlite3.c.
|
||||
# the generated sqlite3.c. Any sqlite3 extensions added this
|
||||
# way may require manual editing, as described in
|
||||
# https://sqlite.org/forum/forumpost/903f721f3e7c0d25
|
||||
#
|
||||
!IFNDEF EXTRA_SRC
|
||||
EXTRA_SRC =
|
||||
@@ -982,10 +984,14 @@ TCLLIBS =
|
||||
!ENDIF
|
||||
|
||||
!IFNDEF LIBTCLSTUB
|
||||
!IF EXISTS("$(TCLLIBDIR)\tclstub$(TCLSUFFIX).lib")
|
||||
LIBTCLSTUB = tclstub$(TCLSUFFIX).lib
|
||||
!ELSE
|
||||
!IF EXISTS("$(TCLLIBDIR)\tclstub$(TCLVERSION)$(TCLSUFFIX).lib")
|
||||
LIBTCLSTUB = tclstub$(TCLVERSION)$(TCLSUFFIX).lib
|
||||
!ELSEIF EXISTS("$(TCLLIBDIR)\tclstub$(TCLSUFFIX).lib")
|
||||
LIBTCLSTUB = tclstub$(TCLSUFFIX).lib
|
||||
!ELSEIF EXISTS("$(TCLLIBDIR)\tclstub$(TCLVERSION).lib")
|
||||
LIBTCLSTUB = tclstub$(TCLVERSION).lib
|
||||
!ELSE
|
||||
LIBTCLSTUB = tclstub.lib
|
||||
!ENDIF
|
||||
!ENDIF
|
||||
|
||||
@@ -1069,7 +1075,7 @@ TCLSH_CMD = tclsh
|
||||
JIM_TCLSH = $(TCLSH_CMD)
|
||||
!ENDIF
|
||||
!IFNDEF JIM_TCLSH
|
||||
JIM_TCLSH = $(TOP)\jimsh0.exe
|
||||
JIM_TCLSH = jimsh0.exe
|
||||
!ENDIF
|
||||
# <</mark>>
|
||||
|
||||
@@ -1101,15 +1107,6 @@ RCC = $(RCC) -DSQLITE_THREAD_OVERRIDE_LOCK=-1
|
||||
TLIBS =
|
||||
!ENDIF
|
||||
|
||||
# Flags controlling use of the in memory btree implementation
|
||||
#
|
||||
# SQLITE_TEMP_STORE is 0 to force temporary tables to be in a file, 1 to
|
||||
# default to file, 2 to default to memory, and 3 to force temporary
|
||||
# tables to always be in memory.
|
||||
#
|
||||
TCC = $(TCC) -DSQLITE_TEMP_STORE=1
|
||||
RCC = $(RCC) -DSQLITE_TEMP_STORE=1
|
||||
|
||||
# Enable/disable loadable extensions, and other optional features
|
||||
# based on configuration. (-DSQLITE_OMIT*, -DSQLITE_ENABLE*).
|
||||
# The same set of OMIT and ENABLE flags should be passed to the
|
||||
@@ -1585,7 +1582,6 @@ TESTSRC = \
|
||||
$(TOP)\src\test8.c \
|
||||
$(TOP)\src\test9.c \
|
||||
$(TOP)\src\test_autoext.c \
|
||||
$(TOP)\src\test_async.c \
|
||||
$(TOP)\src\test_backup.c \
|
||||
$(TOP)\src\test_bestindex.c \
|
||||
$(TOP)\src\test_blob.c \
|
||||
@@ -1682,7 +1678,6 @@ TESTSRC2 = \
|
||||
$(SRC01) \
|
||||
$(SRC07) \
|
||||
$(SRC10) \
|
||||
$(TOP)\ext\async\sqlite3async.c \
|
||||
fts5.c
|
||||
|
||||
# Header files used by all library source files.
|
||||
@@ -1897,7 +1892,10 @@ tclextension-uninstall:
|
||||
$(TCLSH_CMD) $(TOP)\tool\buildtclext.tcl --uninstall
|
||||
|
||||
tclextension-list:
|
||||
$(TCLSH_CMD) $(TOP)\tool\buildtclext.tcl --info
|
||||
@ $(TCLSH_CMD) $(TOP)\tool\buildtclext.tcl --info
|
||||
|
||||
tclextension-verify: sqlite3.h
|
||||
@ $(TCLSH_CMD) $(TOP)\tool\buildtclext.tcl --version-check
|
||||
|
||||
|
||||
# <</mark>>
|
||||
@@ -2336,7 +2334,7 @@ parse.c: $(TOP)\src\parse.y lemon.exe
|
||||
.\lemon.exe $(REQ_FEATURE_FLAGS) $(OPT_FEATURE_FLAGS) $(EXT_FEATURE_FLAGS) $(OPTS) -S parse.y
|
||||
|
||||
$(SQLITE3H): $(TOP)\src\sqlite.h.in $(TOP)\manifest mksourceid.exe $(TOP)\VERSION $(JIM_TCLSH)
|
||||
$(JIM_TCLSH) $(TOP)\tool\mksqlite3h.tcl "$(TOP:\=/)" > $(SQLITE3H) $(MKSQLITE3H_ARGS)
|
||||
$(JIM_TCLSH) $(TOP)\tool\mksqlite3h.tcl "$(TOP:\=/)" -o $(SQLITE3H) $(MKSQLITE3H_ARGS)
|
||||
|
||||
sqlite3ext.h: .target_source
|
||||
!IF $(USE_STDCALL)!=0 || $(FOR_WIN10)!=0
|
||||
@@ -2400,7 +2398,7 @@ SHELL_DEP = $(SHELL_DEP) $(TOP)\ext\misc\zipfile.c
|
||||
!ENDIF
|
||||
|
||||
shell.c: $(SHELL_DEP) $(TOP)\tool\mkshellc.tcl $(JIM_TCLSH)
|
||||
$(JIM_TCLSH) $(TOP)\tool\mkshellc.tcl > shell.c
|
||||
$(JIM_TCLSH) $(TOP)\tool\mkshellc.tcl shell.c
|
||||
|
||||
zlib:
|
||||
pushd $(ZLIBDIR) && $(MAKE) /f win32\Makefile.msc clean $(ZLIBLIB) && popd
|
||||
@@ -2671,7 +2669,7 @@ shelltest: $(TESTPROGS)
|
||||
.\testfixture.exe $(TOP)\test\permutations.test shell
|
||||
|
||||
sqlite3_analyzer.c: $(SQLITE3C) $(SQLITE3H) $(TOP)\src\tclsqlite.c $(TOP)\tool\spaceanal.tcl $(TOP)\tool\mkccode.tcl $(TOP)\tool\sqlite3_analyzer.c.in $(TOP)\ext\misc\sqlite3_stdio.h $(TOP)\ext\misc\sqlite3_stdio.c $(SQLITE_TCL_DEP)
|
||||
$(TCLSH_CMD) $(TOP)\tool\mkccode.tcl $(TOP)\tool\sqlite3_analyzer.c.in > $@
|
||||
$(TCLSH_CMD) $(TOP)\tool\mkccode.tcl -DINCLUDE_SQLITE3_C $(TOP)\tool\sqlite3_analyzer.c.in > $@
|
||||
|
||||
sqlite3_analyzer.exe: sqlite3_analyzer.c $(LIBRESOBJS)
|
||||
$(LTLINK) $(NO_WARN) -DBUILD_sqlite -I$(TCLINCDIR) sqlite3_analyzer.c \
|
||||
@@ -2801,6 +2799,8 @@ tcl-env:
|
||||
@echo LIBTCL = $(LIBTCL)
|
||||
@echo LIBTCLSTUB = $(LIBTCLSTUB)
|
||||
@echo TCLSH_CMD = $(TCLSH_CMD)
|
||||
@echo JIM_TCLSH = $(JIM_TCLSH)
|
||||
@echo VISUALSTUDIOVERSION = $(VISUALSTUDIOVERSION)
|
||||
|
||||
LSMDIR=$(TOP)\ext\lsm1
|
||||
!INCLUDE $(LSMDIR)\Makefile.msc
|
||||
@@ -2811,7 +2811,8 @@ moreclean: clean
|
||||
|
||||
clean:
|
||||
del /Q *.exp *.lo *.ilk *.lib *.obj *.ncb *.pdb *.sdf *.suo 2>NUL
|
||||
del /Q *.bsc *.def *.cod *.da *.bb *.bbg *.vc gmon.out 2>NUL
|
||||
del /Q *.bsc *.cod *.da *.bb *.bbg *.vc gmon.out 2>NUL
|
||||
del /Q sqlite3.def tclsqlite3.def 2>NUL
|
||||
del /Q $(SQLITE3EXE) $(SQLITE3DLL) Replace.exe 2>NUL
|
||||
# <<mark>>
|
||||
del /Q $(SQLITE3TCLDLL) pkgIndex.tcl 2>NUL
|
||||
@@ -2845,4 +2846,5 @@ clean:
|
||||
del /Q fts5.* fts5parse.* 2>NUL
|
||||
del /Q lsm.h lsm1.c 2>NUL
|
||||
del /q src-verify.exe 2>NUL
|
||||
del /q jimsh.exe jimsh0.exe 2>NUL
|
||||
# <</mark>>
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="103.73447mm"
|
||||
height="46.723713mm"
|
||||
viewBox="0 0 103.73447 46.723713"
|
||||
version="1.1"
|
||||
id="svg470"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs467">
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath41">
|
||||
<path
|
||||
d="m 994.055,997.609 c 6.725,-11.629 35.115,-61.371 40.815,-77.398 6.42,-18.121 7.77,-23.313 7.77,-23.313 0,0 -15.57,80.114 -41.12,126.862 5.6,18.9 12.29,39.79 19.86,62.12 8.85,-15.53 28.96,-51.2 36.23,-68.1 0.27,3.19 0.54,6.38 0.82,9.54 -6.44,24.75 -16.22,57.15 -28.74,82.54 32.14,167.25 135.59,386.25 247.04,504.48 H 509.602 c -37.883,0 -68.711,-30.82 -68.711,-68.71 V 731.789 c 173.738,66.68 383.23,127.633 563.529,125.02 -6.693,25.812 -14.315,49.152 -22.318,62.679 -4.122,6.981 0.449,35.653 11.953,78.121 z"
|
||||
id="path39" />
|
||||
</clipPath>
|
||||
<linearGradient
|
||||
x1="0"
|
||||
y1="0"
|
||||
x2="1"
|
||||
y2="0"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(-4.02e-5,-918.907,-918.907,4.02e-5,858.809,1614.34)"
|
||||
spreadMethod="pad"
|
||||
id="linearGradient51">
|
||||
<stop
|
||||
style="stop-opacity:1;stop-color:#97d9f6"
|
||||
offset="0"
|
||||
id="stop43" />
|
||||
<stop
|
||||
style="stop-opacity:1;stop-color:#0f80cc"
|
||||
offset="0.66199914"
|
||||
id="stop45" />
|
||||
<stop
|
||||
style="stop-opacity:1;stop-color:#0f80cc"
|
||||
offset="0.920245"
|
||||
id="stop47" />
|
||||
<stop
|
||||
style="stop-opacity:1;stop-color:#0f80cc"
|
||||
offset="1"
|
||||
id="stop49" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<g
|
||||
id="g337">
|
||||
<rect
|
||||
style="fill:#ffffff;stroke:#ffffff;stroke-width:0.239562;stroke-linecap:round;stroke-linejoin:round"
|
||||
id="rect366"
|
||||
width="103.4949"
|
||||
height="46.48415"
|
||||
x="0.119781"
|
||||
y="0.119781"
|
||||
ry="0" />
|
||||
<g
|
||||
id="g465"
|
||||
transform="translate(-56.57816,-61.353828)">
|
||||
<path
|
||||
d="m 79.198545,96.729705 c -0.02011,-0.25467 -0.0321,-0.420158 -0.0321,-0.420158 0,0 -0.77223,-5.206224 -1.691499,-6.759822 -0.145415,-0.246275 0.01584,-1.257759 0.421676,-2.755936 0.237243,0.410245 1.238779,2.165033 1.439862,2.73043 0.226484,0.639268 0.274109,0.822431 0.274109,0.822431 0,0 -0.549275,-2.826244 -1.450623,-4.47541 0.197556,-0.66675 0.433564,-1.403703 0.700617,-2.191456 0.341489,0.599017 1.158875,2.049286 1.338792,2.552348 0.03634,0.103364 0.06703,0.191205 0.09454,0.271639 0.0088,-0.04833 0.01764,-0.09666 0.02646,-0.144992 -0.206375,-0.875595 -0.611716,-2.399242 -1.166636,-3.524956 1.231195,-6.408209 5.430309,-14.973654 9.735256,-18.795296 H 60.806192 c -1.88214,0 -3.422086,1.540228 -3.422086,3.422298 v 30.970081 c 0,1.881964 1.539946,3.421944 3.422086,3.421944 h 18.49607 c -0.13335,-1.61438 -0.1778,-3.40046 -0.103717,-5.123145"
|
||||
style="fill:#0f80cc;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.0352778"
|
||||
id="path21" />
|
||||
<path
|
||||
d="m 99.934471,84.584659 h 0.474839 v 3.954957 h -0.503061 c -0.115005,-1.093188 -0.510469,-1.946593 -1.186392,-2.560426 -0.676627,-0.612775 -1.526822,-0.920045 -2.5527,-0.920045 -0.911578,0 -1.64465,0.230364 -2.200628,0.690387 -0.555977,0.459669 -0.833966,1.073467 -0.833966,1.840759 0,0.709401 0.230011,1.356536 0.690386,1.940948 0.459669,0.585258 1.457325,1.337134 2.991556,2.258907 1.782939,1.063978 2.981325,1.992912 3.594805,2.789414 0.61348,0.795549 0.92004,1.706421 0.92004,2.732229 0,1.322916 -0.46813,2.454275 -1.405815,3.393691 -0.939094,0.93983 -2.069042,1.40945 -3.389489,1.40945 -0.766233,0 -1.742369,-0.21096 -2.929467,-0.63334 -0.487891,-0.17237 -0.799394,-0.25781 -0.933097,-0.25781 -0.277989,0 -0.492831,0.21523 -0.646289,0.64699 h -0.503414 v -4.558981 h 0.503414 c 0.0092,1.256206 0.418747,2.262752 1.227314,3.020521 0.808567,0.75667 1.753306,1.13524 2.834217,1.13524 1.024819,0 1.844322,-0.27231 2.462389,-0.81979 0.617008,-0.54723 0.925689,-1.276066 0.925689,-2.188068 0,-0.681143 -0.254,-1.333394 -0.760942,-1.956823 -0.506589,-0.623958 -1.567392,-1.427621 -3.180292,-2.412259 -1.31445,-0.812765 -2.192161,-1.452422 -2.63278,-1.923027 -0.44062,-0.470182 -0.766234,-0.985591 -0.976842,-1.547284 -0.210608,-0.560564 -0.316089,-1.177537 -0.316089,-1.848485 0,-1.294659 0.424744,-2.345302 1.273175,-3.151399 0.848431,-0.805392 1.953331,-1.208264 3.314347,-1.208264 0.747889,0 1.563159,0.148519 2.445103,0.445558 0.411692,0.134409 0.699559,0.201436 0.862189,0.201436 0.135114,0 0.225778,-0.02858 0.27305,-0.08608 0.04868,-0.05786 0.1016,-0.186973 0.15875,-0.388409"
|
||||
style="fill:#003b57;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.0352778"
|
||||
id="path23" />
|
||||
<path
|
||||
d="m 119.14851,93.38576 c 0,-2.579547 -0.59019,-4.611476 -1.76953,-6.097835 -1.17969,-1.48583 -2.70369,-2.22878 -4.57412,-2.22878 -1.98437,0 -3.56799,0.746125 -4.75191,2.235977 -1.18463,1.491438 -1.77553,3.482834 -1.77553,5.975562 0,2.42577 0.58702,4.398857 1.76106,5.918271 1.17511,1.519415 2.70616,2.278595 4.59458,2.278595 1.96568,0 3.5426,-0.73562 4.7311,-2.207334 1.18851,-1.472177 1.78435,-3.430094 1.78435,-5.874456 z m 2.93265,12.9716 0.18662,0.46041 c -0.82409,0.37402 -1.7586,0.56085 -2.80353,0.56085 -0.86289,0 -1.66405,-0.11314 -2.40206,-0.33789 -0.73731,-0.22571 -1.43122,-0.57051 -2.07751,-1.03572 -0.647,-0.46496 -1.43616,-1.23941 -2.36608,-2.32198 -0.82515,-0.95928 -1.45768,-1.55445 -1.8983,-1.78404 -1.92723,-0.39232 -3.58246,-1.40973 -4.96852,-3.048067 -1.38536,-1.639323 -2.07822,-3.509716 -2.07822,-5.609167 0,-1.5627 0.39794,-3.033889 1.19345,-4.414556 0.79587,-1.380772 1.87466,-2.461718 3.23709,-3.242416 1.36031,-0.782108 2.87055,-1.172633 4.52896,-1.172633 2.56011,0 4.71699,0.851253 6.47206,2.55263 1.75366,1.7012 2.63067,3.79416 2.63067,6.276975 0,2.09102 -0.67522,3.951923 -2.02706,5.586695 -1.3522,1.635479 -3.08293,2.658779 -5.19148,3.070539 0.20179,0.16151 0.56233,0.5697 1.0795,1.22234 1.10031,1.36204 2.02071,2.28604 2.75837,2.76998 0.73871,0.48274 1.47214,0.72542 2.20133,0.72542 0.53728,0 1.04634,-0.0868 1.52471,-0.25937"
|
||||
style="fill:#003b57;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.0352778"
|
||||
id="path25" />
|
||||
<path
|
||||
d="m 134.47177,99.116318 -0.28116,2.694482 h -11.00385 l 0.0233,-0.53619 c 0.59654,-0.061 1.01458,-0.21413 1.25835,-0.45861 0.24342,-0.24624 0.36654,-0.81111 0.37571,-1.699682 l 0.0127,-11.904593 c -0.004,-0.621877 -0.0346,-1.050502 -0.0861,-1.284393 -0.13828,-0.653698 -0.75565,-0.980017 -1.85984,-0.980017 l -0.0236,-0.535164 h 5.74393 l 0.0219,0.535164 c -0.61242,0.04163 -1.03152,0.206728 -1.26612,0.496711 -0.23212,0.291042 -0.34713,0.880533 -0.34678,1.767699 l -0.0441,12.029053 c 0.002,0.204646 0.0191,0.391901 0.0572,0.565538 0.1845,0.877674 0.88053,1.315474 2.08774,1.315474 h 1.03681 c 1.34161,0 2.27259,-0.15088 2.79788,-0.45226 0.52388,-0.29919 0.8569,-0.818023 1.00048,-1.553212 h 0.49565"
|
||||
style="fill:#003b57;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.0352778"
|
||||
id="path27" />
|
||||
<path
|
||||
d="m 138.12055,87.618936 c 0.25965,0 0.49883,0.09095 0.71967,0.273685 0.21837,0.182034 0.36054,0.407071 0.41522,0.674829 0.0533,0.25975 0.009,0.48507 -0.133,0.676769 -0.14217,0.191523 -0.34114,0.28702 -0.60078,0.28702 -0.26846,0 -0.51858,-0.0955 -0.75001,-0.28702 -0.23283,-0.191699 -0.37535,-0.417019 -0.42827,-0.676769 -0.0547,-0.267758 -0.0106,-0.492795 0.14605,-0.674829 0.15311,-0.182738 0.36266,-0.273685 0.63112,-0.273685 z m 1.75754,4.127783 -0.0176,7.535404 c 0.003,0.526662 0.03,0.900957 0.0769,1.122117 0.0607,0.30688 0.19685,0.5147 0.40111,0.6248 0.20778,0.11081 0.67133,0.1662 1.39065,0.1662 l 0.0166,0.50299 h -5.17702 l 0.0123,-0.50299 c 0.70979,0 1.14582,-0.0656 1.31198,-0.1947 0.16475,-0.12887 0.24941,-0.56307 0.25859,-1.301433 l 0.0325,-5.335094 c -0.006,-0.291042 -0.0243,-0.518548 -0.0586,-0.683613 -0.1016,-0.493219 -0.42686,-0.740587 -0.97367,-0.740587 l -1.12324,0.143616 -0.005,-0.589527 3.26319,-0.747183 h 0.59161"
|
||||
style="fill:#003b57;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.0352778"
|
||||
id="path29" />
|
||||
<path
|
||||
d="m 148.56207,92.004952 0.0247,0.805074 h -2.70545 l -0.0194,6.728955 c 0,0.183409 0.0109,0.341065 0.0423,0.476109 0.11465,0.55605 0.41945,0.83467 0.90946,0.83467 0.79728,0 1.70709,-0.52239 2.73967,-1.567637 l 0.43427,0.366148 c -1.43016,1.587219 -2.79682,2.380119 -4.10033,2.380119 -0.901,0 -1.43828,-0.41229 -1.6129,-1.23677 -0.072,-0.34438 -0.10795,-1.025556 -0.11077,-2.041838 l 0.037,-5.939756 h -1.76954 l -0.0205,-0.502708 c 1.51836,-0.153105 2.50472,-1.106981 2.96087,-2.861769 h 0.51752 l -0.005,2.559403 h 2.67758"
|
||||
style="fill:#003b57;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.0352778"
|
||||
id="path31" />
|
||||
<path
|
||||
d="m 152.6931,96.836244 c 2.82998,-0.546417 4.09434,-1.527845 3.79906,-2.9464 -0.0603,-0.288819 -0.24483,-0.55245 -0.54716,-0.791527 -0.30656,-0.239925 -0.61418,-0.359975 -0.92921,-0.359975 -0.71932,0 -1.3081,0.424462 -1.76178,1.272505 -0.4572,0.848854 -0.6417,1.791017 -0.56091,2.825397 z m -0.0162,0.533436 c 0.024,0.248708 0.0575,0.48394 0.10442,0.704179 0.36089,1.725437 1.3328,2.588371 2.91395,2.588371 1.15005,0 2.67264,-0.694412 3.42829,-2.08471 l 0.38312,0.395217 c -0.47378,1.071703 -0.9899,1.848523 -1.54658,2.331513 -0.55527,0.48327 -1.87678,0.72414 -2.82434,0.72414 -1.01776,0 -1.86161,-0.28497 -2.53259,-0.85548 -0.67204,-0.57076 -1.11407,-1.378306 -1.33456,-2.423128 -0.37465,-1.783751 -0.0843,-3.405012 0.86854,-4.868334 0.95779,-1.460853 2.19145,-2.19329 3.70593,-2.19329 0.59584,0 1.66511,0.152118 2.07574,0.453637 0.40535,0.30166 0.66393,0.707072 0.77118,1.214614 0.18027,0.85411 -0.78352,1.660948 -1.74484,2.423689 -0.96203,0.762318 -2.38725,1.291767 -4.26826,1.589582"
|
||||
style="fill:#003b57;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.0352778"
|
||||
id="path33" />
|
||||
<g
|
||||
id="g37"
|
||||
clip-path="url(#clipPath41)"
|
||||
transform="matrix(0.03527778,0,0,-0.03527778,42.828565,121.98722)">
|
||||
<path
|
||||
d="m 994.055,997.609 c 6.725,-11.629 35.115,-61.371 40.815,-77.398 6.42,-18.121 7.77,-23.313 7.77,-23.313 0,0 -15.57,80.114 -41.12,126.862 5.6,18.9 12.29,39.79 19.86,62.12 8.85,-15.53 28.96,-51.2 36.23,-68.1 0.27,3.19 0.54,6.38 0.82,9.54 -6.44,24.75 -16.22,57.15 -28.74,82.54 32.14,167.25 135.59,386.25 247.04,504.48 H 509.602 c -37.883,0 -68.711,-30.82 -68.711,-68.71 V 731.789 c 173.738,66.68 383.23,127.633 563.529,125.02 -6.693,25.812 -14.315,49.152 -22.318,62.679 -4.122,6.981 0.449,35.653 11.953,78.121"
|
||||
style="fill:url(#linearGradient51);fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path53" />
|
||||
</g>
|
||||
<path
|
||||
d="m 95.439377,63.024997 c -1.923345,-1.715206 -4.252031,-1.026231 -6.550379,1.01353 -0.341136,0.303037 -0.681566,0.639234 -1.020233,0.998362 -3.931709,4.170892 -7.581195,11.896725 -8.715023,17.796934 0.441678,0.895703 0.786695,2.038703 1.013884,2.911828 0.05821,0.224014 0.110772,0.43427 0.152752,0.613128 0.09984,0.423298 0.153459,0.697794 0.153459,0.697794 0,0 -0.03528,-0.133385 -0.179917,-0.552802 -0.02752,-0.08043 -0.05821,-0.168275 -0.09454,-0.271639 -0.01552,-0.04269 -0.03704,-0.09454 -0.06068,-0.149931 -0.25647,-0.596194 -0.965906,-1.854553 -1.278114,-2.402417 -0.267053,0.787753 -0.503061,1.524706 -0.700617,2.191456 0.901348,1.649166 1.450623,4.47541 1.450623,4.47541 0,0 -0.04762,-0.183163 -0.274109,-0.822431 -0.201083,-0.565397 -1.202619,-2.320185 -1.439862,-2.73043 -0.405836,1.498177 -0.567091,2.509661 -0.421676,2.755936 0.282328,0.477202 0.551216,1.300586 0.78733,2.211176 0.5334,2.051367 0.904169,4.548646 0.904169,4.548646 0,0 0.01199,0.165488 0.0321,0.420158 -0.07408,1.722685 -0.02963,3.508765 0.103717,5.123145 0.176741,2.13706 0.509411,3.97288 0.93345,4.9554 l 0.287866,-0.15695 c -0.622652,-1.93573 -0.875594,-4.47255 -0.764822,-7.39814 0.16757,-4.471846 1.196623,-9.86469 3.098095,-15.485534 3.212395,-8.485012 7.669389,-15.292918 11.748559,-18.544118 -3.717925,3.357739 -8.749948,14.22647 -10.256309,18.251312 -1.686631,4.50709 -2.881842,8.736578 -3.602214,12.788831 1.242836,-3.798959 5.261328,-5.431932 5.261328,-5.431932 0,0 1.97097,-2.430745 4.274256,-5.903454 -1.379714,0.314678 -3.645253,0.853369 -4.404078,1.172281 -1.119364,0.469547 -1.420989,0.629708 -1.420989,0.629708 0,0 3.62585,-2.208036 6.736645,-3.207809 4.278136,-6.738056 8.939042,-16.310328 4.245328,-20.497448"
|
||||
style="fill:#003b57;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.0352778"
|
||||
id="path55" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 12 KiB |
@@ -1,370 +0,0 @@
|
||||
Installation Instructions
|
||||
*************************
|
||||
|
||||
Copyright (C) 1994-1996, 1999-2002, 2004-2011 Free Software Foundation,
|
||||
Inc.
|
||||
|
||||
Copying and distribution of this file, with or without modification,
|
||||
are permitted in any medium without royalty provided the copyright
|
||||
notice and this notice are preserved. This file is offered as-is,
|
||||
without warranty of any kind.
|
||||
|
||||
Basic Installation
|
||||
==================
|
||||
|
||||
Briefly, the shell commands `./configure; make; make install' should
|
||||
configure, build, and install this package. The following
|
||||
more-detailed instructions are generic; see the `README' file for
|
||||
instructions specific to this package. Some packages provide this
|
||||
`INSTALL' file but do not implement all of the features documented
|
||||
below. The lack of an optional feature in a given package is not
|
||||
necessarily a bug. More recommendations for GNU packages can be found
|
||||
in *note Makefile Conventions: (standards)Makefile Conventions.
|
||||
|
||||
The `configure' shell script attempts to guess correct values for
|
||||
various system-dependent variables used during compilation. It uses
|
||||
those values to create a `Makefile' in each directory of the package.
|
||||
It may also create one or more `.h' files containing system-dependent
|
||||
definitions. Finally, it creates a shell script `config.status' that
|
||||
you can run in the future to recreate the current configuration, and a
|
||||
file `config.log' containing compiler output (useful mainly for
|
||||
debugging `configure').
|
||||
|
||||
It can also use an optional file (typically called `config.cache'
|
||||
and enabled with `--cache-file=config.cache' or simply `-C') that saves
|
||||
the results of its tests to speed up reconfiguring. Caching is
|
||||
disabled by default to prevent problems with accidental use of stale
|
||||
cache files.
|
||||
|
||||
If you need to do unusual things to compile the package, please try
|
||||
to figure out how `configure' could check whether to do them, and mail
|
||||
diffs or instructions to the address given in the `README' so they can
|
||||
be considered for the next release. If you are using the cache, and at
|
||||
some point `config.cache' contains results you don't want to keep, you
|
||||
may remove or edit it.
|
||||
|
||||
The file `configure.ac' (or `configure.in') is used to create
|
||||
`configure' by a program called `autoconf'. You need `configure.ac' if
|
||||
you want to change it or regenerate `configure' using a newer version
|
||||
of `autoconf'.
|
||||
|
||||
The simplest way to compile this package is:
|
||||
|
||||
1. `cd' to the directory containing the package's source code and type
|
||||
`./configure' to configure the package for your system.
|
||||
|
||||
Running `configure' might take a while. While running, it prints
|
||||
some messages telling which features it is checking for.
|
||||
|
||||
2. Type `make' to compile the package.
|
||||
|
||||
3. Optionally, type `make check' to run any self-tests that come with
|
||||
the package, generally using the just-built uninstalled binaries.
|
||||
|
||||
4. Type `make install' to install the programs and any data files and
|
||||
documentation. When installing into a prefix owned by root, it is
|
||||
recommended that the package be configured and built as a regular
|
||||
user, and only the `make install' phase executed with root
|
||||
privileges.
|
||||
|
||||
5. Optionally, type `make installcheck' to repeat any self-tests, but
|
||||
this time using the binaries in their final installed location.
|
||||
This target does not install anything. Running this target as a
|
||||
regular user, particularly if the prior `make install' required
|
||||
root privileges, verifies that the installation completed
|
||||
correctly.
|
||||
|
||||
6. You can remove the program binaries and object files from the
|
||||
source code directory by typing `make clean'. To also remove the
|
||||
files that `configure' created (so you can compile the package for
|
||||
a different kind of computer), type `make distclean'. There is
|
||||
also a `make maintainer-clean' target, but that is intended mainly
|
||||
for the package's developers. If you use it, you may have to get
|
||||
all sorts of other programs in order to regenerate files that came
|
||||
with the distribution.
|
||||
|
||||
7. Often, you can also type `make uninstall' to remove the installed
|
||||
files again. In practice, not all packages have tested that
|
||||
uninstallation works correctly, even though it is required by the
|
||||
GNU Coding Standards.
|
||||
|
||||
8. Some packages, particularly those that use Automake, provide `make
|
||||
distcheck', which can by used by developers to test that all other
|
||||
targets like `make install' and `make uninstall' work correctly.
|
||||
This target is generally not run by end users.
|
||||
|
||||
Compilers and Options
|
||||
=====================
|
||||
|
||||
Some systems require unusual options for compilation or linking that
|
||||
the `configure' script does not know about. Run `./configure --help'
|
||||
for details on some of the pertinent environment variables.
|
||||
|
||||
You can give `configure' initial values for configuration parameters
|
||||
by setting variables in the command line or in the environment. Here
|
||||
is an example:
|
||||
|
||||
./configure CC=c99 CFLAGS=-g LIBS=-lposix
|
||||
|
||||
*Note Defining Variables::, for more details.
|
||||
|
||||
Compiling For Multiple Architectures
|
||||
====================================
|
||||
|
||||
You can compile the package for more than one kind of computer at the
|
||||
same time, by placing the object files for each architecture in their
|
||||
own directory. To do this, you can use GNU `make'. `cd' to the
|
||||
directory where you want the object files and executables to go and run
|
||||
the `configure' script. `configure' automatically checks for the
|
||||
source code in the directory that `configure' is in and in `..'. This
|
||||
is known as a "VPATH" build.
|
||||
|
||||
With a non-GNU `make', it is safer to compile the package for one
|
||||
architecture at a time in the source code directory. After you have
|
||||
installed the package for one architecture, use `make distclean' before
|
||||
reconfiguring for another architecture.
|
||||
|
||||
On MacOS X 10.5 and later systems, you can create libraries and
|
||||
executables that work on multiple system types--known as "fat" or
|
||||
"universal" binaries--by specifying multiple `-arch' options to the
|
||||
compiler but only a single `-arch' option to the preprocessor. Like
|
||||
this:
|
||||
|
||||
./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
|
||||
CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
|
||||
CPP="gcc -E" CXXCPP="g++ -E"
|
||||
|
||||
This is not guaranteed to produce working output in all cases, you
|
||||
may have to build one architecture at a time and combine the results
|
||||
using the `lipo' tool if you have problems.
|
||||
|
||||
Installation Names
|
||||
==================
|
||||
|
||||
By default, `make install' installs the package's commands under
|
||||
`/usr/local/bin', include files under `/usr/local/include', etc. You
|
||||
can specify an installation prefix other than `/usr/local' by giving
|
||||
`configure' the option `--prefix=PREFIX', where PREFIX must be an
|
||||
absolute file name.
|
||||
|
||||
You can specify separate installation prefixes for
|
||||
architecture-specific files and architecture-independent files. If you
|
||||
pass the option `--exec-prefix=PREFIX' to `configure', the package uses
|
||||
PREFIX as the prefix for installing programs and libraries.
|
||||
Documentation and other data files still use the regular prefix.
|
||||
|
||||
In addition, if you use an unusual directory layout you can give
|
||||
options like `--bindir=DIR' to specify different values for particular
|
||||
kinds of files. Run `configure --help' for a list of the directories
|
||||
you can set and what kinds of files go in them. In general, the
|
||||
default for these options is expressed in terms of `${prefix}', so that
|
||||
specifying just `--prefix' will affect all of the other directory
|
||||
specifications that were not explicitly provided.
|
||||
|
||||
The most portable way to affect installation locations is to pass the
|
||||
correct locations to `configure'; however, many packages provide one or
|
||||
both of the following shortcuts of passing variable assignments to the
|
||||
`make install' command line to change installation locations without
|
||||
having to reconfigure or recompile.
|
||||
|
||||
The first method involves providing an override variable for each
|
||||
affected directory. For example, `make install
|
||||
prefix=/alternate/directory' will choose an alternate location for all
|
||||
directory configuration variables that were expressed in terms of
|
||||
`${prefix}'. Any directories that were specified during `configure',
|
||||
but not in terms of `${prefix}', must each be overridden at install
|
||||
time for the entire installation to be relocated. The approach of
|
||||
makefile variable overrides for each directory variable is required by
|
||||
the GNU Coding Standards, and ideally causes no recompilation.
|
||||
However, some platforms have known limitations with the semantics of
|
||||
shared libraries that end up requiring recompilation when using this
|
||||
method, particularly noticeable in packages that use GNU Libtool.
|
||||
|
||||
The second method involves providing the `DESTDIR' variable. For
|
||||
example, `make install DESTDIR=/alternate/directory' will prepend
|
||||
`/alternate/directory' before all installation names. The approach of
|
||||
`DESTDIR' overrides is not required by the GNU Coding Standards, and
|
||||
does not work on platforms that have drive letters. On the other hand,
|
||||
it does better at avoiding recompilation issues, and works well even
|
||||
when some directory options were not specified in terms of `${prefix}'
|
||||
at `configure' time.
|
||||
|
||||
Optional Features
|
||||
=================
|
||||
|
||||
If the package supports it, you can cause programs to be installed
|
||||
with an extra prefix or suffix on their names by giving `configure' the
|
||||
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
|
||||
|
||||
Some packages pay attention to `--enable-FEATURE' options to
|
||||
`configure', where FEATURE indicates an optional part of the package.
|
||||
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
|
||||
is something like `gnu-as' or `x' (for the X Window System). The
|
||||
`README' should mention any `--enable-' and `--with-' options that the
|
||||
package recognizes.
|
||||
|
||||
For packages that use the X Window System, `configure' can usually
|
||||
find the X include and library files automatically, but if it doesn't,
|
||||
you can use the `configure' options `--x-includes=DIR' and
|
||||
`--x-libraries=DIR' to specify their locations.
|
||||
|
||||
Some packages offer the ability to configure how verbose the
|
||||
execution of `make' will be. For these packages, running `./configure
|
||||
--enable-silent-rules' sets the default to minimal output, which can be
|
||||
overridden with `make V=1'; while running `./configure
|
||||
--disable-silent-rules' sets the default to verbose, which can be
|
||||
overridden with `make V=0'.
|
||||
|
||||
Particular systems
|
||||
==================
|
||||
|
||||
On HP-UX, the default C compiler is not ANSI C compatible. If GNU
|
||||
CC is not installed, it is recommended to use the following options in
|
||||
order to use an ANSI C compiler:
|
||||
|
||||
./configure CC="cc -Ae -D_XOPEN_SOURCE=500"
|
||||
|
||||
and if that doesn't work, install pre-built binaries of GCC for HP-UX.
|
||||
|
||||
HP-UX `make' updates targets which have the same time stamps as
|
||||
their prerequisites, which makes it generally unusable when shipped
|
||||
generated files such as `configure' are involved. Use GNU `make'
|
||||
instead.
|
||||
|
||||
On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot
|
||||
parse its `<wchar.h>' header file. The option `-nodtk' can be used as
|
||||
a workaround. If GNU CC is not installed, it is therefore recommended
|
||||
to try
|
||||
|
||||
./configure CC="cc"
|
||||
|
||||
and if that doesn't work, try
|
||||
|
||||
./configure CC="cc -nodtk"
|
||||
|
||||
On Solaris, don't put `/usr/ucb' early in your `PATH'. This
|
||||
directory contains several dysfunctional programs; working variants of
|
||||
these programs are available in `/usr/bin'. So, if you need `/usr/ucb'
|
||||
in your `PATH', put it _after_ `/usr/bin'.
|
||||
|
||||
On Haiku, software installed for all users goes in `/boot/common',
|
||||
not `/usr/local'. It is recommended to use the following options:
|
||||
|
||||
./configure --prefix=/boot/common
|
||||
|
||||
Specifying the System Type
|
||||
==========================
|
||||
|
||||
There may be some features `configure' cannot figure out
|
||||
automatically, but needs to determine by the type of machine the package
|
||||
will run on. Usually, assuming the package is built to be run on the
|
||||
_same_ architectures, `configure' can figure that out, but if it prints
|
||||
a message saying it cannot guess the machine type, give it the
|
||||
`--build=TYPE' option. TYPE can either be a short name for the system
|
||||
type, such as `sun4', or a canonical name which has the form:
|
||||
|
||||
CPU-COMPANY-SYSTEM
|
||||
|
||||
where SYSTEM can have one of these forms:
|
||||
|
||||
OS
|
||||
KERNEL-OS
|
||||
|
||||
See the file `config.sub' for the possible values of each field. If
|
||||
`config.sub' isn't included in this package, then this package doesn't
|
||||
need to know the machine type.
|
||||
|
||||
If you are _building_ compiler tools for cross-compiling, you should
|
||||
use the option `--target=TYPE' to select the type of system they will
|
||||
produce code for.
|
||||
|
||||
If you want to _use_ a cross compiler, that generates code for a
|
||||
platform different from the build platform, you should specify the
|
||||
"host" platform (i.e., that on which the generated programs will
|
||||
eventually be run) with `--host=TYPE'.
|
||||
|
||||
Sharing Defaults
|
||||
================
|
||||
|
||||
If you want to set default values for `configure' scripts to share,
|
||||
you can create a site shell script called `config.site' that gives
|
||||
default values for variables like `CC', `cache_file', and `prefix'.
|
||||
`configure' looks for `PREFIX/share/config.site' if it exists, then
|
||||
`PREFIX/etc/config.site' if it exists. Or, you can set the
|
||||
`CONFIG_SITE' environment variable to the location of the site script.
|
||||
A warning: not all `configure' scripts look for a site script.
|
||||
|
||||
Defining Variables
|
||||
==================
|
||||
|
||||
Variables not defined in a site shell script can be set in the
|
||||
environment passed to `configure'. However, some packages may run
|
||||
configure again during the build, and the customized values of these
|
||||
variables may be lost. In order to avoid this problem, you should set
|
||||
them in the `configure' command line, using `VAR=value'. For example:
|
||||
|
||||
./configure CC=/usr/local2/bin/gcc
|
||||
|
||||
causes the specified `gcc' to be used as the C compiler (unless it is
|
||||
overridden in the site shell script).
|
||||
|
||||
Unfortunately, this technique does not work for `CONFIG_SHELL' due to
|
||||
an Autoconf bug. Until the bug is fixed you can use this workaround:
|
||||
|
||||
CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash
|
||||
|
||||
`configure' Invocation
|
||||
======================
|
||||
|
||||
`configure' recognizes the following options to control how it
|
||||
operates.
|
||||
|
||||
`--help'
|
||||
`-h'
|
||||
Print a summary of all of the options to `configure', and exit.
|
||||
|
||||
`--help=short'
|
||||
`--help=recursive'
|
||||
Print a summary of the options unique to this package's
|
||||
`configure', and exit. The `short' variant lists options used
|
||||
only in the top level, while the `recursive' variant lists options
|
||||
also present in any nested packages.
|
||||
|
||||
`--version'
|
||||
`-V'
|
||||
Print the version of Autoconf used to generate the `configure'
|
||||
script, and exit.
|
||||
|
||||
`--cache-file=FILE'
|
||||
Enable the cache: use and save the results of the tests in FILE,
|
||||
traditionally `config.cache'. FILE defaults to `/dev/null' to
|
||||
disable caching.
|
||||
|
||||
`--config-cache'
|
||||
`-C'
|
||||
Alias for `--cache-file=config.cache'.
|
||||
|
||||
`--quiet'
|
||||
`--silent'
|
||||
`-q'
|
||||
Do not print messages saying which checks are being made. To
|
||||
suppress all normal output, redirect it to `/dev/null' (any error
|
||||
messages will still be shown).
|
||||
|
||||
`--srcdir=DIR'
|
||||
Look for the package's source code in directory DIR. Usually
|
||||
`configure' can determine that directory automatically.
|
||||
|
||||
`--prefix=DIR'
|
||||
Use DIR as the installation prefix. *note Installation Names::
|
||||
for more details, including other options available for fine-tuning
|
||||
the installation locations.
|
||||
|
||||
`--no-create'
|
||||
`-n'
|
||||
Run the configure checks, but stop before creating any output
|
||||
files.
|
||||
|
||||
`configure' also accepts some other, not widely useful, options. Run
|
||||
`configure --help' for more details.
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
|
||||
AM_CFLAGS = @BUILD_CFLAGS@
|
||||
lib_LTLIBRARIES = libsqlite3.la
|
||||
libsqlite3_la_SOURCES = sqlite3.c
|
||||
libsqlite3_la_LDFLAGS = -no-undefined -version-info 8:6:8
|
||||
|
||||
bin_PROGRAMS = sqlite3
|
||||
sqlite3_SOURCES = shell.c sqlite3.h
|
||||
EXTRA_sqlite3_SOURCES = sqlite3.c
|
||||
sqlite3_LDADD = @EXTRA_SHELL_OBJ@ @READLINE_LIBS@
|
||||
sqlite3_DEPENDENCIES = @EXTRA_SHELL_OBJ@
|
||||
sqlite3_CFLAGS = $(AM_CFLAGS) -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_DQS=0 -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_ENABLE_STMTVTAB -DSQLITE_ENABLE_DBSTAT_VTAB $(SHELL_CFLAGS)
|
||||
|
||||
include_HEADERS = sqlite3.h sqlite3ext.h
|
||||
|
||||
EXTRA_DIST = sqlite3.1 tea Makefile.msc sqlite3.rc sqlite3rc.h README.txt Replace.cs Makefile.fallback
|
||||
pkgconfigdir = ${libdir}/pkgconfig
|
||||
pkgconfig_DATA = sqlite3.pc
|
||||
|
||||
man_MANS = sqlite3.1
|
||||
@@ -0,0 +1,247 @@
|
||||
########################################################################
|
||||
# This is a main makefile for the "autoconf" bundle of SQLite. This is
|
||||
# a trimmed-down version of the canonical makefile, devoid of most
|
||||
# documentation. For the full docs, see /main.mk in the canonical
|
||||
# source tree.
|
||||
#
|
||||
# Maintenance reminders:
|
||||
#
|
||||
# - To keep this working with an out-of-tree build, be sure to prefix
|
||||
# input file names with $(TOP)/ where appropriate (which is most
|
||||
# places).
|
||||
#
|
||||
# - The original/canonical recipes can be found in /main.mk in the
|
||||
# canonical source tree.
|
||||
all:
|
||||
|
||||
TOP = @abs_top_srcdir@
|
||||
|
||||
PACKAGE_VERSION = @PACKAGE_VERSION@
|
||||
|
||||
#
|
||||
# Filename extensions for binaries and libraries
|
||||
#
|
||||
B.exe = @BUILD_EXEEXT@
|
||||
T.exe = @TARGET_EXEEXT@
|
||||
B.dll = @BUILD_DLLEXT@
|
||||
T.dll = @TARGET_DLLEXT@
|
||||
B.lib = @BUILD_LIBEXT@
|
||||
T.lib = @TARGET_LIBEXT@
|
||||
|
||||
#
|
||||
# Autotools-compatibility dirs
|
||||
#
|
||||
prefix = @prefix@
|
||||
datadir = @datadir@
|
||||
mandir = @mandir@
|
||||
includedir = @includedir@
|
||||
exec_prefix = @exec_prefix@
|
||||
bindir = @bindir@
|
||||
libdir = @libdir@
|
||||
|
||||
#
|
||||
# Required binaries
|
||||
#
|
||||
INSTALL = @BIN_INSTALL@
|
||||
AR = @AR@
|
||||
AR.flags = cr
|
||||
CC = @CC@
|
||||
|
||||
|
||||
ENABLE_LIB_SHARED = @ENABLE_LIB_SHARED@
|
||||
ENABLE_LIB_STATIC = @ENABLE_LIB_STATIC@
|
||||
|
||||
CFLAGS = @CFLAGS@ @CPPFLAGS@
|
||||
#
|
||||
# $(LDFLAGS.configure) represents any LDFLAGS=... the client passes to
|
||||
# configure. See main.mk.
|
||||
#
|
||||
LDFLAGS.configure = @LDFLAGS@
|
||||
|
||||
CFLAGS.core = @SH_CFLAGS@
|
||||
LDFLAGS.shlib = @SH_LDFLAGS@
|
||||
LDFLAGS.zlib = @LDFLAGS_ZLIB@
|
||||
LDFLAGS.math = @LDFLAGS_MATH@
|
||||
LDFLAGS.rpath = @LDFLAGS_RPATH@
|
||||
LDFLAGS.pthread = @LDFLAGS_PTHREAD@
|
||||
LDFLAGS.dlopen = @LDFLAGS_DLOPEN@
|
||||
LDFLAGS.readline = @LDFLAGS_READLINE@
|
||||
CFLAGS.readline = @CFLAGS_READLINE@
|
||||
LDFLAGS.icu = @LDFLAGS_ICU@
|
||||
CFLAGS.icu = @CFLAGS_ICU@
|
||||
|
||||
# When cross-compiling, we need to avoid the -s flag because it only
|
||||
# works on the build host's platform.
|
||||
INSTALL.strip.1 = $(INSTALL)
|
||||
INSTALL.strip.0 = $(INSTALL) -s
|
||||
INSTALL.strip = $(INSTALL.strip.@IS_CROSS_COMPILING@)
|
||||
INSTALL.noexec = $(INSTALL) -m 0644
|
||||
|
||||
install-dir.bin = $(DESTDIR)$(bindir)
|
||||
install-dir.lib = $(DESTDIR)$(libdir)
|
||||
install-dir.include = $(DESTDIR)$(includedir)
|
||||
install-dir.pkgconfig = $(DESTDIR)$(libdir)/pkgconfig
|
||||
install-dir.man1 = $(DESTDIR)$(mandir)/man1
|
||||
install-dir.all = $(install-dir.bin) $(install-dir.include) \
|
||||
$(install-dir.lib) $(install-dir.man1) \
|
||||
$(install-dir.pkgconfig)
|
||||
$(install-dir.all):
|
||||
if [ ! -d "$@" ]; then $(INSTALL) -d "$@"; fi
|
||||
# ^^^^ on some platforms, install -d fails if the target already exists.
|
||||
|
||||
|
||||
#
|
||||
# Vars with the AS_ prefix are specifically related to AutoSetup.
|
||||
#
|
||||
# AS_AUTO_DEF is the main configure script.
|
||||
#
|
||||
AS_AUTO_DEF = $(TOP)/auto.def
|
||||
|
||||
#
|
||||
# Shell commands to re-run $(TOP)/configure with the same args it was
|
||||
# invoked with to produce this makefile.
|
||||
#
|
||||
AS_AUTORECONFIG = @SQLITE_AUTORECONFIG@
|
||||
Makefile: $(TOP)/Makefile.in $(AS_AUTO_DEF)
|
||||
$(AS_AUTORECONFIG)
|
||||
@touch $@
|
||||
|
||||
sqlite3.pc: $(TOP)/sqlite3.pc.in $(AS_AUTO_DEF)
|
||||
$(AS_AUTORECONFIG)
|
||||
@touch $@
|
||||
|
||||
sqlite_cfg.h: $(AS_AUTO_DEF)
|
||||
$(AS_AUTORECONFIG)
|
||||
@touch $@
|
||||
|
||||
#
|
||||
# CFLAGS for sqlite3$(T.exe)
|
||||
#
|
||||
SHELL_OPT ?= @OPT_SHELL@
|
||||
|
||||
#
|
||||
# Library-level feature flags
|
||||
#
|
||||
OPT_FEATURE_FLAGS = @OPT_FEATURE_FLAGS@
|
||||
|
||||
LDFLAGS.libsqlite3.soname = @LDFLAGS_LIBSQLITE3_SONAME@
|
||||
# soname: see https://sqlite.org/src/forumpost/5a3b44f510df8ded
|
||||
LDFLAGS.libsqlite3.os-specific = @LDFLAGS_MAC_CVERSION@ @LDFLAGS_OUT_IMPLIB@
|
||||
# os-specific: see
|
||||
# - https://sqlite.org/forum/forumpost/9dfd5b8fd525a5d7
|
||||
# - https://sqlite.org/forum/forumpost/0c7fc097b2
|
||||
|
||||
LDFLAGS.libsqlite3 = \
|
||||
$(LDFLAGS.rpath) $(LDFLAGS.pthread) \
|
||||
$(LDFLAGS.math) $(LDFLAGS.dlopen) \
|
||||
$(LDFLAGS.zlib) $(LDFLAGS.icu) \
|
||||
$(LDFLAGS.configure)
|
||||
CFLAGS.libsqlite3 = -I. $(CFLAGS.core) $(CFLAGS.icu) $(OPT_FEATURE_FLAGS)
|
||||
|
||||
sqlite3.o: $(TOP)/sqlite3.h $(TOP)/sqlite3.c
|
||||
$(CC) -c $(TOP)/sqlite3.c -o $@ $(CFLAGS) $(CFLAGS.libsqlite3)
|
||||
|
||||
libsqlite3.LIB = libsqlite3$(T.lib)
|
||||
libsqlite3.SO = libsqlite3$(T.dll)
|
||||
|
||||
$(libsqlite3.SO): sqlite3.o
|
||||
$(CC) -o $@ sqlite3.o $(LDFLAGS.shlib) \
|
||||
$(LDFLAGS) $(LDFLAGS.libsqlite3) \
|
||||
$(LDFLAGS.libsqlite3.os-specific) $(LDFLAGS.libsqlite3.soname)
|
||||
all: $(libsqlite3.SO)
|
||||
|
||||
$(libsqlite3.LIB): sqlite3.o
|
||||
$(AR) $(AR.flags) $@ sqlite3.o
|
||||
all: $(libsqlite3.LIB)
|
||||
|
||||
install-so-1: $(install-dir.lib) $(libsqlite3.SO)
|
||||
$(INSTALL) $(libsqlite3.SO) "$(install-dir.lib)"
|
||||
@echo "Setting up $(libsqlite3.SO) version symlinks..."; \
|
||||
cd "$(install-dir.lib)" || exit $$?; \
|
||||
if [ x.dylib = x$(T.dll) ]; then \
|
||||
rm -f libsqlite3.0$(T.dll) libsqlite3.$(PACKAGE_VERSION)$(T.dll) || exit $$?; \
|
||||
dllname=libsqlite3.$(PACKAGE_VERSION)$(T.dll); \
|
||||
mv $(libsqlite3.SO) $$dllname || exit $$?; \
|
||||
ln -s $$dllname $(libsqlite3.SO) || exit $$?; \
|
||||
ln -s $$dllname libsqlite3.0$(T.dll) || exit $$?; \
|
||||
ls -la $$dllname $(libsqlite3.SO) libsqlite3.0$(T.dll); \
|
||||
else \
|
||||
rm -f $(libsqlite3.SO).0 $(libsqlite3.SO).$(PACKAGE_VERSION) || exit $$?; \
|
||||
mv $(libsqlite3.SO) $(libsqlite3.SO).$(PACKAGE_VERSION) || exit $$?; \
|
||||
ln -s $(libsqlite3.SO).$(PACKAGE_VERSION) $(libsqlite3.SO) || exit $$?; \
|
||||
ln -s $(libsqlite3.SO).$(PACKAGE_VERSION) $(libsqlite3.SO).0 || exit $$?; \
|
||||
ls -la $(libsqlite3.SO) $(libsqlite3.SO).[03]*; \
|
||||
if [ -e $(libsqlite3.SO).0.8.6 ]; then \
|
||||
echo "ACHTUNG: legacy libtool-compatible install found. Re-linking it..."; \
|
||||
rm -f libsqlite3.la $(libsqlite3.SO).0.8.6 || exit $$?; \
|
||||
ln -s $(libsqlite3.SO).$(PACKAGE_VERSION) $(libsqlite3.SO).0.8.6 || exit $$?; \
|
||||
ls -la $(libsqlite3.SO).0.8.6; \
|
||||
elif [ x1 = "x$(INSTALL_SO_086_LINK)" ]; then \
|
||||
echo "ACHTUNG: installing legacy libtool-style links because INSTALL_SO_086_LINK=1"; \
|
||||
rm -f libsqlite3.la $(libsqlite3.SO).0.8.6 || exit $$?; \
|
||||
ln -s $(libsqlite3.SO).$(PACKAGE_VERSION) $(libsqlite3.SO).0.8.6 || exit $$?; \
|
||||
ls -la $(libsqlite3.SO).0.8.6; \
|
||||
fi; \
|
||||
fi
|
||||
|
||||
install-so-0 install-so-:
|
||||
install-so: install-so-$(ENABLE_LIB_SHARED)
|
||||
install: install-so
|
||||
|
||||
install-lib-1: $(install-dir.lib) $(libsqlite3.LIB)
|
||||
$(INSTALL.noexec) $(libsqlite3.LIB) "$(install-dir.lib)"
|
||||
install-lib-0 install-lib-:
|
||||
install-lib: install-lib-$(ENABLE_LIB_STATIC)
|
||||
install: install-lib
|
||||
|
||||
|
||||
sqlite3$(T.exe): $(TOP)/shell.c $(TOP)/sqlite3.c
|
||||
$(CC) -o $@ \
|
||||
$(TOP)/shell.c $(TOP)/sqlite3.c \
|
||||
-I. $(OPT_FEATURE_FLAGS) $(SHELL_OPT) \
|
||||
$(CFLAGS) $(CFLAGS.readline) $(CFLAGS.icu) \
|
||||
$(LDFLAGS) $(LDFLAGS.libsqlite3) $(LDFLAGS.readline)
|
||||
all: sqlite3$(T.exe)
|
||||
|
||||
install-shell: sqlite3$(T.exe) $(install-dir.bin)
|
||||
$(INSTALL.strip) sqlite3$(T.exe) "$(install-dir.bin)"
|
||||
install: install-shell
|
||||
|
||||
install-headers: $(TOP)/sqlite3.h $(install-dir.include)
|
||||
$(INSTALL.noexec) $(TOP)/sqlite3.h $(TOP)/sqlite3ext.h "$(install-dir.include)"
|
||||
install: install-headers
|
||||
|
||||
install-pc: sqlite3.pc $(install-dir.pkgconfig)
|
||||
$(INSTALL.noexec) sqlite3.pc "$(install-dir.pkgconfig)"
|
||||
install: install-pc
|
||||
|
||||
install-man1: $(TOP)/sqlite3.1 $(install-dir.man1)
|
||||
$(INSTALL.noexec) $(TOP)/sqlite3.1 "$(install-dir.man1)"
|
||||
install: install-man1
|
||||
|
||||
clean:
|
||||
rm -f *.o sqlite3$(T.exe)
|
||||
rm -f $(libsqlite3.LIB) $(libsqlite3.SO) $(libsqlite3.SO).a
|
||||
|
||||
distclean: clean
|
||||
rm -f jimsh0$(T.exe) config.* sqlite3.pc
|
||||
|
||||
DIST_FILES := \
|
||||
README.txt VERSION \
|
||||
auto.def autosetup configure tea \
|
||||
sqlite3.h sqlite3.c shell.c sqlite3ext.h \
|
||||
Makefile.in Makefile.msc Makefile.fallback \
|
||||
sqlite3.rc sqlite3rc.h Replace.cs \
|
||||
sqlite3.pc.in sqlite3.1
|
||||
|
||||
# Maintenance note: dist_name must be sqlite-$(PACKAGE_VERSION) so
|
||||
# that tool/mkautoconfamal.sh knows how to find it.
|
||||
dist_name = sqlite-$(PACKAGE_VERSION)
|
||||
dist_tarball = $(dist_name).tar.gz
|
||||
dist:
|
||||
rm -fr $(dist_name)
|
||||
mkdir -p $(dist_name)
|
||||
cp -rp $(DIST_FILES) $(dist_name)/.
|
||||
tar czf $(dist_tarball) $(dist_name)
|
||||
rm -fr $(dist_name)
|
||||
ls -l $(dist_tarball)
|
||||
+5
-11
@@ -19,7 +19,9 @@ TOP = .
|
||||
|
||||
|
||||
# Optionally set EXTRA_SRC to a list of C files to append to
|
||||
# the generated sqlite3.c.
|
||||
# the generated sqlite3.c. Any sqlite3 extensions added this
|
||||
# way may require manual editing, as described in
|
||||
# https://sqlite.org/forum/forumpost/903f721f3e7c0d25
|
||||
#
|
||||
!IFNDEF EXTRA_SRC
|
||||
EXTRA_SRC =
|
||||
@@ -799,15 +801,6 @@ RCC = $(RCC) -DSQLITE_THREAD_OVERRIDE_LOCK=-1
|
||||
TLIBS =
|
||||
!ENDIF
|
||||
|
||||
# Flags controlling use of the in memory btree implementation
|
||||
#
|
||||
# SQLITE_TEMP_STORE is 0 to force temporary tables to be in a file, 1 to
|
||||
# default to file, 2 to default to memory, and 3 to force temporary
|
||||
# tables to always be in memory.
|
||||
#
|
||||
TCC = $(TCC) -DSQLITE_TEMP_STORE=1
|
||||
RCC = $(RCC) -DSQLITE_TEMP_STORE=1
|
||||
|
||||
# Enable/disable loadable extensions, and other optional features
|
||||
# based on configuration. (-DSQLITE_OMIT*, -DSQLITE_ENABLE*).
|
||||
# The same set of OMIT and ENABLE flags should be passed to the
|
||||
@@ -1094,5 +1087,6 @@ $(LIBRESOBJS): $(TOP)\sqlite3.rc rcver.vc $(SQLITE3H)
|
||||
|
||||
clean:
|
||||
del /Q *.exp *.lo *.ilk *.lib *.obj *.ncb *.pdb *.sdf *.suo 2>NUL
|
||||
del /Q *.bsc *.def *.cod *.da *.bb *.bbg *.vc gmon.out 2>NUL
|
||||
del /Q *.bsc *.cod *.da *.bb *.bbg *.vc gmon.out 2>NUL
|
||||
del /Q sqlite3.def tclsqlite3.def 2>NUL
|
||||
del /Q $(SQLITE3EXE) $(SQLITE3DLL) Replace.exe 2>NUL
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
This directory contains components use to build an autoconf-ready package
|
||||
of the SQLite amalgamation: sqlite-autoconf-30XXXXXX.tar.gz
|
||||
This directory contains components used to build an autoconf-like
|
||||
package of the SQLite amalgamation: sqlite-autoconf-30XXXXXX.tar.gz
|
||||
|
||||
To build the autoconf amalgamation, run from the top-level:
|
||||
To build the autoconf amalgamation, run from the top of the canonical
|
||||
source tree:
|
||||
|
||||
./configure
|
||||
make amalgamation-tarball
|
||||
|
||||
The amalgamation-tarball target (also available in "main.mk") runs the
|
||||
script tool/mkautoconfamal.sh which does the work. Refer to that script
|
||||
for details.
|
||||
The amalgamation-tarball target (available in "main.mk") runs the
|
||||
script tool/mkautoconfamal.sh which does the work. Refer to that
|
||||
script for details.
|
||||
|
||||
+13
-12
@@ -4,7 +4,7 @@ This package contains:
|
||||
* the sqlite3.h and sqlite3ext.h header files that define the C-language
|
||||
interface to the sqlite3.c library file
|
||||
* the shell.c file used to build the sqlite3 command-line shell program
|
||||
* autoconf/automake installation infrastucture for building on POSIX
|
||||
* autoconf-like installation infrastucture for building on POSIX
|
||||
compliant systems
|
||||
* a Makefile.msc, sqlite3.rc, and Replace.cs for building with Microsoft
|
||||
Visual C++ on Windows
|
||||
@@ -19,8 +19,10 @@ using only generic tools and without having to install TCL. The purpose
|
||||
of this package is to provide that capability.
|
||||
|
||||
This package contains a pre-build SQLite amalgamation file "sqlite3.c"
|
||||
(and its associated header file "sqlite3.h"). Because the amalgamation
|
||||
has been pre-built, no TCL is required.
|
||||
(and its associated header file "sqlite3.h"). Because the
|
||||
amalgamation has been pre-built, no TCL is required for the code
|
||||
generate (the configure script itself is written in TCL but it can use
|
||||
the embedded copy of JimTCL).
|
||||
|
||||
REASONS TO USE THE CANONICAL BUILD SYSTEM RATHER THAN THIS PACKAGE
|
||||
==================================================================
|
||||
@@ -47,14 +49,12 @@ SUMMARY OF HOW TO BUILD USING THIS PACKAGE
|
||||
BUILDING ON POSIX
|
||||
=================
|
||||
|
||||
The generic installation instructions for autoconf/automake are found
|
||||
in the INSTALL file.
|
||||
The configure script follows common conventions, making it easy
|
||||
to use for anyone who has configured a software tree before.
|
||||
It supports a number of build-time flags, the full list of which
|
||||
can be seen by running:
|
||||
|
||||
The following SQLite specific boolean options are supported:
|
||||
|
||||
--enable-readline use readline in shell tool [default=yes]
|
||||
--enable-threadsafe build a thread-safe library [default=yes]
|
||||
--enable-dynamic-extensions support loadable extensions [default=yes]
|
||||
./configure --help
|
||||
|
||||
The default value for the CFLAGS variable (options passed to the C
|
||||
compiler) includes debugging symbols in the build, resulting in larger
|
||||
@@ -65,10 +65,11 @@ line like this:
|
||||
|
||||
to produce a smaller installation footprint.
|
||||
|
||||
Other SQLite compilation parameters can also be set using CFLAGS. For
|
||||
Many SQLite compilation parameters can be defined by passing flags
|
||||
to the configure script. Others may be passed on in the CFLAGS. For
|
||||
example:
|
||||
|
||||
$ CFLAGS="-Os -DSQLITE_THREADSAFE=0" ./configure
|
||||
$ CFLAGS="-Os -DSQLITE_OMIT_DEPRECATED" ./configure
|
||||
|
||||
|
||||
BUILDING WITH MICROSOFT VISUAL C++
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
#/do/not/tclsh
|
||||
# ^^^ help out editors which guess this file's content type.
|
||||
#
|
||||
# This is the main autosetup-compatible configure script for the
|
||||
# "autoconf" bundle of the SQLite project.
|
||||
#
|
||||
# This script must be kept compatible with JimTCL, a copy of which is
|
||||
# included in this source tree as ./autosetup/jimsh0.c.
|
||||
#
|
||||
use sqlite-config
|
||||
|
||||
options {
|
||||
# <build-modes>
|
||||
static=1 => {Disable build of static library}
|
||||
shared=1 => {Disable build of shared library}
|
||||
# </build-modes>
|
||||
# <lib-feature>
|
||||
threadsafe=1 => {Disable mutexing}
|
||||
with-tempstore:=no => {Use an in-RAM database for temporary tables: never,no,yes,always}
|
||||
load-extension=1 => {Disable loading of external extensions}
|
||||
math=1 => {Disable math functions}
|
||||
json=1 => {Disable JSON functions}
|
||||
memsys5 => {Enable MEMSYS5}
|
||||
memsys3 => {Enable MEMSYS3}
|
||||
fts3 => {Enable the FTS3 extension}
|
||||
fts4 => {Enable the FTS4 extension}
|
||||
fts5 => {Enable the FTS5 extension}
|
||||
update-limit => {Enable the UPDATE/DELETE LIMIT clause}
|
||||
geopoly => {Enable the GEOPOLY extension}
|
||||
rtree => {Enable the RTREE extension}
|
||||
session => {Enable the SESSION extension}
|
||||
all => {Enable FTS4, FTS5, Geopoly, RTree, Sessions}
|
||||
# </lib-feature>
|
||||
# <line-editing>
|
||||
readline=1 => {Disable readline support}
|
||||
# --with-readline-lib is a backwards-compatible alias for
|
||||
# --with-readline-ldflags
|
||||
with-readline-lib:
|
||||
with-readline-ldflags:=auto
|
||||
=> {Readline LDFLAGS, e.g. -lreadline -lncurses}
|
||||
# --with-readline-inc is a backwards-compatible alias for
|
||||
# --with-readline-cflags.
|
||||
with-readline-inc:
|
||||
with-readline-cflags:=auto
|
||||
=> {Readline CFLAGS, e.g. -I/path/to/includes}
|
||||
with-readline-header:PATH
|
||||
=> {Full path to readline.h, from which --with-readline-cflags will be derived}
|
||||
with-linenoise:DIR => {Source directory for linenoise.c and linenoise.h}
|
||||
editline=0 => {Enable BSD editline support}
|
||||
# </line-editing>
|
||||
# <icu>
|
||||
with-icu-ldflags:LDFLAGS
|
||||
=> {Enable SQLITE_ENABLE_ICU and add the given linker flags for the ICU libraries}
|
||||
with-icu-cflags:CFLAGS
|
||||
=> {Apply extra CFLAGS/CPPFLAGS necessary for building with ICU. e.g. -I/usr/local/include}
|
||||
with-icu-config:=auto => {Enable SQLITE_ENABLE_ICU. Value must be one of: auto, pkg-config, /path/to/icu-config}
|
||||
icu-collations=0 => {Enable SQLITE_ENABLE_ICU_COLLATIONS. Requires --with-icu-ldflags=... or --with-icu-config}
|
||||
# </icu>
|
||||
# <developer>
|
||||
# Note that using the --debug/--enable-debug flag here requires patching
|
||||
# autosetup/autosetup to rename the --debug to --autosetup-debug.
|
||||
with-debug=0
|
||||
debug=0 =>
|
||||
{Enable debug build flags. This option will impact performance by
|
||||
as much as 4x, as it includes large numbers of assert()s in
|
||||
performance-critical loops. Never use --debug for production
|
||||
builds.}
|
||||
# </developer>
|
||||
soname:=legacy =>
|
||||
# --soname has a long story behind it: https://sqlite.org/src/forumpost/5a3b44f510df8ded
|
||||
{SONAME for libsqlite3.so. "none", or not using this flag, sets no
|
||||
soname. "legacy" sets it to its historical value of
|
||||
libsqlite3.so.0. A value matching the glob "libsqlite3.*" sets
|
||||
it to that literal value. Any other value is assumed to be a
|
||||
suffix which gets applied to "libsqlite3.so.",
|
||||
e.g. --soname=9.10 equates to "libsqlite3.so.9.10".
|
||||
}
|
||||
}
|
||||
|
||||
sqlite-post-options-init
|
||||
sqlite-check-common-bins
|
||||
sqlite-check-common-system-deps
|
||||
proj-check-rpath
|
||||
sqlite-handle-soname
|
||||
sqlite-setup-default-cflags
|
||||
sqlite-handle-debug
|
||||
sqlite-handle-threadsafe
|
||||
sqlite-handle-tempstore
|
||||
sqlite-handle-line-editing
|
||||
sqlite-handle-load-extension
|
||||
sqlite-handle-math
|
||||
sqlite-handle-icu
|
||||
|
||||
define ENABLE_LIB_SHARED [opt-bool shared]
|
||||
define ENABLE_LIB_STATIC [opt-bool static]
|
||||
|
||||
sqlite-common-late-stage-config
|
||||
@@ -1,270 +0,0 @@
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Supports the following non-standard switches.
|
||||
#
|
||||
# --enable-threadsafe
|
||||
# --enable-readline
|
||||
# --enable-editline
|
||||
# --enable-static-shell
|
||||
# --enable-dynamic-extensions
|
||||
#
|
||||
|
||||
AC_PREREQ(2.61)
|
||||
AC_INIT(sqlite, --SQLITE-VERSION--, http://www.sqlite.org)
|
||||
AC_CONFIG_SRCDIR([sqlite3.c])
|
||||
AC_CONFIG_AUX_DIR([.])
|
||||
|
||||
# Use automake.
|
||||
AM_INIT_AUTOMAKE([foreign])
|
||||
|
||||
AC_SYS_LARGEFILE
|
||||
|
||||
# Check for required programs.
|
||||
AC_PROG_CC
|
||||
AC_PROG_LIBTOOL
|
||||
AC_PROG_MKDIR_P
|
||||
|
||||
# Check for library functions that SQLite can optionally use.
|
||||
AC_CHECK_FUNCS([fdatasync usleep fullfsync localtime_r gmtime_r])
|
||||
AC_FUNC_STRERROR_R
|
||||
|
||||
AC_CONFIG_FILES([Makefile sqlite3.pc])
|
||||
BUILD_CFLAGS=
|
||||
AC_SUBST(BUILD_CFLAGS)
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Two options to enable readline compatible libraries:
|
||||
#
|
||||
# --enable-editline
|
||||
# --enable-readline
|
||||
#
|
||||
# Both are enabled by default. If, after command line processing both are
|
||||
# still enabled, the script searches for editline first and automatically
|
||||
# disables readline if it is found. So, to use readline explicitly, the
|
||||
# user must pass "--disable-editline". To disable command line editing
|
||||
# support altogether, "--disable-editline --disable-readline".
|
||||
#
|
||||
# When searching for either library, check for headers before libraries
|
||||
# as some distros supply packages that contain libraries but not header
|
||||
# files, which come as a separate development package.
|
||||
#
|
||||
AC_ARG_ENABLE(editline, [AS_HELP_STRING([--enable-editline],[use BSD libedit])])
|
||||
AC_ARG_ENABLE(readline, [AS_HELP_STRING([--enable-readline],[use readline])])
|
||||
|
||||
AS_IF([ test x"$enable_editline" != xno ],[
|
||||
AC_CHECK_HEADERS([editline/readline.h],[
|
||||
sLIBS=$LIBS
|
||||
LIBS=""
|
||||
AC_SEARCH_LIBS([readline],[edit],[
|
||||
AC_DEFINE([HAVE_EDITLINE],1,Define to use BSD editline)
|
||||
READLINE_LIBS="$LIBS -ltinfo"
|
||||
enable_readline=no
|
||||
],[],[-ltinfo])
|
||||
AS_UNSET(ac_cv_search_readline)
|
||||
LIBS=$sLIBS
|
||||
])
|
||||
])
|
||||
|
||||
AS_IF([ test x"$enable_readline" != xno ],[
|
||||
AC_CHECK_HEADERS([readline/readline.h],[
|
||||
sLIBS=$LIBS
|
||||
LIBS=""
|
||||
AC_SEARCH_LIBS(tgetent, termcap curses ncurses ncursesw, [], [])
|
||||
AC_SEARCH_LIBS(readline,[readline edit], [
|
||||
AC_DEFINE([HAVE_READLINE],1,Define to use readline or wrapper)
|
||||
READLINE_LIBS=$LIBS
|
||||
])
|
||||
LIBS=$sLIBS
|
||||
])
|
||||
])
|
||||
|
||||
AC_SUBST(READLINE_LIBS)
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# --enable-threadsafe
|
||||
#
|
||||
AC_ARG_ENABLE(threadsafe, [AS_HELP_STRING(
|
||||
[--enable-threadsafe], [build a thread-safe library [default=yes]])],
|
||||
[], [enable_threadsafe=yes])
|
||||
if test x"$enable_threadsafe" == "xno"; then
|
||||
BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_THREADSAFE=0"
|
||||
else
|
||||
BUILD_CFLAGS="$BUILD_CFLAGS -D_REENTRANT=1 -DSQLITE_THREADSAFE=1"
|
||||
AC_SEARCH_LIBS(pthread_create, pthread)
|
||||
AC_SEARCH_LIBS(pthread_mutexattr_init, pthread)
|
||||
fi
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# --enable-dynamic-extensions
|
||||
#
|
||||
AC_ARG_ENABLE(dynamic-extensions, [AS_HELP_STRING(
|
||||
[--enable-dynamic-extensions], [support loadable extensions [default=yes]])],
|
||||
[], [enable_dynamic_extensions=yes])
|
||||
if test x"$enable_dynamic_extensions" != "xno"; then
|
||||
AC_SEARCH_LIBS(dlopen, dl)
|
||||
else
|
||||
BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_OMIT_LOAD_EXTENSION=1"
|
||||
fi
|
||||
AC_MSG_CHECKING([for whether to support dynamic extensions])
|
||||
AC_MSG_RESULT($enable_dynamic_extensions)
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# --enable-math
|
||||
#
|
||||
AC_ARG_ENABLE(math, [AS_HELP_STRING(
|
||||
[--enable-math], [SQL math functions [default=yes]])],
|
||||
[], [enable_math=yes])
|
||||
AC_MSG_CHECKING([SQL math functions])
|
||||
if test x"$enable_math" = "xyes"; then
|
||||
BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_ENABLE_MATH_FUNCTIONS"
|
||||
AC_MSG_RESULT([enabled])
|
||||
AC_SEARCH_LIBS(ceil, m)
|
||||
else
|
||||
AC_MSG_RESULT([disabled])
|
||||
fi
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# --enable-fts4
|
||||
#
|
||||
AC_ARG_ENABLE(fts4, [AS_HELP_STRING(
|
||||
[--enable-fts4], [include fts4 support [default=yes]])],
|
||||
[], [enable_fts4=yes])
|
||||
AC_MSG_CHECKING([FTS4 extension])
|
||||
if test x"$enable_fts4" = "xyes"; then
|
||||
BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_ENABLE_FTS4"
|
||||
AC_MSG_RESULT([enabled])
|
||||
else
|
||||
AC_MSG_RESULT([disabled])
|
||||
fi
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# --enable-fts3
|
||||
#
|
||||
AC_ARG_ENABLE(fts3, [AS_HELP_STRING(
|
||||
[--enable-fts3], [include fts3 support [default=no]])],
|
||||
[], [])
|
||||
AC_MSG_CHECKING([FTS3 extension])
|
||||
if test x"$enable_fts3" = "xyes" -a x"$enable_fts4" = "xno"; then
|
||||
BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_ENABLE_FTS3"
|
||||
AC_MSG_RESULT([enabled])
|
||||
else
|
||||
AC_MSG_RESULT([disabled])
|
||||
fi
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# --enable-fts5
|
||||
#
|
||||
AC_ARG_ENABLE(fts5, [AS_HELP_STRING(
|
||||
[--enable-fts5], [include fts5 support [default=yes]])],
|
||||
[], [enable_fts5=yes])
|
||||
AC_MSG_CHECKING([FTS5 extension])
|
||||
if test x"$enable_fts5" = "xyes"; then
|
||||
AC_MSG_RESULT([enabled])
|
||||
AC_SEARCH_LIBS(log, m)
|
||||
BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_ENABLE_FTS5"
|
||||
else
|
||||
AC_MSG_RESULT([disabled])
|
||||
fi
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# --enable-rtree
|
||||
#
|
||||
AC_ARG_ENABLE(rtree, [AS_HELP_STRING(
|
||||
[--enable-rtree], [include rtree support [default=yes]])],
|
||||
[], [enable_rtree=yes])
|
||||
AC_MSG_CHECKING([RTREE extension])
|
||||
if test x"$enable_rtree" = "xyes"; then
|
||||
BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_ENABLE_RTREE -DSQLITE_ENABLE_GEOPOLY"
|
||||
AC_MSG_RESULT([enabled])
|
||||
else
|
||||
AC_MSG_RESULT([disabled])
|
||||
fi
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# --enable-session
|
||||
#
|
||||
AC_ARG_ENABLE(session, [AS_HELP_STRING(
|
||||
[--enable-session], [enable the session extension [default=no]])],
|
||||
[], [])
|
||||
AC_MSG_CHECKING([Session extension])
|
||||
if test x"$enable_session" = "xyes"; then
|
||||
BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_ENABLE_SESSION -DSQLITE_ENABLE_PREUPDATE_HOOK"
|
||||
AC_MSG_RESULT([enabled])
|
||||
else
|
||||
AC_MSG_RESULT([disabled])
|
||||
fi
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# --enable-debug
|
||||
#
|
||||
AC_ARG_ENABLE(debug, [AS_HELP_STRING(
|
||||
[--enable-debug], [build with debugging features enabled [default=no]])],
|
||||
[], [])
|
||||
AC_MSG_CHECKING([Build type])
|
||||
if test x"$enable_debug" = "xyes"; then
|
||||
BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_DEBUG -DSQLITE_ENABLE_SELECTTRACE -DSQLITE_ENABLE_WHERETRACE"
|
||||
CFLAGS="-g -O0"
|
||||
AC_MSG_RESULT([debug])
|
||||
else
|
||||
AC_MSG_RESULT([release])
|
||||
fi
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# --enable-static-shell
|
||||
#
|
||||
AC_ARG_ENABLE(static-shell, [AS_HELP_STRING(
|
||||
[--enable-static-shell],
|
||||
[statically link libsqlite3 into shell tool [default=yes]])],
|
||||
[], [enable_static_shell=yes])
|
||||
if test x"$enable_static_shell" = "xyes"; then
|
||||
EXTRA_SHELL_OBJ=sqlite3-sqlite3.$OBJEXT
|
||||
else
|
||||
EXTRA_SHELL_OBJ=libsqlite3.la
|
||||
fi
|
||||
AC_SUBST(EXTRA_SHELL_OBJ)
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
AC_CHECK_FUNCS(posix_fallocate)
|
||||
AC_CHECK_HEADERS(zlib.h,[
|
||||
AC_SEARCH_LIBS(deflate,z,[BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_HAVE_ZLIB"])
|
||||
])
|
||||
|
||||
AC_SEARCH_LIBS(system,,,[SHELL_CFLAGS="-DSQLITE_NOHAVE_SYSTEM"])
|
||||
AC_SUBST(SHELL_CFLAGS)
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# UPDATE: Maybe it's better if users just set CFLAGS before invoking
|
||||
# configure. This option doesn't really add much...
|
||||
#
|
||||
# --enable-tempstore
|
||||
#
|
||||
# AC_ARG_ENABLE(tempstore, [AS_HELP_STRING(
|
||||
# [--enable-tempstore],
|
||||
# [in-memory temporary tables (never, no, yes, always) [default=no]])],
|
||||
# [], [enable_tempstore=no])
|
||||
# AC_MSG_CHECKING([for whether or not to store temp tables in-memory])
|
||||
# case "$enable_tempstore" in
|
||||
# never ) TEMP_STORE=0 ;;
|
||||
# no ) TEMP_STORE=1 ;;
|
||||
# always ) TEMP_STORE=3 ;;
|
||||
# yes ) TEMP_STORE=3 ;;
|
||||
# * )
|
||||
# TEMP_STORE=1
|
||||
# enable_tempstore=yes
|
||||
# ;;
|
||||
# esac
|
||||
# AC_MSG_RESULT($enable_tempstore)
|
||||
# AC_SUBST(TEMP_STORE)
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
AC_OUTPUT
|
||||
@@ -19,7 +19,7 @@ dnl to configure the system for the local environment.
|
||||
# so that we create the export library with the dll.
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
AC_INIT([sqlite],[3.48.0])
|
||||
AC_INIT([sqlite],[3.50.0])
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# Call TEA_INIT as the first TEA_ macro to set up initial vars.
|
||||
|
||||
@@ -0,0 +1,380 @@
|
||||
Maintaining Autosetup in the SQLite Tree
|
||||
========================================================================
|
||||
|
||||
This document provides some tips and reminders for the SQLite
|
||||
developers regarding using and maintaining the [Autosetup][]-based
|
||||
build infrastructure. It is not an [Autosetup][] reference.
|
||||
|
||||
**Table of Contents**:
|
||||
|
||||
- [Autosetup API Reference](#apiref)
|
||||
- [API Tips](#apitips)
|
||||
- [Ensuring TCL Compatibility](#tclcompat)
|
||||
- [Design Conventions](#conventions)
|
||||
- Symbolic Names of Feature Flags
|
||||
- Do Not Update Global Shared State
|
||||
- [Updating Autosetup](#updating)
|
||||
- [Patching Autosetup for Project-local changes](#patching)
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
<a name="apiref"></a>
|
||||
Autosetup API Reference
|
||||
========================================================================
|
||||
|
||||
The Autosetup API is quite extensive and can be read either in
|
||||
the [files in the `autosetup` dir](/dir/autosetup) or using:
|
||||
|
||||
>
|
||||
```
|
||||
$ ./configure --reference | less
|
||||
```
|
||||
|
||||
That will include any docs from any TCL files in the `./autosetup` dir
|
||||
which contain certain (simple) markup defined by autosetup.
|
||||
|
||||
This project's own configuration-related TCL code is spread across the
|
||||
following files:
|
||||
|
||||
- [proj.tcl][]: project-agnostic utility code for autosetup-driven
|
||||
projects. This file is designed to be shared between this project,
|
||||
other projects managed under the SQLite/Hwaci umbrella
|
||||
(e.g. Fossil), and personal projects of SQLite's developers. It is
|
||||
essentially an amalgamation of a decade's worth of autosetup-related
|
||||
utility code.
|
||||
- [auto.def][]: the primary driver for the `./configure` process.
|
||||
When we talk about "the configure script," we're referring to
|
||||
this file.
|
||||
- [sqlite-config.tcl][]: utility code which is too project-specific
|
||||
for `proj.tcl`. We split this out of `auto.def` so that it can be
|
||||
used by both `auto.def` and...
|
||||
- [autoconf/auto.def][]: the main driver script for the "autoconf"
|
||||
bundle's configure script. It is essentially a slightly trimmed-down
|
||||
version of the main `auto.def` file. The `autoconf` dir was ported
|
||||
from the Autotools to Autosetup in the 3.49.0 dev cycle but retains
|
||||
the "autoconf" name to minimize downstream disruption.
|
||||
|
||||
|
||||
<a name="apitips"></a>
|
||||
Autosetup API Tips
|
||||
========================================================================
|
||||
|
||||
This section briefly covers only APIs which are frequently useful in
|
||||
day-to-day maintenance and might not be immediately recognized as such
|
||||
obvious from a casual perusal of the relevant TCL files. The complete
|
||||
docs of those with `proj-` prefix can be found in [proj.tcl][] and
|
||||
those with an `sqlite-` prefix are in [sqlite-config.tcl][]. The
|
||||
others are scattered around [the TCL files in
|
||||
./autosetup](/dir/autosetup).
|
||||
|
||||
In (mostly) alphabetical order:
|
||||
|
||||
- **`file-isexec filename`**\
|
||||
Should be used in place of `[file executable]`, as it will also
|
||||
check for `${filename}.exe` on Windows platforms. However, on such
|
||||
platforms it also assumes that _any_ existing file is executable.
|
||||
|
||||
- **`get-env VAR ?default?`**\
|
||||
Will fetch an "environment variable" from the first of either: (1) a
|
||||
KEY=VALUE passed to the configure script or (2) the system's
|
||||
environment variables. Not to be confused with `getenv`, which only
|
||||
does the latter and is rarely, if ever, useful in this tree.
|
||||
- **`proj-get-env VAR ?default?`**\
|
||||
Works like `get-env` but will, if that function finds no match,
|
||||
look for a file named `./.env-$VAR` and, if found, return its
|
||||
trimmed contents. This can be used, e.g., to set a developer's
|
||||
local preferences for the default `CFLAGS`.
|
||||
|
||||
- **`define-for-opt flag defineName ?checkingMsg? ?yesVal=1? ?noVal=0?`**\
|
||||
`[define $defineName]` to either `$yesVal` or `$noVal`, depending on
|
||||
whether `--$flag` is truthy or not. `$checkingMsg` is a
|
||||
human-readable description of the check being made, e.g. "enable foo?"
|
||||
If no `checkingMsg` is provided, the operation is silent.\
|
||||
Potential TODO: change the final two args to `-yes` and `-no`
|
||||
flags. They're rarely needed, though: search [auto.def][] for
|
||||
`TSTRNNR_OPTS` for an example of where they are used.
|
||||
|
||||
- **`proj-fatal msg`**\
|
||||
Emits `$msg` to stderr and exits with non-zero.
|
||||
|
||||
- **`proj-if-opt-truthy flag thenScript ?elseScript?`**\
|
||||
Evals `thenScript` if the given `--flag` is truthy, else it
|
||||
evals the optional `elseScript`.
|
||||
|
||||
- **`proj-indented-notice ?-error? ?-notice? msg`**\
|
||||
Breaks its `msg` argument into lines, trims them, and emits them
|
||||
with consistent indentation. Exactly how it emits depends on the
|
||||
flags passed to it (or not), as covered in its docs. This will stick
|
||||
out starkly from normal output and is intended to be used only for
|
||||
important notices.
|
||||
|
||||
- **`proj-opt-truthy flag`**\
|
||||
Returns 1 if `--flag`'s value is "truthy," i.e. one of (1, on,
|
||||
enabled, yes, true).
|
||||
|
||||
- **`proj-opt-was-provided FLAG`**\
|
||||
Returns 1 if `--FLAG` was explicitly provided to configure,
|
||||
else 0. This distinction can be used to determine, e.g., whether
|
||||
`--with-readline` was provided or whether we're searching for
|
||||
readline by default. In the former case, failure to find it should
|
||||
be treated as fatal, where in the latter case it's not.
|
||||
|
||||
- **`proj-val-truthy value`**\
|
||||
Returns 1 if `$value` is "truthy," See `proj-opt-truthy` for the definition
|
||||
of "truthy."
|
||||
|
||||
- **`proj-warn msg`**\
|
||||
Emits `$msg` to stderr. Closely-related is autosetup's `user-notice`
|
||||
(described below).
|
||||
|
||||
- **`sqlite-add-feature-flag ?-shell? FLAG...`**\
|
||||
Adds the given feature flag to the CFLAGS which are specific to
|
||||
building libsqlite3. It's intended to be passed one or more
|
||||
`-DSQLITE_ENABLE_...`, or similar, flags. If the `-shell` flag is
|
||||
used then it also passes its arguments to
|
||||
`sqlite-add-shell-opt`. This is a no-op if `FLAG` is not provided or
|
||||
is empty.
|
||||
|
||||
- **`sqlite-add-shell-opt FLAG...`**\
|
||||
The shell-specific counterpart of `sqlite-add-feature-flag` which
|
||||
only adds the given flag(s) to the CLI-shell-specific CFLAGS.
|
||||
|
||||
- **`user-notice msg`**\
|
||||
Queues `$msg` to be sent to stderr, but does not emit it until
|
||||
either `show-notices` is called or the next time autosetup would
|
||||
output something (it internally calls `show-notices`). This can be
|
||||
used to generate warnings between a "checking for..." message and
|
||||
its resulting "yes/no/whatever" message in such a way as to not
|
||||
spoil the layout of such messages.
|
||||
|
||||
|
||||
<a name="tclcompat"></a>
|
||||
Ensuring TCL Compatibility
|
||||
========================================================================
|
||||
|
||||
It is important that any TCL files used by the configure process
|
||||
remain compatible with both [JimTCL][] and the canonical TCL. Though
|
||||
JimTCL has outstanding compatibility with canonical TCL, it does have
|
||||
a few corners with incompatibilities, e.g. regular expressions. If a
|
||||
script runs in JimTCL without using any JimTCL-specific features, then
|
||||
it's a certainty that it will run in canonical TCL as well. The
|
||||
opposite, however, is not _always_ the case.
|
||||
|
||||
When [`./configure`](/file/configure) is run, it goes through a
|
||||
bootstrapping process to find a suitable TCL with which to run the
|
||||
autosetup framework. The first step involves [finding or building a
|
||||
TCL shell](/file/autosetup/autosetup-find-tclsh). That will first
|
||||
search for an available `tclsh` (under several common names,
|
||||
e.g. `tclsh8.6`) before falling back to compiling the copy of
|
||||
`jimsh0.c` included in the source tree. i.e. it will prefer to use a
|
||||
system-installed TCL for running the configure script. Once it finds
|
||||
(or builds) a TCL shell, it then runs [a sanity test to ensure that
|
||||
the shell is suitable](/file/autosetup/autosetup-test-tclsh) before
|
||||
using it to run the main autosetup app.
|
||||
|
||||
There are two simple ways to ensure that running of the configure
|
||||
process uses JimTCL instead of the canonical `tclsh`, and either
|
||||
approach provides equally high assurances about configure script
|
||||
compatibility across TCL implementations:
|
||||
|
||||
1. Build on a system with no `tclsh` installed in the `$PATH`. In that
|
||||
case, the configure process will fall back to building the in-tree
|
||||
copy of JimTCL.
|
||||
|
||||
2. Manually build `./jimsh0` in the top of the checkout with:\
|
||||
`cc -o jimsh0 autosetup/jimsh0.c`\
|
||||
With that in place, the configure script will prefer to use that
|
||||
before looking for a system-level `tclsh`. Be aware, though, that
|
||||
`make distclean` will remove that file.
|
||||
|
||||
**Note that `jimsh0` is distinctly different from the `jimsh`** which
|
||||
gets built for code-generation purposes. The latter requires
|
||||
non-default build flags to enable features which are
|
||||
platform-dependent, most notably to make its `[file normalize]` work.
|
||||
This means, for example, that the configure script and its utility
|
||||
APIs must not use `[file normalize]`, but autosetup provides a
|
||||
TCL-only implementation of `[file-normalize]` (note the dash) for
|
||||
portable use in the configure script.
|
||||
|
||||
Known TCL Incompatibilities
|
||||
------------------------------------------------------------------------
|
||||
|
||||
A summary of known incompatibilities in JimTCL
|
||||
|
||||
- **CRNL line endings**: prior to 2025-02-05 `fconfigure -translation ...`
|
||||
was a no-op in JimTCL, and it emits CRNL line endings by default on
|
||||
Windows. Since then, it supports `-translation binary`, which is
|
||||
close enough to `-translation lf` for our purposes. When working
|
||||
with files using the `open` command, it is important to use mode
|
||||
`"rb"` or `"wb"`, as appropriate, so that the output does not get
|
||||
CRNL-mangled on Windows.
|
||||
|
||||
- **`file copy`** does not support multiple source files. See
|
||||
[](/info/61f18c96183867fe) for a workaround.
|
||||
|
||||
- **Regular expressions**:
|
||||
|
||||
- Patterns treat `\nnn` octal values as back-references (which it
|
||||
does not support). Those can be reformulated as demonstrated in
|
||||
[](/info/aeac23359bb681c0).
|
||||
|
||||
- `regsub` does not support the `\y` flag. A workaround is demonstrated
|
||||
in [](/info/c2e5dd791cce3ec4).
|
||||
|
||||
<a name="conventions"></a>
|
||||
Design Conventions
|
||||
========================================================================
|
||||
|
||||
This section describes the motivations for the most glaring of the
|
||||
build's design decisions, in particular how they deviate from
|
||||
historical, or even widely-conventional, practices.
|
||||
|
||||
Symbolic Names of Feature Flags
|
||||
------------------------------------------------------------------------
|
||||
|
||||
Historically, the project's makefile has exclusively used
|
||||
`UPPER_UNDERSCORE` form for makefile variables. This build, however,
|
||||
primarily uses `X.y` format, where `X` is often a category label,
|
||||
e.g. `CFLAGS`, and `y` is the specific instance of that category,
|
||||
e.g. `CFLAGS.readline`.
|
||||
|
||||
When the configure script exports flags for consumption by filtered
|
||||
files, e.g. [Makefile.in][] and the generated
|
||||
`sqlite_cfg.h`, it does so in the more conventional `X_Y` form because
|
||||
those flags get exported as as C `#define`s to `sqlite_cfg.h`, where
|
||||
dots are not permitted.
|
||||
|
||||
The `X.y` convention is used in the makefiles primarily because the
|
||||
person who did the initial port finds that considerably easier on the
|
||||
eyes and fingers. In practice, the `X_Y` form of such exports is used
|
||||
exactly once in [Makefile.in][], where it's translated into into `X.y`
|
||||
form for consumption by [Makefile.in][] and [main.mk][]. For example:
|
||||
|
||||
>
|
||||
```
|
||||
LDFLAGS.shobj = @SHOBJ_LDFLAGS@
|
||||
LDFLAGS.zlib = @LDFLAGS_ZLIB@
|
||||
LDFLAGS.math = @LDFLAGS_MATH@
|
||||
```
|
||||
|
||||
(That first one is defined by autosetup, and thus applies "LDFLAGS" as
|
||||
the suffix rather than the prefix. Which is more legible is a matter
|
||||
of taste, for which there is no accounting.)
|
||||
|
||||
|
||||
Do Not Update Global Shared State
|
||||
------------------------------------------------------------------------
|
||||
|
||||
In both the legacy Autotools-driven build and in common Autosetup
|
||||
usage, feature tests performed by the configure script may amend
|
||||
global flags such as `LIBS`, `LDFLAGS`, and `CFLAGS`[^as-cflags]. That's
|
||||
appropriate for a makefile which builds a single deliverable, but less
|
||||
so for makefiles which produce multiple deliverables. Drawbacks of
|
||||
that approach include:
|
||||
|
||||
- It's unlikely that every single deliverable will require the same
|
||||
core set of those flags.
|
||||
- It can be difficult to determine the origin of any given change to
|
||||
that global state because those changes are hidden behind voodoo performed
|
||||
outside the immediate visibility of the configure script's
|
||||
maintainer.
|
||||
- It can force the maintainers of the configure script to place tests
|
||||
in a specific order so that the resulting flags get applied at
|
||||
the correct time and/or in the correct order.\
|
||||
(A real-life example: before the approach described below was taken
|
||||
to collecting build-time flags, the test for `-rpath` had to come
|
||||
_after_ the test for zlib because the results of the `-rpath` test
|
||||
implicitly modified global state which broke the zlib feature
|
||||
test. Because the feature tests no longer (intentionally) modify
|
||||
shared global state, that is not an issue.)
|
||||
|
||||
In this build, cases where feature tests modify global state in such a
|
||||
way that it may impact later feature tests are either (A) very
|
||||
intentionally defined to do so (e.g. the `--with-wasi-sdk` flag has
|
||||
invasive side-effects) or (B) are oversights (i.e. bugs).
|
||||
|
||||
This tree's [configure script][auto.def], [utility APIs][proj.tcl],
|
||||
[Makefile.in][], and [main.mk][] therefore strive to separate the
|
||||
results of any given feature test into its own well-defined
|
||||
variables. For example:
|
||||
|
||||
- The linker flags for zlib are exported from the configure script as
|
||||
`LDFLAGS_ZLIB`, which [Makefile.in][] and [main.mk][] then expose as
|
||||
`LDFLAGS.zlib`.
|
||||
- `CFLAGS_READLINE` (a.k.a. `CFLAGS.readline`) contains the `CFLAGS`
|
||||
needed for including `libreadline`, `libedit`, or `linenoise`, and
|
||||
`LDFLAGS_READLINE` (a.k.a. `LDFLAGS.readline`) is its link-time
|
||||
counterpart.
|
||||
|
||||
It is then up to the Makefile to apply and order the flags however is
|
||||
appropriate.
|
||||
|
||||
At the end of the configure script, the global `CFLAGS` _ideally_
|
||||
holds only flags which are either relevant to all targets or, failing
|
||||
that, will have no unintended side-effects on any targets. That said:
|
||||
clients frequently pass custom `CFLAGS` to `./configure` or `make` to
|
||||
set library-level feature toggles, e.g. `-DSQLITE_OMIT_FOO`, in which
|
||||
case there is no practical way to avoid "polluting" the builds of
|
||||
arbitrary makefile targets with those. _C'est la vie._
|
||||
|
||||
|
||||
[^as-cflags]: But see this article for a detailed discussion of how
|
||||
autosetup currently deals specifically with CFLAGS:
|
||||
<https://msteveb.github.io/autosetup/articles/handling-cflags/>
|
||||
|
||||
|
||||
<a name="updating"></a>
|
||||
Updating Autosetup
|
||||
========================================================================
|
||||
|
||||
Updating autosetup is, more often than not, painless. It requires having
|
||||
a checked-out copy of [the autosetup git repository][autosetup-git]:
|
||||
|
||||
>
|
||||
```
|
||||
$ git clone https://github.com/msteveb/autosetup
|
||||
$ cd autosetup
|
||||
# Or, if it's already checked out:
|
||||
$ git pull
|
||||
```
|
||||
|
||||
Then, from the top-most directory of an SQLite checkout:
|
||||
|
||||
>
|
||||
```
|
||||
$ /path/to/autosetup-checkout/autosetup --install .
|
||||
$ fossil status # show the modified files
|
||||
```
|
||||
|
||||
Unless the upgrade made any incompatible changes (which is exceedingly
|
||||
rare), that's all there is to it. After that's done, **apply a patch
|
||||
for the change described in the following section**, test the
|
||||
configure process, and check it in.
|
||||
|
||||
<a name="patching"></a>
|
||||
Patching Autosetup for Project-local Changes
|
||||
------------------------------------------------------------------------
|
||||
|
||||
Autosetup reserves the flag name **`--debug`** for its own purposes,
|
||||
and its own special handling of `--enable-...` flags makes `--debug`
|
||||
an alias for `--enable-debug`. As we have a long history of using
|
||||
`--enable-debug` for this project's own purposes, we patch autosetup
|
||||
to use the name `--autosetup-debug` in place of `--debug`. That
|
||||
requires (as of this writing) four small edits in
|
||||
[](/file/autosetup/autosetup), as demonstrated in [check-in
|
||||
3296c8d3](/info/3296c8d3).
|
||||
|
||||
If autosetup is upgraded and this patch is _not_ applied the invoking
|
||||
`./configure` will fail loudly because of the declaration of the
|
||||
`debug` flag in `auto.def` - duplicated flags are not permitted.
|
||||
|
||||
|
||||
[Autosetup]: https://msteveb.github.io/autosetup/
|
||||
[auto.def]: /file/auto.def
|
||||
[autoconf/auto.def]: /file/autoconf/auto.def
|
||||
[autosetup-git]: https://github.com/msteveb/autosetup
|
||||
[proj.tcl]: /file/autosetup/proj.tcl
|
||||
[sqlite-config.tcl]: /file/autosetup/sqlite-config.tcl
|
||||
[Makefile.in]: /file/Makefile.in
|
||||
[main.mk]: /file/main.mk
|
||||
[JimTCL]: https://jim.tcl.tk
|
||||
+4
-4
@@ -9,7 +9,7 @@ dir=`dirname "$0"`; exec "`$dir/autosetup-find-tclsh`" "$0" "$@"
|
||||
set autosetup(version) 0.7.2
|
||||
|
||||
# Can be set to 1 to debug early-init problems
|
||||
set autosetup(debug) [expr {"--debug" in $argv}]
|
||||
set autosetup(debug) [expr {"--autosetup-debug" in $argv}]
|
||||
|
||||
##################################################################
|
||||
#
|
||||
@@ -98,7 +98,7 @@ proc main {argv} {
|
||||
version => "display the version of autosetup"
|
||||
ref:=text manual:=text
|
||||
reference:=text => "display the autosetup command reference. 'text', 'wiki', 'asciidoc' or 'markdown'"
|
||||
debug => "display debugging output as autosetup runs"
|
||||
autosetup-debug => "display debugging output as autosetup runs"
|
||||
install:=. => "install autosetup to the current or given directory"
|
||||
}
|
||||
if {$autosetup(installed)} {
|
||||
@@ -132,7 +132,7 @@ proc main {argv} {
|
||||
}
|
||||
|
||||
# Debugging output (set this early)
|
||||
incr autosetup(debug) [opt-bool debug]
|
||||
incr autosetup(debug) [opt-bool autosetup-debug]
|
||||
incr autosetup(force) [opt-bool force]
|
||||
incr autosetup(msg-quiet) [opt-bool quiet]
|
||||
incr autosetup(msg-timing) [opt-bool timing]
|
||||
@@ -2530,7 +2530,7 @@ if {[catch {main $argv} msg opts] == 1} {
|
||||
show-notices
|
||||
autosetup-full-error [error-dump $msg $opts $autosetup(debug)]
|
||||
if {!$autosetup(debug)} {
|
||||
puts stderr "Try: '[file tail $autosetup(exe)] --debug' for a full stack trace"
|
||||
puts stderr "Try: '[file tail $autosetup(exe)] --autosetup-debug' for a full stack trace"
|
||||
}
|
||||
exit 1
|
||||
}
|
||||
|
||||
@@ -5,12 +5,12 @@
|
||||
# If an argument is given, use that as the test instead of autosetup-test-tclsh
|
||||
d="`dirname "$0"`"
|
||||
for tclsh in ./jimsh0 $autosetup_tclsh jimsh tclsh tclsh8.5 tclsh8.6 tclsh8.7; do
|
||||
{ $tclsh "$d/${1-autosetup-test-tclsh}"; } 2>/dev/null && exit 0
|
||||
{ $tclsh "$d/${1-autosetup-test-tclsh}"; } 2>/dev/null && exit 0
|
||||
done
|
||||
echo 1>&2 "No installed jimsh or tclsh, building local bootstrap jimsh0"
|
||||
for cc in ${CC_FOR_BUILD:-cc} gcc; do
|
||||
{ $cc -o jimsh0 "$d/jimsh0.c"; } >/dev/null 2>&1 || continue
|
||||
./jimsh0 "$d/${1-autosetup-test-tclsh}" && exit 0
|
||||
{ $cc -o jimsh0 "$d/jimsh0.c"; } >/dev/null 2>&1 || continue
|
||||
./jimsh0 "$d/${1-autosetup-test-tclsh}" && exit 0
|
||||
done
|
||||
echo 1>&2 "No working C compiler found. Tried ${CC_FOR_BUILD:-cc} and gcc."
|
||||
echo false
|
||||
|
||||
+70
-68
@@ -677,80 +677,82 @@ proc calc-define-output-type {name spec} {
|
||||
return ""
|
||||
}
|
||||
|
||||
# Initialise some values from the environment or commandline or default settings
|
||||
foreach i {LDFLAGS LIBS CPPFLAGS LINKFLAGS CFLAGS} {
|
||||
lassign $i var default
|
||||
define $var [get-env $var $default]
|
||||
}
|
||||
proc cc-init {} {
|
||||
global autosetup
|
||||
|
||||
if {[env-is-set CC]} {
|
||||
# Set by the user, so don't try anything else
|
||||
set try [list [get-env CC ""]]
|
||||
} else {
|
||||
# Try some reasonable options
|
||||
set try [list [get-define cross]cc [get-define cross]gcc]
|
||||
}
|
||||
define CC [find-an-executable {*}$try]
|
||||
if {[get-define CC] eq ""} {
|
||||
user-error "Could not find a C compiler. Tried: [join $try ", "]"
|
||||
}
|
||||
|
||||
define CPP [get-env CPP "[get-define CC] -E"]
|
||||
|
||||
# XXX: Could avoid looking for a C++ compiler until requested
|
||||
# If CXX isn't found, it is set to the empty string.
|
||||
if {[env-is-set CXX]} {
|
||||
define CXX [find-an-executable -required [get-env CXX ""]]
|
||||
} else {
|
||||
define CXX [find-an-executable [get-define cross]c++ [get-define cross]g++]
|
||||
}
|
||||
|
||||
# CXXFLAGS default to CFLAGS if not specified
|
||||
define CXXFLAGS [get-env CXXFLAGS [get-define CFLAGS]]
|
||||
|
||||
# May need a CC_FOR_BUILD, so look for one
|
||||
define CC_FOR_BUILD [find-an-executable [get-env CC_FOR_BUILD ""] cc gcc false]
|
||||
|
||||
if {[get-define CC] eq ""} {
|
||||
user-error "Could not find a C compiler. Tried: [join $try ", "]"
|
||||
}
|
||||
|
||||
# These start empty and never come from the user or environment
|
||||
define AS_CFLAGS ""
|
||||
define AS_CPPFLAGS ""
|
||||
define AS_CXXFLAGS ""
|
||||
|
||||
define CCACHE [find-an-executable [get-env CCACHE ccache]]
|
||||
|
||||
# If any of these are set in the environment, propagate them to the AUTOREMAKE commandline
|
||||
foreach i {CC CXX CCACHE CPP CFLAGS CXXFLAGS CXXFLAGS LDFLAGS LIBS CROSS CPPFLAGS LINKFLAGS CC_FOR_BUILD LD} {
|
||||
if {[env-is-set $i]} {
|
||||
# Note: If the variable is set on the command line, get-env will return that value
|
||||
# so the command line will continue to override the environment
|
||||
define-append-argv AUTOREMAKE $i=[get-env $i ""]
|
||||
# Initialise some values from the environment or commandline or default settings
|
||||
foreach i {LDFLAGS LIBS CPPFLAGS LINKFLAGS CFLAGS} {
|
||||
lassign $i var default
|
||||
define $var [get-env $var $default]
|
||||
}
|
||||
}
|
||||
|
||||
# Initial cctest settings
|
||||
cc-store-settings {-cflags {} -includes {} -declare {} -link 0 -lang c -libs {} -code {} -nooutput 0}
|
||||
set autosetup(cc-include-deps) {}
|
||||
if {[env-is-set CC]} {
|
||||
# Set by the user, so don't try anything else
|
||||
set try [list [get-env CC ""]]
|
||||
} else {
|
||||
# Try some reasonable options
|
||||
set try [list [get-define cross]cc [get-define cross]gcc]
|
||||
}
|
||||
define CC [find-an-executable {*}$try]
|
||||
if {[get-define CC] eq ""} {
|
||||
user-error "Could not find a C compiler. Tried: [join $try ", "]"
|
||||
}
|
||||
|
||||
msg-result "C compiler...[get-define CCACHE] [get-define CC] [get-define CFLAGS] [get-define CPPFLAGS]"
|
||||
if {[get-define CXX] ne "false"} {
|
||||
msg-result "C++ compiler...[get-define CCACHE] [get-define CXX] [get-define CXXFLAGS] [get-define CPPFLAGS]"
|
||||
}
|
||||
msg-result "Build C compiler...[get-define CC_FOR_BUILD]"
|
||||
define CPP [get-env CPP "[get-define CC] -E"]
|
||||
|
||||
# On Darwin, we prefer to use -g0 to avoid creating .dSYM directories
|
||||
# but some compilers may not support it, so test here.
|
||||
switch -glob -- [get-define host] {
|
||||
*-*-darwin* {
|
||||
if {[cctest -cflags {-g0}]} {
|
||||
define cc-default-debug -g0
|
||||
# XXX: Could avoid looking for a C++ compiler until requested
|
||||
# If CXX isn't found, it is set to the empty string.
|
||||
if {[env-is-set CXX]} {
|
||||
define CXX [find-an-executable -required [get-env CXX ""]]
|
||||
} else {
|
||||
define CXX [find-an-executable [get-define cross]c++ [get-define cross]g++]
|
||||
}
|
||||
|
||||
# CXXFLAGS default to CFLAGS if not specified
|
||||
define CXXFLAGS [get-env CXXFLAGS [get-define CFLAGS]]
|
||||
|
||||
# May need a CC_FOR_BUILD, so look for one
|
||||
define CC_FOR_BUILD [find-an-executable [get-env CC_FOR_BUILD ""] cc gcc false]
|
||||
|
||||
# These start empty and never come from the user or environment
|
||||
define AS_CFLAGS ""
|
||||
define AS_CPPFLAGS ""
|
||||
define AS_CXXFLAGS ""
|
||||
|
||||
define CCACHE [find-an-executable [get-env CCACHE ccache]]
|
||||
|
||||
# If any of these are set in the environment, propagate them to the AUTOREMAKE commandline
|
||||
foreach i {CC CXX CCACHE CPP CFLAGS CXXFLAGS CXXFLAGS LDFLAGS LIBS CROSS CPPFLAGS LINKFLAGS CC_FOR_BUILD LD} {
|
||||
if {[env-is-set $i]} {
|
||||
# Note: If the variable is set on the command line, get-env will return that value
|
||||
# so the command line will continue to override the environment
|
||||
define-append-argv AUTOREMAKE $i=[get-env $i ""]
|
||||
}
|
||||
}
|
||||
|
||||
# Initial cctest settings
|
||||
cc-store-settings {-cflags {} -includes {} -declare {} -link 0 -lang c -libs {} -code {} -nooutput 0}
|
||||
set autosetup(cc-include-deps) {}
|
||||
|
||||
msg-result "C compiler...[get-define CCACHE] [get-define CC] [get-define CFLAGS] [get-define CPPFLAGS]"
|
||||
if {[get-define CXX] ne "false"} {
|
||||
msg-result "C++ compiler...[get-define CCACHE] [get-define CXX] [get-define CXXFLAGS] [get-define CPPFLAGS]"
|
||||
}
|
||||
msg-result "Build C compiler...[get-define CC_FOR_BUILD]"
|
||||
|
||||
# On Darwin, we prefer to use -g0 to avoid creating .dSYM directories
|
||||
# but some compilers may not support it, so test here.
|
||||
switch -glob -- [get-define host] {
|
||||
*-*-darwin* {
|
||||
if {[cctest -cflags {-g0}]} {
|
||||
define cc-default-debug -g0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if {![cc-check-includes stdlib.h]} {
|
||||
user-error "Compiler does not work. See config.log"
|
||||
}
|
||||
}
|
||||
|
||||
if {![cc-check-includes stdlib.h]} {
|
||||
user-error "Compiler does not work. See config.log"
|
||||
}
|
||||
cc-init
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
# Copyright (c) 2012 WorkWare Systems http://www.workware.net.au/
|
||||
# All rights reserved
|
||||
|
||||
# Auto-load module for 'make' build system integration
|
||||
|
||||
use init
|
||||
|
||||
autosetup_add_init_type make {Simple "make" build system} {
|
||||
autosetup_check_create auto.def \
|
||||
{# Initial auto.def created by 'autosetup --init=make'
|
||||
|
||||
use cc
|
||||
|
||||
# Add any user options here
|
||||
options {
|
||||
}
|
||||
|
||||
make-config-header config.h
|
||||
make-template Makefile.in
|
||||
}
|
||||
|
||||
if {![file exists Makefile.in]} {
|
||||
puts "Note: I don't see Makefile.in. You will probably need to create one."
|
||||
}
|
||||
}
|
||||
@@ -1,892 +0,0 @@
|
||||
########################################################################
|
||||
# 2024 September 25
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# * May you do good and not evil.
|
||||
# * May you find forgiveness for yourself and forgive others.
|
||||
# * May you share freely, never taking more than you give.
|
||||
#
|
||||
########################################################################
|
||||
# Routines for Steve Bennett's autosetup which are common to trees
|
||||
# managed in and around the umbrella of the SQLite project.
|
||||
#
|
||||
# Routines with a suffix of _ are intended for internal use,
|
||||
# within this file, and are not part of the API which auto.def files
|
||||
# should rely on.
|
||||
#
|
||||
# This file was initially derived from one used in the libfossil
|
||||
# project, authored by the same person who ported it here, noted here
|
||||
# only as an indication that there are no licensing issue despite this
|
||||
# code having at least two near-twins running around in other trees.
|
||||
#
|
||||
########################################################################
|
||||
#
|
||||
# Design notes: by and large, autosetup prefers to update global state
|
||||
# with the results of feature checks, e.g. whether the compiler
|
||||
# supports flag --X. In this developer's opinion that (A) causes more
|
||||
# confusion than it solves[^1] and (B) adds an unnecessary layer of
|
||||
# "voodoo" between the autosetup user and its internals. This module,
|
||||
# in contrast, instead injects the results of its own tests into
|
||||
# well-defined variables and leaves the integration of those values to
|
||||
# the caller's discretion.
|
||||
#
|
||||
# [1]: As an example: testing for the -rpath flag, using
|
||||
# cc-check-flags, can break later checks which use
|
||||
# [cc-check-function-in-lib ...] because the resulting -rpath flag
|
||||
# implicitly becomes part of those tests. In the case of an rpath
|
||||
# test, downstream tests may not like the $prefix/lib path added by
|
||||
# the rpath test. To avoid such problems, we avoid (intentionally)
|
||||
# updating global state via feature tests.
|
||||
########################################################################
|
||||
|
||||
########################################################################
|
||||
# $hwaci is an internal-use-only array for storing whatever generic
|
||||
# internal stuff we need stored.
|
||||
array set hwaci_ {}
|
||||
|
||||
proc hwaci-warn {msg} {
|
||||
puts stderr "WARNING: $msg"
|
||||
}
|
||||
proc hwaci-notice {msg} {
|
||||
puts stderr "NOTICE: $msg"
|
||||
}
|
||||
proc hwaci-fatal {msg} {
|
||||
user-error "ERROR: $msg"
|
||||
}
|
||||
|
||||
########################################################################
|
||||
# hwaci-lshift_ shifts $count elements from the list named $listVar and
|
||||
# returns them.
|
||||
#
|
||||
# Modified slightly from: https://wiki.tcl-lang.org/page/lshift
|
||||
#
|
||||
# On an empty list, returns "".
|
||||
proc hwaci-lshift_ {listVar {count 1}} {
|
||||
upvar 1 $listVar l
|
||||
if {![info exists l]} {
|
||||
# make the error message show the real variable name
|
||||
error "can't read \"$listVar\": no such variable"
|
||||
}
|
||||
if {![llength $l]} {
|
||||
# error Empty
|
||||
return ""
|
||||
}
|
||||
set r [lrange $l 0 [incr count -1]]
|
||||
set l [lreplace $l [set l 0] $count]
|
||||
return $r
|
||||
}
|
||||
|
||||
########################################################################
|
||||
# A proxy for cc-check-function-in-lib which "undoes" any changes that
|
||||
# routine makes to the LIBS define. Returns the result of
|
||||
# cc-check-function-in-lib.
|
||||
proc hwaci-check-function-in-lib {function libs {otherlibs {}}} {
|
||||
set found 0
|
||||
define-push {LIBS} {
|
||||
set found [cc-check-function-in-lib $function $libs $otherlibs]
|
||||
}
|
||||
return $found
|
||||
}
|
||||
|
||||
########################################################################
|
||||
# If $v is true, [puts $msg] is called, else puts is not called.
|
||||
#proc hwaci-maybe-verbose {v msg} {
|
||||
# if {$v} {
|
||||
# puts $msg
|
||||
# }
|
||||
#}
|
||||
|
||||
########################################################################
|
||||
# Usage: hwaci-find-executable-path ?-v? binaryName
|
||||
#
|
||||
# Works similarly to autosetup's [find-executable-path $binName] but:
|
||||
#
|
||||
# - If the first arg is -v, it's verbose about searching, else it's quiet.
|
||||
#
|
||||
# Returns the full path to the result or an empty string.
|
||||
proc hwaci-find-executable-path {args} {
|
||||
set binName $args
|
||||
set verbose 0
|
||||
if {[lindex $args 0] eq "-v"} {
|
||||
set verbose 1
|
||||
set binName [lrange $args 1 end]
|
||||
msg-checking "Looking for $binName ... "
|
||||
}
|
||||
set check [find-executable-path $binName]
|
||||
if {$verbose} {
|
||||
if {"" eq $check} {
|
||||
msg-result "not found"
|
||||
} else {
|
||||
msg-result $check
|
||||
}
|
||||
}
|
||||
return $check
|
||||
}
|
||||
|
||||
########################################################################
|
||||
# Uses [hwaci-find-executable-path $binName] to (verbosely) search for
|
||||
# a binary, sets a define (see below) to the result, and returns the
|
||||
# result (an empty string if not found).
|
||||
#
|
||||
# The define'd name is: if defName is empty then "BIN_X" is used,
|
||||
# where X is the upper-case form of $binName with any '-' characters
|
||||
# replaced with '_'.
|
||||
proc hwaci-bin-define {binName {defName {}}} {
|
||||
set check [hwaci-find-executable-path -v $binName]
|
||||
if {"" eq $defName} {
|
||||
set defName "BIN_[string toupper [string map {- _} $binName]]"
|
||||
}
|
||||
define $defName $check
|
||||
return $check
|
||||
}
|
||||
|
||||
########################################################################
|
||||
# Usage: hwaci-first-bin-of bin...
|
||||
#
|
||||
# Looks for the first binary found of the names passed to this
|
||||
# function. If a match is found, the full path to that binary is
|
||||
# returned, else "" is returned.
|
||||
#
|
||||
# Despite using cc-path-progs to do the search, this function clears
|
||||
# any define'd name that function stores for the result (because the
|
||||
# caller has no sensible way of knowing which result it was unless
|
||||
# they pass only a single argument).
|
||||
proc hwaci-first-bin-of {args} {
|
||||
foreach b $args {
|
||||
if {[cc-path-progs $b]} {
|
||||
set u [string toupper $b]
|
||||
set x [get-define $u]
|
||||
undefine $u
|
||||
return $x
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
########################################################################
|
||||
# Looks for `bash` binary and dies if not found. On success, defines
|
||||
# BIN_BASH to the full path to bash and returns that value.
|
||||
#
|
||||
# TODO: move this out of this file and back into the 1 or 2 downstream
|
||||
# trees which use it.
|
||||
proc hwaci-require-bash {} {
|
||||
set bash [hwaci-bin-define bash]
|
||||
if {"" eq $bash} {
|
||||
user-error "Cannot find required bash shell"
|
||||
}
|
||||
return $bash
|
||||
}
|
||||
|
||||
########################################################################
|
||||
# Force-set autosetup option $flag to $val. The value can be fetched
|
||||
# later with [opt-val], [opt-bool], and friends.
|
||||
proc hwaci-opt-set {flag {val 1}} {
|
||||
global autosetup
|
||||
if {$flag ni $::autosetup(options)} {
|
||||
# We have to add this to autosetup(options) or else future calls
|
||||
# to [opt-bool $flag] will fail validation of $flag.
|
||||
lappend ::autosetup(options) $flag
|
||||
}
|
||||
dict set ::autosetup(optset) $flag $val
|
||||
}
|
||||
|
||||
########################################################################
|
||||
# Returns 1 if $val appears to be a truthy value, else returns
|
||||
# 0. Truthy values are any of {1 on enabled yes}
|
||||
proc hwaci-val-truthy {val} {
|
||||
expr {$val in {1 on enabled yes}}
|
||||
}
|
||||
|
||||
########################################################################
|
||||
# Returns 1 if [opt-val $flag] appears to be a truthy value or
|
||||
# [opt-bool $flag] is true. See hwaci-val-truthy.
|
||||
proc hwaci-opt-truthy {flag} {
|
||||
if {[hwaci-val-truthy [opt-val $flag]]} { return 1 }
|
||||
set rc 0
|
||||
catch {
|
||||
# opt-bool will throw if $flag is not a known boolean flag
|
||||
set rc [opt-bool $flag]
|
||||
}
|
||||
return $rc
|
||||
}
|
||||
|
||||
########################################################################
|
||||
# If [hwaci-opt-truthy $flag] is true, eval $then, else eval $else.
|
||||
proc hwaci-if-opt-truthy {boolFlag thenScript {elseScript {}}} {
|
||||
if {[hwaci-opt-truthy $boolFlag]} {
|
||||
uplevel 1 $thenScript
|
||||
} else {
|
||||
uplevel 1 $elseScript
|
||||
}
|
||||
}
|
||||
|
||||
########################################################################
|
||||
# If [hwaci-opt-truthy $flag] then [define $def $iftrue] else [define
|
||||
# $def $iffalse]. If $msg is not empty, output [msg-checking $msg] and
|
||||
# a [msg-results ...] which corresponds to the result. Returns 1 if
|
||||
# the opt-truthy check passes, else 0.
|
||||
proc hwaci-define-if-opt-truthy {flag def {msg ""} {iftrue 1} {iffalse 0}} {
|
||||
if {"" ne $msg} {
|
||||
msg-checking "$msg "
|
||||
}
|
||||
set rcMsg ""
|
||||
set rc 0
|
||||
if {[hwaci-opt-truthy $flag]} {
|
||||
define $def $iftrue
|
||||
set rc 1
|
||||
} else {
|
||||
define $def $iffalse
|
||||
}
|
||||
switch -- [hwaci-val-truthy [get-define $def]] {
|
||||
0 { set rcMsg no }
|
||||
1 { set rcMsg yes }
|
||||
}
|
||||
if {"" ne $msg} {
|
||||
msg-result $rcMsg
|
||||
}
|
||||
return $rc
|
||||
}
|
||||
|
||||
########################################################################
|
||||
# Args: [-v] optName defName {descr {}}
|
||||
#
|
||||
# Checks [hwaci-opt-truthy $optName] and calls [define $defName X]
|
||||
# where X is 0 for false and 1 for true. descr is an optional
|
||||
# [msg-checking] argument which defaults to $defName. Returns X.
|
||||
#
|
||||
# If args[0] is -v then the boolean semantics are inverted: if
|
||||
# the option is set, it gets define'd to 0, else 1. Returns the
|
||||
# define'd value.
|
||||
proc hwaci-opt-define-bool {args} {
|
||||
set invert 0
|
||||
if {[lindex $args 0] eq "-v"} {
|
||||
set invert 1
|
||||
set args [lrange $args 1 end]
|
||||
}
|
||||
set optName [hwaci-lshift_ args]
|
||||
set defName [hwaci-lshift_ args]
|
||||
set descr [hwaci-lshift_ args]
|
||||
if {"" eq $descr} {
|
||||
set descr $defName
|
||||
}
|
||||
set rc 0
|
||||
msg-checking "$descr ... "
|
||||
if {[hwaci-opt-truthy $optName]} {
|
||||
if {0 eq $invert} {
|
||||
set rc 1
|
||||
} else {
|
||||
set rc 0
|
||||
}
|
||||
} elseif {0 ne $invert} {
|
||||
set rc 1
|
||||
}
|
||||
msg-result $rc
|
||||
define $defName $rc
|
||||
return $rc
|
||||
}
|
||||
|
||||
########################################################################
|
||||
# Check for module-loading APIs (libdl/libltdl)...
|
||||
#
|
||||
# Looks for libltdl or dlopen(), the latter either in -ldl or built in
|
||||
# to libc (as it is on some platforms). Returns 1 if found, else
|
||||
# 0. Either way, it `define`'s:
|
||||
#
|
||||
# - HAVE_LIBLTDL to 1 or 0 if libltdl is found/not found
|
||||
# - HAVE_LIBDL to 1 or 0 if dlopen() is found/not found
|
||||
# - LDFLAGS_MODULE_LOADER one of ("-lltdl", "-ldl", or ""), noting
|
||||
# that -ldl may legally be empty on some platforms even if
|
||||
# HAVE_LIBDL is true (indicating that dlopen() is available without
|
||||
# extra link flags). LDFLAGS_MODULE_LOADER also gets "-rdynamic" appended
|
||||
# to it because otherwise trying to open DLLs will result in undefined
|
||||
# symbol errors.
|
||||
#
|
||||
# Note that if it finds LIBLTDL it does not look for LIBDL, so will
|
||||
# report only that is has LIBLTDL.
|
||||
proc hwaci-check-module-loader {} {
|
||||
msg-checking "Looking for module-loader APIs... "
|
||||
if {99 ne [get-define LDFLAGS_MODULE_LOADER 99]} {
|
||||
if {1 eq [get-define HAVE_LIBLTDL 0]} {
|
||||
msg-result "(cached) libltdl"
|
||||
return 1
|
||||
} elseif {1 eq [get-define HAVE_LIBDL 0]} {
|
||||
msg-result "(cached) libdl"
|
||||
return 1
|
||||
}
|
||||
# else: wha???
|
||||
}
|
||||
set HAVE_LIBLTDL 0
|
||||
set HAVE_LIBDL 0
|
||||
set LDFLAGS_MODULE_LOADER ""
|
||||
set rc 0
|
||||
puts "" ;# cosmetic kludge for cc-check-XXX
|
||||
if {[cc-check-includes ltdl.h] && [cc-check-function-in-lib lt_dlopen ltdl]} {
|
||||
set HAVE_LIBLTDL 1
|
||||
set LDFLAGS_MODULE_LOADER "-lltdl -rdynamic"
|
||||
msg-result " - Got libltdl."
|
||||
set rc 1
|
||||
} elseif {[cc-with {-includes dlfcn.h} {
|
||||
cctest -link 1 -declare "extern char* dlerror(void);" -code "dlerror();"}]} {
|
||||
msg-result " - This system can use dlopen() without -ldl."
|
||||
set HAVE_LIBDL 1
|
||||
set LDFLAGS_MODULE_LOADER ""
|
||||
set rc 1
|
||||
} elseif {[cc-check-includes dlfcn.h]} {
|
||||
set HAVE_LIBDL 1
|
||||
set rc 1
|
||||
if {[cc-check-function-in-lib dlopen dl]} {
|
||||
msg-result " - dlopen() needs libdl."
|
||||
set LDFLAGS_MODULE_LOADER "-ldl -rdynamic"
|
||||
} else {
|
||||
msg-result " - dlopen() not found in libdl. Assuming dlopen() is built-in."
|
||||
set LDFLAGS_MODULE_LOADER "-rdynamic"
|
||||
}
|
||||
}
|
||||
define HAVE_LIBLTDL $HAVE_LIBLTDL
|
||||
define HAVE_LIBDL $HAVE_LIBDL
|
||||
define LDFLAGS_MODULE_LOADER $LDFLAGS_MODULE_LOADER
|
||||
return $rc
|
||||
}
|
||||
|
||||
########################################################################
|
||||
# Sets all flags which would be set by hwaci-check-module-loader to
|
||||
# empty/falsy values, as if those checks had failed to find a module
|
||||
# loader. Intended to be called in place of that function when
|
||||
# a module loader is explicitly not desired.
|
||||
proc hwaci-no-check-module-loader {} {
|
||||
define HAVE_LIBDL 0
|
||||
define HAVE_LIBLTDL 0
|
||||
define LDFLAGS_MODULE_LOADER ""
|
||||
}
|
||||
|
||||
########################################################################
|
||||
# Opens the given file, reads all of its content, and returns it.
|
||||
proc hwaci-file-content {fname} {
|
||||
set fp [open $fname r]
|
||||
set rc [read $fp]
|
||||
close $fp
|
||||
return $rc
|
||||
}
|
||||
|
||||
########################################################################
|
||||
# Returns the contents of the given file as an array of lines, with
|
||||
# the EOL stripped from each input line.
|
||||
proc hwaci-file-content-list {fname} {
|
||||
set fp [open $fname r]
|
||||
set rc {}
|
||||
while { [gets $fp line] >= 0 } {
|
||||
lappend rc $line
|
||||
}
|
||||
return $rc
|
||||
}
|
||||
|
||||
########################################################################
|
||||
# Checks the compiler for compile_commands.json support. If passed an
|
||||
# argument it is assumed to be the name of an autosetup boolean config
|
||||
# which controls whether to run/skip this check.
|
||||
#
|
||||
# Returns 1 if supported, else 0. Defines MAKE_COMPILATION_DB to "yes"
|
||||
# if supported, "no" if not.
|
||||
#
|
||||
# This test has a long history of false positive results because of
|
||||
# compilers reacting differently to the -MJ flag.
|
||||
proc hwaci-check-compile-commands {{configOpt {}}} {
|
||||
msg-checking "compile_commands.json support... "
|
||||
if {"" ne $configOpt && ![hwaci-opt-truthy $configOpt]} {
|
||||
msg-result "explicitly disabled"
|
||||
define MAKE_COMPILATION_DB no
|
||||
return 0
|
||||
} else {
|
||||
if {[cctest -lang c -cflags {/dev/null -MJ} -source {}]} {
|
||||
# This test reportedly incorrectly succeeds on one of
|
||||
# Martin G.'s older systems. drh also reports a false
|
||||
# positive on an unspecified older Mac system.
|
||||
msg-result "compiler supports compile_commands.json"
|
||||
define MAKE_COMPILATION_DB yes
|
||||
return 1
|
||||
} else {
|
||||
msg-result "compiler does not support compile_commands.json"
|
||||
define MAKE_COMPILATION_DB no
|
||||
return 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
########################################################################
|
||||
# Runs the 'touch' command on one or more files, ignoring any errors.
|
||||
proc hwaci-touch {filename} {
|
||||
catch { exec touch {*}$filename }
|
||||
}
|
||||
|
||||
########################################################################
|
||||
# Usage:
|
||||
#
|
||||
# hwaci-make-from-dot-in ?-touch? filename(s)...
|
||||
#
|
||||
# Uses [make-template] to create makefile(-like) file(s) $filename
|
||||
# from $filename.in but explicitly makes the output read-only, to
|
||||
# avoid inadvertent editing (who, me?).
|
||||
#
|
||||
# If the first argument is -touch then the generated file is touched
|
||||
# to update its timestamp. This can be used as a workaround for
|
||||
# cases where (A) autosetup does not update the file because it was
|
||||
# not really modified and (B) the file *really* needs to be updated to
|
||||
# please the build process.
|
||||
#
|
||||
# Failures when running chmod or touch are silently ignored.
|
||||
proc hwaci-make-from-dot-in {args} {
|
||||
set filename $args
|
||||
set touch 0
|
||||
if {[lindex $args 0] eq "-touch"} {
|
||||
set touch 1
|
||||
set filename [lrange $args 1 end]
|
||||
}
|
||||
foreach f $filename {
|
||||
set f [string trim $f]
|
||||
catch { exec chmod u+w $f }
|
||||
make-template $f.in $f
|
||||
if {$touch} {
|
||||
hwaci-touch $f
|
||||
}
|
||||
catch { exec chmod -w $f }
|
||||
}
|
||||
}
|
||||
|
||||
########################################################################
|
||||
# Checks for the boolean configure option named by $flagname. If set,
|
||||
# it checks if $CC seems to refer to gcc. If it does (or appears to)
|
||||
# then it defines CC_PROFILE_FLAG to "-pg" and returns 1, else it
|
||||
# defines CC_PROFILE_FLAG to "" and returns 0.
|
||||
#
|
||||
# Note that the resulting flag must be added to both CFLAGS and
|
||||
# LDFLAGS in order for binaries to be able to generate "gmon.out". In
|
||||
# order to avoid potential problems with escaping, space-containing
|
||||
# tokens, and interfering with autosetup's use of these vars, this
|
||||
# routine does not directly modify CFLAGS or LDFLAGS.
|
||||
proc hwaci-check-profile-flag {{flagname profile}} {
|
||||
#puts "flagname=$flagname ?[hwaci-opt-truthy $flagname]?"
|
||||
if {[hwaci-opt-truthy $flagname]} {
|
||||
set CC [get-define CC]
|
||||
regsub {.*ccache *} $CC "" CC
|
||||
# ^^^ if CC="ccache gcc" then [exec] treats "ccache gcc" as a
|
||||
# single binary name and fails. So strip any leading ccache part
|
||||
# for this purpose.
|
||||
if { ![catch { exec $CC --version } msg]} {
|
||||
if {[string first gcc $CC] != -1} {
|
||||
define CC_PROFILE_FLAG "-pg"
|
||||
return 1
|
||||
}
|
||||
}
|
||||
}
|
||||
define CC_PROFILE_FLAG ""
|
||||
return 0
|
||||
}
|
||||
|
||||
########################################################################
|
||||
# Returns 1 if this appears to be a Windows environment (MinGw,
|
||||
# Cygwin, MSys), else returns 0. The optional argument is the name of
|
||||
# an autosetup define which contains platform name info, defaulting to
|
||||
# "host" (meaning, somewhat counterintuitively, the target system, not
|
||||
# the current host). The other legal value is "build" (the build
|
||||
# machine, i.e. the local host). If $key == "build" then some
|
||||
# additional checks may be performed which are not applicable when
|
||||
# $key == "host".
|
||||
proc hwaci-looks-like-windows {{key host}} {
|
||||
global autosetup
|
||||
switch -glob -- [get-define $key] {
|
||||
*-*-ming* - *-*-cygwin - *-*-msys {
|
||||
return 1
|
||||
}
|
||||
}
|
||||
if {$key eq "build"} {
|
||||
# These apply only to the local OS, not a cross-compilation target,
|
||||
# as the above check can potentially.
|
||||
if {$::autosetup(iswin)} { return 1 }
|
||||
if {[find-an-executable cygpath] ne "" || $::tcl_platform(os)=="Windows NT"} {
|
||||
return 1
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
########################################################################
|
||||
# Looks at either the 'host' (==compilation target platform) or
|
||||
# 'build' (==the being-built-on platform) define value and returns if
|
||||
# if that value seems to indicate that it represents a Mac platform,
|
||||
# else returns 0.
|
||||
#
|
||||
# TODO: have someone verify whether this is correct for the
|
||||
# non-Linux/BSD platforms.
|
||||
proc hwaci-looks-like-mac {{key host}} {
|
||||
switch -glob -- [get-define $key] {
|
||||
*apple* {
|
||||
return 1
|
||||
}
|
||||
default {
|
||||
return 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
########################################################################
|
||||
# Checks autosetup's "host" and "build" defines to see if the build
|
||||
# host and target are Windows-esque (Cygwin, MinGW, MSys). If the
|
||||
# build environment is then BUILD_EXEEXT is [define]'d to ".exe", else
|
||||
# "". If the target, a.k.a. "host", is then TARGET_EXEEXT is
|
||||
# [define]'d to ".exe", else "".
|
||||
proc hwaci-exe-extension {} {
|
||||
set rH ""
|
||||
set rB ""
|
||||
if {[hwaci-looks-like-windows host]} {
|
||||
set rH ".exe"
|
||||
}
|
||||
if {[hwaci-looks-like-windows build]} {
|
||||
set rB ".exe"
|
||||
}
|
||||
define BUILD_EXEEXT $rB
|
||||
define TARGET_EXEEXT $rH
|
||||
}
|
||||
|
||||
########################################################################
|
||||
# Works like hwaci-exe-extension except that it defines BUILD_DLLEXT
|
||||
# and TARGET_DLLEXT to one of (.so, ,dll, .dylib).
|
||||
#
|
||||
# Trivia: for .dylib files, the linker needs the -dynamiclib flag
|
||||
# instead of -shared.
|
||||
#
|
||||
# TODO: have someone verify whether this is correct for the
|
||||
# non-Linux/BSD platforms.
|
||||
proc hwaci-dll-extension {} {
|
||||
proc inner {key} {
|
||||
switch -glob -- [get-define $key] {
|
||||
*apple* {
|
||||
return ".dylib"
|
||||
}
|
||||
*-*-ming* - *-*-cygwin - *-*-msys {
|
||||
return ".dll"
|
||||
}
|
||||
default {
|
||||
return ".so"
|
||||
}
|
||||
}
|
||||
}
|
||||
define BUILD_DLLEXT [inner build]
|
||||
define TARGET_DLLEXT [inner host]
|
||||
}
|
||||
|
||||
########################################################################
|
||||
# Static-library counterpart of hwaci-dll-extension. Defines
|
||||
# BUILD_LIBEXT and TARGET_LIBEXT to the conventional static library
|
||||
# extension for the being-built-on resp. the target platform.
|
||||
proc hwaci-lib-extension {} {
|
||||
proc inner {key} {
|
||||
switch -glob -- [get-define $key] {
|
||||
*-*-ming* - *-*-cygwin - *-*-msys {
|
||||
return ".lib"
|
||||
}
|
||||
default {
|
||||
return ".a"
|
||||
}
|
||||
}
|
||||
}
|
||||
define BUILD_LIBEXT [inner build]
|
||||
define TARGET_LIBEXT [inner host]
|
||||
}
|
||||
|
||||
########################################################################
|
||||
# Calls all of the hwaci-*-extension functions.
|
||||
proc hwaci-file-extensions {} {
|
||||
hwaci-exe-extension
|
||||
hwaci-dll-extension
|
||||
hwaci-lib-extension
|
||||
}
|
||||
|
||||
########################################################################
|
||||
# Expects a list of file names. If any one of them does not exist in
|
||||
# the filesystem, it fails fatally with an informative message.
|
||||
# Returns the last file name it checks. If the first argument is -v
|
||||
# then it emits msg-checking/msg-result messages for each file.
|
||||
proc hwaci-affirm-files-exist {args} {
|
||||
set rc ""
|
||||
set verbose 0
|
||||
if {[lindex $args 0] eq "-v"} {
|
||||
set verbose 1
|
||||
set args [lrange $args 1 end]
|
||||
}
|
||||
foreach f $args {
|
||||
if {$verbose} { msg-checking "Looking for $f ... " }
|
||||
if {![file exists $f]} {
|
||||
user-error "not found: $f"
|
||||
}
|
||||
if {$verbose} { msg-result "" }
|
||||
set rc $f
|
||||
}
|
||||
return rc
|
||||
}
|
||||
|
||||
########################################################################
|
||||
# Emscripten is used for doing in-tree builds of web-based WASM stuff,
|
||||
# as opposed to WASI-based WASM or WASM binaries we import from other
|
||||
# places. This is only set up for Unix-style OSes and is untested
|
||||
# anywhere but Linux.
|
||||
#
|
||||
# Defines the following:
|
||||
#
|
||||
# - EMSDK_HOME = top dir of the emsdk or "". It looks for
|
||||
# --with-emsdk=DIR or the $EMSDK environment variable.
|
||||
# - EMSDK_ENV = path to EMSDK_HOME/emsdk_env.sh or ""
|
||||
# - BIN_EMCC = $EMSDK_HOME/upstream/emscripten/emcc or ""
|
||||
# - HAVE_EMSDK = 0 or 1 (this function's return value)
|
||||
#
|
||||
# Returns 1 if EMSDK_ENV is found, else 0. If EMSDK_HOME is not empty
|
||||
# but BIN_EMCC is then emcc was not found in the EMSDK_HOME, in which
|
||||
# case we have to rely on the fact that sourcing $EMSDK_ENV from a
|
||||
# shell will add emcc to the $PATH.
|
||||
proc hwaci-check-emsdk {} {
|
||||
set emsdkHome [opt-val with-emsdk]
|
||||
define EMSDK_HOME ""
|
||||
define EMSDK_ENV ""
|
||||
define BIN_EMCC ""
|
||||
msg-checking "Emscripten SDK? "
|
||||
if {$emsdkHome eq ""} {
|
||||
# Fall back to checking the environment. $EMSDK gets set by
|
||||
# sourcing emsdk_env.sh.
|
||||
set emsdkHome [get-env EMSDK ""]
|
||||
}
|
||||
set rc 0
|
||||
if {$emsdkHome ne ""} {
|
||||
define EMSDK_HOME $emsdkHome
|
||||
set emsdkEnv "$emsdkHome/emsdk_env.sh"
|
||||
if {[file exists $emsdkEnv]} {
|
||||
msg-result "$emsdkHome"
|
||||
define EMSDK_ENV $emsdkEnv
|
||||
set rc 1
|
||||
set emcc "$emsdkHome/upstream/emscripten/emcc"
|
||||
if {[file exists $emcc]} {
|
||||
define BIN_EMCC $emcc
|
||||
}
|
||||
} else {
|
||||
msg-result "emsdk_env.sh not found in $emsdkHome"
|
||||
}
|
||||
} else {
|
||||
msg-result "not found"
|
||||
}
|
||||
define HAVE_EMSDK $rc
|
||||
return $rc
|
||||
}
|
||||
|
||||
########################################################################
|
||||
# Tries various approaches to handling the -rpath link-time
|
||||
# flag. Defines LDFLAGS_RPATH to that/those flag(s) or an empty
|
||||
# string. Returns 1 if it finds an option, else 0.
|
||||
#
|
||||
# Achtung: we have seen platforms which report that a given option
|
||||
# checked here will work but then fails at build-time, and the current
|
||||
# order of checks reflects that.
|
||||
proc hwaci-check-rpath {} {
|
||||
set rc 1
|
||||
set lp "[get-define prefix]/lib"
|
||||
# If we _don't_ use cc-with {} here (to avoid updating the global
|
||||
# CFLAGS or LIBS or whatever it is that cc-check-flags updates) then
|
||||
# downstream tests may fail because the resulting rpath gets
|
||||
# implicitly injected into them.
|
||||
cc-with {} {
|
||||
if {[cc-check-flags "-rpath $lp"]} {
|
||||
define LDFLAGS_RPATH "-rpath $lp"
|
||||
} elseif {[cc-check-flags "-Wl,-rpath -Wl,$lp"]} {
|
||||
define LDFLAGS_RPATH "-Wl,-rpath -Wl,$lp"
|
||||
} elseif {[cc-check-flags -Wl,-R$lp]} {
|
||||
define LDFLAGS_RPATH "-Wl,-R$lp"
|
||||
} else {
|
||||
define LDFLAGS_RPATH ""
|
||||
set rc 0
|
||||
}
|
||||
}
|
||||
return $rc
|
||||
}
|
||||
|
||||
########################################################################
|
||||
# Under construction - check for libreadline functionality. Linking
|
||||
# in readline varies wildly by platform and this check does not cover
|
||||
# all known options.
|
||||
#
|
||||
# Defines the following vars:
|
||||
#
|
||||
# - HAVE_READLINE: 0 or 1
|
||||
# - LDFLAGS_READLINE: "" or linker flags
|
||||
# - CFLAGS_READLINE: "" or c-flags
|
||||
# - READLINE_H: "" or "readline/readlin.h" (or similar)
|
||||
#
|
||||
# Returns the value of HAVE_READLINE.
|
||||
proc hwaci-check-readline {} {
|
||||
define HAVE_READLINE 0
|
||||
define LDFLAGS_READLINE ""
|
||||
define CFLAGS_READLINE ""
|
||||
define READLINE_H ""
|
||||
if {![opt-bool readline]} {
|
||||
msg-result "libreadline disabled via --disable-readline."
|
||||
return 0
|
||||
}
|
||||
|
||||
if {[pkg-config-init 0] && [pkg-config readline]} {
|
||||
define HAVE_READLINE 1
|
||||
define LDFLAGS_READLINE [get-define PKG_READLINE_LDFLAGS]
|
||||
define-append LDFLAGS_READLINE [get-define PKG_READLINE_LIBS]
|
||||
define CFLAGS_READLINE [get-define PKG_READLINE_CFLAGS]
|
||||
return 1
|
||||
}
|
||||
|
||||
# On OpenBSD on a Raspberry pi 4:
|
||||
#
|
||||
# $ pkg-config readline; echo $?
|
||||
# 0
|
||||
# $ pkg-config --cflags readline
|
||||
# Package termcap was not found in the pkg-config search path
|
||||
# $ echo $?
|
||||
# 1
|
||||
# $ pkg-config --print-requires readline; echo $?
|
||||
# 1
|
||||
#
|
||||
# i.e. there's apparently no way to find out that readline
|
||||
# requires termcap beyond parsing the error message.
|
||||
|
||||
set h "readline/readline.h"
|
||||
if {[cc-check-includes $h]} {
|
||||
define READLINE_H $h
|
||||
if {[hwaci-check-function-in-lib readline readline]} {
|
||||
msg-result "Enabling libreadline."
|
||||
define HAVE_READLINE 1
|
||||
define LDFLAGS_READLINE [get-define lib_readline]
|
||||
undefine lib_readline
|
||||
return 1
|
||||
}
|
||||
# else TODO: look in various places and [define CFLAGS_READLINE
|
||||
# -I...]
|
||||
}
|
||||
# Numerous TODOs:
|
||||
# - Requires linking with ncurses or similar on some platforms.
|
||||
# - Headers are in a weird place on some BSD systems.
|
||||
# - Add --with-readline=DIR
|
||||
# - Add --with-readline-lib=lib file
|
||||
# - Add --with-readline-inc=dir -Idir
|
||||
msg-result "libreadline not found."
|
||||
return 0
|
||||
}
|
||||
|
||||
|
||||
########################################################################
|
||||
# Internal helper for hwaci-dump-defs-json. Expects to be passed a
|
||||
# [define] name and the variadic $args which are passed to
|
||||
# hwaci-dump-defs-json. If it finds a pattern match for the given
|
||||
# $name in the various $args, it returns the type flag for that $name,
|
||||
# e.g. "-str" or "-bare", else returns an empty string.
|
||||
proc hwaci-defs-type_ {name spec} {
|
||||
foreach {type patterns} $spec {
|
||||
foreach pattern $patterns {
|
||||
if {[string match $pattern $name]} {
|
||||
return $type
|
||||
}
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
########################################################################
|
||||
# Internal helper for hwaci-defs-format_: returns a JSON-ish quoted
|
||||
# form of the given (JSON) string-type values.
|
||||
proc hwaci-quote-str_ {value} {
|
||||
return \"[string map [list \\ \\\\ \" \\\"] $value]\"
|
||||
}
|
||||
|
||||
########################################################################
|
||||
# An internal impl detail of hwaci-dump-defs-json. Requires a data
|
||||
# type specifier, as used by make-config-header, and a value. Returns
|
||||
# the formatted value or the value $::hwaci_(defs-skip) if the caller
|
||||
# should skip emitting that value.
|
||||
set hwaci_(defs-skip) "-hwaci-defs-format_ sentinel"
|
||||
proc hwaci-defs-format_ {type value} {
|
||||
switch -exact -- $type {
|
||||
-bare {
|
||||
# Just output the value unchanged
|
||||
}
|
||||
-none {
|
||||
set value $::hwaci_(defs-skip)
|
||||
}
|
||||
-str {
|
||||
set value [hwaci-quote-str_ $value]
|
||||
}
|
||||
-auto {
|
||||
# Automatically determine the type
|
||||
if {![string is integer -strict $value]} {
|
||||
set value [hwaci-quote-str_ $value]
|
||||
}
|
||||
}
|
||||
-array {
|
||||
set ar {}
|
||||
foreach v $value {
|
||||
set v [hwaci-defs-format_ -auto $v]
|
||||
if {$::hwaci_(defs-skip) ne $v} {
|
||||
lappend ar $v
|
||||
}
|
||||
}
|
||||
set value "\[ [join $ar {, }] \]"
|
||||
}
|
||||
"" {
|
||||
set value $::hwaci_(defs-skip)
|
||||
}
|
||||
default {
|
||||
hwaci-fatal "Unknown type in hwaci-dump-defs-json: $type"
|
||||
}
|
||||
}
|
||||
return $value
|
||||
}
|
||||
|
||||
########################################################################
|
||||
# This function works almost identically to autosetup's
|
||||
# make-config-header but emits its output in JSON form. It is not a
|
||||
# fully-functional JSON emitter, and will emit broken JSON for
|
||||
# complicated outputs, but should be sufficient for purposes of
|
||||
# emitting most configure vars (numbers and simple strings).
|
||||
#
|
||||
# In addition to the formatting flags supported by make-config-header,
|
||||
# it also supports:
|
||||
#
|
||||
# -array {patterns...}
|
||||
#
|
||||
# Any defines matching the given patterns will be treated as a list of
|
||||
# values, each of which will be formatted as if it were in an -auto {...}
|
||||
# set, and the define will be emitted to JSON in the form:
|
||||
#
|
||||
# "ITS_NAME": [ "value1", ...valueN ]
|
||||
#
|
||||
# Achtung: if a given -array pattern contains values which themselves
|
||||
# contains spaces...
|
||||
#
|
||||
# define-append foo {"-DFOO=bar baz" -DBAR="baz barre"}
|
||||
#
|
||||
# will lead to:
|
||||
#
|
||||
# ["-DFOO=bar baz", "-DBAR=\"baz", "barre\""]
|
||||
#
|
||||
# Neither is especially satisfactory (and the second is useless), and
|
||||
# handling of such values is subject to change if any such values ever
|
||||
# _really_ need to be processed by our source trees.
|
||||
proc hwaci-dump-defs-json {file args} {
|
||||
file mkdir [file dirname $file]
|
||||
set lines {}
|
||||
lappend args -bare {SIZEOF_* HAVE_DECL_*} -auto HAVE_*
|
||||
foreach n [lsort [dict keys [all-defines]]] {
|
||||
set type [hwaci-defs-type_ $n $args]
|
||||
set value [hwaci-defs-format_ $type [get-define $n]]
|
||||
if {$::hwaci_(defs-skip) ne $value} {
|
||||
lappend lines "\"$n\": ${value}"
|
||||
}
|
||||
}
|
||||
set buf {}
|
||||
lappend buf [join $lines ",\n"]
|
||||
write-if-changed $file $buf {
|
||||
msg-result "Created $file"
|
||||
}
|
||||
}
|
||||
+51
-6
@@ -1198,6 +1198,11 @@ int Jim_OpenForRead(const char *filename);
|
||||
#define Jim_FileStat _fstat64
|
||||
#define Jim_Lseek _lseeki64
|
||||
#define O_TEXT _O_TEXT
|
||||
#define O_BINARY _O_BINARY
|
||||
#define Jim_SetMode _setmode
|
||||
#ifndef STDIN_FILENO
|
||||
#define STDIN_FILENO 0
|
||||
#endif
|
||||
|
||||
#else
|
||||
#if defined(HAVE_STAT64)
|
||||
@@ -1293,8 +1298,14 @@ int Jim_initjimshInit(Jim_Interp *interp)
|
||||
" if {[string match \"*/*\" $jim::argv0]} {\n"
|
||||
" set jim::exe [file join [pwd] $jim::argv0]\n"
|
||||
" } else {\n"
|
||||
" foreach path [split [env PATH \"\"] $tcl_platform(pathSeparator)] {\n"
|
||||
" set exec [file join [pwd] [string map {\\\\ /} $path] $jim::argv0]\n"
|
||||
" set jim::argv0 [file tail $jim::argv0]\n"
|
||||
" set path [split [env PATH \"\"] $tcl_platform(pathSeparator)]\n"
|
||||
" if {$tcl_platform(platform) eq \"windows\"} {\n"
|
||||
"\n"
|
||||
" set path [lmap p [list \"\" {*}$path] { string map {\\\\ /} $p }]\n"
|
||||
" }\n"
|
||||
" foreach p $path {\n"
|
||||
" set exec [file join [pwd] $p $jim::argv0]\n"
|
||||
" if {[file executable $exec]} {\n"
|
||||
" set jim::exe $exec\n"
|
||||
" break\n"
|
||||
@@ -1858,7 +1869,7 @@ int Jim_tclcompatInit(Jim_Interp *interp)
|
||||
" $f buffering $v\n"
|
||||
" }\n"
|
||||
" -tr* {\n"
|
||||
"\n"
|
||||
" $f translation $v\n"
|
||||
" }\n"
|
||||
" default {\n"
|
||||
" return -code error \"fconfigure: unknown option $n\"\n"
|
||||
@@ -2930,6 +2941,28 @@ static int aio_cmd_buffering(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
|
||||
return JIM_OK;
|
||||
}
|
||||
|
||||
static int aio_cmd_translation(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
|
||||
{
|
||||
enum {OPT_BINARY, OPT_TEXT};
|
||||
static const char * const options[] = {
|
||||
"binary",
|
||||
"text",
|
||||
NULL
|
||||
};
|
||||
int opt;
|
||||
|
||||
if (Jim_GetEnum(interp, argv[0], options, &opt, NULL, JIM_ERRMSG) != JIM_OK) {
|
||||
return JIM_ERR;
|
||||
}
|
||||
#if defined(Jim_SetMode)
|
||||
else {
|
||||
AioFile *af = Jim_CmdPrivData(interp);
|
||||
Jim_SetMode(af->fd, opt == OPT_BINARY ? O_BINARY : O_TEXT);
|
||||
}
|
||||
#endif
|
||||
return JIM_OK;
|
||||
}
|
||||
|
||||
static int aio_cmd_readsize(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
|
||||
{
|
||||
AioFile *af = Jim_CmdPrivData(interp);
|
||||
@@ -3139,6 +3172,13 @@ static const jim_subcmd_type aio_command_table[] = {
|
||||
0,
|
||||
2,
|
||||
|
||||
},
|
||||
{ "translation",
|
||||
"binary|text",
|
||||
aio_cmd_translation,
|
||||
1,
|
||||
1,
|
||||
|
||||
},
|
||||
{ "readsize",
|
||||
"?size?",
|
||||
@@ -19286,7 +19326,7 @@ static int Jim_StringCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *a
|
||||
JIM_DEF_SUBCMD("trim", "string ?trimchars?", 1, 2),
|
||||
JIM_DEF_SUBCMD("trimleft", "string ?trimchars?", 1, 2),
|
||||
JIM_DEF_SUBCMD("trimright", "string ?trimchars?", 1, 2),
|
||||
{ }
|
||||
{ NULL }
|
||||
};
|
||||
const jim_subcmd_type *ct = Jim_ParseSubCmd(interp, cmds, argc, argv);
|
||||
if (!ct) {
|
||||
@@ -20179,7 +20219,7 @@ static int Jim_DictCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
|
||||
JIM_DEF_SUBCMD("for", "vars dictionary script", 3, 3),
|
||||
JIM_DEF_SUBCMD("replace", "dictionary ?key value ...?", 1, -1),
|
||||
JIM_DEF_SUBCMD("update", "varName ?arg ...? script", 2, -1),
|
||||
{ }
|
||||
{ NULL }
|
||||
};
|
||||
const jim_subcmd_type *ct = Jim_ParseSubCmd(interp, cmds, argc, argv);
|
||||
if (!ct) {
|
||||
@@ -20388,7 +20428,7 @@ static int Jim_InfoCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
|
||||
JIM_DEF_SUBCMD("statics", "procname", 1, 1),
|
||||
JIM_DEF_SUBCMD("vars", "?pattern?", 0, 1),
|
||||
JIM_DEF_SUBCMD("version", NULL, 0, 0),
|
||||
{ }
|
||||
{ NULL }
|
||||
};
|
||||
const jim_subcmd_type *ct;
|
||||
#ifdef jim_ext_namespace
|
||||
@@ -24419,6 +24459,10 @@ int main(int argc, char *const argv[])
|
||||
}
|
||||
if (retcode != JIM_EXIT) {
|
||||
JimSetArgv(interp, 0, NULL);
|
||||
if (!isatty(STDIN_FILENO)) {
|
||||
|
||||
goto eval_stdin;
|
||||
}
|
||||
retcode = Jim_InteractivePrompt(interp);
|
||||
}
|
||||
}
|
||||
@@ -24441,6 +24485,7 @@ int main(int argc, char *const argv[])
|
||||
Jim_SetVariableStr(interp, "argv0", Jim_NewStringObj(interp, argv[1], -1));
|
||||
JimSetArgv(interp, argc - 2, argv + 2);
|
||||
if (strcmp(argv[1], "-") == 0) {
|
||||
eval_stdin:
|
||||
retcode = Jim_Eval(interp, "eval [info source [stdin read] stdin 1]");
|
||||
} else {
|
||||
retcode = Jim_EvalFile(interp, argv[1]);
|
||||
|
||||
+1277
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
+93
-85
@@ -55,6 +55,8 @@ options {
|
||||
program-prefix:
|
||||
program-suffix:
|
||||
program-transform-name:
|
||||
x-includes:
|
||||
x-libraries:
|
||||
}
|
||||
|
||||
# @check-feature name { script }
|
||||
@@ -318,95 +320,101 @@ proc make-template {template {out {}}} {
|
||||
}
|
||||
}
|
||||
|
||||
# build/host tuples and cross-compilation prefix
|
||||
opt-str build build ""
|
||||
define build_alias $build
|
||||
if {$build eq ""} {
|
||||
define build [config_guess]
|
||||
} else {
|
||||
define build [config_sub $build]
|
||||
}
|
||||
proc system-init {} {
|
||||
global autosetup
|
||||
|
||||
opt-str host host ""
|
||||
define host_alias $host
|
||||
if {$host eq ""} {
|
||||
define host [get-define build]
|
||||
set cross ""
|
||||
} else {
|
||||
define host [config_sub $host]
|
||||
set cross $host-
|
||||
}
|
||||
define cross [get-env CROSS $cross]
|
||||
|
||||
# build/host _cpu, _vendor and _os
|
||||
foreach type {build host} {
|
||||
set v [get-define $type]
|
||||
if {![regexp {^([^-]+)-([^-]+)-(.*)$} $v -> cpu vendor os]} {
|
||||
user-error "Invalid canonical $type: $v"
|
||||
# build/host tuples and cross-compilation prefix
|
||||
opt-str build build ""
|
||||
define build_alias $build
|
||||
if {$build eq ""} {
|
||||
define build [config_guess]
|
||||
} else {
|
||||
define build [config_sub $build]
|
||||
}
|
||||
define ${type}_cpu $cpu
|
||||
define ${type}_vendor $vendor
|
||||
define ${type}_os $os
|
||||
}
|
||||
|
||||
opt-str prefix prefix /usr/local
|
||||
|
||||
# These are for compatibility with autoconf
|
||||
define target [get-define host]
|
||||
define prefix $prefix
|
||||
define builddir $autosetup(builddir)
|
||||
define srcdir $autosetup(srcdir)
|
||||
define top_srcdir $autosetup(srcdir)
|
||||
define abs_top_srcdir [file-normalize $autosetup(srcdir)]
|
||||
define abs_top_builddir [file-normalize $autosetup(builddir)]
|
||||
|
||||
# autoconf supports all of these
|
||||
define exec_prefix [opt-str exec-prefix exec_prefix $prefix]
|
||||
foreach {name defpath} {
|
||||
bindir /bin
|
||||
sbindir /sbin
|
||||
libexecdir /libexec
|
||||
libdir /lib
|
||||
} {
|
||||
define $name [opt-str $name o $exec_prefix$defpath]
|
||||
}
|
||||
foreach {name defpath} {
|
||||
datadir /share
|
||||
sharedstatedir /com
|
||||
infodir /share/info
|
||||
mandir /share/man
|
||||
includedir /include
|
||||
} {
|
||||
define $name [opt-str $name o $prefix$defpath]
|
||||
}
|
||||
if {$prefix ne {/usr}} {
|
||||
opt-str sysconfdir sysconfdir $prefix/etc
|
||||
} else {
|
||||
opt-str sysconfdir sysconfdir /etc
|
||||
}
|
||||
define sysconfdir $sysconfdir
|
||||
|
||||
define localstatedir [opt-str localstatedir o /var]
|
||||
define runstatedir [opt-str runstatedir o /run]
|
||||
|
||||
define SHELL [get-env SHELL [find-an-executable sh bash ksh]]
|
||||
|
||||
# These could be used to generate Makefiles following some automake conventions
|
||||
define AM_SILENT_RULES [opt-bool silent-rules]
|
||||
define AM_MAINTAINER_MODE [opt-bool maintainer-mode]
|
||||
define AM_DEPENDENCY_TRACKING [opt-bool dependency-tracking]
|
||||
|
||||
# Windows vs. non-Windows
|
||||
switch -glob -- [get-define host] {
|
||||
*-*-ming* - *-*-cygwin - *-*-msys {
|
||||
define-feature windows
|
||||
define EXEEXT .exe
|
||||
opt-str host host ""
|
||||
define host_alias $host
|
||||
if {$host eq ""} {
|
||||
define host [get-define build]
|
||||
set cross ""
|
||||
} else {
|
||||
define host [config_sub $host]
|
||||
set cross $host-
|
||||
}
|
||||
default {
|
||||
define EXEEXT ""
|
||||
define cross [get-env CROSS $cross]
|
||||
|
||||
# build/host _cpu, _vendor and _os
|
||||
foreach type {build host} {
|
||||
set v [get-define $type]
|
||||
if {![regexp {^([^-]+)-([^-]+)-(.*)$} $v -> cpu vendor os]} {
|
||||
user-error "Invalid canonical $type: $v"
|
||||
}
|
||||
define ${type}_cpu $cpu
|
||||
define ${type}_vendor $vendor
|
||||
define ${type}_os $os
|
||||
}
|
||||
|
||||
opt-str prefix prefix /usr/local
|
||||
|
||||
# These are for compatibility with autoconf
|
||||
define target [get-define host]
|
||||
define prefix $prefix
|
||||
define builddir $autosetup(builddir)
|
||||
define srcdir $autosetup(srcdir)
|
||||
define top_srcdir $autosetup(srcdir)
|
||||
define abs_top_srcdir [file-normalize $autosetup(srcdir)]
|
||||
define abs_top_builddir [file-normalize $autosetup(builddir)]
|
||||
|
||||
# autoconf supports all of these
|
||||
define exec_prefix [opt-str exec-prefix exec_prefix $prefix]
|
||||
foreach {name defpath} {
|
||||
bindir /bin
|
||||
sbindir /sbin
|
||||
libexecdir /libexec
|
||||
libdir /lib
|
||||
} {
|
||||
define $name [opt-str $name o $exec_prefix$defpath]
|
||||
}
|
||||
foreach {name defpath} {
|
||||
datadir /share
|
||||
sharedstatedir /com
|
||||
infodir /share/info
|
||||
mandir /share/man
|
||||
includedir /include
|
||||
} {
|
||||
define $name [opt-str $name o $prefix$defpath]
|
||||
}
|
||||
if {$prefix ne {/usr}} {
|
||||
opt-str sysconfdir sysconfdir $prefix/etc
|
||||
} else {
|
||||
opt-str sysconfdir sysconfdir /etc
|
||||
}
|
||||
define sysconfdir $sysconfdir
|
||||
|
||||
define localstatedir [opt-str localstatedir o /var]
|
||||
define runstatedir [opt-str runstatedir o /run]
|
||||
|
||||
define SHELL [get-env SHELL [find-an-executable sh bash ksh]]
|
||||
|
||||
# These could be used to generate Makefiles following some automake conventions
|
||||
define AM_SILENT_RULES [opt-bool silent-rules]
|
||||
define AM_MAINTAINER_MODE [opt-bool maintainer-mode]
|
||||
define AM_DEPENDENCY_TRACKING [opt-bool dependency-tracking]
|
||||
|
||||
# Windows vs. non-Windows
|
||||
switch -glob -- [get-define host] {
|
||||
*-*-ming* - *-*-cygwin - *-*-msys {
|
||||
define-feature windows
|
||||
define EXEEXT .exe
|
||||
}
|
||||
default {
|
||||
define EXEEXT ""
|
||||
}
|
||||
}
|
||||
|
||||
# Display
|
||||
msg-result "Host System...[get-define host]"
|
||||
msg-result "Build System...[get-define build]"
|
||||
}
|
||||
|
||||
# Display
|
||||
msg-result "Host System...[get-define host]"
|
||||
msg-result "Build System...[get-define build]"
|
||||
system-init
|
||||
|
||||
@@ -1,73 +0,0 @@
|
||||
# Copyright (c) 2016 WorkWare Systems http://www.workware.net.au/
|
||||
# All rights reserved
|
||||
|
||||
# Auto-load module for 'tmake' build system integration
|
||||
|
||||
use init
|
||||
|
||||
autosetup_add_init_type tmake "Tcl-based tmake build system" {
|
||||
autosetup_check_create auto.def \
|
||||
{# Initial auto.def created by 'autosetup --init=tmake'
|
||||
# vim:set syntax=tcl:
|
||||
|
||||
use cc cc-lib cc-db cc-shared
|
||||
use tmake
|
||||
|
||||
# Add any user options here
|
||||
# Really want a --configure that takes over the rest of the command line
|
||||
options {
|
||||
}
|
||||
|
||||
cc-check-tools ar ranlib
|
||||
|
||||
set objdir [get-env BUILDDIR objdir]
|
||||
|
||||
make-config-header $objdir/include/autoconf.h
|
||||
make-tmake-settings $objdir/settings.conf {[A-Z]*} *dir lib_*
|
||||
}
|
||||
|
||||
autosetup_check_create project.spec \
|
||||
{# Initial project.spec created by 'autosetup --init=tmake'
|
||||
|
||||
tmake-require-version 0.7.3
|
||||
|
||||
# vim:set syntax=tcl:
|
||||
define? DESTDIR _install
|
||||
|
||||
# XXX If configure creates additional/different files than include/autoconf.h
|
||||
# that should be reflected here
|
||||
Autosetup include/autoconf.h
|
||||
|
||||
# e.g. for autoconf.h
|
||||
IncludePaths include
|
||||
|
||||
ifconfig !CONFIGURED {
|
||||
# Not configured, so don't process subdirs
|
||||
AutoSubDirs off
|
||||
# And don't process this file any further
|
||||
ifconfig false
|
||||
}
|
||||
}
|
||||
|
||||
set configure [readfile configure]
|
||||
# XXX Do we need also need to support a system install of tmake?
|
||||
if {[string first {#@TMAKEUPDATED@} $configure] < 0} {
|
||||
if {[regsub {#@@INITCHECK@@#} $configure \
|
||||
{test -z "$TMAKE" -a -x "$dir/tmake" \&\& exec "$dir/tmake" --force --configure "$@"; #@TMAKEUPDATED@} configure]} {
|
||||
writefile configure $configure\n
|
||||
exec chmod +x configure
|
||||
puts "Updated configure to invoke local tmake."
|
||||
if {![file exec autosetup/tmake]} {
|
||||
puts "Warning: autosetup/tmake is missing."
|
||||
puts " Install it with: tmake --install=autosetup"
|
||||
}
|
||||
} else {
|
||||
puts "Warning: configure isn't created by a recent autosetup, not updating."
|
||||
}
|
||||
} else {
|
||||
puts "I see configure for tmake already exists."
|
||||
}
|
||||
if {![file exists build.spec]} {
|
||||
puts "Note: I don't see build.spec. Try running: tmake --genie"
|
||||
}
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
# Copyright (c) 2011 WorkWare Systems http://www.workware.net.au/
|
||||
# All rights reserved
|
||||
|
||||
# @synopsis:
|
||||
#
|
||||
# The 'tmake' module makes it easy to support the tmake build system.
|
||||
#
|
||||
# The following variables are set:
|
||||
#
|
||||
## CONFIGURED - to indicate that the project is configured
|
||||
|
||||
use system
|
||||
|
||||
options {}
|
||||
|
||||
define CONFIGURED
|
||||
|
||||
# @make-tmake-settings outfile patterns ...
|
||||
#
|
||||
# Examines all defined variables which match the given patterns (defaults to '*')
|
||||
# and writes a tmake-compatible .conf file defining those variables.
|
||||
# For example, if 'ABC' is '"3 monkeys"' and 'ABC' matches a pattern, then the file will include:
|
||||
#
|
||||
## define ABC {3 monkeys}
|
||||
#
|
||||
# If the file would be unchanged, it is not written.
|
||||
#
|
||||
# Typical usage is:
|
||||
#
|
||||
## make-tmake-settings [get-env BUILDDIR objdir]/settings.conf {[A-Z]*}
|
||||
proc make-tmake-settings {file args} {
|
||||
file mkdir [file dirname $file]
|
||||
set lines {}
|
||||
|
||||
if {[llength $args] == 0} {
|
||||
set args *
|
||||
}
|
||||
|
||||
foreach n [lsort [dict keys [all-defines]]] {
|
||||
foreach p $args {
|
||||
if {[string match $p $n]} {
|
||||
set value [get-define $n]
|
||||
lappend lines "define $n [list $value]"
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
set buf [join $lines \n]
|
||||
write-if-changed $file $buf {
|
||||
msg-result "Created $file"
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,8 @@ Here are step-by-step instructions on how to build SQLite from
|
||||
canonical source on any modern machine that isn't Windows. These
|
||||
notes are tested (on 2024-10-11) on Ubuntu and on MacOS, but they
|
||||
are general and should work on most any modern unix platform.
|
||||
See the companion document ([](./compile-for-windows.md>)) for
|
||||
guidance on building for Windows.
|
||||
|
||||
1. Install a C-compiler. GCC or Clang both work fine. If you are
|
||||
reading this document, you've probably already done that.
|
||||
@@ -12,6 +14,8 @@ are general and should work on most any modern unix platform.
|
||||
we'll do a private install in the $HOME/local directory,
|
||||
but you can make adjustments to install TCL wherever you like.
|
||||
This document assumes you are working with TCL version 9.0.
|
||||
See also the [](./tcl-extension-testing.md) document that contains
|
||||
more details on compiling Tcl for use with SQLite.
|
||||
<ol type="a">
|
||||
<li>Get the TCL source archive, perhaps from
|
||||
<https://www.tcl.tk/software/tcltk/download.html>
|
||||
@@ -45,7 +49,7 @@ are general and should work on most any modern unix platform.
|
||||
<li> `make sqldiff`
|
||||
<li> `make sqlite3_rsync`
|
||||
</ul>
|
||||
<p>None of the targets above require TCL. TCL is only needed
|
||||
<p>None of the targets above require TCL. TCL is needed
|
||||
for the following targets:
|
||||
<ul>
|
||||
<li> `make tclextension-install`
|
||||
|
||||
@@ -1,12 +1,23 @@
|
||||
# Notes On Compiling SQLite On Windows 11
|
||||
|
||||
Here are step-by-step instructions on how to build SQLite from
|
||||
canonical source on a new Windows 11 PC, as of 2024-10-09:
|
||||
Below are step-by-step instructions on how to build SQLite from
|
||||
canonical source on a new Windows 11 PC, as of 2024-10-09.
|
||||
See [](./compile-for-unix.md) for a similar guide for unix-like
|
||||
systems, including MacOS.
|
||||
|
||||
1. Install Microsoft Visual Studio. The free "community edition"
|
||||
will work fine. Do a standard install for C++ development.
|
||||
SQLite only needs the
|
||||
"cl" compiler and the "nmake" build tool.
|
||||
<ul><li><b>Note:</b>
|
||||
VS2015 or later is required for the procedures below to
|
||||
all work. You *might* be able to get the build to work with
|
||||
earlier versions of MSVC, but in that case the TCL installation
|
||||
of step 3 will be required, since the "jimsh0.c" program of
|
||||
Autosetup that is used as a substitute for "tclsh.exe" won't
|
||||
compile with versions of Visual Studio prior to VS2015. In any
|
||||
event, building SQLite from canonical source code on Windows
|
||||
is not supported for earlier versions of Visual Studio.</ul>
|
||||
|
||||
2. Under the "Start" menu, find "All Apps" then go to "Visual Studio 20XX"
|
||||
and find "x64 Native Tools Command Prompt for VS 20XX". Pin that
|
||||
@@ -24,16 +35,21 @@ canonical source on a new Windows 11 PC, as of 2024-10-09:
|
||||
"tclsh90.exe" command-line tool as part of the build process, and
|
||||
the "tcl90.lib" and "tclstub.lib" libraries in order to run tests.
|
||||
This document assumes you are working with TCL version 9.0.
|
||||
See versions of this document from prior to 2024-10-10 for
|
||||
instructions on how to build using TCL version 8.6.
|
||||
See [](./tcl-extension-testing.md#windows) for guidance on how
|
||||
to compile TCL version 8.6 for use with SQLite.
|
||||
<ol type="a">
|
||||
<li>Get the TCL source archive, perhaps from
|
||||
<https://www.tcl.tk/software/tcltk/download.html>
|
||||
or <https://sqlite.org/tmp/tcl9.0.0.tar.gz>.
|
||||
<li>Untar or unzip the source archive. CD into the "win/" subfolder
|
||||
of the source tree.
|
||||
<li>Run: `nmake /f makefile.vc release`
|
||||
<li>Run: `nmake /f makefile.vc INSTALLDIR=c:\Tcl install`
|
||||
<li>Run: `nmake /f makefile.vc INSTALLDIR=c:\Tcl release`
|
||||
<li>Run: `nmake /f makefile.vc INSTALLDIR=c:\Tcl install` <br>
|
||||
Notes:
|
||||
<ol type="i">
|
||||
<li> The previous two `nmake` commands must be run separately.
|
||||
<li> Also, the INSTALLDIR=... argument is required on both.
|
||||
</ol>
|
||||
<li><i>Optional:</i> CD to `c:\Tcl\bin` and make a copy of
|
||||
`tclsh90.exe` over into just `tclsh.exe`.
|
||||
<li><i>Optional:</i>
|
||||
|
||||
@@ -0,0 +1,208 @@
|
||||
# Test Procedures For The SQLite TCL Extension
|
||||
|
||||
## 1.0 Background
|
||||
|
||||
The SQLite TCL extension logic (in the
|
||||
"[tclsqlite.c](/file/src/tclsqlite.c)" source
|
||||
file) is statically linked into "textfixture" executable
|
||||
which is the program used to do most of the testing
|
||||
associated with "make test", "make devtest", and/or
|
||||
"make releasetest". So the functionality of the SQLite
|
||||
TCL extension is thoroughly vetted during normal testing. The
|
||||
procedures below are designed to test the loadable extension
|
||||
aspect of the SQLite TCL extension, and in particular to verify
|
||||
that the "make tclextension-install" build target works and that
|
||||
an ordinary tclsh can subsequently run "package require sqlite3".
|
||||
|
||||
This procedure can also be used as a template for how to set up
|
||||
a local TCL+SQLite development environment. In other words, it
|
||||
can be be used as a guide on how to compile per-user copies of
|
||||
Tcl that are used to develop, test, and debug SQLite. In that
|
||||
case, perhaps make minor changes to the procedure such as:
|
||||
|
||||
* Make TCLBUILD directory is permanent.
|
||||
* Enable debugging symbols on the Tcl library build.
|
||||
* Reduce the optimization level to -O0 for easier debugging.
|
||||
* Also compile "wish" to go with each "tclsh".
|
||||
|
||||
|
||||
<a id="unix"></a>
|
||||
## 2.0 Testing On Unix-like Systems (Including Mac)
|
||||
|
||||
See also the [](./compile-for-unix.md) document which provides another
|
||||
perspective on how to compile SQLite on unix-like systems.
|
||||
|
||||
### 2.1 Setup
|
||||
|
||||
<ol type="1">
|
||||
<li value="1">
|
||||
[Fossil](https://fossil-scm.org/) installed.
|
||||
<li> Check out source code and set environment variables:
|
||||
<ol type="a">
|
||||
<li> **TCLSOURCE** →
|
||||
The top-level directory of a Fossil check-out of the TCL source tree.
|
||||
<li> **SQLITESOURCE** →
|
||||
A Fossil check-out of the SQLite source tree.
|
||||
<li> **TCLBUILD** →
|
||||
A directory that does not exist at the start of the test and which
|
||||
will be deleted at the end of the test, and that will contain the
|
||||
test builds of the TCL libraries and the SQLite TCL Extensions.
|
||||
</ol>
|
||||
</ol>
|
||||
|
||||
### 2.2 Testing TCL 8.6 on unix
|
||||
|
||||
<ol type="1">
|
||||
<li value="3"> `mkdir -p $TCLBUILD/tcl86`
|
||||
<li> `cd $TCLSOURCE/unix`
|
||||
<li> `fossil up core-8-6-16` <br>
|
||||
↑ Or some other version of Tcl8.6.
|
||||
<li> `fossil clean -x`
|
||||
<li> `./configure --prefix=$TCLBUILD/tcl86 --disable-shared` <br>
|
||||
↑ The --disable-shared is to avoid the need to set LD_LIBRARY_PATH
|
||||
when using this Tcl build.
|
||||
<li> `make install`
|
||||
<li> `cd $SQLITESOURCE`
|
||||
<li> `fossil clean -x`
|
||||
<li> `./configure --with-tclsh=$TCLBUILD/tcl86/bin/tclsh8.6 --all`
|
||||
<li> `make tclextension-install` <br>
|
||||
↑ Verify extension installed at $TCLBUILD/tcl86/lib/tcl8.6/sqlite3.*
|
||||
<li> `make tclextension-list` <br>
|
||||
↑ Verify TCL extension correctly installed.
|
||||
<li> `make tclextension-verify` <br>
|
||||
↑ Verify that the correct version is installed.
|
||||
<li> `$TCLBUILD/tcl86/bin/tclsh8.6 test/testrunner.tcl release --explain` <br>
|
||||
↑ Verify thousands of lines of output with no errors. Or
|
||||
consider running "devtest" without --explain instead of "release".
|
||||
</ol>
|
||||
|
||||
### 2.3 Testing TCL 9.0 on unix
|
||||
|
||||
<ol>
|
||||
<li value="16"> `mkdir -p $TCLBUILD/tcl90`
|
||||
<li> `fossil up core-9-0-0` <br>
|
||||
↑ Or some other version of Tcl9
|
||||
<li> `fossil clean -x`
|
||||
<li> `./configure --prefix=$TCLBUILD/tcl90 --disable-shared` <br>
|
||||
↑ The --disable-shared is to avoid the need to set LD_LIBRARY_PATH
|
||||
when using this Tcl build.
|
||||
<li> `make install`
|
||||
<li> `cp -r ../library $TCLBUILD/tcl90/lib/tcl9.0` <br>
|
||||
↑ The Tcl library is not installed by "make install" for Tcl9.0 unless
|
||||
you also include the --disable-zipfs to ./configure. But if you do that
|
||||
then the generated tclsh9.0 is no longer stand-alone. On the other hand,
|
||||
if you don't install the Tcl library, other programs like testfixture
|
||||
won't be able to find the Tcl library and hence won't work. This
|
||||
extra installation step resolves the dilemma.
|
||||
This step is not required when building Tcl8.6, which lacks support for
|
||||
zipfs and hence always installs its Tcl library.
|
||||
<li> `cd $SQLITESOURCE`
|
||||
<li> `fossil clean -x`
|
||||
<li> `./configure --with-tclsh=$TCLBUILD/tcl90/bin/tclsh9.0 --all`
|
||||
<li> `make tclextension-install` <br>
|
||||
↑ Verify extension installed at $TCLBUILD/tcl90/lib/sqlite3.*
|
||||
<li> `make tclextension-list` <br>
|
||||
↑ Verify TCL extension correctly installed.
|
||||
<li> `make tclextension-verify`
|
||||
<li> `$TCLBUILD/tcl90/bin/tclsh9.0 test/testrunner.tcl release --explain` <br>
|
||||
↑ Verify thousands of lines of output with no errors. Or
|
||||
consider running "devtest" without --explain instead of "release".
|
||||
</ol>
|
||||
|
||||
### 2.4 Cleanup
|
||||
|
||||
<ol type="1">
|
||||
<li value="29"> `rm -rf $TCLBUILD`
|
||||
</ol>
|
||||
|
||||
<a id="windows"></a>
|
||||
## 3.0 Testing On Windows
|
||||
|
||||
See also the [](./compile-for-windows.md) document which provides another
|
||||
perspective on how to compile SQLite on Windows.
|
||||
|
||||
### 3.1 Setup for Windows
|
||||
|
||||
<ol type="1">
|
||||
<li value="1">
|
||||
[Fossil](https://fossil-scm.org/) installed.
|
||||
<li>
|
||||
Unix-like command-line tools installed. Example:
|
||||
[unxutils](https://unxutils.sourceforge.net/)
|
||||
<li> [Visual Studio](https://visualstudio.microsoft.com/vs/community/)
|
||||
installed. VS2015 or later required.
|
||||
<li> Check out source code and set environment variables.
|
||||
<ol type="a">
|
||||
<li> **TCLSOURCE** →
|
||||
The top-level directory of a Fossil check-out of the TCL source tree.
|
||||
<li> **SQLITESOURCE** →
|
||||
A Fossil check-out of the SQLite source tree.
|
||||
<li> **TCLBUILD** →
|
||||
A directory that does not exist at the start of the test and which
|
||||
will be deleted at the end of the test, and that will contain the
|
||||
test builds of the TCL libraries and the SQLite TCL Extensions.
|
||||
<li> **ORIGINALPATH** →
|
||||
The original value of %PATH%. In other words, set as follows:
|
||||
`set ORIGINALPATH %PATH%`
|
||||
</ol>
|
||||
</ol>
|
||||
|
||||
### 3.2 Testing TCL 8.6 on Windows
|
||||
|
||||
<ol type="1">
|
||||
<li value="5"> `mkdir %TCLBUILD%\tcl86`
|
||||
<li> `cd %TCLSOURCE%\win`
|
||||
<li> `fossil up core-8-6-16` <br>
|
||||
↑ Or some other version of Tcl8.6.
|
||||
<li> `fossil clean -x`
|
||||
<li> `set INSTALLDIR=%TCLBUILD%\tcl86`
|
||||
<li> `nmake /f makefile.vc release` <br>
|
||||
⇅ You *must* invoke the "release" and "install" targets
|
||||
using separate "nmake" commands or tclsh86t.exe won't be
|
||||
installed.
|
||||
<li> `nmake /f makefile.vc install`
|
||||
<li> `cd %SQLITESOURCE%`
|
||||
<li> `fossil clean -x`
|
||||
<li> `set TCLDIR=%TCLBUILD%\tcl86`
|
||||
<li> `set PATH=%TCLBUILD%\tcl86\bin;%ORIGINALPATH%`
|
||||
<li> `set TCLSH_CMD=%TCLBUILD%\tcl86\bin\tclsh86t.exe`
|
||||
<li> `nmake /f Makefile.msc tclextension-install` <br>
|
||||
↑ Verify extension installed at %TCLBUILD%\\tcl86\\lib\\tcl8.6\\sqlite3.*
|
||||
<li> `nmake /f Makefile.msc tclextension-verify`
|
||||
<li>`tclsh86t test/testrunner.tcl release --explain` <br>
|
||||
↑ Verify thousands of lines of output with no errors. Or
|
||||
consider running "devtest" without --explain instead of "release".
|
||||
</ol>
|
||||
|
||||
### 3.3 Testing TCL 9.0 on Windows
|
||||
|
||||
<ol>
|
||||
<li value="20"> `mkdir %TCLBUILD%\tcl90`
|
||||
<li> `cd %TCLSOURCE%\win`
|
||||
<li> `fossil up core-9-0-0` <br>
|
||||
↑ Or some other version of Tcl9
|
||||
<li> `fossil clean -x`
|
||||
<li> `set INSTALLDIR=%TCLBUILD%\tcl90`
|
||||
<li> `nmake /f makefile.vc release` <br>
|
||||
⇅ You *must* invoke the "release" and "install" targets
|
||||
using separate "nmake" commands or tclsh90.exe won't be
|
||||
installed.
|
||||
<li> `nmake /f makefile.vc install`
|
||||
<li> `cd %SQLITESOURCE%`
|
||||
<li> `fossil clean -x`
|
||||
<li> `set TCLDIR=%TCLBUILD%\tcl90`
|
||||
<li> `set PATH=%TCLBUILD%\tcl90\bin;%ORIGINALPATH%`
|
||||
<li> `set TCLSH_CMD=%TCLBUILD%\tcl90\bin\tclsh90.exe`
|
||||
<li> `nmake /f Makefile.msc tclextension-install` <br>
|
||||
↑ Verify extension installed at %TCLBUILD%\\tcl90\\lib\\sqlite3.*
|
||||
<li> `nmake /f Makefile.msc tclextension-verify`
|
||||
<li> `tclsh90 test/testrunner.tcl release --explain` <br>
|
||||
↑ Verify thousands of lines of output with no errors. Or
|
||||
consider running "devtest" without --explain instead of "release".
|
||||
</ol>
|
||||
|
||||
### 3.4 Cleanup
|
||||
|
||||
<ol type="1">
|
||||
<li value="35"> `rm -rf %TCLBUILD%`
|
||||
</ol>
|
||||
@@ -1,170 +0,0 @@
|
||||
NOTE (2012-11-29):
|
||||
|
||||
The functionality implemented by this extension has been superseded
|
||||
by WAL-mode. This module is no longer supported or maintained. The
|
||||
code is retained for historical reference only.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
Normally, when SQLite writes to a database file, it waits until the write
|
||||
operation is finished before returning control to the calling application.
|
||||
Since writing to the file-system is usually very slow compared with CPU
|
||||
bound operations, this can be a performance bottleneck. This directory
|
||||
contains an extension that causes SQLite to perform all write requests
|
||||
using a separate thread running in the background. Although this does not
|
||||
reduce the overall system resources (CPU, disk bandwidth etc.) at all, it
|
||||
allows SQLite to return control to the caller quickly even when writing to
|
||||
the database, eliminating the bottleneck.
|
||||
|
||||
1. Functionality
|
||||
|
||||
1.1 How it Works
|
||||
1.2 Limitations
|
||||
1.3 Locking and Concurrency
|
||||
|
||||
2. Compilation and Usage
|
||||
|
||||
3. Porting
|
||||
|
||||
|
||||
|
||||
1. FUNCTIONALITY
|
||||
|
||||
With asynchronous I/O, write requests are handled by a separate thread
|
||||
running in the background. This means that the thread that initiates
|
||||
a database write does not have to wait for (sometimes slow) disk I/O
|
||||
to occur. The write seems to happen very quickly, though in reality
|
||||
it is happening at its usual slow pace in the background.
|
||||
|
||||
Asynchronous I/O appears to give better responsiveness, but at a price.
|
||||
You lose the Durable property. With the default I/O backend of SQLite,
|
||||
once a write completes, you know that the information you wrote is
|
||||
safely on disk. With the asynchronous I/O, this is not the case. If
|
||||
your program crashes or if a power loss occurs after the database
|
||||
write but before the asynchronous write thread has completed, then the
|
||||
database change might never make it to disk and the next user of the
|
||||
database might not see your change.
|
||||
|
||||
You lose Durability with asynchronous I/O, but you still retain the
|
||||
other parts of ACID: Atomic, Consistent, and Isolated. Many
|
||||
appliations get along fine without the Durablity.
|
||||
|
||||
1.1 How it Works
|
||||
|
||||
Asynchronous I/O works by creating a special SQLite "vfs" structure
|
||||
and registering it with sqlite3_vfs_register(). When files opened via
|
||||
this vfs are written to (using the vfs xWrite() method), the data is not
|
||||
written directly to disk, but is placed in the "write-queue" to be
|
||||
handled by the background thread.
|
||||
|
||||
When files opened with the asynchronous vfs are read from
|
||||
(using the vfs xRead() method), the data is read from the file on
|
||||
disk and the write-queue, so that from the point of view of
|
||||
the vfs reader the xWrite() appears to have already completed.
|
||||
|
||||
The special vfs is registered (and unregistered) by calls to the
|
||||
API functions sqlite3async_initialize() and sqlite3async_shutdown().
|
||||
See section "Compilation and Usage" below for details.
|
||||
|
||||
1.2 Limitations
|
||||
|
||||
In order to gain experience with the main ideas surrounding asynchronous
|
||||
IO, this implementation is deliberately kept simple. Additional
|
||||
capabilities may be added in the future.
|
||||
|
||||
For example, as currently implemented, if writes are happening at a
|
||||
steady stream that exceeds the I/O capability of the background writer
|
||||
thread, the queue of pending write operations will grow without bound.
|
||||
If this goes on for long enough, the host system could run out of memory.
|
||||
A more sophisticated module could to keep track of the quantity of
|
||||
pending writes and stop accepting new write requests when the queue of
|
||||
pending writes grows too large.
|
||||
|
||||
1.3 Locking and Concurrency
|
||||
|
||||
Multiple connections from within a single process that use this
|
||||
implementation of asynchronous IO may access a single database
|
||||
file concurrently. From the point of view of the user, if all
|
||||
connections are from within a single process, there is no difference
|
||||
between the concurrency offered by "normal" SQLite and SQLite
|
||||
using the asynchronous backend.
|
||||
|
||||
If file-locking is enabled (it is enabled by default), then connections
|
||||
from multiple processes may also read and write the database file.
|
||||
However concurrency is reduced as follows:
|
||||
|
||||
* When a connection using asynchronous IO begins a database
|
||||
transaction, the database is locked immediately. However the
|
||||
lock is not released until after all relevant operations
|
||||
in the write-queue have been flushed to disk. This means
|
||||
(for example) that the database may remain locked for some
|
||||
time after a "COMMIT" or "ROLLBACK" is issued.
|
||||
|
||||
* If an application using asynchronous IO executes transactions
|
||||
in quick succession, other database users may be effectively
|
||||
locked out of the database. This is because when a BEGIN
|
||||
is executed, a database lock is established immediately. But
|
||||
when the corresponding COMMIT or ROLLBACK occurs, the lock
|
||||
is not released until the relevant part of the write-queue
|
||||
has been flushed through. As a result, if a COMMIT is followed
|
||||
by a BEGIN before the write-queue is flushed through, the database
|
||||
is never unlocked,preventing other processes from accessing
|
||||
the database.
|
||||
|
||||
File-locking may be disabled at runtime using the sqlite3async_control()
|
||||
API (see below). This may improve performance when an NFS or other
|
||||
network file-system, as the synchronous round-trips to the server be
|
||||
required to establish file locks are avoided. However, if multiple
|
||||
connections attempt to access the same database file when file-locking
|
||||
is disabled, application crashes and database corruption is a likely
|
||||
outcome.
|
||||
|
||||
|
||||
2. COMPILATION AND USAGE
|
||||
|
||||
The asynchronous IO extension consists of a single file of C code
|
||||
(sqlite3async.c), and a header file (sqlite3async.h) that defines the
|
||||
C API used by applications to activate and control the modules
|
||||
functionality.
|
||||
|
||||
To use the asynchronous IO extension, compile sqlite3async.c as
|
||||
part of the application that uses SQLite. Then use the API defined
|
||||
in sqlite3async.h to initialize and configure the module.
|
||||
|
||||
The asynchronous IO VFS API is described in detail in comments in
|
||||
sqlite3async.h. Using the API usually consists of the following steps:
|
||||
|
||||
1. Register the asynchronous IO VFS with SQLite by calling the
|
||||
sqlite3async_initialize() function.
|
||||
|
||||
2. Create a background thread to perform write operations and call
|
||||
sqlite3async_run().
|
||||
|
||||
3. Use the normal SQLite API to read and write to databases via
|
||||
the asynchronous IO VFS.
|
||||
|
||||
Refer to sqlite3async.h for details.
|
||||
|
||||
|
||||
3. PORTING
|
||||
|
||||
Currently the asynchronous IO extension is compatible with win32 systems
|
||||
and systems that support the pthreads interface, including Mac OSX, Linux,
|
||||
and other varieties of Unix.
|
||||
|
||||
To port the asynchronous IO extension to another platform, the user must
|
||||
implement mutex and condition variable primitives for the new platform.
|
||||
Currently there is no externally available interface to allow this, but
|
||||
modifying the code within sqlite3async.c to include the new platforms
|
||||
concurrency primitives is relatively easy. Search within sqlite3async.c
|
||||
for the comment string "PORTING FUNCTIONS" for details. Then implement
|
||||
new versions of each of the following:
|
||||
|
||||
static void async_mutex_enter(int eMutex);
|
||||
static void async_mutex_leave(int eMutex);
|
||||
static void async_cond_wait(int eCond, int eMutex);
|
||||
static void async_cond_signal(int eCond);
|
||||
static void async_sched_yield(void);
|
||||
|
||||
The functionality required of each of the above functions is described
|
||||
in comments in sqlite3async.c.
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,222 +0,0 @@
|
||||
|
||||
#ifndef __SQLITEASYNC_H_
|
||||
#define __SQLITEASYNC_H_ 1
|
||||
|
||||
/*
|
||||
** Make sure we can call this stuff from C++.
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define SQLITEASYNC_VFSNAME "sqlite3async"
|
||||
|
||||
/*
|
||||
** THREAD SAFETY NOTES:
|
||||
**
|
||||
** Of the four API functions in this file, the following are not threadsafe:
|
||||
**
|
||||
** sqlite3async_initialize()
|
||||
** sqlite3async_shutdown()
|
||||
**
|
||||
** Care must be taken that neither of these functions is called while
|
||||
** another thread may be calling either any sqlite3async_XXX() function
|
||||
** or an sqlite3_XXX() API function related to a database handle that
|
||||
** is using the asynchronous IO VFS.
|
||||
**
|
||||
** These functions:
|
||||
**
|
||||
** sqlite3async_run()
|
||||
** sqlite3async_control()
|
||||
**
|
||||
** are threadsafe. It is quite safe to call either of these functions even
|
||||
** if another thread may also be calling one of them or an sqlite3_XXX()
|
||||
** function related to a database handle that uses the asynchronous IO VFS.
|
||||
*/
|
||||
|
||||
/*
|
||||
** Initialize the asynchronous IO VFS and register it with SQLite using
|
||||
** sqlite3_vfs_register(). If the asynchronous VFS is already initialized
|
||||
** and registered, this function is a no-op. The asynchronous IO VFS
|
||||
** is registered as "sqlite3async".
|
||||
**
|
||||
** The asynchronous IO VFS does not make operating system IO requests
|
||||
** directly. Instead, it uses an existing VFS implementation for all
|
||||
** required file-system operations. If the first parameter to this function
|
||||
** is NULL, then the current default VFS is used for IO. If it is not
|
||||
** NULL, then it must be the name of an existing VFS. In other words, the
|
||||
** first argument to this function is passed to sqlite3_vfs_find() to
|
||||
** locate the VFS to use for all real IO operations. This VFS is known
|
||||
** as the "parent VFS".
|
||||
**
|
||||
** If the second parameter to this function is non-zero, then the
|
||||
** asynchronous IO VFS is registered as the default VFS for all SQLite
|
||||
** database connections within the process. Otherwise, the asynchronous IO
|
||||
** VFS is only used by connections opened using sqlite3_open_v2() that
|
||||
** specifically request VFS "sqlite3async".
|
||||
**
|
||||
** If a parent VFS cannot be located, then SQLITE_ERROR is returned.
|
||||
** In the unlikely event that operating system specific initialization
|
||||
** fails (win32 systems create the required critical section and event
|
||||
** objects within this function), then SQLITE_ERROR is also returned.
|
||||
** Finally, if the call to sqlite3_vfs_register() returns an error, then
|
||||
** the error code is returned to the user by this function. In all three
|
||||
** of these cases, intialization has failed and the asynchronous IO VFS
|
||||
** is not registered with SQLite.
|
||||
**
|
||||
** Otherwise, if no error occurs, SQLITE_OK is returned.
|
||||
*/
|
||||
int sqlite3async_initialize(const char *zParent, int isDefault);
|
||||
|
||||
/*
|
||||
** This function unregisters the asynchronous IO VFS using
|
||||
** sqlite3_vfs_unregister().
|
||||
**
|
||||
** On win32 platforms, this function also releases the small number of
|
||||
** critical section and event objects created by sqlite3async_initialize().
|
||||
*/
|
||||
void sqlite3async_shutdown(void);
|
||||
|
||||
/*
|
||||
** This function may only be called when the asynchronous IO VFS is
|
||||
** installed (after a call to sqlite3async_initialize()). It processes
|
||||
** zero or more queued write operations before returning. It is expected
|
||||
** (but not required) that this function will be called by a different
|
||||
** thread than those threads that use SQLite. The "background thread"
|
||||
** that performs IO.
|
||||
**
|
||||
** How many queued write operations are performed before returning
|
||||
** depends on the global setting configured by passing the SQLITEASYNC_HALT
|
||||
** verb to sqlite3async_control() (see below for details). By default
|
||||
** this function never returns - it processes all pending operations and
|
||||
** then blocks waiting for new ones.
|
||||
**
|
||||
** If multiple simultaneous calls are made to sqlite3async_run() from two
|
||||
** or more threads, then the calls are serialized internally.
|
||||
*/
|
||||
void sqlite3async_run(void);
|
||||
|
||||
/*
|
||||
** This function may only be called when the asynchronous IO VFS is
|
||||
** installed (after a call to sqlite3async_initialize()). It is used
|
||||
** to query or configure various parameters that affect the operation
|
||||
** of the asynchronous IO VFS. At present there are three parameters
|
||||
** supported:
|
||||
**
|
||||
** * The "halt" parameter, which configures the circumstances under
|
||||
** which the sqlite3async_run() parameter is configured.
|
||||
**
|
||||
** * The "delay" parameter. Setting the delay parameter to a non-zero
|
||||
** value causes the sqlite3async_run() function to sleep for the
|
||||
** configured number of milliseconds between each queued write
|
||||
** operation.
|
||||
**
|
||||
** * The "lockfiles" parameter. This parameter determines whether or
|
||||
** not the asynchronous IO VFS locks the database files it operates
|
||||
** on. Disabling file locking can improve throughput.
|
||||
**
|
||||
** This function is always passed two arguments. When setting the value
|
||||
** of a parameter, the first argument must be one of SQLITEASYNC_HALT,
|
||||
** SQLITEASYNC_DELAY or SQLITEASYNC_LOCKFILES. The second argument must
|
||||
** be passed the new value for the parameter as type "int".
|
||||
**
|
||||
** When querying the current value of a paramter, the first argument must
|
||||
** be one of SQLITEASYNC_GET_HALT, GET_DELAY or GET_LOCKFILES. The second
|
||||
** argument to this function must be of type (int *). The current value
|
||||
** of the queried parameter is copied to the memory pointed to by the
|
||||
** second argument. For example:
|
||||
**
|
||||
** int eCurrentHalt;
|
||||
** int eNewHalt = SQLITEASYNC_HALT_IDLE;
|
||||
**
|
||||
** sqlite3async_control(SQLITEASYNC_HALT, eNewHalt);
|
||||
** sqlite3async_control(SQLITEASYNC_GET_HALT, &eCurrentHalt);
|
||||
** assert( eNewHalt==eCurrentHalt );
|
||||
**
|
||||
** See below for more detail on each configuration parameter.
|
||||
**
|
||||
** SQLITEASYNC_HALT:
|
||||
**
|
||||
** This is used to set the value of the "halt" parameter. The second
|
||||
** argument must be one of the SQLITEASYNC_HALT_XXX symbols defined
|
||||
** below (either NEVER, IDLE and NOW).
|
||||
**
|
||||
** If the parameter is set to NEVER, then calls to sqlite3async_run()
|
||||
** never return. This is the default setting. If the parameter is set
|
||||
** to IDLE, then calls to sqlite3async_run() return as soon as the
|
||||
** queue of pending write operations is empty. If the parameter is set
|
||||
** to NOW, then calls to sqlite3async_run() return as quickly as
|
||||
** possible, without processing any pending write requests.
|
||||
**
|
||||
** If an attempt is made to set this parameter to an integer value other
|
||||
** than SQLITEASYNC_HALT_NEVER, IDLE or NOW, then sqlite3async_control()
|
||||
** returns SQLITE_MISUSE and the current value of the parameter is not
|
||||
** modified.
|
||||
**
|
||||
** Modifying the "halt" parameter affects calls to sqlite3async_run()
|
||||
** made by other threads that are currently in progress.
|
||||
**
|
||||
** SQLITEASYNC_DELAY:
|
||||
**
|
||||
** This is used to set the value of the "delay" parameter. If set to
|
||||
** a non-zero value, then after completing a pending write request, the
|
||||
** sqlite3async_run() function sleeps for the configured number of
|
||||
** milliseconds.
|
||||
**
|
||||
** If an attempt is made to set this parameter to a negative value,
|
||||
** sqlite3async_control() returns SQLITE_MISUSE and the current value
|
||||
** of the parameter is not modified.
|
||||
**
|
||||
** Modifying the "delay" parameter affects calls to sqlite3async_run()
|
||||
** made by other threads that are currently in progress.
|
||||
**
|
||||
** SQLITEASYNC_LOCKFILES:
|
||||
**
|
||||
** This is used to set the value of the "lockfiles" parameter. This
|
||||
** parameter must be set to either 0 or 1. If set to 1, then the
|
||||
** asynchronous IO VFS uses the xLock() and xUnlock() methods of the
|
||||
** parent VFS to lock database files being read and/or written. If
|
||||
** the parameter is set to 0, then these locks are omitted.
|
||||
**
|
||||
** This parameter may only be set when there are no open database
|
||||
** connections using the VFS and the queue of pending write requests
|
||||
** is empty. Attempting to set it when this is not true, or to set it
|
||||
** to a value other than 0 or 1 causes sqlite3async_control() to return
|
||||
** SQLITE_MISUSE and the value of the parameter to remain unchanged.
|
||||
**
|
||||
** If this parameter is set to zero, then it is only safe to access the
|
||||
** database via the asynchronous IO VFS from within a single process. If
|
||||
** while writing to the database via the asynchronous IO VFS the database
|
||||
** is also read or written from within another process, or via another
|
||||
** connection that does not use the asynchronous IO VFS within the same
|
||||
** process, the results are undefined (and may include crashes or database
|
||||
** corruption).
|
||||
**
|
||||
** Alternatively, if this parameter is set to 1, then it is safe to access
|
||||
** the database from multiple connections within multiple processes using
|
||||
** either the asynchronous IO VFS or the parent VFS directly.
|
||||
*/
|
||||
int sqlite3async_control(int op, ...);
|
||||
|
||||
/*
|
||||
** Values that can be used as the first argument to sqlite3async_control().
|
||||
*/
|
||||
#define SQLITEASYNC_HALT 1
|
||||
#define SQLITEASYNC_GET_HALT 2
|
||||
#define SQLITEASYNC_DELAY 3
|
||||
#define SQLITEASYNC_GET_DELAY 4
|
||||
#define SQLITEASYNC_LOCKFILES 5
|
||||
#define SQLITEASYNC_GET_LOCKFILES 6
|
||||
|
||||
/*
|
||||
** If the first argument to sqlite3async_control() is SQLITEASYNC_HALT,
|
||||
** the second argument should be one of the following.
|
||||
*/
|
||||
#define SQLITEASYNC_HALT_NEVER 0 /* Never halt (default value) */
|
||||
#define SQLITEASYNC_HALT_NOW 1 /* Halt as soon as possible */
|
||||
#define SQLITEASYNC_HALT_IDLE 2 /* Halt when write-queue is empty */
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* End of the 'extern "C"' block */
|
||||
#endif
|
||||
#endif /* ifndef __SQLITEASYNC_H_ */
|
||||
@@ -1,773 +0,0 @@
|
||||
/*
|
||||
** 2023 November 4
|
||||
**
|
||||
** The author disclaims copyright to this source code. In place of
|
||||
** a legal notice, here is a blessing:
|
||||
**
|
||||
** May you do good and not evil.
|
||||
** May you find forgiveness for yourself and forgive others.
|
||||
** May you share freely, never taking more than you give.
|
||||
**
|
||||
********************************************************************************
|
||||
** This file implements various interfaces used for console and stream I/O
|
||||
** by the SQLite project command-line tools, as explained in console_io.h .
|
||||
** Functions prefixed by "SQLITE_INTERNAL_LINKAGE" behave as described there.
|
||||
*/
|
||||
|
||||
#ifndef SQLITE_CDECL
|
||||
# define SQLITE_CDECL
|
||||
#endif
|
||||
|
||||
#ifndef SHELL_NO_SYSINC
|
||||
# include <stdarg.h>
|
||||
# include <string.h>
|
||||
# include <stdlib.h>
|
||||
# include <limits.h>
|
||||
# include <assert.h>
|
||||
# include "sqlite3.h"
|
||||
#endif
|
||||
#ifndef HAVE_CONSOLE_IO_H
|
||||
# include "console_io.h"
|
||||
#endif
|
||||
#if defined(_MSC_VER)
|
||||
# pragma warning(disable : 4204)
|
||||
#endif
|
||||
|
||||
#ifndef SQLITE_CIO_NO_TRANSLATE
|
||||
# if (defined(_WIN32) || defined(WIN32)) && !SQLITE_OS_WINRT
|
||||
# ifndef SHELL_NO_SYSINC
|
||||
# include <io.h>
|
||||
# include <fcntl.h>
|
||||
# undef WIN32_LEAN_AND_MEAN
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
# include <windows.h>
|
||||
# endif
|
||||
# define CIO_WIN_WC_XLATE 1 /* Use WCHAR Windows APIs for console I/O */
|
||||
# else
|
||||
# ifndef SHELL_NO_SYSINC
|
||||
# include <unistd.h>
|
||||
# endif
|
||||
# define CIO_WIN_WC_XLATE 0 /* Use plain C library stream I/O at console */
|
||||
# endif
|
||||
#else
|
||||
# define CIO_WIN_WC_XLATE 0 /* Not exposing translation routines at all */
|
||||
#endif
|
||||
|
||||
#if CIO_WIN_WC_XLATE
|
||||
static HANDLE handleOfFile(FILE *pf){
|
||||
int fileDesc = _fileno(pf);
|
||||
union { intptr_t osfh; HANDLE fh; } fid = {
|
||||
(fileDesc>=0)? _get_osfhandle(fileDesc) : (intptr_t)INVALID_HANDLE_VALUE
|
||||
};
|
||||
return fid.fh;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef SQLITE_CIO_NO_TRANSLATE
|
||||
typedef struct PerStreamTags {
|
||||
# if CIO_WIN_WC_XLATE
|
||||
HANDLE hx;
|
||||
DWORD consMode;
|
||||
char acIncomplete[4];
|
||||
# else
|
||||
short reachesConsole;
|
||||
# endif
|
||||
FILE *pf;
|
||||
} PerStreamTags;
|
||||
|
||||
/* Define NULL-like value for things which can validly be 0. */
|
||||
# define SHELL_INVALID_FILE_PTR ((FILE *)~0)
|
||||
# if CIO_WIN_WC_XLATE
|
||||
# define SHELL_INVALID_CONS_MODE 0xFFFF0000
|
||||
# endif
|
||||
|
||||
# if CIO_WIN_WC_XLATE
|
||||
# define PST_INITIALIZER { INVALID_HANDLE_VALUE, SHELL_INVALID_CONS_MODE, \
|
||||
{0,0,0,0}, SHELL_INVALID_FILE_PTR }
|
||||
# else
|
||||
# define PST_INITIALIZER { 0, SHELL_INVALID_FILE_PTR }
|
||||
# endif
|
||||
|
||||
/* Quickly say whether a known output is going to the console. */
|
||||
# if CIO_WIN_WC_XLATE
|
||||
static short pstReachesConsole(PerStreamTags *ppst){
|
||||
return (ppst->hx != INVALID_HANDLE_VALUE);
|
||||
}
|
||||
# else
|
||||
# define pstReachesConsole(ppst) 0
|
||||
# endif
|
||||
|
||||
# if CIO_WIN_WC_XLATE
|
||||
static void restoreConsoleArb(PerStreamTags *ppst){
|
||||
if( pstReachesConsole(ppst) ) SetConsoleMode(ppst->hx, ppst->consMode);
|
||||
}
|
||||
# else
|
||||
# define restoreConsoleArb(ppst)
|
||||
# endif
|
||||
|
||||
/* Say whether FILE* appears to be a console, collect associated info. */
|
||||
static short streamOfConsole(FILE *pf, /* out */ PerStreamTags *ppst){
|
||||
# if CIO_WIN_WC_XLATE
|
||||
short rv = 0;
|
||||
DWORD dwCM = SHELL_INVALID_CONS_MODE;
|
||||
HANDLE fh = handleOfFile(pf);
|
||||
ppst->pf = pf;
|
||||
if( INVALID_HANDLE_VALUE != fh ){
|
||||
rv = (GetFileType(fh) == FILE_TYPE_CHAR && GetConsoleMode(fh,&dwCM));
|
||||
}
|
||||
ppst->hx = (rv)? fh : INVALID_HANDLE_VALUE;
|
||||
ppst->consMode = dwCM;
|
||||
return rv;
|
||||
# else
|
||||
ppst->pf = pf;
|
||||
ppst->reachesConsole = ( (short)isatty(fileno(pf)) );
|
||||
return ppst->reachesConsole;
|
||||
# endif
|
||||
}
|
||||
|
||||
# ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
|
||||
# define ENABLE_VIRTUAL_TERMINAL_PROCESSING (0x4)
|
||||
# endif
|
||||
|
||||
# if CIO_WIN_WC_XLATE
|
||||
/* Define console modes for use with the Windows Console API. */
|
||||
# define SHELL_CONI_MODE \
|
||||
(ENABLE_ECHO_INPUT | ENABLE_INSERT_MODE | ENABLE_LINE_INPUT | 0x80 \
|
||||
| ENABLE_QUICK_EDIT_MODE | ENABLE_EXTENDED_FLAGS | ENABLE_PROCESSED_INPUT)
|
||||
# define SHELL_CONO_MODE (ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT \
|
||||
| ENABLE_VIRTUAL_TERMINAL_PROCESSING)
|
||||
# endif
|
||||
|
||||
typedef struct ConsoleInfo {
|
||||
PerStreamTags pstSetup[3];
|
||||
PerStreamTags pstDesignated[3];
|
||||
StreamsAreConsole sacSetup;
|
||||
} ConsoleInfo;
|
||||
|
||||
static short isValidStreamInfo(PerStreamTags *ppst){
|
||||
return (ppst->pf != SHELL_INVALID_FILE_PTR);
|
||||
}
|
||||
|
||||
static ConsoleInfo consoleInfo = {
|
||||
{ /* pstSetup */ PST_INITIALIZER, PST_INITIALIZER, PST_INITIALIZER },
|
||||
{ /* pstDesignated[] */ PST_INITIALIZER, PST_INITIALIZER, PST_INITIALIZER },
|
||||
SAC_NoConsole /* sacSetup */
|
||||
};
|
||||
|
||||
SQLITE_INTERNAL_LINKAGE FILE* invalidFileStream = (FILE *)~0;
|
||||
|
||||
# if CIO_WIN_WC_XLATE
|
||||
static void maybeSetupAsConsole(PerStreamTags *ppst, short odir){
|
||||
if( pstReachesConsole(ppst) ){
|
||||
DWORD cm = odir? SHELL_CONO_MODE : SHELL_CONI_MODE;
|
||||
SetConsoleMode(ppst->hx, cm);
|
||||
}
|
||||
}
|
||||
# else
|
||||
# define maybeSetupAsConsole(ppst,odir)
|
||||
# endif
|
||||
|
||||
SQLITE_INTERNAL_LINKAGE void consoleRenewSetup(void){
|
||||
# if CIO_WIN_WC_XLATE
|
||||
int ix = 0;
|
||||
while( ix < 6 ){
|
||||
PerStreamTags *ppst = (ix<3)?
|
||||
&consoleInfo.pstSetup[ix] : &consoleInfo.pstDesignated[ix-3];
|
||||
maybeSetupAsConsole(ppst, (ix % 3)>0);
|
||||
++ix;
|
||||
}
|
||||
# endif
|
||||
}
|
||||
|
||||
SQLITE_INTERNAL_LINKAGE StreamsAreConsole
|
||||
consoleClassifySetup( FILE *pfIn, FILE *pfOut, FILE *pfErr ){
|
||||
StreamsAreConsole rv = SAC_NoConsole;
|
||||
FILE* apf[3] = { pfIn, pfOut, pfErr };
|
||||
int ix;
|
||||
for( ix = 2; ix >= 0; --ix ){
|
||||
PerStreamTags *ppst = &consoleInfo.pstSetup[ix];
|
||||
if( streamOfConsole(apf[ix], ppst) ){
|
||||
rv |= (SAC_InConsole<<ix);
|
||||
}
|
||||
consoleInfo.pstDesignated[ix] = *ppst;
|
||||
if( ix > 0 ) fflush(apf[ix]);
|
||||
}
|
||||
consoleInfo.sacSetup = rv;
|
||||
consoleRenewSetup();
|
||||
return rv;
|
||||
}
|
||||
|
||||
SQLITE_INTERNAL_LINKAGE void SQLITE_CDECL consoleRestore( void ){
|
||||
# if CIO_WIN_WC_XLATE
|
||||
static ConsoleInfo *pci = &consoleInfo;
|
||||
if( pci->sacSetup ){
|
||||
int ix;
|
||||
for( ix=0; ix<3; ++ix ){
|
||||
if( pci->sacSetup & (SAC_InConsole<<ix) ){
|
||||
PerStreamTags *ppst = &pci->pstSetup[ix];
|
||||
SetConsoleMode(ppst->hx, ppst->consMode);
|
||||
}
|
||||
}
|
||||
}
|
||||
# endif
|
||||
}
|
||||
#endif /* !defined(SQLITE_CIO_NO_TRANSLATE) */
|
||||
|
||||
#ifdef SQLITE_CIO_INPUT_REDIR
|
||||
/* Say whether given FILE* is among those known, via either
|
||||
** consoleClassifySetup() or set{Output,Error}Stream, as
|
||||
** readable, and return an associated PerStreamTags pointer
|
||||
** if so. Otherwise, return 0.
|
||||
*/
|
||||
static PerStreamTags * isKnownReadable(FILE *pf){
|
||||
static PerStreamTags *apst[] = {
|
||||
&consoleInfo.pstDesignated[0], &consoleInfo.pstSetup[0], 0
|
||||
};
|
||||
int ix = 0;
|
||||
do {
|
||||
if( apst[ix]->pf == pf ) break;
|
||||
} while( apst[++ix] != 0 );
|
||||
return apst[ix];
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef SQLITE_CIO_NO_TRANSLATE
|
||||
/* Say whether given FILE* is among those known, via either
|
||||
** consoleClassifySetup() or set{Output,Error}Stream, as
|
||||
** writable, and return an associated PerStreamTags pointer
|
||||
** if so. Otherwise, return 0.
|
||||
*/
|
||||
static PerStreamTags * isKnownWritable(FILE *pf){
|
||||
static PerStreamTags *apst[] = {
|
||||
&consoleInfo.pstDesignated[1], &consoleInfo.pstDesignated[2],
|
||||
&consoleInfo.pstSetup[1], &consoleInfo.pstSetup[2], 0
|
||||
};
|
||||
int ix = 0;
|
||||
do {
|
||||
if( apst[ix]->pf == pf ) break;
|
||||
} while( apst[++ix] != 0 );
|
||||
return apst[ix];
|
||||
}
|
||||
|
||||
static FILE *designateEmitStream(FILE *pf, unsigned chix){
|
||||
FILE *rv = consoleInfo.pstDesignated[chix].pf;
|
||||
if( pf == invalidFileStream ) return rv;
|
||||
else{
|
||||
/* Setting a possibly new output stream. */
|
||||
PerStreamTags *ppst = isKnownWritable(pf);
|
||||
if( ppst != 0 ){
|
||||
PerStreamTags pst = *ppst;
|
||||
consoleInfo.pstDesignated[chix] = pst;
|
||||
}else streamOfConsole(pf, &consoleInfo.pstDesignated[chix]);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
SQLITE_INTERNAL_LINKAGE FILE *setOutputStream(FILE *pf){
|
||||
return designateEmitStream(pf, 1);
|
||||
}
|
||||
# ifdef CONSIO_SET_ERROR_STREAM
|
||||
SQLITE_INTERNAL_LINKAGE FILE *setErrorStream(FILE *pf){
|
||||
return designateEmitStream(pf, 2);
|
||||
}
|
||||
# endif
|
||||
#endif /* !defined(SQLITE_CIO_NO_TRANSLATE) */
|
||||
|
||||
#ifndef SQLITE_CIO_NO_SETMODE
|
||||
# if CIO_WIN_WC_XLATE
|
||||
static void setModeFlushQ(FILE *pf, short bFlush, int mode){
|
||||
if( bFlush ) fflush(pf);
|
||||
_setmode(_fileno(pf), mode);
|
||||
}
|
||||
# else
|
||||
# define setModeFlushQ(f, b, m) if(b) fflush(f)
|
||||
# endif
|
||||
|
||||
SQLITE_INTERNAL_LINKAGE void setBinaryMode(FILE *pf, short bFlush){
|
||||
setModeFlushQ(pf, bFlush, _O_BINARY);
|
||||
}
|
||||
SQLITE_INTERNAL_LINKAGE void setTextMode(FILE *pf, short bFlush){
|
||||
setModeFlushQ(pf, bFlush, _O_TEXT);
|
||||
}
|
||||
# undef setModeFlushQ
|
||||
|
||||
#else /* defined(SQLITE_CIO_NO_SETMODE) */
|
||||
# define setBinaryMode(f, bFlush) do{ if((bFlush)) fflush(f); }while(0)
|
||||
# define setTextMode(f, bFlush) do{ if((bFlush)) fflush(f); }while(0)
|
||||
#endif /* defined(SQLITE_CIO_NO_SETMODE) */
|
||||
|
||||
#ifndef SQLITE_CIO_NO_TRANSLATE
|
||||
# if CIO_WIN_WC_XLATE
|
||||
/* Write buffer cBuf as output to stream known to reach console,
|
||||
** limited to ncTake char's. Return ncTake on success, else 0. */
|
||||
static int conZstrEmit(PerStreamTags *ppst, const char *z, int ncTake){
|
||||
int rv = 0;
|
||||
if( z!=NULL ){
|
||||
int nwc = MultiByteToWideChar(CP_UTF8,0, z,ncTake, 0,0);
|
||||
if( nwc > 0 ){
|
||||
WCHAR *zw = sqlite3_malloc64(nwc*sizeof(WCHAR));
|
||||
if( zw!=NULL ){
|
||||
nwc = MultiByteToWideChar(CP_UTF8,0, z,ncTake, zw,nwc);
|
||||
if( nwc > 0 ){
|
||||
/* Translation from UTF-8 to UTF-16, then WCHARs out. */
|
||||
if( WriteConsoleW(ppst->hx, zw,nwc, 0, NULL) ){
|
||||
rv = ncTake;
|
||||
}
|
||||
}
|
||||
sqlite3_free(zw);
|
||||
}
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* For {f,o,e}PrintfUtf8() when stream is known to reach console. */
|
||||
static int conioVmPrintf(PerStreamTags *ppst, const char *zFormat, va_list ap){
|
||||
char *z = sqlite3_vmprintf(zFormat, ap);
|
||||
if( z ){
|
||||
int rv = conZstrEmit(ppst, z, (int)strlen(z));
|
||||
sqlite3_free(z);
|
||||
return rv;
|
||||
}else return 0;
|
||||
}
|
||||
# endif /* CIO_WIN_WC_XLATE */
|
||||
|
||||
# ifdef CONSIO_GET_EMIT_STREAM
|
||||
static PerStreamTags * getDesignatedEmitStream(FILE *pf, unsigned chix,
|
||||
PerStreamTags *ppst){
|
||||
PerStreamTags *rv = isKnownWritable(pf);
|
||||
short isValid = (rv!=0)? isValidStreamInfo(rv) : 0;
|
||||
if( rv != 0 && isValid ) return rv;
|
||||
streamOfConsole(pf, ppst);
|
||||
return ppst;
|
||||
}
|
||||
# endif
|
||||
|
||||
/* Get stream info, either for designated output or error stream when
|
||||
** chix equals 1 or 2, or for an arbitrary stream when chix == 0.
|
||||
** In either case, ppst references a caller-owned PerStreamTags
|
||||
** struct which may be filled in if none of the known writable
|
||||
** streams is being held by consoleInfo. The ppf parameter is a
|
||||
** byref output when chix!=0 and a byref input when chix==0.
|
||||
*/
|
||||
static PerStreamTags *
|
||||
getEmitStreamInfo(unsigned chix, PerStreamTags *ppst,
|
||||
/* in/out */ FILE **ppf){
|
||||
PerStreamTags *ppstTry;
|
||||
FILE *pfEmit;
|
||||
if( chix > 0 ){
|
||||
ppstTry = &consoleInfo.pstDesignated[chix];
|
||||
if( !isValidStreamInfo(ppstTry) ){
|
||||
ppstTry = &consoleInfo.pstSetup[chix];
|
||||
pfEmit = ppst->pf;
|
||||
}else pfEmit = ppstTry->pf;
|
||||
if( !isValidStreamInfo(ppstTry) ){
|
||||
pfEmit = (chix > 1)? stderr : stdout;
|
||||
ppstTry = ppst;
|
||||
streamOfConsole(pfEmit, ppstTry);
|
||||
}
|
||||
*ppf = pfEmit;
|
||||
}else{
|
||||
ppstTry = isKnownWritable(*ppf);
|
||||
if( ppstTry != 0 ) return ppstTry;
|
||||
streamOfConsole(*ppf, ppst);
|
||||
return ppst;
|
||||
}
|
||||
return ppstTry;
|
||||
}
|
||||
|
||||
SQLITE_INTERNAL_LINKAGE int oPrintfUtf8(const char *zFormat, ...){
|
||||
va_list ap;
|
||||
int rv;
|
||||
FILE *pfOut;
|
||||
PerStreamTags pst = PST_INITIALIZER; /* for unknown streams */
|
||||
# if CIO_WIN_WC_XLATE
|
||||
PerStreamTags *ppst = getEmitStreamInfo(1, &pst, &pfOut);
|
||||
# else
|
||||
getEmitStreamInfo(1, &pst, &pfOut);
|
||||
# endif
|
||||
assert(zFormat!=0);
|
||||
va_start(ap, zFormat);
|
||||
# if CIO_WIN_WC_XLATE
|
||||
if( pstReachesConsole(ppst) ){
|
||||
rv = conioVmPrintf(ppst, zFormat, ap);
|
||||
}else{
|
||||
# endif
|
||||
rv = vfprintf(pfOut, zFormat, ap);
|
||||
# if CIO_WIN_WC_XLATE
|
||||
}
|
||||
# endif
|
||||
va_end(ap);
|
||||
return rv;
|
||||
}
|
||||
|
||||
SQLITE_INTERNAL_LINKAGE int ePrintfUtf8(const char *zFormat, ...){
|
||||
va_list ap;
|
||||
int rv;
|
||||
FILE *pfErr;
|
||||
PerStreamTags pst = PST_INITIALIZER; /* for unknown streams */
|
||||
# if CIO_WIN_WC_XLATE
|
||||
PerStreamTags *ppst = getEmitStreamInfo(2, &pst, &pfErr);
|
||||
# else
|
||||
getEmitStreamInfo(2, &pst, &pfErr);
|
||||
# endif
|
||||
assert(zFormat!=0);
|
||||
va_start(ap, zFormat);
|
||||
# if CIO_WIN_WC_XLATE
|
||||
if( pstReachesConsole(ppst) ){
|
||||
rv = conioVmPrintf(ppst, zFormat, ap);
|
||||
}else{
|
||||
# endif
|
||||
rv = vfprintf(pfErr, zFormat, ap);
|
||||
# if CIO_WIN_WC_XLATE
|
||||
}
|
||||
# endif
|
||||
va_end(ap);
|
||||
return rv;
|
||||
}
|
||||
|
||||
SQLITE_INTERNAL_LINKAGE int fPrintfUtf8(FILE *pfO, const char *zFormat, ...){
|
||||
va_list ap;
|
||||
int rv;
|
||||
PerStreamTags pst = PST_INITIALIZER; /* for unknown streams */
|
||||
# if CIO_WIN_WC_XLATE
|
||||
PerStreamTags *ppst = getEmitStreamInfo(0, &pst, &pfO);
|
||||
# else
|
||||
getEmitStreamInfo(0, &pst, &pfO);
|
||||
# endif
|
||||
assert(zFormat!=0);
|
||||
va_start(ap, zFormat);
|
||||
# if CIO_WIN_WC_XLATE
|
||||
if( pstReachesConsole(ppst) ){
|
||||
maybeSetupAsConsole(ppst, 1);
|
||||
rv = conioVmPrintf(ppst, zFormat, ap);
|
||||
if( 0 == isKnownWritable(ppst->pf) ) restoreConsoleArb(ppst);
|
||||
}else{
|
||||
# endif
|
||||
rv = vfprintf(pfO, zFormat, ap);
|
||||
# if CIO_WIN_WC_XLATE
|
||||
}
|
||||
# endif
|
||||
va_end(ap);
|
||||
return rv;
|
||||
}
|
||||
|
||||
SQLITE_INTERNAL_LINKAGE int fPutsUtf8(const char *z, FILE *pfO){
|
||||
PerStreamTags pst = PST_INITIALIZER; /* for unknown streams */
|
||||
# if CIO_WIN_WC_XLATE
|
||||
PerStreamTags *ppst = getEmitStreamInfo(0, &pst, &pfO);
|
||||
# else
|
||||
getEmitStreamInfo(0, &pst, &pfO);
|
||||
# endif
|
||||
assert(z!=0);
|
||||
# if CIO_WIN_WC_XLATE
|
||||
if( pstReachesConsole(ppst) ){
|
||||
int rv;
|
||||
maybeSetupAsConsole(ppst, 1);
|
||||
rv = conZstrEmit(ppst, z, (int)strlen(z));
|
||||
if( 0 == isKnownWritable(ppst->pf) ) restoreConsoleArb(ppst);
|
||||
return rv;
|
||||
}else {
|
||||
# endif
|
||||
return (fputs(z, pfO)<0)? 0 : (int)strlen(z);
|
||||
# if CIO_WIN_WC_XLATE
|
||||
}
|
||||
# endif
|
||||
}
|
||||
|
||||
SQLITE_INTERNAL_LINKAGE int ePutsUtf8(const char *z){
|
||||
FILE *pfErr;
|
||||
PerStreamTags pst = PST_INITIALIZER; /* for unknown streams */
|
||||
# if CIO_WIN_WC_XLATE
|
||||
PerStreamTags *ppst = getEmitStreamInfo(2, &pst, &pfErr);
|
||||
# else
|
||||
getEmitStreamInfo(2, &pst, &pfErr);
|
||||
# endif
|
||||
assert(z!=0);
|
||||
# if CIO_WIN_WC_XLATE
|
||||
if( pstReachesConsole(ppst) ) return conZstrEmit(ppst, z, (int)strlen(z));
|
||||
else {
|
||||
# endif
|
||||
return (fputs(z, pfErr)<0)? 0 : (int)strlen(z);
|
||||
# if CIO_WIN_WC_XLATE
|
||||
}
|
||||
# endif
|
||||
}
|
||||
|
||||
SQLITE_INTERNAL_LINKAGE int oPutsUtf8(const char *z){
|
||||
FILE *pfOut;
|
||||
PerStreamTags pst = PST_INITIALIZER; /* for unknown streams */
|
||||
# if CIO_WIN_WC_XLATE
|
||||
PerStreamTags *ppst = getEmitStreamInfo(1, &pst, &pfOut);
|
||||
# else
|
||||
getEmitStreamInfo(1, &pst, &pfOut);
|
||||
# endif
|
||||
assert(z!=0);
|
||||
# if CIO_WIN_WC_XLATE
|
||||
if( pstReachesConsole(ppst) ) return conZstrEmit(ppst, z, (int)strlen(z));
|
||||
else {
|
||||
# endif
|
||||
return (fputs(z, pfOut)<0)? 0 : (int)strlen(z);
|
||||
# if CIO_WIN_WC_XLATE
|
||||
}
|
||||
# endif
|
||||
}
|
||||
|
||||
#endif /* !defined(SQLITE_CIO_NO_TRANSLATE) */
|
||||
|
||||
#if !(defined(SQLITE_CIO_NO_UTF8SCAN) && defined(SQLITE_CIO_NO_TRANSLATE))
|
||||
/* Skip over as much z[] input char sequence as is valid UTF-8,
|
||||
** limited per nAccept char's or whole characters and containing
|
||||
** no char cn such that ((1<<cn) & ccm)!=0. On return, the
|
||||
** sequence z:return (inclusive:exclusive) is validated UTF-8.
|
||||
** Limit: nAccept>=0 => char count, nAccept<0 => character
|
||||
*/
|
||||
SQLITE_INTERNAL_LINKAGE const char*
|
||||
zSkipValidUtf8(const char *z, int nAccept, long ccm){
|
||||
int ng = (nAccept<0)? -nAccept : 0;
|
||||
const char *pcLimit = (nAccept>=0)? z+nAccept : 0;
|
||||
assert(z!=0);
|
||||
while( (pcLimit)? (z<pcLimit) : (ng-- != 0) ){
|
||||
char c = *z;
|
||||
if( (c & 0x80) == 0 ){
|
||||
if( ccm != 0L && c < 0x20 && ((1L<<c) & ccm) != 0 ) return z;
|
||||
++z; /* ASCII */
|
||||
}else if( (c & 0xC0) != 0xC0 ) return z; /* not a lead byte */
|
||||
else{
|
||||
const char *zt = z+1; /* Got lead byte, look at trail bytes.*/
|
||||
do{
|
||||
if( pcLimit && zt >= pcLimit ) return z;
|
||||
else{
|
||||
char ct = *zt++;
|
||||
if( ct==0 || (zt-z)>4 || (ct & 0xC0)!=0x80 ){
|
||||
/* Trailing bytes are too few, too many, or invalid. */
|
||||
return z;
|
||||
}
|
||||
}
|
||||
} while( ((c <<= 1) & 0x40) == 0x40 ); /* Eat lead byte's count. */
|
||||
z = zt;
|
||||
}
|
||||
}
|
||||
return z;
|
||||
}
|
||||
#endif /*!(defined(SQLITE_CIO_NO_UTF8SCAN)&&defined(SQLITE_CIO_NO_TRANSLATE))*/
|
||||
|
||||
#ifndef SQLITE_CIO_NO_TRANSLATE
|
||||
# ifdef CONSIO_SPUTB
|
||||
SQLITE_INTERNAL_LINKAGE int
|
||||
fPutbUtf8(FILE *pfO, const char *cBuf, int nAccept){
|
||||
assert(pfO!=0);
|
||||
# if CIO_WIN_WC_XLATE
|
||||
PerStreamTags pst = PST_INITIALIZER; /* for unknown streams */
|
||||
PerStreamTags *ppst = getEmitStreamInfo(0, &pst, &pfO);
|
||||
if( pstReachesConsole(ppst) ){
|
||||
int rv;
|
||||
maybeSetupAsConsole(ppst, 1);
|
||||
rv = conZstrEmit(ppst, cBuf, nAccept);
|
||||
if( 0 == isKnownWritable(ppst->pf) ) restoreConsoleArb(ppst);
|
||||
return rv;
|
||||
}else {
|
||||
# endif
|
||||
return (int)fwrite(cBuf, 1, nAccept, pfO);
|
||||
# if CIO_WIN_WC_XLATE
|
||||
}
|
||||
# endif
|
||||
}
|
||||
# endif
|
||||
|
||||
SQLITE_INTERNAL_LINKAGE int
|
||||
oPutbUtf8(const char *cBuf, int nAccept){
|
||||
FILE *pfOut;
|
||||
PerStreamTags pst = PST_INITIALIZER; /* for unknown streams */
|
||||
# if CIO_WIN_WC_XLATE
|
||||
PerStreamTags *ppst = getEmitStreamInfo(1, &pst, &pfOut);
|
||||
# else
|
||||
getEmitStreamInfo(1, &pst, &pfOut);
|
||||
# endif
|
||||
# if CIO_WIN_WC_XLATE
|
||||
if( pstReachesConsole(ppst) ){
|
||||
return conZstrEmit(ppst, cBuf, nAccept);
|
||||
}else {
|
||||
# endif
|
||||
return (int)fwrite(cBuf, 1, nAccept, pfOut);
|
||||
# if CIO_WIN_WC_XLATE
|
||||
}
|
||||
# endif
|
||||
}
|
||||
|
||||
/*
|
||||
** Flush the given output stream. Return non-zero for success, else 0.
|
||||
*/
|
||||
#if !defined(SQLITE_CIO_NO_FLUSH) && !defined(SQLITE_CIO_NO_SETMODE)
|
||||
SQLITE_INTERNAL_LINKAGE int
|
||||
fFlushBuffer(FILE *pfOut){
|
||||
# if CIO_WIN_WC_XLATE && !defined(SHELL_OMIT_FIO_DUPE)
|
||||
return FlushFileBuffers(handleOfFile(pfOut))? 1 : 0;
|
||||
# else
|
||||
return fflush(pfOut);
|
||||
# endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CIO_WIN_WC_XLATE \
|
||||
&& !defined(SHELL_OMIT_FIO_DUPE) \
|
||||
&& defined(SQLITE_USE_ONLY_WIN32)
|
||||
static struct FileAltIds {
|
||||
int fd;
|
||||
HANDLE fh;
|
||||
} altIdsOfFile(FILE *pf){
|
||||
struct FileAltIds rv = { _fileno(pf) };
|
||||
union { intptr_t osfh; HANDLE fh; } fid = {
|
||||
(rv.fd>=0)? _get_osfhandle(rv.fd) : (intptr_t)INVALID_HANDLE_VALUE
|
||||
};
|
||||
rv.fh = fid.fh;
|
||||
return rv;
|
||||
}
|
||||
|
||||
SQLITE_INTERNAL_LINKAGE size_t
|
||||
cfWrite(const void *buf, size_t osz, size_t ocnt, FILE *pf){
|
||||
size_t rv = 0;
|
||||
struct FileAltIds fai = altIdsOfFile(pf);
|
||||
int fmode = _setmode(fai.fd, _O_BINARY);
|
||||
_setmode(fai.fd, fmode);
|
||||
while( rv < ocnt ){
|
||||
size_t nbo = osz;
|
||||
while( nbo > 0 ){
|
||||
DWORD dwno = (nbo>(1L<<24))? 1L<<24 : (DWORD)nbo;
|
||||
BOOL wrc = TRUE;
|
||||
BOOL genCR = (fmode & _O_TEXT)!=0;
|
||||
if( genCR ){
|
||||
const char *pnl = (const char*)memchr(buf, '\n', nbo);
|
||||
if( pnl ) nbo = pnl - (const char*)buf;
|
||||
else genCR = 0;
|
||||
}
|
||||
if( dwno>0 ) wrc = WriteFile(fai.fh, buf, dwno, 0,0);
|
||||
if( genCR && wrc ){
|
||||
wrc = WriteFile(fai.fh, "\r\n", 2, 0,0);
|
||||
++dwno; /* Skip over the LF */
|
||||
}
|
||||
if( !wrc ) return rv;
|
||||
buf = (const char*)buf + dwno;
|
||||
nbo += dwno;
|
||||
}
|
||||
++rv;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* An fgets() equivalent, using Win32 file API for actual input.
|
||||
** Input ends when given buffer is filled or a newline is read.
|
||||
** If the FILE object is in text mode, swallows 0x0D. (ASCII CR)
|
||||
*/
|
||||
SQLITE_INTERNAL_LINKAGE char *
|
||||
cfGets(char *cBuf, int n, FILE *pf){
|
||||
int nci = 0;
|
||||
struct FileAltIds fai = altIdsOfFile(pf);
|
||||
int fmode = _setmode(fai.fd, _O_BINARY);
|
||||
BOOL eatCR = (fmode & _O_TEXT)!=0;
|
||||
_setmode(fai.fd, fmode);
|
||||
while( nci < n-1 ){
|
||||
DWORD nr;
|
||||
if( !ReadFile(fai.fh, cBuf+nci, 1, &nr, 0) || nr==0 ) break;
|
||||
if( nr>0 && (!eatCR || cBuf[nci]!='\r') ){
|
||||
nci += nr;
|
||||
if( cBuf[nci-nr]=='\n' ) break;
|
||||
}
|
||||
}
|
||||
if( nci < n ) cBuf[nci] = 0;
|
||||
return (nci>0)? cBuf : 0;
|
||||
}
|
||||
# else
|
||||
# define cfWrite(b,os,no,f) fwrite(b,os,no,f)
|
||||
# define cfGets(b,n,f) fgets(b,n,f)
|
||||
# endif
|
||||
|
||||
# ifdef CONSIO_EPUTB
|
||||
SQLITE_INTERNAL_LINKAGE int
|
||||
ePutbUtf8(const char *cBuf, int nAccept){
|
||||
FILE *pfErr;
|
||||
PerStreamTags pst = PST_INITIALIZER; /* for unknown streams */
|
||||
PerStreamTags *ppst = getEmitStreamInfo(2, &pst, &pfErr);
|
||||
# if CIO_WIN_WC_XLATE
|
||||
if( pstReachesConsole(ppst) ){
|
||||
return conZstrEmit(ppst, cBuf, nAccept);
|
||||
}else {
|
||||
# endif
|
||||
return (int)cfWrite(cBuf, 1, nAccept, pfErr);
|
||||
# if CIO_WIN_WC_XLATE
|
||||
}
|
||||
# endif
|
||||
}
|
||||
# endif /* defined(CONSIO_EPUTB) */
|
||||
|
||||
SQLITE_INTERNAL_LINKAGE char* fGetsUtf8(char *cBuf, int ncMax, FILE *pfIn){
|
||||
if( pfIn==0 ) pfIn = stdin;
|
||||
# if CIO_WIN_WC_XLATE
|
||||
if( pfIn == consoleInfo.pstSetup[0].pf
|
||||
&& (consoleInfo.sacSetup & SAC_InConsole)!=0 ){
|
||||
# if CIO_WIN_WC_XLATE==1
|
||||
# define SHELL_GULP 150 /* Count of WCHARS to be gulped at a time */
|
||||
WCHAR wcBuf[SHELL_GULP+1];
|
||||
int lend = 0, noc = 0;
|
||||
if( ncMax > 0 ) cBuf[0] = 0;
|
||||
while( noc < ncMax-8-1 && !lend ){
|
||||
/* There is room for at least 2 more characters and a 0-terminator. */
|
||||
int na = (ncMax > SHELL_GULP*4+1 + noc)? SHELL_GULP : (ncMax-1 - noc)/4;
|
||||
# undef SHELL_GULP
|
||||
DWORD nbr = 0;
|
||||
BOOL bRC = ReadConsoleW(consoleInfo.pstSetup[0].hx, wcBuf, na, &nbr, 0);
|
||||
if( bRC && nbr>0 && (wcBuf[nbr-1]&0xF800)==0xD800 ){
|
||||
/* Last WHAR read is first of a UTF-16 surrogate pair. Grab its mate. */
|
||||
DWORD nbrx;
|
||||
bRC &= ReadConsoleW(consoleInfo.pstSetup[0].hx, wcBuf+nbr, 1, &nbrx, 0);
|
||||
if( bRC ) nbr += nbrx;
|
||||
}
|
||||
if( !bRC || (noc==0 && nbr==0) ) return 0;
|
||||
if( nbr > 0 ){
|
||||
int nmb = WideCharToMultiByte(CP_UTF8, 0, wcBuf,nbr,0,0,0,0);
|
||||
if( nmb != 0 && noc+nmb <= ncMax ){
|
||||
int iseg = noc;
|
||||
nmb = WideCharToMultiByte(CP_UTF8, 0, wcBuf,nbr,cBuf+noc,nmb,0,0);
|
||||
noc += nmb;
|
||||
/* Fixup line-ends as coded by Windows for CR (or "Enter".)
|
||||
** This is done without regard for any setMode{Text,Binary}()
|
||||
** call that might have been done on the interactive input.
|
||||
*/
|
||||
if( noc > 0 ){
|
||||
if( cBuf[noc-1]=='\n' ){
|
||||
lend = 1;
|
||||
if( noc > 1 && cBuf[noc-2]=='\r' ) cBuf[--noc-1] = '\n';
|
||||
}
|
||||
}
|
||||
/* Check for ^Z (anywhere in line) too, to act as EOF. */
|
||||
while( iseg < noc ){
|
||||
if( cBuf[iseg]=='\x1a' ){
|
||||
noc = iseg; /* Chop ^Z and anything following. */
|
||||
lend = 1; /* Counts as end of line too. */
|
||||
break;
|
||||
}
|
||||
++iseg;
|
||||
}
|
||||
}else break; /* Drop apparent garbage in. (Could assert.) */
|
||||
}else break;
|
||||
}
|
||||
/* If got nothing, (after ^Z chop), must be at end-of-file. */
|
||||
if( noc > 0 ){
|
||||
cBuf[noc] = 0;
|
||||
return cBuf;
|
||||
}else return 0;
|
||||
# endif
|
||||
}else{
|
||||
# endif
|
||||
return cfGets(cBuf, ncMax, pfIn);
|
||||
# if CIO_WIN_WC_XLATE
|
||||
}
|
||||
# endif
|
||||
}
|
||||
#endif /* !defined(SQLITE_CIO_NO_TRANSLATE) */
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
# pragma warning(default : 4204)
|
||||
#endif
|
||||
|
||||
#undef SHELL_INVALID_FILE_PTR
|
||||
@@ -1,287 +0,0 @@
|
||||
/*
|
||||
** 2023 November 1
|
||||
**
|
||||
** 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 exposes various interfaces used for console and other I/O
|
||||
** by the SQLite project command-line tools. These interfaces are used
|
||||
** at either source conglomeration time, compilation time, or run time.
|
||||
** This source provides for either inclusion into conglomerated,
|
||||
** "single-source" forms or separate compilation then linking.
|
||||
**
|
||||
** Platform dependencies are "hidden" here by various stratagems so
|
||||
** that, provided certain conditions are met, the programs using this
|
||||
** source or object code compiled from it need no explicit conditional
|
||||
** compilation in their source for their console and stream I/O.
|
||||
**
|
||||
** The symbols and functionality exposed here are not a public API.
|
||||
** This code may change in tandem with other project code as needed.
|
||||
**
|
||||
** When this .h file and its companion .c are directly incorporated into
|
||||
** a source conglomeration (such as shell.c), the preprocessor symbol
|
||||
** CIO_WIN_WC_XLATE is defined as 0 or 1, reflecting whether console I/O
|
||||
** translation for Windows is effected for the build.
|
||||
*/
|
||||
#define HAVE_CONSOLE_IO_H 1
|
||||
#ifndef SQLITE_INTERNAL_LINKAGE
|
||||
# define SQLITE_INTERNAL_LINKAGE extern /* external to translation unit */
|
||||
# include <stdio.h>
|
||||
#else
|
||||
# define SHELL_NO_SYSINC /* Better yet, modify mkshellc.tcl for this. */
|
||||
#endif
|
||||
|
||||
#ifndef SQLITE3_H
|
||||
# include "sqlite3.h"
|
||||
#endif
|
||||
|
||||
#ifndef SQLITE_CIO_NO_CLASSIFY
|
||||
|
||||
/* Define enum for use with following function. */
|
||||
typedef enum StreamsAreConsole {
|
||||
SAC_NoConsole = 0,
|
||||
SAC_InConsole = 1, SAC_OutConsole = 2, SAC_ErrConsole = 4,
|
||||
SAC_AnyConsole = 0x7
|
||||
} StreamsAreConsole;
|
||||
|
||||
/*
|
||||
** Classify the three standard I/O streams according to whether
|
||||
** they are connected to a console attached to the process.
|
||||
**
|
||||
** Returns the bit-wise OR of SAC_{In,Out,Err}Console values,
|
||||
** or SAC_NoConsole if none of the streams reaches a console.
|
||||
**
|
||||
** This function should be called before any I/O is done with
|
||||
** the given streams. As a side-effect, the given inputs are
|
||||
** recorded so that later I/O operations on them may be done
|
||||
** differently than the C library FILE* I/O would be done,
|
||||
** iff the stream is used for the I/O functions that follow,
|
||||
** and to support the ones that use an implicit stream.
|
||||
**
|
||||
** On some platforms, stream or console mode alteration (aka
|
||||
** "Setup") may be made which is undone by consoleRestore().
|
||||
*/
|
||||
SQLITE_INTERNAL_LINKAGE StreamsAreConsole
|
||||
consoleClassifySetup( FILE *pfIn, FILE *pfOut, FILE *pfErr );
|
||||
/* A usual call for convenience: */
|
||||
#define SQLITE_STD_CONSOLE_INIT() consoleClassifySetup(stdin,stdout,stderr)
|
||||
|
||||
/*
|
||||
** After an initial call to consoleClassifySetup(...), renew
|
||||
** the same setup it effected. (A call not after is an error.)
|
||||
** This will restore state altered by consoleRestore();
|
||||
**
|
||||
** Applications which run an inferior (child) process which
|
||||
** inherits the same I/O streams may call this function after
|
||||
** such a process exits to guard against console mode changes.
|
||||
*/
|
||||
SQLITE_INTERNAL_LINKAGE void consoleRenewSetup(void);
|
||||
|
||||
/*
|
||||
** Undo any side-effects left by consoleClassifySetup(...).
|
||||
**
|
||||
** This should be called after consoleClassifySetup() and
|
||||
** before the process terminates normally. It is suitable
|
||||
** for use with the atexit() C library procedure. After
|
||||
** this call, no console I/O should be done until one of
|
||||
** console{Classify or Renew}Setup(...) is called again.
|
||||
**
|
||||
** Applications which run an inferior (child) process that
|
||||
** inherits the same I/O streams might call this procedure
|
||||
** before so that said process will have a console setup
|
||||
** however users have configured it or come to expect.
|
||||
*/
|
||||
SQLITE_INTERNAL_LINKAGE void SQLITE_CDECL consoleRestore( void );
|
||||
|
||||
#else /* defined(SQLITE_CIO_NO_CLASSIFY) */
|
||||
# define consoleClassifySetup(i,o,e)
|
||||
# define consoleRenewSetup()
|
||||
# define consoleRestore()
|
||||
#endif /* defined(SQLITE_CIO_NO_CLASSIFY) */
|
||||
|
||||
#ifndef SQLITE_CIO_NO_REDIRECT
|
||||
/*
|
||||
** Set stream to be used for the functions below which write
|
||||
** to "the designated X stream", where X is Output or Error.
|
||||
** Returns the previous value.
|
||||
**
|
||||
** Alternatively, pass the special value, invalidFileStream,
|
||||
** to get the designated stream value without setting it.
|
||||
**
|
||||
** Before the designated streams are set, they default to
|
||||
** those passed to consoleClassifySetup(...), and before
|
||||
** that is called they default to stdout and stderr.
|
||||
**
|
||||
** It is error to close a stream so designated, then, without
|
||||
** designating another, use the corresponding {o,e}Emit(...).
|
||||
*/
|
||||
SQLITE_INTERNAL_LINKAGE FILE *invalidFileStream;
|
||||
SQLITE_INTERNAL_LINKAGE FILE *setOutputStream(FILE *pf);
|
||||
# ifdef CONSIO_SET_ERROR_STREAM
|
||||
SQLITE_INTERNAL_LINKAGE FILE *setErrorStream(FILE *pf);
|
||||
# endif
|
||||
#else
|
||||
# define setOutputStream(pf)
|
||||
# define setErrorStream(pf)
|
||||
#endif /* !defined(SQLITE_CIO_NO_REDIRECT) */
|
||||
|
||||
#ifndef SQLITE_CIO_NO_TRANSLATE
|
||||
/*
|
||||
** Emit output like fprintf(). If the output is going to the
|
||||
** console and translation from UTF-8 is necessary, perform
|
||||
** the needed translation. Otherwise, write formatted output
|
||||
** to the provided stream almost as-is, possibly with newline
|
||||
** translation as specified by set{Binary,Text}Mode().
|
||||
*/
|
||||
SQLITE_INTERNAL_LINKAGE int fPrintfUtf8(FILE *pfO, const char *zFormat, ...);
|
||||
/* Like fPrintfUtf8 except stream is always the designated output. */
|
||||
SQLITE_INTERNAL_LINKAGE int oPrintfUtf8(const char *zFormat, ...);
|
||||
/* Like fPrintfUtf8 except stream is always the designated error. */
|
||||
SQLITE_INTERNAL_LINKAGE int ePrintfUtf8(const char *zFormat, ...);
|
||||
|
||||
/*
|
||||
** Emit output like fputs(). If the output is going to the
|
||||
** console and translation from UTF-8 is necessary, perform
|
||||
** the needed translation. Otherwise, write given text to the
|
||||
** provided stream almost as-is, possibly with newline
|
||||
** translation as specified by set{Binary,Text}Mode().
|
||||
*/
|
||||
SQLITE_INTERNAL_LINKAGE int fPutsUtf8(const char *z, FILE *pfO);
|
||||
/* Like fPutsUtf8 except stream is always the designated output. */
|
||||
SQLITE_INTERNAL_LINKAGE int oPutsUtf8(const char *z);
|
||||
/* Like fPutsUtf8 except stream is always the designated error. */
|
||||
SQLITE_INTERNAL_LINKAGE int ePutsUtf8(const char *z);
|
||||
|
||||
/*
|
||||
** Emit output like fPutsUtf8(), except that the length of the
|
||||
** accepted char or character sequence is limited by nAccept.
|
||||
**
|
||||
** Returns the number of accepted char values.
|
||||
*/
|
||||
#ifdef CONSIO_SPUTB
|
||||
SQLITE_INTERNAL_LINKAGE int
|
||||
fPutbUtf8(FILE *pfOut, const char *cBuf, int nAccept);
|
||||
/* Like fPutbUtf8 except stream is always the designated output. */
|
||||
#endif
|
||||
SQLITE_INTERNAL_LINKAGE int
|
||||
oPutbUtf8(const char *cBuf, int nAccept);
|
||||
/* Like fPutbUtf8 except stream is always the designated error. */
|
||||
#ifdef CONSIO_EPUTB
|
||||
SQLITE_INTERNAL_LINKAGE int
|
||||
ePutbUtf8(const char *cBuf, int nAccept);
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Flush the given output stream. Return non-zero for success, else 0.
|
||||
*/
|
||||
#if !defined(SQLITE_CIO_NO_FLUSH) && !defined(SQLITE_CIO_NO_SETMODE)
|
||||
SQLITE_INTERNAL_LINKAGE int
|
||||
fFlushBuffer(FILE *pfOut);
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Collect input like fgets(...) with special provisions for input
|
||||
** from the console on such platforms as require same. Newline
|
||||
** translation may be done as set by set{Binary,Text}Mode().
|
||||
** As a convenience, pfIn==NULL is treated as stdin.
|
||||
*/
|
||||
SQLITE_INTERNAL_LINKAGE char* fGetsUtf8(char *cBuf, int ncMax, FILE *pfIn);
|
||||
/* Like fGetsUtf8 except stream is always the designated input. */
|
||||
/* SQLITE_INTERNAL_LINKAGE char* iGetsUtf8(char *cBuf, int ncMax); */
|
||||
|
||||
#endif /* !defined(SQLITE_CIO_NO_TRANSLATE) */
|
||||
|
||||
#ifndef SQLITE_CIO_NO_SETMODE
|
||||
/*
|
||||
** Set given stream for binary mode, where newline translation is
|
||||
** not done, or for text mode where, for some platforms, newlines
|
||||
** are translated to the platform's conventional char sequence.
|
||||
** If bFlush true, flush the stream.
|
||||
**
|
||||
** An additional side-effect is that if the stream is one passed
|
||||
** to consoleClassifySetup() as an output, it is flushed first.
|
||||
**
|
||||
** Note that binary/text mode has no effect on console I/O
|
||||
** translation. On all platforms, newline to the console starts
|
||||
** a new line and CR,LF chars from the console become a newline.
|
||||
*/
|
||||
SQLITE_INTERNAL_LINKAGE void setBinaryMode(FILE *, short bFlush);
|
||||
SQLITE_INTERNAL_LINKAGE void setTextMode(FILE *, short bFlush);
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_CIO_PROMPTED_IN
|
||||
typedef struct Prompts {
|
||||
int numPrompts;
|
||||
const char **azPrompts;
|
||||
} Prompts;
|
||||
|
||||
/*
|
||||
** Macros for use of a line editor.
|
||||
**
|
||||
** The following macros define operations involving use of a
|
||||
** line-editing library or simple console interaction.
|
||||
** A "T" argument is a text (char *) buffer or filename.
|
||||
** A "N" argument is an integer.
|
||||
**
|
||||
** SHELL_ADD_HISTORY(T) // Record text as line(s) of history.
|
||||
** SHELL_READ_HISTORY(T) // Read history from file named by T.
|
||||
** SHELL_WRITE_HISTORY(T) // Write history to file named by T.
|
||||
** SHELL_STIFLE_HISTORY(N) // Limit history to N entries.
|
||||
**
|
||||
** A console program which does interactive console input is
|
||||
** expected to call:
|
||||
** SHELL_READ_HISTORY(T) before collecting such input;
|
||||
** SHELL_ADD_HISTORY(T) as record-worthy input is taken;
|
||||
** SHELL_STIFLE_HISTORY(N) after console input ceases; then
|
||||
** SHELL_WRITE_HISTORY(T) before the program exits.
|
||||
*/
|
||||
|
||||
/*
|
||||
** Retrieve a single line of input text from an input stream.
|
||||
**
|
||||
** If pfIn is the input stream passed to consoleClassifySetup(),
|
||||
** and azPrompt is not NULL, then a prompt is issued before the
|
||||
** line is collected, as selected by the isContinuation flag.
|
||||
** Array azPrompt[{0,1}] holds the {main,continuation} prompt.
|
||||
**
|
||||
** If zBufPrior is not NULL then it is a buffer from a prior
|
||||
** call to this routine that can be reused, or will be freed.
|
||||
**
|
||||
** The result is stored in space obtained from malloc() and
|
||||
** must either be freed by the caller or else passed back to
|
||||
** this function as zBufPrior for reuse.
|
||||
**
|
||||
** This function may call upon services of a line-editing
|
||||
** library to interactively collect line edited input.
|
||||
*/
|
||||
SQLITE_INTERNAL_LINKAGE char *
|
||||
shellGetLine(FILE *pfIn, char *zBufPrior, int nLen,
|
||||
short isContinuation, Prompts azPrompt);
|
||||
#endif /* defined(SQLITE_CIO_PROMPTED_IN) */
|
||||
/*
|
||||
** TBD: Define an interface for application(s) to generate
|
||||
** completion candidates for use by the line-editor.
|
||||
**
|
||||
** This may be premature; the CLI is the only application
|
||||
** that does this. Yet, getting line-editing melded into
|
||||
** console I/O is desirable because a line-editing library
|
||||
** may have to establish console operating mode, possibly
|
||||
** in a way that interferes with the above functionality.
|
||||
*/
|
||||
|
||||
#if !(defined(SQLITE_CIO_NO_UTF8SCAN)&&defined(SQLITE_CIO_NO_TRANSLATE))
|
||||
/* Skip over as much z[] input char sequence as is valid UTF-8,
|
||||
** limited per nAccept char's or whole characters and containing
|
||||
** no char cn such that ((1<<cn) & ccm)!=0. On return, the
|
||||
** sequence z:return (inclusive:exclusive) is validated UTF-8.
|
||||
** Limit: nAccept>=0 => char count, nAccept<0 => character
|
||||
*/
|
||||
SQLITE_INTERNAL_LINKAGE const char*
|
||||
zSkipValidUtf8(const char *z, int nAccept, long ccm);
|
||||
|
||||
#endif
|
||||
@@ -1491,7 +1491,7 @@ static int idxCreateVtabSchema(sqlite3expert *p, char **pzErrmsg){
|
||||
}else{
|
||||
IdxTable *pTab;
|
||||
rc = idxGetTableInfo(p->db, zName, &pTab, pzErrmsg);
|
||||
if( rc==SQLITE_OK ){
|
||||
if( rc==SQLITE_OK && ALWAYS(pTab!=0) ){
|
||||
int i;
|
||||
char *zInner = 0;
|
||||
char *zOuter = 0;
|
||||
|
||||
+24
-1
@@ -2344,10 +2344,15 @@ static int fts3PoslistPhraseMerge(
|
||||
if( *p1==POS_COLUMN ){
|
||||
p1++;
|
||||
p1 += fts3GetVarint32(p1, &iCol1);
|
||||
/* iCol1==0 indicates corruption. Column 0 does not have a POS_COLUMN
|
||||
** entry, so this is actually end-of-doclist. */
|
||||
if( iCol1==0 ) return 0;
|
||||
}
|
||||
if( *p2==POS_COLUMN ){
|
||||
p2++;
|
||||
p2 += fts3GetVarint32(p2, &iCol2);
|
||||
/* As above, iCol2==0 indicates corruption. */
|
||||
if( iCol2==0 ) return 0;
|
||||
}
|
||||
|
||||
while( 1 ){
|
||||
@@ -5518,7 +5523,7 @@ static int fts3EvalNearTest(Fts3Expr *pExpr, int *pRc){
|
||||
nTmp += p->pRight->pPhrase->doclist.nList;
|
||||
}
|
||||
nTmp += p->pPhrase->doclist.nList;
|
||||
aTmp = sqlite3_malloc64(nTmp*2);
|
||||
aTmp = sqlite3_malloc64(nTmp*2 + FTS3_VARINT_MAX);
|
||||
if( !aTmp ){
|
||||
*pRc = SQLITE_NOMEM;
|
||||
res = 0;
|
||||
@@ -5782,6 +5787,24 @@ static void fts3EvalRestart(
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Expression node pExpr is an MSR phrase. This function restarts pExpr
|
||||
** so that it is a regular phrase query, not an MSR. SQLITE_OK is returned
|
||||
** if successful, or an SQLite error code otherwise.
|
||||
*/
|
||||
int sqlite3Fts3MsrCancel(Fts3Cursor *pCsr, Fts3Expr *pExpr){
|
||||
int rc = SQLITE_OK;
|
||||
if( pExpr->bEof==0 ){
|
||||
i64 iDocid = pExpr->iDocid;
|
||||
fts3EvalRestart(pCsr, pExpr, &rc);
|
||||
while( rc==SQLITE_OK && pExpr->iDocid!=iDocid ){
|
||||
fts3EvalNextRow(pCsr, pExpr, &rc);
|
||||
if( pExpr->bEof ) rc = FTS_CORRUPT_VTAB;
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** After allocating the Fts3Expr.aMI[] array for each phrase in the
|
||||
** expression rooted at pExpr, the cursor iterates through all rows matched
|
||||
|
||||
@@ -640,6 +640,7 @@ int sqlite3Fts3MsrIncrNext(
|
||||
int sqlite3Fts3EvalPhrasePoslist(Fts3Cursor *, Fts3Expr *, int iCol, char **);
|
||||
int sqlite3Fts3MsrOvfl(Fts3Cursor *, Fts3MultiSegReader *, int *);
|
||||
int sqlite3Fts3MsrIncrRestart(Fts3MultiSegReader *pCsr);
|
||||
int sqlite3Fts3MsrCancel(Fts3Cursor*, Fts3Expr*);
|
||||
|
||||
/* fts3_tokenize_vtab.c */
|
||||
int sqlite3Fts3InitTok(sqlite3*, Fts3Hash *, void(*xDestroy)(void*));
|
||||
|
||||
+16
-17
@@ -319,10 +319,11 @@ static int getNextString(
|
||||
Fts3PhraseToken *pToken;
|
||||
|
||||
p = fts3ReallocOrFree(p, nSpace + ii*sizeof(Fts3PhraseToken));
|
||||
if( !p ) goto no_mem;
|
||||
|
||||
zTemp = fts3ReallocOrFree(zTemp, nTemp + nByte);
|
||||
if( !zTemp ) goto no_mem;
|
||||
if( !zTemp || !p ){
|
||||
rc = SQLITE_NOMEM;
|
||||
goto getnextstring_out;
|
||||
}
|
||||
|
||||
assert( nToken==ii );
|
||||
pToken = &((Fts3Phrase *)(&p[1]))->aToken[ii];
|
||||
@@ -337,9 +338,6 @@ static int getNextString(
|
||||
nToken = ii+1;
|
||||
}
|
||||
}
|
||||
|
||||
pModule->xClose(pCursor);
|
||||
pCursor = 0;
|
||||
}
|
||||
|
||||
if( rc==SQLITE_DONE ){
|
||||
@@ -347,7 +345,10 @@ static int getNextString(
|
||||
char *zBuf = 0;
|
||||
|
||||
p = fts3ReallocOrFree(p, nSpace + nToken*sizeof(Fts3PhraseToken) + nTemp);
|
||||
if( !p ) goto no_mem;
|
||||
if( !p ){
|
||||
rc = SQLITE_NOMEM;
|
||||
goto getnextstring_out;
|
||||
}
|
||||
memset(p, 0, (char *)&(((Fts3Phrase *)&p[1])->aToken[0])-(char *)p);
|
||||
p->eType = FTSQUERY_PHRASE;
|
||||
p->pPhrase = (Fts3Phrase *)&p[1];
|
||||
@@ -355,11 +356,9 @@ static int getNextString(
|
||||
p->pPhrase->nToken = nToken;
|
||||
|
||||
zBuf = (char *)&p->pPhrase->aToken[nToken];
|
||||
assert( nTemp==0 || zTemp );
|
||||
if( zTemp ){
|
||||
memcpy(zBuf, zTemp, nTemp);
|
||||
sqlite3_free(zTemp);
|
||||
}else{
|
||||
assert( nTemp==0 );
|
||||
}
|
||||
|
||||
for(jj=0; jj<p->pPhrase->nToken; jj++){
|
||||
@@ -369,17 +368,17 @@ static int getNextString(
|
||||
rc = SQLITE_OK;
|
||||
}
|
||||
|
||||
*ppExpr = p;
|
||||
return rc;
|
||||
no_mem:
|
||||
|
||||
getnextstring_out:
|
||||
if( pCursor ){
|
||||
pModule->xClose(pCursor);
|
||||
}
|
||||
sqlite3_free(zTemp);
|
||||
sqlite3_free(p);
|
||||
*ppExpr = 0;
|
||||
return SQLITE_NOMEM;
|
||||
if( rc!=SQLITE_OK ){
|
||||
sqlite3_free(p);
|
||||
p = 0;
|
||||
}
|
||||
*ppExpr = p;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -1586,6 +1586,22 @@ static int fts3ExprTermOffsetInit(Fts3Expr *pExpr, int iPhrase, void *ctx){
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** If expression pExpr is a phrase expression that uses an MSR query,
|
||||
** restart it as a regular, non-incremental query. Return SQLITE_OK
|
||||
** if successful, or an SQLite error code otherwise.
|
||||
*/
|
||||
static int fts3ExprRestartIfCb(Fts3Expr *pExpr, int iPhrase, void *ctx){
|
||||
TermOffsetCtx *p = (TermOffsetCtx*)ctx;
|
||||
int rc = SQLITE_OK;
|
||||
UNUSED_PARAMETER(iPhrase);
|
||||
if( pExpr->pPhrase && pExpr->pPhrase->bIncr ){
|
||||
rc = sqlite3Fts3MsrCancel(p->pCsr, pExpr);
|
||||
pExpr->pPhrase->bIncr = 0;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Implementation of offsets() function.
|
||||
*/
|
||||
@@ -1622,6 +1638,12 @@ void sqlite3Fts3Offsets(
|
||||
sCtx.iDocid = pCsr->iPrevId;
|
||||
sCtx.pCsr = pCsr;
|
||||
|
||||
/* If a query restart will be required, do it here, rather than later of
|
||||
** after pointers to poslist buffers that may be invalidated by a restart
|
||||
** have been saved. */
|
||||
rc = sqlite3Fts3ExprIterate(pCsr->pExpr, fts3ExprRestartIfCb, (void*)&sCtx);
|
||||
if( rc!=SQLITE_OK ) goto offsets_out;
|
||||
|
||||
/* Loop through the table columns, appending offset information to
|
||||
** string-buffer res for each column.
|
||||
*/
|
||||
|
||||
+19
-4
@@ -298,16 +298,31 @@ struct Fts5PhraseIter {
|
||||
** value returned by xInstCount(), SQLITE_RANGE is returned. Otherwise,
|
||||
** output variable (*ppToken) is set to point to a buffer containing the
|
||||
** matching document token, and (*pnToken) to the size of that buffer in
|
||||
** bytes. This API is not available if the specified token matches a
|
||||
** prefix query term. In that case both output variables are always set
|
||||
** to 0.
|
||||
** bytes.
|
||||
**
|
||||
** The output text is not a copy of the document text that was tokenized.
|
||||
** It is the output of the tokenizer module. For tokendata=1 tables, this
|
||||
** includes any embedded 0x00 and trailing data.
|
||||
**
|
||||
** This API may be slow in some cases if the token identified by parameters
|
||||
** iIdx and iToken matched a prefix token in the query. In most cases, the
|
||||
** first call to this API for each prefix token in the query is forced
|
||||
** to scan the portion of the full-text index that matches the prefix
|
||||
** token to collect the extra data required by this API. If the prefix
|
||||
** token matches a large number of token instances in the document set,
|
||||
** this may be a performance problem.
|
||||
**
|
||||
** If the user knows in advance that a query may use this API for a
|
||||
** prefix token, FTS5 may be configured to collect all required data as part
|
||||
** of the initial querying of the full-text index, avoiding the second scan
|
||||
** entirely. This also causes prefix queries that do not use this API to
|
||||
** run more slowly and use more memory. FTS5 may be configured in this way
|
||||
** either on a per-table basis using the [FTS5 insttoken | 'insttoken']
|
||||
** option, or on a per-query basis using the
|
||||
** [fts5_insttoken | fts5_insttoken()] user function.
|
||||
**
|
||||
** This API can be quite slow if used with an FTS5 table created with the
|
||||
** "detail=none" or "detail=column" option.
|
||||
** "detail=none" or "detail=column" option.
|
||||
**
|
||||
** xColumnLocale(pFts5, iIdx, pzLocale, pnLocale)
|
||||
** If parameter iCol is less than zero, or greater than or equal to the
|
||||
|
||||
+10
-2
@@ -247,7 +247,8 @@ struct Fts5Config {
|
||||
char *zRank; /* Name of rank function */
|
||||
char *zRankArgs; /* Arguments to rank function */
|
||||
int bSecureDelete; /* 'secure-delete' */
|
||||
int nDeleteMerge; /* 'deletemerge' */
|
||||
int nDeleteMerge; /* 'deletemerge' */
|
||||
int bPrefixInsttoken; /* 'prefix-insttoken' */
|
||||
|
||||
/* If non-NULL, points to sqlite3_vtab.base.zErrmsg. Often NULL. */
|
||||
char **pzErrmsg;
|
||||
@@ -504,7 +505,14 @@ int sqlite3Fts5StructureTest(Fts5Index*, void*);
|
||||
/*
|
||||
** Used by xInstToken():
|
||||
*/
|
||||
int sqlite3Fts5IterToken(Fts5IndexIter*, i64, int, int, const char**, int*);
|
||||
int sqlite3Fts5IterToken(
|
||||
Fts5IndexIter *pIndexIter,
|
||||
const char *pToken, int nToken,
|
||||
i64 iRowid,
|
||||
int iCol,
|
||||
int iOff,
|
||||
const char **ppOut, int *pnOut
|
||||
);
|
||||
|
||||
/*
|
||||
** Insert or remove data to or from the index. Each time a document is
|
||||
|
||||
@@ -1026,6 +1026,19 @@ int sqlite3Fts5ConfigSetValue(
|
||||
}else{
|
||||
pConfig->bSecureDelete = (bVal ? 1 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
else if( 0==sqlite3_stricmp(zKey, "insttoken") ){
|
||||
int bVal = -1;
|
||||
if( SQLITE_INTEGER==sqlite3_value_numeric_type(pVal) ){
|
||||
bVal = sqlite3_value_int(pVal);
|
||||
}
|
||||
if( bVal<0 ){
|
||||
*pbBadkey = 1;
|
||||
}else{
|
||||
pConfig->bPrefixInsttoken = (bVal ? 1 : 0);
|
||||
}
|
||||
|
||||
}else{
|
||||
*pbBadkey = 1;
|
||||
}
|
||||
|
||||
+9
-10
@@ -3046,7 +3046,7 @@ static int fts5ExprPopulatePoslistsCb(
|
||||
int rc = sqlite3Fts5PoslistWriterAppend(
|
||||
&pExpr->apExprPhrase[i]->poslist, &p->aPopulator[i].writer, p->iOff
|
||||
);
|
||||
if( rc==SQLITE_OK && pExpr->pConfig->bTokendata && !pT->bPrefix ){
|
||||
if( rc==SQLITE_OK && (pExpr->pConfig->bTokendata || pT->bPrefix) ){
|
||||
int iCol = p->iOff>>32;
|
||||
int iTokOff = p->iOff & 0x7FFFFFFF;
|
||||
rc = sqlite3Fts5IndexIterWriteTokendata(
|
||||
@@ -3239,15 +3239,14 @@ int sqlite3Fts5ExprInstToken(
|
||||
return SQLITE_RANGE;
|
||||
}
|
||||
pTerm = &pPhrase->aTerm[iToken];
|
||||
if( pTerm->bPrefix==0 ){
|
||||
if( pExpr->pConfig->bTokendata ){
|
||||
rc = sqlite3Fts5IterToken(
|
||||
pTerm->pIter, iRowid, iCol, iOff+iToken, ppOut, pnOut
|
||||
);
|
||||
}else{
|
||||
*ppOut = pTerm->pTerm;
|
||||
*pnOut = pTerm->nFullTerm;
|
||||
}
|
||||
if( pExpr->pConfig->bTokendata || pTerm->bPrefix ){
|
||||
rc = sqlite3Fts5IterToken(
|
||||
pTerm->pIter, pTerm->pTerm, pTerm->nQueryTerm,
|
||||
iRowid, iCol, iOff+iToken, ppOut, pnOut
|
||||
);
|
||||
}else{
|
||||
*ppOut = pTerm->pTerm;
|
||||
*pnOut = pTerm->nFullTerm;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
+599
-219
File diff suppressed because it is too large
Load Diff
+31
-21
@@ -93,6 +93,7 @@ struct Fts5Global {
|
||||
#define FTS5_LOCALE_HDR_SIZE ((int)sizeof( ((Fts5Global*)0)->aLocaleHdr ))
|
||||
#define FTS5_LOCALE_HDR(pConfig) ((const u8*)(pConfig->pGlobal->aLocaleHdr))
|
||||
|
||||
#define FTS5_INSTTOKEN_SUBTYPE 73
|
||||
|
||||
/*
|
||||
** Each auxiliary function registered with the FTS5 module is represented
|
||||
@@ -632,6 +633,7 @@ static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
|
||||
if( p->usable==0 || iCol<0 ){
|
||||
/* As there exists an unusable MATCH constraint this is an
|
||||
** unusable plan. Return SQLITE_CONSTRAINT. */
|
||||
idxStr[iIdxStr] = 0;
|
||||
return SQLITE_CONSTRAINT;
|
||||
}else{
|
||||
if( iCol==nCol+1 ){
|
||||
@@ -1417,6 +1419,7 @@ static int fts5FilterMethod(
|
||||
sqlite3_value *pRowidGe = 0; /* rowid >= ? expression (or NULL) */
|
||||
int iCol; /* Column on LHS of MATCH operator */
|
||||
char **pzErrmsg = pConfig->pzErrmsg;
|
||||
int bPrefixInsttoken = pConfig->bPrefixInsttoken;
|
||||
int i;
|
||||
int iIdxStr = 0;
|
||||
Fts5Expr *pExpr = 0;
|
||||
@@ -1452,6 +1455,9 @@ static int fts5FilterMethod(
|
||||
rc = fts5ExtractExprText(pConfig, apVal[i], &zText, &bFreeAndReset);
|
||||
if( rc!=SQLITE_OK ) goto filter_out;
|
||||
if( zText==0 ) zText = "";
|
||||
if( sqlite3_value_subtype(apVal[i])==FTS5_INSTTOKEN_SUBTYPE ){
|
||||
pConfig->bPrefixInsttoken = 1;
|
||||
}
|
||||
|
||||
iCol = 0;
|
||||
do{
|
||||
@@ -1592,6 +1598,7 @@ static int fts5FilterMethod(
|
||||
filter_out:
|
||||
sqlite3Fts5ExprFree(pExpr);
|
||||
pConfig->pzErrmsg = pzErrmsg;
|
||||
pConfig->bPrefixInsttoken = bPrefixInsttoken;
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -1894,7 +1901,6 @@ static int fts5UpdateMethod(
|
||||
Fts5Config *pConfig = pTab->p.pConfig;
|
||||
int eType0; /* value_type() of apVal[0] */
|
||||
int rc = SQLITE_OK; /* Return code */
|
||||
int bUpdateOrDelete = 0;
|
||||
|
||||
/* A transaction must be open when this is called. */
|
||||
assert( pTab->ts.eState==1 || pTab->ts.eState==2 );
|
||||
@@ -1906,7 +1912,7 @@ static int fts5UpdateMethod(
|
||||
);
|
||||
assert( pTab->p.pConfig->pzErrmsg==0 );
|
||||
if( pConfig->pgsz==0 ){
|
||||
rc = sqlite3Fts5IndexLoadConfig(pTab->p.pIndex);
|
||||
rc = sqlite3Fts5ConfigLoad(pTab->p.pConfig, pTab->p.pConfig->iCookie);
|
||||
if( rc!=SQLITE_OK ) return rc;
|
||||
}
|
||||
|
||||
@@ -1931,7 +1937,6 @@ static int fts5UpdateMethod(
|
||||
rc = SQLITE_ERROR;
|
||||
}else{
|
||||
rc = fts5SpecialDelete(pTab, apVal);
|
||||
bUpdateOrDelete = 1;
|
||||
}
|
||||
}else{
|
||||
rc = fts5SpecialInsert(pTab, z, apVal[2 + pConfig->nCol + 1]);
|
||||
@@ -1968,7 +1973,6 @@ static int fts5UpdateMethod(
|
||||
}else{
|
||||
i64 iDel = sqlite3_value_int64(apVal[0]); /* Rowid to delete */
|
||||
rc = sqlite3Fts5StorageDelete(pTab->pStorage, iDel, 0, 0);
|
||||
bUpdateOrDelete = 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1996,7 +2000,6 @@ static int fts5UpdateMethod(
|
||||
if( eConflict==SQLITE_REPLACE && eType1==SQLITE_INTEGER ){
|
||||
i64 iNew = sqlite3_value_int64(apVal[1]); /* Rowid to delete */
|
||||
rc = sqlite3Fts5StorageDelete(pTab->pStorage, iNew, 0, 0);
|
||||
bUpdateOrDelete = 1;
|
||||
}
|
||||
fts5StorageInsert(&rc, pTab, apVal, pRowid);
|
||||
}
|
||||
@@ -2050,23 +2053,8 @@ static int fts5UpdateMethod(
|
||||
rc = sqlite3Fts5StorageDelete(pStorage, iOld, 0, 1);
|
||||
fts5StorageInsert(&rc, pTab, apVal, pRowid);
|
||||
}
|
||||
bUpdateOrDelete = 1;
|
||||
sqlite3Fts5StorageReleaseDeleteRow(pStorage);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK
|
||||
&& bUpdateOrDelete
|
||||
&& pConfig->bSecureDelete
|
||||
&& pConfig->iVersion==FTS5_CURRENT_VERSION
|
||||
){
|
||||
rc = sqlite3Fts5StorageConfigValue(
|
||||
pTab->pStorage, "version", 0, FTS5_CURRENT_VERSION_SECUREDELETE
|
||||
);
|
||||
if( rc==SQLITE_OK ){
|
||||
pConfig->iVersion = FTS5_CURRENT_VERSION_SECUREDELETE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2119,6 +2107,7 @@ static int fts5RollbackMethod(sqlite3_vtab *pVtab){
|
||||
Fts5FullTable *pTab = (Fts5FullTable*)pVtab;
|
||||
fts5CheckTransactionState(pTab, FTS5_ROLLBACK, 0);
|
||||
rc = sqlite3Fts5StorageRollback(pTab->pStorage);
|
||||
pTab->p.pConfig->pgsz = 0;
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -3651,6 +3640,20 @@ static void fts5LocaleFunc(
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Implementation of fts5_insttoken() function.
|
||||
*/
|
||||
static void fts5InsttokenFunc(
|
||||
sqlite3_context *pCtx, /* Function call context */
|
||||
int nArg, /* Number of args */
|
||||
sqlite3_value **apArg /* Function arguments */
|
||||
){
|
||||
assert( nArg==1 );
|
||||
(void)nArg;
|
||||
sqlite3_result_value(pCtx, apArg[0]);
|
||||
sqlite3_result_subtype(pCtx, FTS5_INSTTOKEN_SUBTYPE);
|
||||
}
|
||||
|
||||
/*
|
||||
** Return true if zName is the extension on one of the shadow tables used
|
||||
** by this module.
|
||||
@@ -3780,10 +3783,17 @@ static int fts5Init(sqlite3 *db){
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3_create_function(
|
||||
db, "fts5_locale", 2,
|
||||
SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_RESULT_SUBTYPE,
|
||||
SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_RESULT_SUBTYPE|SQLITE_SUBTYPE,
|
||||
p, fts5LocaleFunc, 0, 0
|
||||
);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3_create_function(
|
||||
db, "fts5_insttoken", 1,
|
||||
SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_RESULT_SUBTYPE,
|
||||
p, fts5InsttokenFunc, 0, 0
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/* If SQLITE_FTS5_ENABLE_TEST_MI is defined, assume that the file
|
||||
|
||||
@@ -205,6 +205,11 @@ static int fts5StorageGetStmt(
|
||||
if( rc!=SQLITE_OK && pzErrMsg ){
|
||||
*pzErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(pC->db));
|
||||
}
|
||||
if( rc==SQLITE_ERROR && eStmt>FTS5_STMT_LOOKUP2 && eStmt<FTS5_STMT_SCAN ){
|
||||
/* One of the internal tables - not the %_content table - is missing.
|
||||
** This counts as a corrupted table. */
|
||||
rc = SQLITE_CORRUPT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+77
-6
@@ -21,6 +21,7 @@
|
||||
#include "fts5.h"
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef SQLITE_DEBUG
|
||||
extern int sqlite3_fts5_may_be_corrupt;
|
||||
@@ -729,8 +730,9 @@ static int SQLITE_TCLAPI f5tTokenize(
|
||||
int objc,
|
||||
Tcl_Obj *CONST objv[]
|
||||
){
|
||||
char *zText;
|
||||
Tcl_Size nText;
|
||||
char *pCopy = 0;
|
||||
char *zText = 0;
|
||||
Tcl_Size nText = 0;
|
||||
sqlite3 *db = 0;
|
||||
fts5_api *pApi = 0;
|
||||
Fts5Tokenizer *pTok = 0;
|
||||
@@ -777,22 +779,33 @@ static int SQLITE_TCLAPI f5tTokenize(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
if( nText>0 ){
|
||||
pCopy = sqlite3_malloc(nText);
|
||||
if( pCopy==0 ){
|
||||
tokenizer.xDelete(pTok);
|
||||
Tcl_AppendResult(interp, "error in sqlite3_malloc()", (char*)0);
|
||||
return TCL_ERROR;
|
||||
}else{
|
||||
memcpy(pCopy, zText, nText);
|
||||
}
|
||||
}
|
||||
|
||||
pRet = Tcl_NewObj();
|
||||
Tcl_IncrRefCount(pRet);
|
||||
ctx.bSubst = (objc==5);
|
||||
ctx.pRet = pRet;
|
||||
ctx.zInput = zText;
|
||||
ctx.zInput = pCopy;
|
||||
rc = tokenizer.xTokenize(
|
||||
pTok, (void*)&ctx, FTS5_TOKENIZE_DOCUMENT, zText,(int)nText, xTokenizeCb2
|
||||
pTok, (void*)&ctx, FTS5_TOKENIZE_DOCUMENT, pCopy,(int)nText, xTokenizeCb2
|
||||
);
|
||||
tokenizer.xDelete(pTok);
|
||||
sqlite3_free(pCopy);
|
||||
if( rc!=SQLITE_OK ){
|
||||
Tcl_AppendResult(interp, "error in tokenizer.xTokenize()", (char*)0);
|
||||
Tcl_DecrRefCount(pRet);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
|
||||
Tcl_Free((void*)azArg);
|
||||
Tcl_SetObjResult(interp, pRet);
|
||||
Tcl_DecrRefCount(pRet);
|
||||
@@ -1626,6 +1639,63 @@ static int SQLITE_TCLAPI f5tDropCorruptTable(
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Free a buffer returned to SQLite by the str() function.
|
||||
*/
|
||||
void f5tFree(void *p){
|
||||
char *x = (char *)p;
|
||||
ckfree(&x[-8]);
|
||||
}
|
||||
|
||||
/*
|
||||
** Implementation of str().
|
||||
*/
|
||||
void f5tStrFunc(sqlite3_context *pCtx, int nArg, sqlite3_value **apArg){
|
||||
const char *zText = 0;
|
||||
assert( nArg==1 );
|
||||
|
||||
zText = (const char*)sqlite3_value_text(apArg[0]);
|
||||
if( zText ){
|
||||
sqlite3_int64 nText = strlen(zText);
|
||||
char *zCopy = (char*)ckalloc(nText+8);
|
||||
if( zCopy==0 ){
|
||||
sqlite3_result_error_nomem(pCtx);
|
||||
}else{
|
||||
zCopy += 8;
|
||||
memcpy(zCopy, zText, nText);
|
||||
sqlite3_result_text64(pCtx, zCopy, nText, f5tFree, SQLITE_UTF8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** sqlite3_fts5_register_str DB
|
||||
**
|
||||
** Register the str() function with database handle DB. str() interprets
|
||||
** its only argument as text and returns a copy of the value in a
|
||||
** non-nul-terminated buffer.
|
||||
*/
|
||||
static int SQLITE_TCLAPI f5tRegisterStr(
|
||||
void * clientData,
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
Tcl_Obj *CONST objv[]
|
||||
){
|
||||
sqlite3 *db = 0;
|
||||
|
||||
if( objc!=2 ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "DB");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if( f5tDbPointer(interp, objv[1], &db) ){
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
sqlite3_create_function(db, "str", 1, SQLITE_UTF8, 0, f5tStrFunc, 0, 0);
|
||||
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Entry point.
|
||||
*/
|
||||
@@ -1645,7 +1715,8 @@ int Fts5tcl_Init(Tcl_Interp *interp){
|
||||
{ "sqlite3_fts5_register_matchinfo", f5tRegisterMatchinfo, 0 },
|
||||
{ "sqlite3_fts5_register_fts5tokenize", f5tRegisterTok, 0 },
|
||||
{ "sqlite3_fts5_register_origintext",f5tRegisterOriginText, 0 },
|
||||
{ "sqlite3_fts5_drop_corrupt_table", f5tDropCorruptTable, 0 }
|
||||
{ "sqlite3_fts5_drop_corrupt_table", f5tDropCorruptTable, 0 },
|
||||
{ "sqlite3_fts5_register_str", f5tRegisterStr, 0 }
|
||||
};
|
||||
int i;
|
||||
F5tTokenizerContext *pContext;
|
||||
|
||||
@@ -1353,8 +1353,8 @@ static int fts5TriTokenize(
|
||||
char *zOut = aBuf;
|
||||
int ii;
|
||||
const unsigned char *zIn = (const unsigned char*)pText;
|
||||
const unsigned char *zEof = &zIn[nText];
|
||||
u32 iCode;
|
||||
const unsigned char *zEof = (zIn ? &zIn[nText] : 0);
|
||||
u32 iCode = 0;
|
||||
int aStart[3]; /* Input offset of each character in aBuf[] */
|
||||
|
||||
UNUSED_PARAM(unusedFlags);
|
||||
@@ -1363,8 +1363,8 @@ static int fts5TriTokenize(
|
||||
for(ii=0; ii<3; ii++){
|
||||
do {
|
||||
aStart[ii] = zIn - (const unsigned char*)pText;
|
||||
if( zIn>=zEof ) return SQLITE_OK;
|
||||
READ_UTF8(zIn, zEof, iCode);
|
||||
if( iCode==0 ) return SQLITE_OK;
|
||||
if( p->bFold ) iCode = sqlite3Fts5UnicodeFold(iCode, p->iFoldParam);
|
||||
}while( iCode==0 );
|
||||
WRITE_UTF8(zOut, iCode);
|
||||
@@ -1385,8 +1385,11 @@ static int fts5TriTokenize(
|
||||
/* Read characters from the input up until the first non-diacritic */
|
||||
do {
|
||||
iNext = zIn - (const unsigned char*)pText;
|
||||
if( zIn>=zEof ){
|
||||
iCode = 0;
|
||||
break;
|
||||
}
|
||||
READ_UTF8(zIn, zEof, iCode);
|
||||
if( iCode==0 ) break;
|
||||
if( p->bFold ) iCode = sqlite3Fts5UnicodeFold(iCode, p->iFoldParam);
|
||||
}while( iCode==0 );
|
||||
|
||||
|
||||
@@ -72,7 +72,7 @@ foreach {tn schema sql} {
|
||||
} {
|
||||
db_restore_and_reopen
|
||||
do_execsql_test 1.1.$tn.1 $schema
|
||||
do_catchsql_test 1.1.$tn.2 $sql {1 {SQL logic error}}
|
||||
do_catchsql_test 1.1.$tn.2 $sql {1 {database disk image is malformed}}
|
||||
db close
|
||||
}
|
||||
|
||||
|
||||
@@ -15678,6 +15678,239 @@ do_catchsql_test 81.2 {
|
||||
UPDATE t1 SET b=zeroblob(299);
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_test 82.0 {
|
||||
sqlite3 db {}
|
||||
db deserialize [decode_hexdb {
|
||||
.open --hexdb
|
||||
| size 32768 pagesize 4096 filename c0.txt.db
|
||||
| page 1 offset 0
|
||||
| 0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00 SQLite format 3.
|
||||
| 16: 10 00 01 01 00 40 20 20 00 00 00 00 00 00 00 08 .....@ ........
|
||||
| 32: 00 00 00 02 00 00 00 01 00 00 00 09 00 00 00 04 ................
|
||||
| 96: 00 00 00 00 0d 0f c7 00 07 0d 92 00 0f 8d 0f 36 ...............6
|
||||
| 112: 0e cb 0e 6b 0e 0e 0d b6 0d 92 0d 92 00 00 00 00 ...k............
|
||||
| 3472: 00 00 22 08 06 17 11 11 01 31 74 61 62 6c 65 74 .........1tablet
|
||||
| 3488: 32 74 32 08 43 52 45 41 54 45 20 54 41 42 4c 45 2t2.CREATE TABLE
|
||||
| 3504: 20 74 32 28 78 29 56 07 06 17 1f 1f 01 7d 74 61 t2(x)V.......ta
|
||||
| 3520: 62 6c 65 74 31 5f 63 6f 6e 66 69 67 74 31 5f 63 blet1_configt1_c
|
||||
| 3536: 6f 6e 66 69 67 07 43 52 45 41 54 45 20 54 41 42 onfig.CREATE TAB
|
||||
| 3552: 4c 45 20 27 74 31 5f 63 6f 6e 66 69 67 27 28 6b LE 't1_config'(k
|
||||
| 3568: 20 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 76 29 PRIMARY KEY, v)
|
||||
| 3584: 20 57 49 54 48 4f 55 54 20 52 4f 57 49 44 5b 06 WITHOUT ROWID[.
|
||||
| 3600: 07 17 21 21 01 81 01 74 61 62 6c 65 74 31 5f 64 ..!!...tablet1_d
|
||||
| 3616: 6f 63 73 69 7a 65 74 31 5f 64 6f 63 73 69 7a 65 ocsizet1_docsize
|
||||
| 3632: 06 43 52 45 41 54 45 20 54 41 42 4c 45 20 27 74 .CREATE TABLE 't
|
||||
| 3648: 31 5f 64 6f 63 73 69 7a 65 27 28 69 64 20 49 4e 1_docsize'(id IN
|
||||
| 3664: 54 45 47 45 52 20 50 52 49 4d 41 52 59 20 4b 45 TEGER PRIMARY KE
|
||||
| 3680: 59 2c 20 73 7a 20 42 4c 4f 42 29 5e 05 07 17 21 Y, sz BLOB)^...!
|
||||
| 3696: 21 01 81 07 74 61 62 6c 65 74 31 5f 63 6f 6e 74 !...tablet1_cont
|
||||
| 3712: 65 6e 74 74 31 5f 63 6f 6e 74 65 6e 74 05 43 52 entt1_content.CR
|
||||
| 3728: 45 41 54 45 20 54 41 42 4c 45 20 27 74 31 5f 63 EATE TABLE 't1_c
|
||||
| 3744: 6f 6e 74 65 6e 74 27 28 69 64 20 49 4e 54 45 47 ontent'(id INTEG
|
||||
| 3760: 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 ER PRIMARY KEY,
|
||||
| 3776: 63 30 2c 20 63 31 2c 20 63 32 29 69 04 07 17 19 c0, c1, c2)i....
|
||||
| 3792: 19 01 81 2d 74 61 62 6c 65 74 31 5f 69 64 78 74 ...-tablet1_idxt
|
||||
| 3808: 31 5f 69 64 78 04 43 52 45 41 54 45 20 54 41 42 1_idx.CREATE TAB
|
||||
| 3824: 4c 45 20 27 74 31 5f 69 64 78 27 28 73 65 67 69 LE 't1_idx'(segi
|
||||
| 3840: 64 2c 20 74 65 72 6d 2c 20 70 67 6e 6f 2c 20 50 d, term, pgno, P
|
||||
| 3856: 52 49 4d 41 52 59 20 4b 45 59 28 73 65 67 69 64 RIMARY KEY(segid
|
||||
| 3872: 2c 20 74 65 72 6d 29 29 20 57 49 54 48 4f 55 54 , term)) WITHOUT
|
||||
| 3888: 20 52 4f 57 49 44 55 03 07 17 1b 1b 01 81 01 74 ROWIDU........t
|
||||
| 3904: 61 62 6c 65 74 31 5f 64 61 74 61 74 31 5f 64 61 ablet1_datat1_da
|
||||
| 3920: 74 61 03 43 52 45 41 54 45 20 54 41 42 4c 45 20 ta.CREATE TABLE
|
||||
| 3936: 27 74 31 5f 64 61 74 61 27 28 69 64 20 49 4e 54 't1_data'(id INT
|
||||
| 3952: 45 47 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59 EGER PRIMARY KEY
|
||||
| 3968: 2c 20 62 6c 6f 63 6b 20 42 4c 4f 42 29 38 02 06 , block BLOB)8..
|
||||
| 3984: 17 11 11 08 5f 74 61 62 6c 65 74 31 74 31 43 52 ...._tablet1t1CR
|
||||
| 4000: 45 41 54 45 20 56 49 52 54 55 41 4c 20 54 41 42 EATE VIRTUAL TAB
|
||||
| 4016: 4c 45 20 74 31 20 55 53 49 4e 47 20 66 74 73 35 LE t1 USING fts5
|
||||
| 4032: 28 61 2c 62 2c 63 29 00 00 00 00 00 00 00 00 00 (a,b,c).........
|
||||
| page 3 offset 8192
|
||||
| 0: 0d 00 00 00 03 0c 94 00 0f e6 0f ef 0c 94 00 00 ................
|
||||
| 3216: 00 00 00 00 86 4a 84 80 80 80 80 01 04 00 8d 18 .....J..........
|
||||
| 3232: 00 00 03 2b 02 30 30 01 02 06 01 02 06 01 02 06 ...+.00.........
|
||||
| 3248: 1f 02 03 01 02 03 01 02 03 01 08 32 30 31 36 30 ...........20160
|
||||
| 3264: 36 30 39 01 02 07 01 02 07 01 02 07 01 01 34 01 609...........4.
|
||||
| 3280: 02 05 01 02 05 01 02 05 01 01 35 01 02 04 01 02 ..........5.....
|
||||
| 3296: 04 01 02 04 02 07 30 30 30 30 30 30 30 1c 02 04 ......0000000...
|
||||
| 3312: 01 02 04 01 02 04 01 06 62 69 6e 61 72 79 03 06 ........binary..
|
||||
| 3328: 01 02 02 03 06 01 02 02 03 06 01 02 02 03 06 01 ................
|
||||
| 3344: 02 02 03 06 01 02 02 03 06 01 02 02 03 06 01 02 ................
|
||||
| 3360: 02 03 06 01 02 02 03 06 01 02 02 03 06 01 02 02 ................
|
||||
| 3376: 03 06 01 02 02 03 06 01 02 02 01 08 63 6f 6d 70 ............comp
|
||||
| 3392: 69 6c 65 72 01 02 02 01 02 02 01 02 02 01 06 64 iler...........d
|
||||
| 3408: 62 73 74 61 74 07 02 03 01 02 03 01 02 03 02 04 bstat...........
|
||||
| 3424: 65 62 75 67 04 02 02 01 02 02 01 02 02 01 06 65 ebug...........e
|
||||
| 3440: 6e 61 62 6c 65 07 02 02 01 02 02 01 02 02 01 02 nable...........
|
||||
| 3456: 02 01 02 02 01 02 02 01 02 02 01 02 02 01 02 02 ................
|
||||
| 3472: 01 02 02 01 02 02 01 02 02 01 02 02 01 02 02 01 ................
|
||||
| 3488: 02 02 01 02 02 01 02 02 01 02 02 01 02 02 01 02 ................
|
||||
| 3504: 02 01 02 02 02 08 78 74 65 6e 73 69 6f 6e 1f 02 ......xtension..
|
||||
| 3520: 04 01 02 04 01 02 04 01 04 66 74 73 34 0a 02 03 .........fts4...
|
||||
| 3536: 01 02 03 01 02 03 04 01 35 0d 02 03 01 02 03 01 ........5.......
|
||||
| 3552: 02 03 01 03 67 63 63 01 02 03 01 02 03 01 02 03 ....gcc.........
|
||||
| 3568: 02 06 65 6f 70 6f 6c 79 10 02 03 01 02 03 01 02 ..eopoly........
|
||||
| 3584: 03 01 05 6a 73 6f 6e 31 13 02 03 01 02 03 01 02 ...json1........
|
||||
| 3600: 03 01 04 6c 6f 61 64 1f 02 03 01 02 03 01 02 03 ...load.........
|
||||
| 3616: 01 03 6d 61 78 1c 02 02 01 02 02 01 02 02 02 05 ..max...........
|
||||
| 3632: 65 6d 6f 72 79 1c 02 03 01 02 03 01 02 03 04 04 emory...........
|
||||
| 3648: 73 79 73 35 16 02 03 01 02 02 03 01 03 01 06 6e sys5...........n
|
||||
| 3664: 6f 63 61 73 65 02 06 01 02 02 03 06 01 02 02 03 ocase...........
|
||||
| 3680: 06 01 02 02 03 06 01 02 02 03 06 01 02 02 03 06 ................
|
||||
| 3696: 01 02 02 03 06 01 02 02 03 06 01 02 02 03 06 01 ................
|
||||
| 3712: 02 02 03 06 01 02 02 03 06 01 02 02 03 06 01 02 ................
|
||||
| 3728: 02 01 04 6f 6d 69 74 1f 02 02 01 02 02 01 02 02 ...omit.........
|
||||
| 3744: 01 05 72 74 72 65 65 19 02 03 01 02 03 01 02 03 ..rtree.........
|
||||
| 3760: 04 02 69 6d 01 06 01 02 02 03 06 01 02 02 03 06 ..im............
|
||||
| 3776: 01 02 02 03 06 01 02 02 03 06 01 02 02 03 06 01 ................
|
||||
| 3792: 02 02 03 06 01 02 02 03 06 01 02 02 03 06 01 02 ................
|
||||
| 3808: 02 03 06 01 02 02 03 06 01 02 02 03 06 01 02 02 ................
|
||||
| 3824: 01 0a 74 68 72 65 61 64 73 61 66 65 03 57 34 56 ..threadsafe.W4V
|
||||
| 3840: 94 64 91 46 85 84 04 76 74 61 62 07 02 04 01 02 .d.F...vtab.....
|
||||
| 3856: 04 01 02 04 01 01 78 01 06 01 01 02 01 06 01 01 ......x.........
|
||||
| 3872: 02 01 06 01 01 02 01 06 01 01 02 01 06 01 10 02 ................
|
||||
| 3888: 01 06 01 01 02 01 06 01 01 02 01 06 01 01 02 01 ................
|
||||
| 3904: 06 01 01 02 01 06 01 01 02 01 06 01 01 02 01 06 ................
|
||||
| 3920: 01 01 02 01 06 01 01 02 01 06 01 01 02 01 06 01 ................
|
||||
| 3936: 01 02 01 06 01 01 10 01 06 01 01 02 01 06 01 01 ................
|
||||
| 3952: 02 01 06 01 01 02 01 06 01 01 02 01 06 01 01 02 ................
|
||||
| 3968: 01 06 01 01 02 01 06 01 01 02 01 06 01 01 02 01 ................
|
||||
| 3984: 06 01 01 02 01 06 01 01 02 01 06 01 01 02 01 06 ................
|
||||
| 4000: 01 01 02 01 06 01 01 02 01 06 01 01 02 01 06 01 ................
|
||||
| 4016: 01 02 01 06 01 01 02 01 06 01 01 02 01 06 01 01 ................
|
||||
| 4032: 02 01 06 01 01 02 01 06 01 01 02 04 15 13 0c 0c ................
|
||||
| 4048: 12 44 13 11 0f 47 13 0f 0c 0e 11 10 0f 0e 10 0f .D...G..........
|
||||
| 4064: 44 0f 10 40 15 0f 07 01 03 00 14 24 5a 24 24 0f D..@.......$Z$$.
|
||||
| 4080: 0a 03 00 24 00 00 00 00 01 01 01 00 01 01 01 01 ...$............
|
||||
| page 4 offset 12288
|
||||
| 0: 0a 00 00 00 01 0f fa 00 00 00 00 00 00 00 00 00 ................
|
||||
| 4080: 00 00 00 00 00 00 00 00 00 00 05 04 09 0c 01 02 ................
|
||||
| page 5 offset 16384
|
||||
| 0: 0d 00 00 00 24 0c 0a 00 0f d8 0f af 0f 86 0f 74 ....$..........t
|
||||
| 16: 0f 61 0f 4e 0f 2f 0f 0f 0e ef 0e d7 0e be 0e a5 .a.N./..........
|
||||
| 32: 0e 8d 0e 74 0e 5b 0e 40 0e 24 0e 08 0d ef 0d d5 ...t.[.@.$......
|
||||
| 48: 0d bb 0d a0 0d 84 0d 68 0d 4f 0d 35 0d 1b 0c fb .......h.O.5....
|
||||
| 64: 0c da 0c b9 0c 99 0c 78 0c 57 00 00 00 00 00 00 .......x.W......
|
||||
| 3072: 00 00 00 00 00 00 00 00 00 00 18 24 05 00 25 0f ...........$..%.
|
||||
| 3088: 19 54 48 52 45 41 44 53 41 46 45 3d 30 58 42 49 .THREADSAFE=0XBI
|
||||
| 3104: 4e 41 52 59 18 23 05 00 25 0f 19 54 48 52 45 41 NARY.#..%..THREA
|
||||
| 3120: 44 53 41 46 45 3d 30 58 4e 4f 43 41 53 45 17 22 DSAFE=0XNOCASE..
|
||||
| 3136: 05 00 25 0f 17 54 48 52 45 41 44 53 31 46 45 3d ..%..THREADS1FE=
|
||||
| 3152: 30 58 52 64 52 49 4d 1f 21 05 00 33 0f 19 4f 4d 0XRdRIM.!..3..OM
|
||||
| 3168: 49 54 20 4c 4f 41 44 20 45 58 54 45 4e 53 49 4f IT LOAD EXTENSIO
|
||||
| 3184: 4e 58 42 49 4e 41 52 59 1f 20 05 00 33 0f 19 4f NXBINARY. ..3..O
|
||||
| 3200: 4d 49 54 20 4c 4f 41 44 20 45 58 54 45 4e 53 49 MIT LOAD EXTENSI
|
||||
| 3216: 4f 4e 58 4e 4f 43 41 53 45 1e 1f 05 00 33 0f 17 ONXNOCASE....3..
|
||||
| 3232: 4f 4d 49 54 20 4c 4f 41 44 20 45 58 54 45 4e 53 OMIT LOAD EXTENS
|
||||
| 3248: 49 4f 4e 58 52 54 52 49 4d 1f 1e 05 00 33 0f 19 IONXRTRIM....3..
|
||||
| 3264: 4d 41 58 20 4d 45 4d 4f 52 59 3d 35 30 30 30 30 MAX MEMORY=50000
|
||||
| 3280: 30 30 30 58 42 49 4e 41 52 59 1f 1d 05 00 33 0f 000XBINARY....3.
|
||||
| 3296: 19 4d 41 58 20 4d 45 4d 4f 52 59 3d 35 30 30 30 .MAX MEMORY=5000
|
||||
| 3312: 30 30 30 30 58 4e 4f 43 41 53 45 1e 1c 05 00 33 0000XNOCASE....3
|
||||
| 3328: 0f 17 4d 41 58 20 4d 45 4d 4f 52 59 3d 35 30 30 ..MAX MEMORY=500
|
||||
| 3344: 30 30 30 30 30 58 52 54 52 49 4d 18 1b 05 00 25 00000XRTRIM....%
|
||||
| 3360: 0f 19 45 4e 41 42 4c 45 20 52 54 52 45 45 58 42 ..ENABLE RTREEXB
|
||||
| 3376: 49 4e 41 52 59 18 1a 05 00 25 0f 19 45 4e 41 42 INARY....%..ENAB
|
||||
| 3392: 4c 45 20 52 54 52 45 45 58 4e 4f 43 41 53 45 17 LE RTREEXNOCASE.
|
||||
| 3408: 19 05 00 25 0f 17 45 4e 41 42 4c 45 20 52 54 52 ...%..ENABLE RTR
|
||||
| 3424: 45 45 58 52 54 52 49 4d 1a 18 05 00 29 0f 19 45 EEXRTRIM....)..E
|
||||
| 3440: 4e 41 42 4b 45 20 4d 45 4d 53 59 53 35 58 42 49 NABKE MEMSYS5XBI
|
||||
| 3456: 4e 41 52 59 1a 17 05 00 29 0f 19 45 4e 41 42 4c NARY....)..ENABL
|
||||
| 3472: 42 60 2d 45 4d 53 59 53 35 58 4e 4f 43 41 53 45 B`-EMSYS5XNOCASE
|
||||
| 3488: 19 16 05 00 29 0f 17 45 4e 41 42 4c 45 20 4d 45 ....)..ENABLE ME
|
||||
| 3504: 4d 53 59 53 35 58 52 54 52 49 4d 18 15 05 00 25 MSYS5XRTRIM....%
|
||||
| 3520: 0f 19 45 4e 41 42 4c 45 20 4a 53 4f 4e 31 58 42 ..ENABLE JSON1XB
|
||||
| 3536: 49 4e 41 52 59 18 14 05 00 25 0f 19 45 4e 41 42 INARY....%..ENAB
|
||||
| 3552: 4c 45 20 4a 53 4f 4e 31 58 4e 4f 43 41 53 45 17 LE JSON1XNOCASE.
|
||||
| 3568: 13 05 00 25 0f 17 45 4e 41 42 4c 45 20 4a 53 4f ...%..ENABLE JSO
|
||||
| 3584: 4e 31 58 52 54 52 49 4d 1a 12 05 00 29 0f 19 45 N1XRTRIM....)..E
|
||||
| 3600: 42 4c 45 20 47 45 4f 50 4f 4c 59 58 42 49 4e 41 BLE GEOPOLYXBINA
|
||||
| 3616: 52 59 1a 11 05 00 39 0f 19 45 4e 41 42 4c 45 2e RY....9..ENABLE.
|
||||
| 3632: 41 40 47 45 4f 50 4f 4c 59 58 4e 4f 43 41 53 40 A@GEOPOLYXNOCAS@
|
||||
| 3648: 4f 4c 59 58 55 19 10 05 00 29 0f 17 45 4e 41 42 OLYXU....)..ENAB
|
||||
| 3664: 4c 45 20 47 45 4f 52 54 52 49 4d 17 0f 05 00 23 LE GEORTRIM....#
|
||||
| 3680: 0f 19 45 4e 41 42 4c 45 20 46 54 53 35 58 42 49 ..ENABLE FTS5XBI
|
||||
| 3696: 4e 41 52 59 17 0e 05 00 23 0f 19 45 4e 41 42 4c NARY....#..ENABL
|
||||
| 3712: 45 20 46 54 53 35 58 4e 4f 43 41 53 45 16 0d 05 E FTS5XNOCASE...
|
||||
| 3728: 00 23 0f 17 45 4e 41 42 4c 45 20 46 54 53 35 58 .#..ENABLE FTS5X
|
||||
| 3744: 52 54 52 49 4d 17 0c 05 00 23 0f 19 45 4e 41 42 RTRIM....#..ENAB
|
||||
| 3760: 4c 45 20 46 54 53 34 58 42 49 4e 41 52 59 17 0b LE FTS4XBINARY..
|
||||
| 3776: 05 00 23 0f 19 45 4e 41 42 4c 45 20 46 54 53 34 ..#..ENABLE FTS4
|
||||
| 3792: 58 4e 4f 43 41 53 45 16 0a 05 00 23 0f 17 45 4e XNOCASE....#..EN
|
||||
| 3808: 41 42 4c 45 20 46 54 53 34 58 52 54 52 49 4d 1e ABLE FTS4XRTRIM.
|
||||
| 3824: 09 05 00 31 0f 19 45 4e 41 42 4c 45 20 44 42 53 ...1..ENABLE DBS
|
||||
| 3840: 54 41 54 20 56 54 41 42 58 42 49 4e 41 52 59 1e TAT VTABXBINARY.
|
||||
| 3856: 08 05 00 31 0f 19 45 4e 41 42 4c 45 20 44 42 53 ...1..ENABLE DBS
|
||||
| 3872: 54 41 54 20 56 54 24 15 48 4e 4f 43 41 53 45 1d TAT VT$.HNOCASE.
|
||||
| 3888: 07 05 00 31 0f 17 45 4e 41 42 4c 45 20 44 42 53 ...1..ENABLE DBS
|
||||
| 3904: 54 41 54 20 56 54 41 42 58 52 54 52 49 4d 11 06 TAT VTABXRTRIM..
|
||||
| 3920: 05 00 17 0f 19 44 45 42 55 47 58 42 49 4e 41 52 .....DEBUGXBINAR
|
||||
| 3936: 59 11 05 05 00 17 0f 19 44 45 42 55 47 58 4e 4f Y.......DEBUGXNO
|
||||
| 3952: 43 41 53 45 10 04 05 00 17 0f 17 44 45 42 55 47 CASE.......DEBUG
|
||||
| 3968: 58 52 54 52 49 4d 27 03 05 00 43 0f 19 43 4f 4d XRTRIM'...C..COM
|
||||
| 3984: 50 49 4c 45 52 3d 67 63 63 2d 35 2e 34 2e 30 20 PILER=gcc-5.4.0
|
||||
| 4000: 32 30 31 36 30 36 30 39 58 42 49 4e 41 52 59 27 20160609XBINARY'
|
||||
| 4016: 02 05 00 43 0f 19 43 4f 4d 50 49 4c 45 52 3d 67 ...C..COMPILER=g
|
||||
| 4032: 63 63 2d 35 2e 34 2e 30 20 32 30 31 36 30 36 30 cc-5.4.0 2016060
|
||||
| 4048: 39 58 4e 4f 43 41 53 45 26 01 05 00 43 0f 17 43 9XNOCASE&...C..C
|
||||
| 4064: 4f 4d 50 49 4c 45 52 3d 67 63 63 2d 35 2e 34 2e OMPILER=gcc-5.4.
|
||||
| 4080: 30 20 32 30 31 36 30 36 30 39 58 52 54 52 49 4d 0 20160609XRTRIM
|
||||
| page 6 offset 20480
|
||||
| 0: 0d 00 00 00 24 0e e0 00 0f f8 0f f0 0f e8 0f e0 ....$...........
|
||||
| 16: 0f d8 0f d0 0f c8 0f c0 0f b8 0f b0 0f a8 0f a0 ................
|
||||
| 32: 1f 98 0f 90 0f 88 0f 80 0f 78 0f 70 0f 68 0f 60 .........x.p.h.`
|
||||
| 48: 0f 58 0f 50 0f 48 0f 40 0f 38 0f 30 0f 28 0f 20 .X.P.H.@.8.0.(.
|
||||
| 64: 0f 18 0f 10 0f 08 0f 00 0e f8 0e f0 0e e8 00 00 ................
|
||||
| 3808: 06 24 03 00 12 02 01 01 06 23 03 00 12 02 01 01 .$.......#......
|
||||
| 3824: 06 22 03 00 12 02 01 01 06 21 03 00 12 03 01 01 .........!......
|
||||
| 3840: 06 20 03 00 12 03 01 01 06 1f 03 00 12 03 01 01 . ..............
|
||||
| 3856: 06 1e 03 00 12 03 01 01 06 1d 03 00 12 03 01 01 ................
|
||||
| 3872: 06 1c 03 00 12 03 01 01 06 1b 03 00 12 02 01 01 ................
|
||||
| 3888: 06 1a 03 00 12 02 01 01 06 19 03 00 12 02 01 01 ................
|
||||
| 3904: 06 18 03 00 12 02 01 01 06 17 03 00 12 02 01 01 ................
|
||||
| 3920: 06 15 f3 00 12 02 01 01 06 15 03 00 12 02 01 01 ................
|
||||
| 3936: 06 14 03 00 12 02 01 01 06 13 03 00 12 02 01 01 ................
|
||||
| 3952: 06 12 03 00 12 02 01 01 06 11 03 00 12 02 01 01 ................
|
||||
| 3968: 06 10 03 00 12 02 01 01 06 0f 03 00 12 02 01 01 ................
|
||||
| 3984: 06 0e 03 00 12 02 01 01 06 0d 03 00 12 02 01 01 ................
|
||||
| 4000: 06 0c 03 00 12 02 01 01 06 0b 03 00 12 02 01 01 ................
|
||||
| 4016: 06 0a 03 00 12 02 01 01 06 09 03 00 12 03 01 01 ................
|
||||
| 4032: 06 08 03 00 12 03 01 01 06 07 03 00 12 03 01 01 ................
|
||||
| 4048: 06 06 03 00 12 01 01 01 06 05 03 00 12 01 01 01 ................
|
||||
| 4064: 06 04 03 00 12 01 01 01 06 03 03 00 12 06 01 01 ................
|
||||
| 4080: 06 02 03 00 12 06 01 01 06 01 03 00 12 06 01 01 ................
|
||||
| page 7 offset 24576
|
||||
| 0: 0a 00 00 00 01 0f f4 00 0f f4 00 00 00 00 00 00 ................
|
||||
| 4080: 00 00 00 00 0b 03 1b 01 76 65 72 73 69 6f 6e 04 ........version.
|
||||
| page 8 offset 28672
|
||||
| 0: 0d 00 00 00 03 0f d6 00 0f f4 0f e9 0f d6 00 00 ................
|
||||
| 4048: 00 00 00 00 00 00 11 03 02 2b 69 6e 74 65 67 72 .........+integr
|
||||
| 4064: 69 74 79 2d 63 68 65 63 6b 09 02 02 1b 72 65 62 ity-check....reb
|
||||
| 4080: 75 69 6c 64 0a 01 02 1d 6f 70 74 69 00 00 00 00 uild....opti....
|
||||
| end c0.txt.db
|
||||
}]} {}
|
||||
|
||||
do_execsql_test 82.2 {
|
||||
UPDATE t1 SET b=quote(zeroblob(current_date)) WHERE t1 MATCH 't*';
|
||||
PRAGMA writable_schema=ON;
|
||||
|
||||
UPDATE sqlite_schema SET sql='SELECT * FROM t1' WHERE rowid=6;
|
||||
INSERT INTO t1(t1,rank) VALUES('secure-delete',1);
|
||||
}
|
||||
|
||||
do_catchsql_test 82.3 {
|
||||
CREATE VIRTUAL TABLE IF NOT EXISTS t USING rtree(x,c);
|
||||
} {1 {Too few columns for an rtree table}}
|
||||
|
||||
do_catchsql_test 82.4 {
|
||||
BEGIN;
|
||||
REPLACE INTO t1(rowid,b,a,rowid) VALUES(x'44023b9eb002d28b0ee90c',1,2,3);
|
||||
SAVEPOINT b;
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
|
||||
|
||||
sqlite3_fts5_may_be_corrupt 0
|
||||
finish_test
|
||||
|
||||
@@ -1451,6 +1451,473 @@ do_catchsql_test 9.2 {
|
||||
DELETE FROM t1;
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_test 10.0 {
|
||||
sqlite3 db {}
|
||||
db deserialize [decode_hexdb {
|
||||
.open --hexdb
|
||||
| size 32768 pagesize 4096 filename crash-b06f016068bcea.db
|
||||
| page 1 offset 0
|
||||
| 0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00 SQLite format 3.
|
||||
| 16: 10 00 01 01 00 40 20 20 00 00 00 00 00 00 00 08 .....@ ........
|
||||
| 32: 00 00 00 02 00 00 00 01 00 00 00 09 00 00 00 04 ................
|
||||
| 96: 00 00 00 00 0d 0f c7 00 07 0d 92 00 0f 8d 0f 36 ...............6
|
||||
| 112: 0e cb 0e 6b 0e 0e 0d b6 0d 92 0d 92 00 00 00 00 ...k............
|
||||
| 3472: 00 00 22 08 06 17 11 11 01 31 74 61 62 6c 65 74 .........1tablet
|
||||
| 3488: 32 74 32 08 43 52 45 41 54 45 20 54 41 42 4c 45 2t2.CREATE TABLE
|
||||
| 3504: 20 74 32 28 78 29 56 07 06 17 1f 1f 01 7d 74 61 t2(x)V.......ta
|
||||
| 3520: 62 6c 65 74 31 5f 63 6f 6e 66 69 67 74 31 5f 63 blet1_configt1_c
|
||||
| 3536: 6f 6e 66 69 67 07 43 52 45 41 54 45 20 54 41 42 onfig.CREATE TAB
|
||||
| 3552: 4c 45 20 27 74 31 5f 63 6f 6e 66 69 67 27 28 6b LE 't1_config'(k
|
||||
| 3568: 20 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 76 29 PRIMARY KEY, v)
|
||||
| 3584: 20 57 49 54 48 4f 55 54 20 52 4f 57 49 44 5b 06 WITHOUT ROWID[.
|
||||
| 3600: 07 17 21 21 01 81 01 74 61 62 6c 65 74 31 5f 64 ..!!...tablet1_d
|
||||
| 3616: 6f 63 73 69 7a 65 74 31 5f 64 6f 63 73 69 7a 65 ocsizet1_docsize
|
||||
| 3632: 06 43 52 45 41 54 45 20 54 41 42 4c 45 20 27 74 .CREATE TABLE 't
|
||||
| 3648: 31 5f 64 6f 63 73 69 7a 65 27 28 69 64 20 49 4e 1_docsize'(id IN
|
||||
| 3664: 54 45 47 45 52 20 50 52 49 4d 41 52 59 20 4b 45 TEGER PRIMARY KE
|
||||
| 3680: 59 2c 20 73 7a 20 42 4c 4f 42 29 5e 05 07 17 21 Y, sz BLOB)^...!
|
||||
| 3696: 21 01 81 07 74 61 62 6c 65 74 31 5f 63 6f 6e 74 !...tablet1_cont
|
||||
| 3712: 65 6e 74 74 31 5f 63 6f 6e 74 65 6e 74 05 43 52 entt1_content.CR
|
||||
| 3728: 45 41 54 45 20 54 41 42 4c 45 20 27 74 31 5f 63 EATE TABLE 't1_c
|
||||
| 3744: 6f 6e 74 65 6e 74 27 28 69 64 20 49 4e 54 45 47 ontent'(id INTEG
|
||||
| 3760: 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 ER PRIMARY KEY,
|
||||
| 3776: 63 30 2c 20 63 31 2c 20 63 32 29 69 04 07 17 19 c0, c1, c2)i....
|
||||
| 3792: 19 01 81 2d 74 61 62 6c 65 74 31 5f 69 64 78 74 ...-tablet1_idxt
|
||||
| 3808: 31 5f 69 64 78 04 43 52 45 41 54 45 20 54 41 42 1_idx.CREATE TAB
|
||||
| 3824: 4c 45 20 27 74 31 5f 69 64 78 27 28 73 65 67 69 LE 't1_idx'(segi
|
||||
| 3840: 64 2c 20 74 65 72 6d 2c 20 70 67 6e 6f 2c 20 50 d, term, pgno, P
|
||||
| 3856: 52 49 4d 41 52 59 20 4b 45 59 28 73 65 67 69 64 RIMARY KEY(segid
|
||||
| 3872: 2c 20 74 65 72 6d 29 29 20 57 49 54 48 4f 55 54 , term)) WITHOUT
|
||||
| 3888: 20 52 4f 57 49 44 55 03 07 17 1b 1b 01 81 01 74 ROWIDU........t
|
||||
| 3904: 61 62 6c 65 74 31 5f 64 61 74 61 74 31 5f 64 61 ablet1_datat1_da
|
||||
| 3920: 74 61 03 43 52 45 41 54 45 20 54 41 42 4c 45 20 ta.CREATE TABLE
|
||||
| 3936: 27 74 31 5f 64 61 74 61 27 28 69 64 20 49 4e 54 't1_data'(id INT
|
||||
| 3952: 45 47 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59 EGER PRIMARY KEY
|
||||
| 3968: 2c 20 62 6c 6f 63 6b 20 42 4c 4f 42 29 38 02 06 , block BLOB)8..
|
||||
| 3984: 17 11 11 08 5f 74 61 62 6c 65 74 31 74 31 43 52 ...._tablet1t1CR
|
||||
| 4000: 45 41 54 45 20 56 49 52 54 55 41 4c 20 54 41 42 EATE VIRTUAL TAB
|
||||
| 4016: 4c 45 20 74 31 20 55 53 49 4e 47 20 66 74 73 35 LE t1 USING fts5
|
||||
| 4032: 28 61 2c 62 2c 63 29 00 00 00 00 00 00 00 00 00 (a,b,c).........
|
||||
| page 3 offset 8192
|
||||
| 0: 0d 00 00 00 03 0c 94 00 0f e6 0f ef 0c 94 00 00 ................
|
||||
| 3216: 00 00 00 00 86 4a 84 80 80 80 80 01 04 00 8d 18 .....J..........
|
||||
| 3232: 00 00 03 2b 02 30 30 01 02 06 01 02 06 01 02 06 ...+.00.........
|
||||
| 3248: 1f 02 03 01 02 03 01 02 03 01 08 32 30 31 36 30 ...........20160
|
||||
| 3264: 36 30 39 01 02 07 01 02 07 01 02 07 01 01 34 01 609...........4.
|
||||
| 3280: 02 05 01 02 05 01 02 05 01 01 35 01 02 04 01 02 ..........5.....
|
||||
| 3296: 04 01 02 04 02 07 30 30 30 30 30 30 30 1c 02 04 ......0000000...
|
||||
| 3312: 01 02 04 01 02 04 01 06 62 69 6e 61 72 79 03 06 ........binary..
|
||||
| 3328: 01 02 02 03 06 01 02 02 03 06 01 02 02 03 06 01 ................
|
||||
| 3344: 02 02 03 06 01 02 02 03 06 01 02 02 03 06 01 02 ................
|
||||
| 3360: 02 03 06 01 02 02 03 06 01 02 02 03 06 01 02 02 ................
|
||||
| 3376: 03 06 01 02 02 03 06 01 02 02 01 08 63 6f 6d 70 ............comp
|
||||
| 3392: 69 6c 65 72 01 02 02 01 02 02 01 02 02 01 06 64 iler...........d
|
||||
| 3408: 62 73 74 61 74 07 02 03 01 02 03 01 02 03 02 04 bstat...........
|
||||
| 3424: 65 62 75 67 04 02 02 01 02 02 01 02 02 01 06 65 ebug...........e
|
||||
| 3440: 6e 61 62 6c 65 07 02 02 01 02 02 01 02 02 01 02 nable...........
|
||||
| 3456: 02 01 02 02 01 02 02 01 02 02 01 02 02 01 02 02 ................
|
||||
| 3472: 01 02 02 01 02 02 01 02 02 01 02 02 01 02 02 01 ................
|
||||
| 3488: 02 02 01 02 02 01 02 02 01 02 02 01 02 02 01 02 ................
|
||||
| 3504: 02 01 02 02 02 08 78 74 65 6e 73 69 6f 6e 1f 02 ......xtension..
|
||||
| 3520: 04 01 02 04 01 02 04 01 04 66 74 73 34 0a 02 03 .........fts4...
|
||||
| 3536: 01 02 03 01 02 03 04 01 35 0d 02 03 01 02 03 01 ........5.......
|
||||
| 3552: 02 03 01 03 67 63 63 01 02 03 01 02 03 01 02 03 ....gcc.........
|
||||
| 3568: 02 06 65 6f 70 6f 6c 79 10 02 03 01 02 03 01 02 ..eopoly........
|
||||
| 3584: 03 01 05 6a 73 6f 6e 31 13 02 03 01 02 03 01 02 ...json1........
|
||||
| 3600: 03 01 04 6c 6f 61 64 1f 02 03 01 02 03 01 02 03 ...load.........
|
||||
| 3616: 01 03 6d 61 78 1c 02 02 01 02 02 01 02 02 02 05 ..max...........
|
||||
| 3632: 65 6d 6f 72 79 1c 02 03 01 02 03 01 02 03 04 04 emory...........
|
||||
| 3648: 73 79 73 35 16 02 03 01 02 02 03 01 03 01 06 6e sys5...........n
|
||||
| 3664: 6f 63 61 73 65 02 06 01 02 02 03 06 01 02 02 03 ocase...........
|
||||
| 3680: 06 01 02 02 03 06 01 02 02 03 06 01 02 02 03 06 ................
|
||||
| 3696: 01 02 02 03 06 01 02 02 03 06 01 02 02 03 06 01 ................
|
||||
| 3712: 02 02 03 06 01 02 02 03 06 01 02 02 03 06 01 02 ................
|
||||
| 3728: 02 01 04 6f 6d 69 74 1f 02 02 01 02 02 01 02 02 ...omit.........
|
||||
| 3744: 01 05 72 74 72 65 65 19 02 03 01 02 03 01 02 03 ..rtree.........
|
||||
| 3760: 04 02 69 6d 01 06 01 02 02 03 06 01 02 02 03 06 ..im............
|
||||
| 3776: 01 02 02 03 06 01 02 02 03 06 01 02 02 03 06 01 ................
|
||||
| 3792: 02 02 03 06 01 02 02 03 06 01 02 02 03 06 01 02 ................
|
||||
| 3808: 02 03 06 01 02 02 03 06 01 02 02 03 06 01 02 02 ................
|
||||
| 3824: 01 0a 74 68 72 65 61 64 73 61 66 65 03 57 34 56 ..threadsafe.W4V
|
||||
| 3840: 94 64 91 46 85 84 04 76 74 61 62 07 02 04 01 02 .d.F...vtab.....
|
||||
| 3856: 04 01 02 04 01 01 78 01 06 01 01 02 01 06 01 01 ......x.........
|
||||
| 3872: 02 01 06 01 01 02 01 06 01 01 02 01 06 01 10 02 ................
|
||||
| 3888: 01 06 01 01 02 01 06 01 01 02 01 06 01 01 02 01 ................
|
||||
| 3904: 06 01 01 02 01 06 01 01 02 01 06 01 01 02 01 06 ................
|
||||
| 3920: 01 01 02 01 06 01 01 02 01 06 01 01 02 01 06 01 ................
|
||||
| 3936: 01 02 01 06 01 01 10 01 06 01 01 02 01 06 01 01 ................
|
||||
| 3952: 02 01 06 01 01 02 01 06 01 01 02 01 06 01 01 02 ................
|
||||
| 3968: 01 06 01 01 02 01 06 01 01 02 01 06 01 01 02 01 ................
|
||||
| 3984: 06 01 01 02 01 06 01 01 02 01 06 01 01 02 01 06 ................
|
||||
| 4000: 01 01 02 01 06 01 01 02 01 06 01 01 02 01 06 01 ................
|
||||
| 4016: 01 02 01 06 01 01 02 01 06 01 01 02 01 06 01 01 ................
|
||||
| 4032: 02 01 06 01 01 02 01 06 01 01 02 04 15 13 0c 0c ................
|
||||
| 4048: 12 44 13 11 0f 47 13 0f 0c 0e 11 10 0f 0e 10 0f .D...G..........
|
||||
| 4064: 44 0f 10 40 15 0f 07 01 03 00 14 24 5a 24 24 0f D..@.......$Z$$.
|
||||
| 4080: 0a 03 00 24 00 00 00 00 01 01 01 00 01 01 01 01 ...$............
|
||||
| page 4 offset 12288
|
||||
| 0: 0a 00 00 00 01 0f fa 00 00 00 00 00 00 00 00 00 ................
|
||||
| 4080: 00 00 00 00 00 00 00 00 00 00 05 04 09 0c 01 02 ................
|
||||
| page 5 offset 16384
|
||||
| 0: 0d 00 00 00 24 0c 0a 00 0f d8 0f af 0f 86 0f 74 ....$..........t
|
||||
| 16: 0f 61 0f 4e 0f 2f 0f 0f 0e ef 0e d7 0e be 0e a5 .a.N./..........
|
||||
| 32: 0e 8d 0e 74 0e 5b 0e 40 0e 24 0e 08 0d ef 0d d5 ...t.[.@.$......
|
||||
| 48: 0d bb 0d a0 0d 84 0d 68 0d 4f 0d 35 0d 1b 0c fb .......h.O.5....
|
||||
| 64: 0c da 0c b9 0c 99 0c 00 00 00 00 00 00 00 00 00 ................
|
||||
| 3072: 00 00 00 00 00 00 00 00 00 00 18 24 05 00 25 0f ...........$..%.
|
||||
| 3088: 19 54 48 52 45 41 44 53 41 46 45 3d 30 58 42 49 .THREADSAFE=0XBI
|
||||
| 3104: 4e 41 52 59 18 23 05 00 25 0f 19 54 48 52 45 41 NARY.#..%..THREA
|
||||
| 3120: 44 53 41 46 45 3d 30 58 4e 4f 43 41 53 45 17 22 DSAFE=0XNOCASE..
|
||||
| 3136: 05 00 25 0f 17 54 48 52 45 41 44 53 31 46 45 3d ..%..THREADS1FE=
|
||||
| 3152: 30 58 52 64 52 49 4d 1f 21 05 00 33 0f 19 4f 4d 0XRdRIM.!..3..OM
|
||||
| 3168: 49 54 20 4c 4f 41 44 20 45 58 54 45 4e 53 49 4f IT LOAD EXTENSIO
|
||||
| 3184: 4e 58 42 49 4e 41 52 59 1f 20 05 00 33 0f 19 4f NXBINARY. ..3..O
|
||||
| 3200: 4d 49 54 20 4c 4f 41 44 20 45 58 54 45 4e 53 49 MIT LOAD EXTENSI
|
||||
| 3216: 4f 4e 58 4e 4f 43 41 53 45 1e 1f 05 00 33 0f 17 ONXNOCASE....3..
|
||||
| 3232: 4f 4d 49 54 20 4c 4f 41 44 20 45 58 54 45 4e 53 OMIT LOAD EXTENS
|
||||
| 3248: 49 4f 4e 58 52 54 52 49 4d 1f 1e 05 00 33 0f 19 IONXRTRIM....3..
|
||||
| 3264: 4d 41 58 20 4d 45 4d 4f 52 59 3d 35 30 30 30 30 MAX MEMORY=50000
|
||||
| 3280: 30 30 30 58 42 49 4e 41 52 59 1f 1d 05 00 33 0f 000XBINARY....3.
|
||||
| 3296: 19 4d 41 58 20 4d 45 4d 4f 52 59 3d 35 30 30 30 .MAX MEMORY=5000
|
||||
| 3312: 30 30 30 30 58 4e 4f 43 41 53 45 1e 1c 05 00 33 0000XNOCASE....3
|
||||
| 3328: 0f 17 4d 41 58 20 4d 45 4d 4f 52 59 3d 35 30 30 ..MAX MEMORY=500
|
||||
| 3344: 30 30 30 30 30 58 52 54 52 49 4d 18 1b 05 00 25 00000XRTRIM....%
|
||||
| 3360: 0f 19 45 4e 41 42 4c 45 20 52 54 52 45 45 58 42 ..ENABLE RTREEXB
|
||||
| 3376: 49 4e 41 52 59 18 1a 05 00 25 0f 19 45 4e 41 42 INARY....%..ENAB
|
||||
| 3392: 4c 45 20 52 54 52 45 45 58 4e 4f 43 41 53 45 17 LE RTREEXNOCASE.
|
||||
| 3408: 19 05 00 25 0f 17 45 4e 41 42 4c 45 20 52 54 52 ...%..ENABLE RTR
|
||||
| 3424: 45 45 58 52 54 52 49 4d 1a 18 05 00 29 0f 19 45 EEXRTRIM....)..E
|
||||
| 3440: 4e 41 42 4b 45 20 4d 45 4d 53 59 53 35 58 42 49 NABKE MEMSYS5XBI
|
||||
| 3456: 4e 41 52 59 1a 17 05 00 29 0f 19 45 4e 41 42 4c NARY....)..ENABL
|
||||
| 3472: 42 60 2d 45 4d 53 59 53 35 58 4e 4f 43 41 53 45 B`-EMSYS5XNOCASE
|
||||
| 3488: 19 16 05 00 29 0f 17 45 4e 41 42 4c 45 20 4d 46 ....)..ENABLE MF
|
||||
| 3504: 4d 53 59 53 35 58 52 54 52 49 4d 18 15 05 00 25 MSYS5XRTRIM....%
|
||||
| 3520: 0f 19 45 4e 41 42 4c 45 20 4a 53 4f 4e 31 58 42 ..ENABLE JSON1XB
|
||||
| 3536: 49 4e 41 52 59 18 14 05 00 25 0f 19 45 4e 41 42 INARY....%..ENAB
|
||||
| 3552: 4c 45 20 4a 53 4f 4e 31 58 4e 4f 43 41 53 45 17 LE JSON1XNOCASE.
|
||||
| 3568: 13 05 00 25 0f 17 45 4e 41 42 4c 45 20 4a 53 4f ...%..ENABLE JSO
|
||||
| 3584: 4e 31 58 52 54 52 49 4d 1a 12 05 00 29 0f 19 45 N1XRTRIM....)..E
|
||||
| 3600: 42 4c 45 20 47 45 4f 50 4f 4c 59 58 42 49 4e 41 BLE GEOPOLYXBINA
|
||||
| 3616: 52 59 1a 11 05 00 39 0f 19 45 4e 41 42 4c 45 2e RY....9..ENABLE.
|
||||
| 3632: 41 40 47 45 4f 50 4f 4c 59 58 4e 4f 43 41 53 40 A@GEOPOLYXNOCAS@
|
||||
| 3648: 4f 4c 59 58 55 09 10 05 00 29 0f 17 45 4e 41 42 OLYXU....)..ENAB
|
||||
| 3664: 4c 45 20 47 45 4f 52 54 52 49 4d 17 0f 05 00 23 LE GEORTRIM....#
|
||||
| 3680: 0f 19 45 4e 41 42 4c 45 20 46 54 53 35 58 42 49 ..ENABLE FTS5XBI
|
||||
| 3696: 4e 41 52 59 17 0e 05 00 23 0f 19 45 4e 41 42 4c NARY....#..ENABL
|
||||
| 3712: 45 20 46 54 53 35 58 4e 4f 43 41 53 45 16 0d 05 E FTS5XNOCASE...
|
||||
| 3728: 00 23 0f 17 45 4e 41 42 4c 45 20 46 54 53 35 58 .#..ENABLE FTS5X
|
||||
| 3744: 52 54 52 49 4d 17 0c 05 00 23 0f 19 45 4e 41 42 RTRIM....#..ENAB
|
||||
| 3760: 4c 45 20 46 54 53 34 58 42 49 4e 41 52 59 17 0b LE FTS4XBINARY..
|
||||
| 3776: 05 00 23 0f 19 45 4e 41 42 4c 45 20 46 54 53 34 ..#..ENABLE FTS4
|
||||
| 3792: 58 4e 4f 43 41 53 45 16 0a 05 00 23 0f 17 45 4e XNOCASE....#..EN
|
||||
| 3808: 41 42 4c 45 20 46 54 53 34 58 52 54 52 49 4d 1e ABLE FTS4XRTRIM.
|
||||
| 3824: 09 05 00 31 0f 19 45 4e 41 42 4c 45 20 44 42 53 ...1..ENABLE DBS
|
||||
| 3840: 54 41 54 20 56 54 41 42 58 42 49 4e 41 52 59 1e TAT VTABXBINARY.
|
||||
| 3856: 08 05 00 31 0f 19 45 4e 41 42 4c 45 20 44 42 53 ...1..ENABLE DBS
|
||||
| 3872: 54 41 54 20 56 54 24 15 48 4e 4f 43 41 53 45 1d TAT VT$.HNOCASE.
|
||||
| 3888: 07 05 00 31 0f 17 45 4e 41 42 4c 45 20 44 42 53 ...1..ENABLE DBS
|
||||
| 3904: 54 41 54 20 56 54 41 42 58 52 54 52 49 4d 11 06 TAT VTABXRTRIM..
|
||||
| 3920: 05 00 17 0f 19 44 45 42 55 47 58 42 49 4e 41 52 .....DEBUGXBINAR
|
||||
| 3936: 59 11 05 05 00 17 0f 19 44 45 42 55 47 58 4e 4f Y.......DEBUGXNO
|
||||
| 3952: 43 41 53 45 10 04 05 00 17 0f 17 44 45 42 55 47 CASE.......DEBUG
|
||||
| 3968: 58 52 54 52 49 4d 27 03 05 00 43 0f 19 43 4f 4d XRTRIM'...C..COM
|
||||
| 3984: 50 49 4c 45 52 3d 67 63 63 2d 35 2e 34 2e 30 20 PILER=gcc-5.4.0
|
||||
| 4000: 32 30 31 36 30 36 30 39 58 42 49 4e 41 52 59 27 20160609XBINARY'
|
||||
| 4016: 02 05 00 43 0f 19 43 4f 4d 50 49 4c 45 52 3d 67 ...C..COMPILER=g
|
||||
| 4032: 63 63 2d 35 2e 34 2e 30 20 32 30 31 36 30 36 30 cc-5.4.0 2016060
|
||||
| 4048: 39 58 4e 4f 43 41 53 45 26 01 05 00 43 0f 17 43 9XNOCASE&...C..C
|
||||
| 4064: 4f 4d 50 49 4c 45 52 3d 67 63 63 2d 35 2e 34 2e OMPILER=gcc-5.4.
|
||||
| 4080: 30 20 32 30 31 36 30 36 30 39 58 52 54 52 49 4d 0 20160609XRTRIM
|
||||
| page 6 offset 20480
|
||||
| 0: 0d 00 00 00 24 0e e0 00 0f f8 0f f0 0f e8 0f e0 ....$...........
|
||||
| 16: 0f d8 0f d0 0f c8 0f c0 0f b8 0f b0 0f a8 0f a0 ................
|
||||
| 32: 1f 98 0f 90 0f 88 0f 80 0f 78 0f 70 0f 68 0f 60 .........x.p.h.`
|
||||
| 48: 0f 58 0f 50 0f 48 0f 40 0f 38 0f 30 0f 28 0f 20 .X.P.H.@.8.0.(.
|
||||
| 64: 0f 18 0f 10 0f 08 0f 00 0e f8 0e f0 0e e8 00 00 ................
|
||||
| 3808: 06 24 03 00 12 02 01 01 06 23 03 00 12 02 01 01 .$.......#......
|
||||
| 3824: 06 22 03 00 12 02 01 01 06 21 03 00 12 03 01 01 .........!......
|
||||
| 3840: 06 20 03 00 12 03 01 01 06 1f 03 00 12 03 01 01 . ..............
|
||||
| 3856: 06 1e 03 00 12 03 01 01 06 1d 03 00 12 03 01 01 ................
|
||||
| 3872: 06 1c 03 00 12 03 01 01 06 1b 03 00 12 02 01 01 ................
|
||||
| 3888: 06 1a 03 00 12 02 01 01 06 19 03 00 12 02 01 01 ................
|
||||
| 3904: 06 18 03 00 12 02 01 01 06 17 03 00 12 02 01 01 ................
|
||||
| 3920: 06 15 f3 00 12 02 01 01 06 15 03 00 12 02 01 01 ................
|
||||
| 3936: 06 14 03 00 12 02 01 01 06 13 03 00 12 02 01 01 ................
|
||||
| 3952: 06 12 03 00 12 02 01 01 06 11 03 00 12 02 01 01 ................
|
||||
| 3968: 06 10 03 00 12 02 01 01 06 0f 03 00 12 02 01 01 ................
|
||||
| 3984: 06 0e 03 00 12 02 01 01 06 0d 03 00 12 02 01 01 ................
|
||||
| 4000: 06 0c 03 00 12 02 01 01 06 0b 03 00 12 02 01 01 ................
|
||||
| 4016: 06 0a 03 00 12 02 01 01 06 09 03 00 12 03 01 01 ................
|
||||
| 4032: 06 08 03 00 12 03 01 01 06 07 03 00 12 03 01 01 ................
|
||||
| 4048: 06 06 03 00 12 01 01 01 06 05 03 00 12 01 01 01 ................
|
||||
| 4064: 06 04 03 00 12 01 01 01 06 03 03 00 12 06 01 01 ................
|
||||
| 4080: 06 02 03 00 12 06 01 01 06 01 03 00 12 06 01 01 ................
|
||||
| page 7 offset 24576
|
||||
| 0: 0a 00 00 00 01 0f f4 00 0f f4 00 00 00 00 00 00 ................
|
||||
| 4080: 00 00 00 00 0b 03 1b 01 76 65 72 73 69 6f 6e 04 ........version.
|
||||
| page 8 offset 28672
|
||||
| 0: 0d 00 00 00 03 0f d6 00 0f f4 0f 00 00 00 00 00 ................
|
||||
| 4048: 00 00 00 00 00 00 11 03 02 2b 69 6e 74 65 67 72 .........+integr
|
||||
| 4064: 69 74 79 2d 63 68 65 63 6b 09 02 02 1b 72 65 62 ity-check....reb
|
||||
| 4080: 75 69 6c 64 0a 01 02 1d 6f 70 74 69 00 00 00 00 uild....opti....
|
||||
| end crash-b06f016068bcea.db
|
||||
.testctrl prng_seed 1 db
|
||||
.testctrl internal_functions
|
||||
.testctrl json_selfcheck on
|
||||
}]} {}
|
||||
|
||||
do_execsql_test 10.1 {
|
||||
UPDATE t1 SET b=quote(zeroblob(current_date)) WHERE t1 MATCH 't*';
|
||||
}
|
||||
|
||||
do_catchsql_test 10.2 {
|
||||
BEGIN;
|
||||
INSERT INTO t1(t1,rank) VALUES('secure-delete',1);
|
||||
REPLACE INTO t1(b,a,rowid) VALUES(1,2,3);
|
||||
} {0 {}}
|
||||
|
||||
do_catchsql_test 10.3 {
|
||||
COMMIT
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
do_catchsql_test 10.4 {
|
||||
REPLACE INTO t1(b,a,rowid) VALUES(1,2,3);
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_test 11.0 {
|
||||
sqlite3 db {}
|
||||
db deserialize [decode_hexdb {
|
||||
.open --hexdb
|
||||
| size 32768 pagesize 4096 filename crash-3d05232c78871b.db
|
||||
| page 1 offset 0
|
||||
| 0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00 SQLite format 3.
|
||||
| 16: 10 00 01 01 00 40 20 20 00 00 00 00 00 00 00 08 .....@ ........
|
||||
| 32: 00 00 00 02 00 00 00 01 00 00 00 09 00 00 00 04 ................
|
||||
| 96: 00 00 00 00 0d 0f c7 00 07 0d 92 00 0f 8d 0f 36 ...............6
|
||||
| 112: 0e cb 0e 6b 0e 0e 0d b6 0d 92 0d 92 00 00 00 00 ...k............
|
||||
| 3472: 00 00 22 08 06 17 11 11 01 31 74 61 62 6c 65 74 .........1tablet
|
||||
| 3488: 32 74 32 08 43 52 45 41 54 45 20 54 41 42 4c 45 2t2.CREATE TABLE
|
||||
| 3504: 20 74 32 28 78 29 56 07 06 17 1f 1f 01 7d 74 61 t2(x)V.......ta
|
||||
| 3520: 62 6c 65 74 31 5f 63 6f 6e 66 69 67 74 31 5f 63 blet1_configt1_c
|
||||
| 3536: 6f 6e 66 69 67 07 43 52 45 41 54 45 20 54 41 42 onfig.CREATE TAB
|
||||
| 3552: 4c 45 20 27 74 31 5f 63 6f 6e 66 69 67 27 28 6b LE 't1_config'(k
|
||||
| 3568: 20 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 76 29 PRIMARY KEY, v)
|
||||
| 3584: 20 57 49 54 48 4f 55 54 20 52 4f 57 49 44 5b 06 WITHOUT ROWID[.
|
||||
| 3600: 07 17 21 21 01 81 01 74 61 62 6c 65 74 31 5f 64 ..!!...tablet1_d
|
||||
| 3616: 6f 63 73 69 7a 65 74 31 5f 64 6f 63 73 69 7a 65 ocsizet1_docsize
|
||||
| 3632: 06 43 52 45 41 54 45 20 54 41 42 4c 45 20 27 74 .CREATE TABLE 't
|
||||
| 3648: 31 5f 64 6f 63 73 69 7a 65 27 28 69 64 20 49 4e 1_docsize'(id IN
|
||||
| 3664: 54 45 47 45 52 20 50 52 49 4d 41 52 59 20 4b 45 TEGER PRIMARY KE
|
||||
| 3680: 59 2c 20 73 7a 20 42 4c 4f 42 29 5e 05 07 17 21 Y, sz BLOB)^...!
|
||||
| 3696: 21 01 81 07 74 61 62 6c 65 74 31 5f 63 6f 6e 74 !...tablet1_cont
|
||||
| 3712: 65 6e 74 74 31 5f 63 6f 6e 74 65 6e 74 05 43 52 entt1_content.CR
|
||||
| 3728: 45 41 54 45 20 54 41 42 4c 45 20 27 74 31 5f 63 EATE TABLE 't1_c
|
||||
| 3744: 6f 6e 74 65 6e 74 27 28 69 64 20 49 4e 54 45 47 ontent'(id INTEG
|
||||
| 3760: 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 ER PRIMARY KEY,
|
||||
| 3776: 63 30 2c 20 63 31 2c 20 63 32 29 69 04 07 17 19 c0, c1, c2)i....
|
||||
| 3792: 19 01 81 2d 74 61 62 6c 65 74 31 5f 69 64 78 74 ...-tablet1_idxt
|
||||
| 3808: 31 5f 69 64 78 04 43 52 45 41 54 45 20 54 41 42 1_idx.CREATE TAB
|
||||
| 3824: 4c 45 20 27 74 31 5f 69 64 78 27 28 73 65 67 69 LE 't1_idx'(segi
|
||||
| 3840: 64 2c 20 74 65 72 6d 2c 20 70 67 6e 6f 2c 20 50 d, term, pgno, P
|
||||
| 3856: 52 49 4d 41 52 59 20 4b 45 59 28 73 65 67 69 64 RIMARY KEY(segid
|
||||
| 3872: 2c 20 74 65 72 6d 29 29 20 57 49 54 48 4f 55 54 , term)) WITHOUT
|
||||
| 3888: 20 52 4f 57 49 44 55 03 07 17 1b 1b 01 81 01 74 ROWIDU........t
|
||||
| 3904: 61 62 6c 65 74 31 5f 64 61 74 61 74 31 5f 64 61 ablet1_datat1_da
|
||||
| 3920: 74 61 03 43 52 45 41 54 45 20 54 41 42 4c 45 20 ta.CREATE TABLE
|
||||
| 3936: 27 74 31 5f 64 61 74 61 27 28 69 64 20 49 4e 54 't1_data'(id INT
|
||||
| 3952: 45 47 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59 EGER PRIMARY KEY
|
||||
| 3968: 2c 20 62 6c 6f 63 6b 20 42 4c 4f 42 29 38 02 06 , block BLOB)8..
|
||||
| 3984: 17 11 11 08 5f 74 61 62 6c 65 74 31 74 31 43 52 ...._tablet1t1CR
|
||||
| 4000: 45 41 54 45 20 56 49 52 54 55 41 4c 20 54 41 42 EATE VIRTUAL TAB
|
||||
| 4016: 4c 45 20 74 31 20 55 53 49 4e 47 20 66 74 73 35 LE t1 USING fts5
|
||||
| 4032: 28 61 2c 62 2c 63 29 00 00 00 00 00 00 00 00 00 (a,b,c).........
|
||||
| page 3 offset 8192
|
||||
| 0: 0d 00 00 00 03 0c 94 00 0f e6 0f ef 0c 94 00 00 ................
|
||||
| 3216: 00 00 00 00 86 4a 84 80 80 80 80 01 04 00 8d 18 .....J..........
|
||||
| 3232: 00 00 03 2b 02 30 30 01 02 06 01 02 06 01 02 06 ...+.00.........
|
||||
| 3248: 1f 02 03 01 02 03 01 02 03 01 08 32 30 31 36 30 ...........20160
|
||||
| 3264: 36 30 39 01 02 07 01 02 07 01 02 07 01 01 34 01 609...........4.
|
||||
| 3280: 02 05 01 02 05 01 02 05 01 01 35 01 02 04 01 02 ..........5.....
|
||||
| 3296: 04 01 02 04 02 07 30 30 30 30 30 30 30 1c 02 04 ......0000000...
|
||||
| 3312: 01 02 04 01 02 04 01 06 62 69 6e 61 72 79 03 06 ........binary..
|
||||
| 3328: 01 02 02 03 06 01 02 02 03 06 01 02 02 03 06 01 ................
|
||||
| 3344: 02 02 03 06 01 02 02 03 06 01 02 02 03 06 01 02 ................
|
||||
| 3360: 02 03 06 01 02 02 03 06 01 02 02 03 06 01 02 02 ................
|
||||
| 3376: 03 06 01 02 02 03 06 01 02 02 01 08 63 6f 6d 70 ............comp
|
||||
| 3392: 69 6c 65 72 01 02 02 01 02 02 01 02 02 01 06 64 iler...........d
|
||||
| 3408: 62 73 74 61 74 07 02 03 01 02 03 01 02 03 02 04 bstat...........
|
||||
| 3424: 65 62 75 67 04 02 02 01 02 02 01 02 02 01 06 65 ebug...........e
|
||||
| 3440: 6e 61 62 6c 65 07 02 02 01 02 02 01 02 02 01 02 nable...........
|
||||
| 3456: 02 01 02 02 01 02 02 01 02 02 01 02 02 01 02 02 ................
|
||||
| 3472: 01 02 02 01 02 02 01 02 02 01 02 02 01 02 02 01 ................
|
||||
| 3488: 02 02 01 02 02 01 02 02 01 02 02 01 02 02 01 02 ................
|
||||
| 3504: 02 01 02 02 02 08 78 74 65 6e 73 69 6f 6e 1f 02 ......xtension..
|
||||
| 3520: 04 01 02 04 01 02 04 01 04 66 74 73 34 0a 02 03 .........fts4...
|
||||
| 3536: 01 02 03 01 02 03 04 01 35 0d 02 03 01 02 03 01 ........5.......
|
||||
| 3552: 02 03 01 03 67 63 63 01 02 03 01 02 03 01 02 03 ....gcc.........
|
||||
| 3568: 02 06 65 6f 70 6f 6c 79 10 02 03 01 02 03 01 02 ..eopoly........
|
||||
| 3584: 03 01 05 6a 73 6f 6e 31 13 02 03 01 02 03 01 02 ...json1........
|
||||
| 3600: 03 01 04 6c 6f 61 64 1f 02 03 01 02 03 01 02 03 ...load.........
|
||||
| 3616: 01 03 6d 61 78 1c 02 02 01 02 02 01 02 02 02 05 ..max...........
|
||||
| 3632: 65 6d 6f 72 79 1c 02 03 01 02 03 01 02 03 04 04 emory...........
|
||||
| 3648: 73 79 73 35 16 02 03 01 02 02 03 01 03 01 06 6e sys5...........n
|
||||
| 3664: 6f 63 61 73 65 02 06 01 02 02 03 06 01 02 02 03 ocase...........
|
||||
| 3680: 06 01 02 02 03 06 01 02 02 03 06 01 02 02 03 06 ................
|
||||
| 3696: 01 02 02 03 06 01 02 02 03 06 01 02 02 03 06 01 ................
|
||||
| 3712: 02 02 03 06 01 02 02 03 06 01 02 02 03 06 01 02 ................
|
||||
| 3728: 02 01 04 6f 6d 69 74 1f 02 02 01 02 02 01 02 02 ...omit.........
|
||||
| 3744: 01 05 72 74 72 65 65 19 02 03 01 02 03 01 02 03 ..rtree.........
|
||||
| 3760: 04 02 69 6d 01 06 01 02 02 03 06 01 02 02 03 06 ..im............
|
||||
| 3776: 01 02 02 03 06 01 02 02 03 06 01 02 02 03 06 01 ................
|
||||
| 3792: 02 02 03 06 01 02 02 03 06 01 02 02 03 06 01 02 ................
|
||||
| 3808: 02 03 06 01 02 02 03 06 01 02 02 03 06 01 02 02 ................
|
||||
| 3824: 01 0a 74 68 72 65 61 64 73 61 66 65 03 57 34 56 ..threadsafe.W4V
|
||||
| 3840: 94 64 91 46 85 84 04 76 74 61 62 07 02 04 01 02 .d.F...vtab.....
|
||||
| 3856: 04 01 02 04 01 01 78 01 06 01 01 02 01 06 01 01 ......x.........
|
||||
| 3872: 02 01 06 01 01 02 01 06 01 01 02 01 06 01 10 02 ................
|
||||
| 3888: 01 06 01 01 02 01 06 01 01 02 01 06 01 01 02 01 ................
|
||||
| 3904: 06 01 01 02 01 06 01 01 02 01 06 01 01 02 01 06 ................
|
||||
| 3920: 01 01 02 01 06 01 01 02 01 06 01 01 02 01 06 01 ................
|
||||
| 3936: 01 02 01 06 01 01 10 01 06 01 01 02 01 06 01 01 ................
|
||||
| 3952: 02 01 06 01 01 02 01 06 01 01 02 01 06 01 01 02 ................
|
||||
| 3968: 01 06 01 01 02 01 06 01 01 02 01 06 01 01 02 01 ................
|
||||
| 3984: 06 01 01 02 01 06 01 01 02 01 06 01 01 02 01 06 ................
|
||||
| 4000: 01 01 02 01 06 01 01 02 01 06 01 01 02 01 06 01 ................
|
||||
| 4016: 01 02 01 06 01 01 02 01 06 01 01 02 01 06 01 01 ................
|
||||
| 4032: 02 01 06 01 01 02 01 06 01 01 02 04 15 13 0c 0c ................
|
||||
| 4048: 12 44 13 11 0f 47 13 0f 0c 0e 11 10 0f 0e 10 0f .D...G..........
|
||||
| 4064: 44 0f 10 40 15 0f 07 01 03 00 14 24 5a 24 24 0f D..@.......$Z$$.
|
||||
| 4080: 0a 03 00 24 00 00 00 00 01 01 01 00 01 01 01 01 ...$............
|
||||
| page 4 offset 12288
|
||||
| 0: 0a 00 00 00 01 0f fa 00 00 00 00 00 00 00 00 00 ................
|
||||
| 4080: 00 00 00 00 00 00 00 00 00 00 05 04 09 0c 01 02 ................
|
||||
| page 5 offset 16384
|
||||
| 0: 0d 00 00 00 24 0c 0a 00 0f d8 0f af 0f 86 0f 74 ....$..........t
|
||||
| 16: 0f 61 0f 4e 0f 2f 0f 0f 0e ef 0e d7 0e be 0e a5 .a.N./..........
|
||||
| 32: 0e 8d 0e 74 0e 5b 0e 40 0e 24 0e 08 0d ef 0d d5 ...t.[.@.$......
|
||||
| 48: 0d bb 0d a0 0d 84 0d 68 0d 4f 0d 35 0d 1b 0c fb .......h.O.5....
|
||||
| 64: 0c da 0c b9 0c 99 0c 00 00 00 00 00 00 00 00 00 ................
|
||||
| 3072: 00 00 00 00 00 00 00 00 00 00 18 24 05 00 25 0f ...........$..%.
|
||||
| 3088: 19 54 48 52 45 41 44 53 41 46 45 3d 30 58 42 49 .THREADSAFE=0XBI
|
||||
| 3104: 4e 41 52 59 18 23 05 00 25 0f 19 54 48 52 45 41 NARY.#..%..THREA
|
||||
| 3120: 44 53 41 46 45 3d 30 58 4e 4f 43 41 53 45 17 22 DSAFE=0XNOCASE..
|
||||
| 3136: 05 00 25 0f 17 54 48 52 45 41 44 53 31 46 45 3d ..%..THREADS1FE=
|
||||
| 3152: 30 58 52 64 52 49 4d 1f 21 05 00 33 0f 19 4f 4d 0XRdRIM.!..3..OM
|
||||
| 3168: 49 54 20 4c 4f 41 44 20 45 58 54 45 4e 53 49 4f IT LOAD EXTENSIO
|
||||
| 3184: 4e 58 42 49 4e 41 52 59 1f 20 05 00 33 0f 19 4f NXBINARY. ..3..O
|
||||
| 3200: 4d 49 54 20 4c 4f 41 44 20 45 58 54 45 4e 53 49 MIT LOAD EXTENSI
|
||||
| 3216: 4f 4e 58 4e 4f 43 41 53 45 1e 1f 05 00 33 0f 17 ONXNOCASE....3..
|
||||
| 3232: 4f 4d 49 54 20 4c 4f 41 44 20 45 58 54 45 4e 53 OMIT LOAD EXTENS
|
||||
| 3248: 49 4f 4e 58 52 54 52 49 4d 1f 1e 05 00 33 0f 19 IONXRTRIM....3..
|
||||
| 3264: 4d 41 58 20 4d 45 4d 4f 52 59 3d 35 30 30 30 30 MAX MEMORY=50000
|
||||
| 3280: 30 30 30 58 42 49 4e 41 52 59 1f 1d 05 00 33 0f 000XBINARY....3.
|
||||
| 3296: 19 4d 41 58 20 4d 45 4d 4f 52 59 3d 35 30 30 30 .MAX MEMORY=5000
|
||||
| 3312: 30 30 30 30 58 4e 4f 43 41 53 45 1e 1c 05 00 33 0000XNOCASE....3
|
||||
| 3328: 0f 17 4d 41 58 20 4d 45 4d 4f 52 59 3d 35 30 30 ..MAX MEMORY=500
|
||||
| 3344: 30 30 30 30 30 58 52 54 52 49 4d 18 1b 05 00 25 00000XRTRIM....%
|
||||
| 3360: 0f 19 45 4e 41 42 4c 45 20 52 54 52 45 45 58 42 ..ENABLE RTREEXB
|
||||
| 3376: 49 4e 41 52 59 18 1a 05 00 25 0f 19 45 4e 41 42 INARY....%..ENAB
|
||||
| 3392: 4c 45 20 52 54 52 45 45 58 4e 4f 43 41 53 45 17 LE RTREEXNOCASE.
|
||||
| 3408: 19 05 00 25 0f 17 45 4e 41 42 4c 45 20 52 54 52 ...%..ENABLE RTR
|
||||
| 3424: 45 45 58 52 54 52 49 4d 1a 18 05 00 29 0f 19 45 EEXRTRIM....)..E
|
||||
| 3440: 4e 41 42 4b 45 20 4d 45 4d 53 59 53 35 58 42 49 NABKE MEMSYS5XBI
|
||||
| 3456: 4e 41 52 59 1a 17 05 00 29 0f 19 45 4e 41 42 4c NARY....)..ENABL
|
||||
| 3472: 42 60 2d 45 4d 53 59 53 35 58 4e 4f 43 41 53 45 B`-EMSYS5XNOCASE
|
||||
| 3488: 19 16 05 00 29 0f 17 45 4e 41 42 4c 45 20 4d 46 ....)..ENABLE MF
|
||||
| 3504: 4d 53 59 53 35 58 52 54 52 49 4d 18 15 05 00 25 MSYS5XRTRIM....%
|
||||
| 3520: 0f 19 45 4e 41 42 4c 45 20 4a 53 4f 4e 31 58 42 ..ENABLE JSON1XB
|
||||
| 3536: 49 4e 41 52 59 18 14 05 00 25 0f 19 45 4e 41 42 INARY....%..ENAB
|
||||
| 3552: 4c 45 20 4a 53 4f 4e 31 58 4e 4f 43 41 53 45 17 LE JSON1XNOCASE.
|
||||
| 3568: 13 05 00 25 0f 17 45 4e 41 42 4c 45 20 4a 53 4f ...%..ENABLE JSO
|
||||
| 3584: 4e 31 58 52 54 52 49 4d 1a 12 05 00 29 0f 19 45 N1XRTRIM....)..E
|
||||
| 3600: 42 4c 45 20 47 45 4f 50 4f 4c 59 58 42 49 4e 41 BLE GEOPOLYXBINA
|
||||
| 3616: 52 59 1a 11 05 00 39 0f 19 45 4e 41 42 4c 45 2e RY....9..ENABLE.
|
||||
| 3632: 41 40 47 45 4f 50 4f 4c 59 58 4e 4f 43 41 53 40 A@GEOPOLYXNOCAS@
|
||||
| 3648: 4f 4c 59 58 55 09 10 05 00 29 0f 17 45 4e 41 42 OLYXU....)..ENAB
|
||||
| 3664: 4c 45 20 47 45 4f 52 54 52 49 4d 17 0f 05 00 23 LE GEORTRIM....#
|
||||
| 3680: 0f 19 45 4e 41 42 4c 45 20 46 54 53 35 58 42 49 ..ENABLE FTS5XBI
|
||||
| 3696: 4e 41 52 59 17 0e 05 00 23 0f 19 45 4e 41 42 4c NARY....#..ENABL
|
||||
| 3712: 45 20 46 54 53 35 58 4e 4f 43 41 53 45 16 0d 05 E FTS5XNOCASE...
|
||||
| 3728: 00 23 0f 17 45 4e 41 42 4c 45 20 46 54 53 35 58 .#..ENABLE FTS5X
|
||||
| 3744: 52 54 52 49 4d 17 0c 05 00 23 0f 19 45 4e 41 42 RTRIM....#..ENAB
|
||||
| 3760: 4c 45 20 46 54 53 34 58 42 49 4e 41 52 59 17 0b LE FTS4XBINARY..
|
||||
| 3776: 05 00 23 0f 19 45 4e 41 42 4c 45 20 46 54 53 34 ..#..ENABLE FTS4
|
||||
| 3792: 58 4e 4f 43 41 53 45 16 0a 05 00 23 0f 17 45 4e XNOCASE....#..EN
|
||||
| 3808: 41 42 4c 45 20 46 54 53 34 58 52 54 52 49 4d 1e ABLE FTS4XRTRIM.
|
||||
| 3824: 09 05 00 31 0f 19 45 4e 41 42 4c 45 20 44 42 53 ...1..ENABLE DBS
|
||||
| 3840: 54 41 54 20 56 54 41 42 58 42 49 4e 41 52 59 1e TAT VTABXBINARY.
|
||||
| 3856: 08 05 00 31 0f 19 45 4e 41 42 4c 45 20 44 42 53 ...1..ENABLE DBS
|
||||
| 3872: 54 41 54 20 56 54 24 15 48 4e 4f 43 41 53 45 1d TAT VT$.HNOCASE.
|
||||
| 3888: 07 05 00 31 0f 17 45 4e 41 42 4c 45 20 44 42 53 ...1..ENABLE DBS
|
||||
| 3904: 54 41 54 20 56 54 41 42 58 52 54 52 49 4d 11 06 TAT VTABXRTRIM..
|
||||
| 3920: 05 00 17 0f 19 44 45 42 55 47 58 42 49 4e 41 52 .....DEBUGXBINAR
|
||||
| 3936: 59 11 05 05 00 17 0f 19 44 45 42 55 47 58 4e 4f Y.......DEBUGXNO
|
||||
| 3952: 43 41 53 45 10 04 05 00 17 0f 17 44 45 42 55 47 CASE.......DEBUG
|
||||
| 3968: 58 52 54 52 49 4d 27 03 05 00 43 0f 19 43 4f 4d XRTRIM'...C..COM
|
||||
| 3984: 50 49 4c 45 52 3d 67 63 63 2d 35 2e 34 2e 30 20 PILER=gcc-5.4.0
|
||||
| 4000: 32 30 31 36 30 36 30 39 58 42 49 4e 41 52 59 27 20160609XBINARY'
|
||||
| 4016: 02 05 00 43 0f 19 43 4f 4d 50 49 4c 45 52 3d 67 ...C..COMPILER=g
|
||||
| 4032: 63 63 2d 35 2e 34 2e 30 20 32 30 31 36 30 36 30 cc-5.4.0 2016060
|
||||
| 4048: 39 58 4e 4f 43 41 53 45 26 01 05 00 43 0f 17 43 9XNOCASE&...C..C
|
||||
| 4064: 4f 4d 50 49 4c 45 52 3d 67 63 63 2d 35 2e 34 2e OMPILER=gcc-5.4.
|
||||
| 4080: 30 20 32 30 31 36 30 36 30 39 58 52 54 52 49 4d 0 20160609XRTRIM
|
||||
| page 6 offset 20480
|
||||
| 0: 0d 00 00 00 24 0e e0 00 0f f8 0f f0 0f e8 0f e0 ....$...........
|
||||
| 16: 0f d8 0f d0 0f c8 0f c0 0f b8 0f b0 0f a8 0f a0 ................
|
||||
| 32: 1f 98 0f 90 0f 88 0f 80 0f 78 0f 70 0f 68 0f 60 .........x.p.h.`
|
||||
| 48: 0f 58 0f 50 0f 48 0f 40 0f 38 0f 30 0f 28 0f 20 .X.P.H.@.8.0.(.
|
||||
| 64: 0f 18 0f 10 0f 08 0f 00 0e f8 0e f0 0e e8 00 00 ................
|
||||
| 3808: 06 24 03 00 12 02 01 01 06 23 03 00 12 02 01 01 .$.......#......
|
||||
| 3824: 06 22 03 00 12 02 01 01 06 21 03 00 12 03 01 01 .........!......
|
||||
| 3840: 06 20 03 00 12 03 01 01 06 1f 03 00 12 03 01 01 . ..............
|
||||
| 3856: 06 1e 03 00 12 03 01 01 06 1d 03 00 12 03 01 01 ................
|
||||
| 3872: 06 1c 03 00 12 03 01 01 06 1b 03 00 12 02 01 01 ................
|
||||
| 3888: 06 1a 03 00 12 02 01 01 06 19 03 00 12 02 01 01 ................
|
||||
| 3904: 06 18 03 00 12 02 01 01 06 17 03 00 12 02 01 01 ................
|
||||
| 3920: 06 15 f3 00 12 02 01 01 06 15 03 00 12 02 01 01 ................
|
||||
| 3936: 06 14 03 00 12 02 01 01 06 13 03 00 12 02 01 01 ................
|
||||
| 3952: 06 12 03 00 12 02 01 01 06 11 03 00 12 02 01 01 ................
|
||||
| 3968: 06 10 03 00 12 02 01 01 06 0f 03 00 12 02 01 01 ................
|
||||
| 3984: 06 0e 03 00 12 02 01 01 06 0d 03 00 12 02 01 01 ................
|
||||
| 4000: 06 0c 03 00 12 02 01 01 06 0b 03 00 12 02 01 01 ................
|
||||
| 4016: 06 0a 03 00 12 02 01 01 06 09 03 00 12 03 01 01 ................
|
||||
| 4032: 06 08 03 00 12 03 01 01 06 07 03 00 12 03 01 01 ................
|
||||
| 4048: 06 06 03 00 12 01 01 01 06 05 03 00 12 01 01 01 ................
|
||||
| 4064: 06 04 03 00 12 01 01 01 06 03 03 00 12 06 01 01 ................
|
||||
| 4080: 06 02 03 00 12 06 01 01 06 01 03 00 12 06 01 01 ................
|
||||
| page 7 offset 24576
|
||||
| 0: 0a 00 00 00 01 0f f4 00 0f f4 00 00 00 00 00 00 ................
|
||||
| 4080: 00 00 00 00 0b 03 1b 01 76 65 72 73 69 6f 6e 04 ........version.
|
||||
| page 8 offset 28672
|
||||
| 0: 0d 00 00 00 03 0f d6 00 0f f4 0f 00 00 00 00 00 ................
|
||||
| 4048: 00 00 00 00 00 00 11 03 02 2b 69 6e 74 65 67 72 .........+integr
|
||||
| 4064: 69 74 79 2d 63 68 65 63 6b 09 02 02 1b 72 65 62 ity-check....reb
|
||||
| 4080: 75 69 6c 64 0a 01 02 1d 6f 00 00 00 00 00 00 00 uild....o.......
|
||||
| end crash-3d05232c78871b.db
|
||||
}]} {}
|
||||
|
||||
do_execsql_test 11.1 {
|
||||
UPDATE t1 SET b=quote(zeroblob('2025-01-09')) WHERE t1 MATCH 't*';
|
||||
INSERT INTO t1(t1,rank) VALUES('secure-delete',1);
|
||||
}
|
||||
|
||||
do_catchsql_test 11.2 {
|
||||
BEGIN;
|
||||
REPLACE INTO t1(rowid,b,a,rowid) VALUES(x'44023b9eb002d28b0ee90c',1,2,3);
|
||||
PRAGMA writable_schema=RESET;
|
||||
INSERT INTO t1(t1) SELECT x FROM t2;
|
||||
ROLLBACK;
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
do_catchsql_test 11.3 {
|
||||
REPLACE INTO t1(rowid,b,a,rowid) VALUES(x'44023b9eb002d28b0ee90c',1,2,3);
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
|
||||
sqlite3_fts5_may_be_corrupt 0
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -290,5 +290,40 @@ do_faultsim_test 11 -faults oom* -prep {
|
||||
faultsim_test_result {0 {}}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
|
||||
ifcapable foreignkey {
|
||||
do_execsql_test 12.0 {
|
||||
CREATE VIRTUAL TABLE f1 USING fts5(content);
|
||||
CREATE TABLE p1(a INTEGER PRIMARY KEY);
|
||||
CREATE TABLE c1(b REFERENCES p1 DEFERRABLE INITIALLY DEFERRED);
|
||||
}
|
||||
|
||||
faultsim_save_and_close
|
||||
|
||||
do_faultsim_test 11 -faults oom* -prep {
|
||||
faultsim_restore_and_reopen
|
||||
execsql {
|
||||
PRAGMA foreign_keys = 1;
|
||||
BEGIN;
|
||||
INSERT INTO c1 VALUES(123);
|
||||
SAVEPOINT xyz;
|
||||
}
|
||||
} -body {
|
||||
execsql {
|
||||
INSERT INTO f1 VALUES('a b c');
|
||||
ROLLBACK TO xyz;
|
||||
COMMIT;
|
||||
}
|
||||
} -test {
|
||||
execsql { SELECT 123 }
|
||||
faultsim_test_result \
|
||||
{1 {FOREIGN KEY constraint failed}} \
|
||||
{1 {out of memory}} \
|
||||
{1 {constraint failed}}
|
||||
}
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -591,7 +591,6 @@ do_execsql_test 21.2 {
|
||||
PRAGMA integrity_check
|
||||
} {ok}
|
||||
|
||||
breakpoint
|
||||
sqlite3_db_config db DEFENSIVE 1
|
||||
do_execsql_test 21.3 {
|
||||
CREATE TABLE xyz_notashadow(x, y);
|
||||
@@ -665,5 +664,26 @@ do_execsql_test 25.0 {
|
||||
SELECT fts5_test_poslist(t1) FROM t1('b') ORDER BY rank;
|
||||
} {{}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
|
||||
do_execsql_test 26.0 {
|
||||
PRAGMA foreign_keys = ON;
|
||||
CREATE TABLE t1(x INTEGER PRIMARY KEY);
|
||||
CREATE TABLE t2(y INTEGER PRIMARY KEY,
|
||||
z INTEGER REFERENCES t1(x) DEFERRABLE INITIALLY DEFERRED
|
||||
);
|
||||
CREATE VIRTUAL TABLE t3 USING fts5(a, b, content='', tokendata=1);
|
||||
}
|
||||
|
||||
do_execsql_test 26.1 {
|
||||
BEGIN;
|
||||
INSERT INTO t2 VALUES(1,111);
|
||||
INSERT INTO t3 VALUES(3,3);
|
||||
PRAGMA defer_foreign_keys=ON;
|
||||
DELETE FROM t2 WHERE y+1;
|
||||
COMMIT;
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -22,34 +22,40 @@ ifcapable !fts5 {
|
||||
}
|
||||
|
||||
foreach_detail_mode $testprefix {
|
||||
foreach {tn insttoken} {
|
||||
1 0
|
||||
2 1
|
||||
} {
|
||||
reset_db
|
||||
|
||||
sqlite3_fts5_register_origintext db
|
||||
do_execsql_test 1.0 {
|
||||
do_execsql_test $tn.1.0 {
|
||||
CREATE VIRTUAL TABLE ft USING fts5(
|
||||
x, tokenize="origintext unicode61", detail=%DETAIL%
|
||||
);
|
||||
INSERT INTO ft(ft, rank) VALUES('insttoken', $insttoken);
|
||||
CREATE VIRTUAL TABLE vocab USING fts5vocab(ft, instance);
|
||||
}
|
||||
|
||||
do_execsql_test 1.1 {
|
||||
do_execsql_test $tn.1.1 {
|
||||
INSERT INTO ft VALUES('Hello world');
|
||||
}
|
||||
|
||||
do_execsql_test 1.2 {
|
||||
do_execsql_test $tn.1.2 {
|
||||
INSERT INTO ft(ft) VALUES('integrity-check');
|
||||
}
|
||||
|
||||
proc b {x} { string map [list "\0" "."] $x }
|
||||
db func b b
|
||||
|
||||
do_execsql_test 1.3 {
|
||||
do_execsql_test $tn.1.3 {
|
||||
select b(term) from vocab;
|
||||
} {
|
||||
hello.Hello
|
||||
world
|
||||
}
|
||||
|
||||
do_execsql_test 1.4 {
|
||||
do_execsql_test $tn.1.4 {
|
||||
SELECT rowid FROM ft('Hello');
|
||||
} {1}
|
||||
|
||||
@@ -88,33 +94,34 @@ proc document {} {
|
||||
db func document document
|
||||
|
||||
sqlite3_fts5_register_origintext db
|
||||
do_execsql_test 2.0 {
|
||||
do_execsql_test $tn.2.0 {
|
||||
CREATE VIRTUAL TABLE ft USING fts5(
|
||||
x, tokenize="origintext unicode61", detail=%DETAIL%
|
||||
);
|
||||
INSERT INTO ft(ft, rank) VALUES('insttoken', $insttoken);
|
||||
INSERT INTO ft(ft, rank) VALUES('pgsz', 128);
|
||||
CREATE VIRTUAL TABLE vocab USING fts5vocab(ft, instance);
|
||||
}
|
||||
|
||||
do_test 2.1 {
|
||||
do_test $tn.2.1 {
|
||||
for {set ii 0} {$ii < 500} {incr ii} {
|
||||
execsql { INSERT INTO ft VALUES( document() ) }
|
||||
}
|
||||
} {}
|
||||
|
||||
do_execsql_test 2.2 {
|
||||
do_execsql_test $tn.2.2 {
|
||||
INSERT INTO ft(ft) VALUES('integrity-check');
|
||||
}
|
||||
|
||||
do_execsql_test 2.3 {
|
||||
do_execsql_test $tn.2.3 {
|
||||
INSERT INTO ft(ft, rank) VALUES('merge', 16);
|
||||
}
|
||||
|
||||
do_execsql_test 2.4 {
|
||||
do_execsql_test $tn.2.4 {
|
||||
INSERT INTO ft(ft) VALUES('integrity-check');
|
||||
}
|
||||
|
||||
do_execsql_test 2.5 {
|
||||
do_execsql_test $tn.2.5 {
|
||||
INSERT INTO ft(ft) VALUES('optimize');
|
||||
}
|
||||
|
||||
@@ -122,10 +129,11 @@ do_execsql_test 2.5 {
|
||||
reset_db
|
||||
|
||||
sqlite3_fts5_register_origintext db
|
||||
do_execsql_test 3.0 {
|
||||
do_execsql_test $tn.3.0 {
|
||||
CREATE VIRTUAL TABLE ft USING fts5(
|
||||
x, tokenize="origintext unicode61", detail=%DETAIL%
|
||||
);
|
||||
INSERT INTO ft(ft, rank) VALUES('insttoken', $insttoken);
|
||||
CREATE VIRTUAL TABLE vocab USING fts5vocab(ft, instance);
|
||||
|
||||
INSERT INTO ft(rowid, x) VALUES(1, 'hello');
|
||||
@@ -137,16 +145,17 @@ do_execsql_test 3.0 {
|
||||
#db func b b
|
||||
#execsql_pp { SELECT b(term) FROM vocab }
|
||||
|
||||
do_execsql_test 3.1.1 { SELECT rowid FROM ft('hello') } 1
|
||||
do_execsql_test 3.1.2 { SELECT rowid FROM ft('Hello') } 2
|
||||
do_execsql_test 3.1.3 { SELECT rowid FROM ft('HELLO') } 3
|
||||
do_execsql_test $tn.3.1.1 { SELECT rowid FROM ft('hello') } 1
|
||||
do_execsql_test $tn.3.1.2 { SELECT rowid FROM ft('Hello') } 2
|
||||
do_execsql_test $tn.3.1.3 { SELECT rowid FROM ft('HELLO') } 3
|
||||
|
||||
do_execsql_test 3.2 {
|
||||
do_execsql_test $tn.3.2 {
|
||||
CREATE VIRTUAL TABLE ft2 USING fts5(x,
|
||||
tokenize="origintext unicode61",
|
||||
tokendata=1,
|
||||
detail=%DETAIL%
|
||||
);
|
||||
INSERT INTO ft2(ft2, rank) VALUES('insttoken', $insttoken);
|
||||
CREATE VIRTUAL TABLE vocab2 USING fts5vocab(ft2, instance);
|
||||
|
||||
INSERT INTO ft2(rowid, x) VALUES(1, 'hello');
|
||||
@@ -160,11 +169,18 @@ do_execsql_test 3.2 {
|
||||
#db func b b
|
||||
#execsql_pp { SELECT b(term) FROM vocab }
|
||||
|
||||
do_execsql_test 3.3.1 { SELECT rowid FROM ft2('hello') } {1 2 3}
|
||||
do_execsql_test 3.3.2 { SELECT rowid FROM ft2('Hello') } {1 2 3}
|
||||
do_execsql_test 3.3.3 { SELECT rowid FROM ft2('HELLO') } {1 2 3}
|
||||
do_execsql_test $tn.3.3.1 { SELECT rowid FROM ft2('hello') } {1 2 3}
|
||||
do_execsql_test $tn.3.3.2 { SELECT rowid FROM ft2('Hello') } {1 2 3}
|
||||
do_execsql_test $tn.3.3.3 { SELECT rowid FROM ft2('HELLO') } {1 2 3}
|
||||
|
||||
do_execsql_test 3.3.4 { SELECT rowid FROM ft2('hello*') } {1 2 3 10}
|
||||
do_execsql_test $tn.3.3.4 { SELECT rowid FROM ft2('hello*') } {1 2 3 10}
|
||||
|
||||
do_execsql_test $tn.3.3.5.1 { SELECT rowid FROM ft2('HELLO') ORDER BY rowid DESC} {
|
||||
3 2 1
|
||||
}
|
||||
do_execsql_test $tn.3.3.5.2 { SELECT rowid FROM ft2('HELLO') ORDER BY +rowid DESC} {
|
||||
3 2 1
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
@@ -176,36 +192,37 @@ proc querytoken {cmd iPhrase iToken} {
|
||||
}
|
||||
sqlite3_fts5_create_function db querytoken querytoken
|
||||
|
||||
do_execsql_test 4.0 {
|
||||
do_execsql_test $tn.4.0 {
|
||||
CREATE VIRTUAL TABLE ft USING fts5(
|
||||
x, tokenize='origintext unicode61', tokendata=1, detail=%DETAIL%
|
||||
);
|
||||
INSERT INTO ft(ft, rank) VALUES('insttoken', $insttoken);
|
||||
INSERT INTO ft VALUES('one two three four');
|
||||
}
|
||||
|
||||
do_execsql_test 4.1 {
|
||||
do_execsql_test $tn.4.1 {
|
||||
SELECT rowid, querytoken(ft, 0, 0) FROM ft('TwO')
|
||||
} {1 two.TwO}
|
||||
do_execsql_test 4.2 {
|
||||
do_execsql_test $tn.4.2 {
|
||||
SELECT rowid, querytoken(ft, 0, 0) FROM ft('one TWO ThreE')
|
||||
} {1 one}
|
||||
do_execsql_test 4.3 {
|
||||
do_execsql_test $tn.4.3 {
|
||||
SELECT rowid, querytoken(ft, 1, 0) FROM ft('one TWO ThreE')
|
||||
} {1 two.TWO}
|
||||
|
||||
if {"%DETAIL%"=="full"} {
|
||||
# Phrase queries are only supported for detail=full.
|
||||
#
|
||||
do_execsql_test 4.4 {
|
||||
do_execsql_test $tn.4.4 {
|
||||
SELECT rowid, querytoken(ft, 0, 2) FROM ft('"one TWO ThreE"')
|
||||
} {1 three.ThreE}
|
||||
do_catchsql_test 4.5 {
|
||||
do_catchsql_test $tn.4.5 {
|
||||
SELECT rowid, querytoken(ft, 0, 3) FROM ft('"one TWO ThreE"')
|
||||
} {1 SQLITE_RANGE}
|
||||
do_catchsql_test 4.6 {
|
||||
do_catchsql_test $tn.4.6 {
|
||||
SELECT rowid, querytoken(ft, 1, 0) FROM ft('"one TWO ThreE"')
|
||||
} {1 SQLITE_RANGE}
|
||||
do_catchsql_test 4.7 {
|
||||
do_catchsql_test $tn.4.7 {
|
||||
SELECT rowid, querytoken(ft, -1, 0) FROM ft('"one TWO ThreE"')
|
||||
} {1 SQLITE_RANGE}
|
||||
}
|
||||
@@ -221,14 +238,15 @@ proc insttoken {cmd iIdx iToken} {
|
||||
sqlite3_fts5_create_function db insttoken insttoken
|
||||
fts5_aux_test_functions db
|
||||
|
||||
do_execsql_test 5.0 {
|
||||
do_execsql_test $tn.5.0 {
|
||||
CREATE VIRTUAL TABLE ft USING fts5(
|
||||
x, tokenize='origintext unicode61', tokendata=1, detail=%DETAIL%
|
||||
);
|
||||
INSERT INTO ft(ft, rank) VALUES('insttoken', $insttoken);
|
||||
INSERT INTO ft VALUES('one ONE One oNe oNE one');
|
||||
}
|
||||
|
||||
do_execsql_test 5.1 {
|
||||
do_execsql_test $tn.5.1 {
|
||||
SELECT insttoken(ft, 0, 0),
|
||||
insttoken(ft, 1, 0),
|
||||
insttoken(ft, 2, 0),
|
||||
@@ -240,13 +258,37 @@ do_execsql_test 5.1 {
|
||||
one one.ONE one.One one.oNe one.oNE one
|
||||
}
|
||||
|
||||
do_execsql_test 5.2 {
|
||||
do_execsql_test $tn.5.2 {
|
||||
SELECT insttoken(ft, 0, 0),
|
||||
insttoken(ft, 1, 0),
|
||||
insttoken(ft, 2, 0),
|
||||
insttoken(ft, 3, 0),
|
||||
insttoken(ft, 4, 0),
|
||||
insttoken(ft, 5, 0)
|
||||
FROM ft('on*');
|
||||
} {
|
||||
one one.ONE one.One one.oNe one.oNE one
|
||||
}
|
||||
|
||||
do_execsql_test $tn.5.3 {
|
||||
SELECT insttoken(ft, 0, 0),
|
||||
insttoken(ft, 1, 0),
|
||||
insttoken(ft, 2, 0),
|
||||
insttoken(ft, 3, 0),
|
||||
insttoken(ft, 4, 0),
|
||||
insttoken(ft, 5, 0)
|
||||
FROM ft(fts5_insttoken('on*'));
|
||||
} {
|
||||
one one.ONE one.One one.oNe one.oNE one
|
||||
}
|
||||
|
||||
do_execsql_test $tn.5.4 {
|
||||
SELECT insttoken(ft, 1, 0) FROM ft('one');
|
||||
} {
|
||||
one.ONE
|
||||
}
|
||||
|
||||
do_execsql_test 5.3 {
|
||||
do_execsql_test $tn.5.5 {
|
||||
SELECT fts5_test_poslist(ft) FROM ft('one');
|
||||
} {
|
||||
{0.0.0 0.0.1 0.0.2 0.0.3 0.0.4 0.0.5}
|
||||
@@ -260,10 +302,11 @@ do_execsql_test 5.3 {
|
||||
#
|
||||
reset_db
|
||||
sqlite3_fts5_register_origintext db
|
||||
do_execsql_test 6.0 {
|
||||
do_execsql_test $tn.6.0 {
|
||||
CREATE VIRTUAL TABLE ft USING fts5(
|
||||
x, y, tokenize='origintext unicode61', detail=%DETAIL%, tokendata=0
|
||||
);
|
||||
INSERT INTO ft(ft, rank) VALUES('insttoken', $insttoken);
|
||||
|
||||
INSERT INTO ft VALUES('One Two', 'Three two');
|
||||
INSERT INTO ft VALUES('three Three', 'one One');
|
||||
@@ -279,34 +322,35 @@ proc tokens {cmd} {
|
||||
}
|
||||
sqlite3_fts5_create_function db tokens tokens
|
||||
|
||||
do_execsql_test 6.1 {
|
||||
do_execsql_test $tn.6.1 {
|
||||
SELECT rowid, tokens(ft) FROM ft('One');
|
||||
} {1 one.One 2 one.One}
|
||||
|
||||
do_execsql_test 6.2 {
|
||||
do_execsql_test $tn.6.2 {
|
||||
SELECT rowid, tokens(ft) FROM ft('on*');
|
||||
} {1 {{}} 2 {{} {}}}
|
||||
} {1 one.One 2 {one one.One}}
|
||||
|
||||
do_execsql_test 6.3 {
|
||||
do_execsql_test $tn.6.3 {
|
||||
SELECT rowid, tokens(ft) FROM ft('Three*');
|
||||
} {1 {{}} 2 {{}}}
|
||||
} {1 three.Three 2 three.Three}
|
||||
|
||||
fts5_aux_test_functions db
|
||||
do_catchsql_test 6.4 {
|
||||
do_catchsql_test $tn.6.4 {
|
||||
SELECT fts5_test_insttoken(ft, -1, 0) FROM ft('one');
|
||||
} {1 SQLITE_RANGE}
|
||||
|
||||
do_catchsql_test 6.5 {
|
||||
do_catchsql_test $tn.6.5 {
|
||||
SELECT fts5_test_insttoken(ft, 1, 0) FROM ft('one');
|
||||
} {1 SQLITE_RANGE}
|
||||
|
||||
do_catchsql_test 6.6 {
|
||||
do_catchsql_test $tn.6.6 {
|
||||
CREATE VIRTUAL TABLE ft2 USING fts5(x, tokendata=2);
|
||||
} {1 {malformed tokendata=... directive}}
|
||||
do_catchsql_test 6.7 {
|
||||
do_catchsql_test $tn.6.7 {
|
||||
CREATE VIRTUAL TABLE ft2 USING fts5(x, content='', tokendata=11);
|
||||
} {1 {malformed tokendata=... directive}}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -22,6 +22,11 @@ ifcapable !fts5 {
|
||||
}
|
||||
|
||||
foreach_detail_mode $testprefix {
|
||||
foreach {tn insttoken} {
|
||||
1 0
|
||||
2 1
|
||||
} {
|
||||
|
||||
reset_db
|
||||
|
||||
sqlite3_fts5_register_origintext db
|
||||
@@ -32,21 +37,25 @@ foreach_detail_mode $testprefix {
|
||||
}
|
||||
sqlite3_fts5_create_function db insttoken insttoken
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
do_execsql_test $tn.1.0 {
|
||||
CREATE VIRTUAL TABLE ft USING fts5(
|
||||
x, tokenize="origintext unicode61", tokendata=1, detail=%DETAIL%
|
||||
);
|
||||
}
|
||||
|
||||
do_execsql_test $tn.1.0.1 {
|
||||
INSERT INTO ft(ft, rank) VALUES('insttoken', 1);
|
||||
}
|
||||
|
||||
do_execsql_test 1.1 {
|
||||
do_execsql_test $tn.1.1 {
|
||||
INSERT INTO ft VALUES('Hello world HELLO WORLD hello');
|
||||
}
|
||||
|
||||
do_execsql_test 1.2 {
|
||||
do_execsql_test $tn.1.2 {
|
||||
SELECT fts5_test_poslist(ft) FROM ft('hello');
|
||||
} {{0.0.0 0.0.2 0.0.4}}
|
||||
|
||||
do_execsql_test 1.3 {
|
||||
do_execsql_test $tn.1.3 {
|
||||
SELECT
|
||||
insttoken(ft, 0, 0),
|
||||
insttoken(ft, 1, 0),
|
||||
@@ -54,7 +63,15 @@ foreach_detail_mode $testprefix {
|
||||
FROM ft('hello');
|
||||
} {hello.Hello hello.HELLO hello}
|
||||
|
||||
do_execsql_test 1.4 {
|
||||
do_execsql_test $tn.1.3.1 {
|
||||
SELECT
|
||||
insttoken(ft, 0, 0),
|
||||
insttoken(ft, 1, 0),
|
||||
insttoken(ft, 2, 0)
|
||||
FROM ft('hel*');
|
||||
} {hello.Hello hello.HELLO hello}
|
||||
|
||||
do_execsql_test $tn.1.4 {
|
||||
SELECT
|
||||
insttoken(ft, 0, 0),
|
||||
insttoken(ft, 1, 0),
|
||||
@@ -62,7 +79,7 @@ foreach_detail_mode $testprefix {
|
||||
FROM ft('hello') ORDER BY rank;
|
||||
} {hello.Hello hello.HELLO hello}
|
||||
|
||||
do_execsql_test 1.5 {
|
||||
do_execsql_test $tn.1.5 {
|
||||
CREATE VIRTUAL TABLE ft2 USING fts5(
|
||||
x, tokenize="origintext unicode61", tokendata=1, detail=%DETAIL%
|
||||
);
|
||||
@@ -71,11 +88,11 @@ foreach_detail_mode $testprefix {
|
||||
INSERT INTO ft2(rowid, x) VALUES(3, 'THREE one two three THREE');
|
||||
}
|
||||
|
||||
do_execsql_test 1.6 {
|
||||
do_execsql_test $tn.1.6 {
|
||||
SELECT insttoken(ft2, 0, 0), rowid FROM ft2('three') ORDER BY rank;
|
||||
} {three.THREE 3 three 1 three 2}
|
||||
|
||||
do_execsql_test 1.7 {
|
||||
do_execsql_test $tn.1.7 {
|
||||
INSERT INTO ft2(rowid, x) VALUES(10, 'aaa bbb BBB');
|
||||
INSERT INTO ft2(rowid, x) VALUES(12, 'bbb bbb bbb');
|
||||
INSERT INTO ft2(rowid, x) VALUES(13, 'bbb bbb bbb');
|
||||
@@ -92,9 +109,32 @@ foreach_detail_mode $testprefix {
|
||||
INSERT INTO ft2(rowid, x) VALUES(24, 'aaa bbb BBB');
|
||||
}
|
||||
|
||||
do_execsql_test 1.8 { SELECT rowid FROM ft2('aaa AND bbb'); } {10 24}
|
||||
do_execsql_test 1.9 { SELECT rowid FROM ft2('bbb AND aaa'); } {10 24}
|
||||
do_execsql_test $tn.1.8 { SELECT rowid FROM ft2('aaa AND bbb'); } {10 24}
|
||||
do_execsql_test $tn.1.9 { SELECT rowid FROM ft2('bbb AND aaa'); } {10 24}
|
||||
|
||||
do_execsql_test $tn.2.0 {
|
||||
CREATE VIRTUAL TABLE ft3 USING fts5(
|
||||
x, tokenize="origintext unicode61", tokendata=1, detail=%DETAIL%,
|
||||
prefix=2
|
||||
);
|
||||
}
|
||||
do_execsql_test $tn.2.1 {
|
||||
INSERT INTO ft3(rowid, x) VALUES(1, 'one');
|
||||
INSERT INTO ft3(rowid, x) VALUES(2, 'ONE');
|
||||
INSERT INTO ft3(rowid, x) VALUES(3, 'ONT');
|
||||
INSERT INTO ft3(rowid, x) VALUES(4, 'on');
|
||||
INSERT INTO ft3(rowid, x) VALUES(5, 'On');
|
||||
}
|
||||
|
||||
do_execsql_test $tn.2.2 {
|
||||
SELECT rowid FROM ft3('on*');
|
||||
} {1 2 3 4 5}
|
||||
|
||||
do_execsql_test $tn.2.3 {
|
||||
SELECT rowid, insttoken(ft3, 0, 0) FROM ft3('on*');
|
||||
} {1 one 2 one.ONE 3 ont.ONT 4 on 5 on.On}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -0,0 +1,209 @@
|
||||
# 2014 Jan 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 focused on phrase queries.
|
||||
#
|
||||
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5origintext6
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
proc insert_data {tbl} {
|
||||
db eval "
|
||||
INSERT INTO $tbl (rowid, x, y) VALUES
|
||||
(1, 'ChH BDd HhG efc BjJ BGi GBG FdD','ciJ AFf ADf fBJ fhC GFI JEH fcA'),
|
||||
(2, 'deg AIG Fie jII cCd Hbf igF fEE','GeA Ija gJg EDc HFi DDI dCf aDd'),
|
||||
(3, 'IJC hga deC Jfa Aeg hfh CcH dfb','ajD hgC Jaf IfH CHe jIG AjD adF'),
|
||||
(4, 'FiH GJH IDA AiG bBc CGG Eih bIH','hHg JaH aii IHE Ggd gcH gji CGc'),
|
||||
(5, 'ceg CAd jFI GAB BGg EeC IdH acG','bBC eIG ifH eDE Adj bjb GCj ebA'),
|
||||
(6, 'Eac Fbh aFF Eea jeG EIj HCc JJH','hbd giE Gfe eiI dEF abE cJf cAb'),
|
||||
(7, 'dic hAc jEC AiG FEF jHc HiD HBI','aEd ebE Gfi AJG EBA faj GiG jjE'),
|
||||
(8, 'Fca iEe EgE jjJ gce ijf EGc EBi','gaI dhH bFg CFc HeC CjI Jfg ccH'),
|
||||
(9, 'cfd iaa HCf iHJ HjG ffh ABb ibi','CfG bia Dai eii Ejg Jeg fCg hDb'),
|
||||
(10, 'Jjf hJC IID HJj bGB EbJ cgg eBj','jci jhi JAF jIg Bei Bcd cAC AJd'),
|
||||
(11, 'egG Cdi bFf fEB hfH jDH jia Efd','FAd eCg fAi aiC baC eJG acF iGE'),
|
||||
(12, 'Ada Gde CJI ADG gJA Cbb ccF iAB','eAE ajC FBB ccd Jgh fJg ieg hGE'),
|
||||
(13, 'gBb fDG Jdd HdD fiJ Bed Cig iGg','heC FeI iaj gdg ebB giC HaD FIe'),
|
||||
(14, 'FiI iDd Ffe igI bgB EJf FHG hDF','cjC AeI abf Fah cbJ ffH jEb aib'),
|
||||
(15, 'jaF hBI jIH Gdh FEc Fij hgj jFh','dGA ADH feh AAI AfJ DbC gBi hGH'),
|
||||
(16, 'gjH BGg iGj aFE CAH edI idf HEH','hIf DDg fjB hGi cHF BCH FjG Bgd'),
|
||||
(17, 'iaI JGH hji gcj Dda eeG jDd CBi','cHg jeh caG gIc feF ihG hgJ Abj'),
|
||||
(18, 'jHI iDB eFf AiH EFB CDb IAj GbC','Ghe dEI gdI jai gib dAG BIa djb'),
|
||||
(19, 'abI fHG Ccf aAc FDa fiC agF bdB','afi hde IgE bGF cfg DHD diE aca'),
|
||||
(20, 'IFh eDJ jfh cDg dde JGJ GAf fIJ','IBa EfH faE aeI FIF baJ FGj EIH'),
|
||||
(21, 'Dee bFC bBA dEI CEj aJI ghA dCH','hBA ddA HJh dfj egI Dij dFE bGE'),
|
||||
(22, 'JFE BCj FgA afc Jda FGD iHJ HDh','eAI jHe BHD Gah bbD Bgj gbh eGB'),
|
||||
(23, 'edE CJE FjG aFI edA Cea FId iFe','ABG jcA ddj EEc Dcg hAI agA biA'),
|
||||
(24, 'AgE cfc eef cGh aFB DcH efJ hcH','eGF HaB diG fgi bdc iGJ FGJ fFB'),
|
||||
(25, 'aCa AgI GhC DDI hGJ Hgc Gcg bbG','iID Fga jHa jIj idj DFD bAC AFJ'),
|
||||
(26, 'gjC JGh Fge faa eCA iGG gHE Gai','bDi hFE BbI DHD Adb Fgi hCa Hij'),
|
||||
(27, 'Eji jEI jhF DFC afH cDh AGc dHA','IDe GcA ChF DIb Bif HfH agD DGh'),
|
||||
(28, 'gDD AEE Dfg ICf Cbi JdE jgH eEi','eEb dBG FDE jgf cAI FaJ jaA cDd'),
|
||||
(29, 'cbe Gec hgB Egi bca dHg bAJ jBf','EFB DgD GJc fDb EeE bBA GFC Hbe'),
|
||||
(30, 'Adc eHB afI hDc Bhh baE hcJ BBd','JAH deg bcF Dab Bgj Gbb JHi FIB'),
|
||||
(31, 'agF dIj AJJ Hfg cCG hED Igc fHC','JEf eia dHf Ggc Agj geD bEE Gei'),
|
||||
(32, 'DAd cCe cbJ FjG gJe gba dJA GCf','eAf hFc bGE ABI hHA IcE abF CCE'),
|
||||
(33, 'fFh jJe DhJ cDJ EBi AfD eFI IhG','fEG GCc Bjd EFF ggg CFe EHd ciB'),
|
||||
(34, 'Ejb BjI eAF HaD eEJ FaG Eda AHC','Iah hgD EJG fdD cIE Daj IFf eJh'),
|
||||
(35, 'aHG eCe FjA djJ dAJ jiJ IaE GGB','Acg iEF JfB FIC Eei ggj dic Iii'),
|
||||
(36, 'Fdb EDF GaF JjB ehH IgC hgi DCG','cag DHI Fah hAJ bbh egG Hia hgJ'),
|
||||
(37, 'HGg icC JEC AFJ Ddh dhi hfC Ich','fEg bED Bff hCJ EiA cIf bfG cGA'),
|
||||
(38, 'aEJ jGI BCi FaA ebA BHj cIJ GcC','dCH ADd bGB cFE AgF geD cbG jIc'),
|
||||
(39, 'JFB bBi heA BFA hgB Ahj EIE CgI','EIJ JFG FJE GeA Hdg HeH ACh GiA'),
|
||||
(40, 'agB DDC CED igC Dfc DhI eiC fHi','dAB dcg iJF cej Fcc cAc AfB Fdd'),
|
||||
(41, 'BdF DHj Ege hcG DEd eFa dCf gBb','FBG ChB cej iGd Hbh fCc Ibe Abh'),
|
||||
(42, 'Bgc DjI cbC jGD bdb hHB IJA IJH','heg cii abb IGf eDe hJc dii fcE'),
|
||||
(43, 'fhf ECa FiA aDh Jbf CiB Jhe ajD','GFE bIF aeD gDE BIE Jea DfC BEc'),
|
||||
(44, 'GjE dBj DbJ ICF aDh EEH Ejb jFb','dJj aEc IBg bEG Faf fjA hjf FAF'),
|
||||
(45, 'BfA efd IIJ AHG dDF eGg dIJ Gcb','Bfj jeb Ahc dAE ACH Dfb ieb dhC'),
|
||||
(46, 'Ibj ege geC dJh CIi hbD EAG fGA','DEb BFe Bjg FId Fhg HeF JAc BbE'),
|
||||
(47, 'dhB afC hgG bEJ aIe Cbe iEE JCD','bdg Ajc FGA jbh Jge iAj fIA jbE'),
|
||||
(48, 'egH iDi bfH iiI hGC jFF Hfd AHB','bjE Beb iCc haB gIH Dea bga dfd'),
|
||||
(49, 'jgf chc jGc Baj HBb jdE hgh heI','FFB aBd iEB EIG HGf Bbj EIi JbI'),
|
||||
(50, 'jhe EGi ajA fbH geh EHe FdC bij','jDE bBC gbH HeE dcH iBH IFE AHi'),
|
||||
(51, 'aCb JiD cgJ Bjj iAI Hbe IAF FhH','ijf bhE Jdf FED dCH bbG HcJ ebH');
|
||||
"
|
||||
}
|
||||
|
||||
foreach_detail_mode $testprefix {
|
||||
foreach external {0 1 2} {
|
||||
reset_db
|
||||
|
||||
proc tokens {cmd} {
|
||||
set ret [list]
|
||||
for {set iTok 0} {$iTok < [$cmd xInstCount]} {incr iTok} {
|
||||
set txt [$cmd xInstToken $iTok 0]
|
||||
set txt [string map [list "\0" "."] $txt]
|
||||
lappend ret $txt
|
||||
}
|
||||
set ret
|
||||
}
|
||||
sqlite3_fts5_create_function db tokens tokens
|
||||
sqlite3_fts5_register_origintext db
|
||||
|
||||
set E(0) internal
|
||||
set E(1) external
|
||||
set E(2) contentless
|
||||
set e $E($external)
|
||||
|
||||
db eval { CREATE TABLE ex(x, y) }
|
||||
switch -- $external {
|
||||
0 {
|
||||
do_execsql_test 1.$e.0 {
|
||||
CREATE VIRTUAL TABLE ft USING fts5(
|
||||
x, y, tokenize="origintext unicode61", tokendata=1, detail=%DETAIL%
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
1 {
|
||||
do_execsql_test 1.$e.0 {
|
||||
CREATE VIRTUAL TABLE ft USING fts5(
|
||||
x, y, tokenize="origintext unicode61", tokendata=1, detail=%DETAIL%,
|
||||
content=ex
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
2 {
|
||||
do_execsql_test 1.$e.0 {
|
||||
CREATE VIRTUAL TABLE ft USING fts5(
|
||||
x, y, tokenize="origintext unicode61", tokendata=1, detail=%DETAIL%,
|
||||
content=
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
insert_data ex
|
||||
insert_data ft
|
||||
|
||||
proc prefixquery {prefix bInst bYOnly} {
|
||||
set ret [list]
|
||||
db eval { SELECT rowid, x, y FROM ex ORDER BY rowid } {
|
||||
set row [list]
|
||||
set bSeen 0
|
||||
|
||||
set T [concat $x $y]
|
||||
if {$bYOnly} { set T $y }
|
||||
|
||||
foreach w $T {
|
||||
if {[string match -nocase $prefix $w]} {
|
||||
set bSeen 1
|
||||
if {$bInst} {
|
||||
set v [string tolower $w]
|
||||
if {$w != $v} { append v ".$w" }
|
||||
lappend row $v
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if {$bSeen} {
|
||||
lappend ret $rowid
|
||||
lappend ret $row
|
||||
}
|
||||
}
|
||||
|
||||
set ret
|
||||
}
|
||||
|
||||
proc do_prefixquery_test {tn prefix} {
|
||||
set bInst [expr {$::e!="contentless" || "%DETAIL%"=="full"}]
|
||||
set expect [prefixquery $prefix $bInst 0]
|
||||
set expect2 [prefixquery $prefix $bInst 1]
|
||||
|
||||
uplevel [list do_execsql_test $tn.1 "
|
||||
SELECT rowid, tokens(ft) FROM ft('$prefix')
|
||||
" $expect]
|
||||
uplevel [list do_execsql_test $tn.2 "
|
||||
SELECT rowid, tokens(ft) FROM ft(fts5_insttoken('$prefix'))
|
||||
" $expect]
|
||||
db eval { INSERT INTO ft(ft, rank) VALUES('insttoken', 1) }
|
||||
uplevel [list do_execsql_test $tn.3 "
|
||||
SELECT rowid, tokens(ft) FROM ft('$prefix')
|
||||
" $expect]
|
||||
db eval { INSERT INTO ft(ft, rank) VALUES('insttoken', 0) }
|
||||
|
||||
if {"%DETAIL%"!="none"} {
|
||||
uplevel [list do_execsql_test $tn.4 "
|
||||
SELECT rowid, tokens(ft) FROM ft('y: $prefix')
|
||||
" $expect2]
|
||||
uplevel [list do_execsql_test $tn.5 "
|
||||
SELECT rowid, tokens(ft) FROM ft(fts5_insttoken('y: $prefix'))
|
||||
" $expect2]
|
||||
db eval { INSERT INTO ft(ft, rank) VALUES('insttoken', 1) }
|
||||
uplevel [list do_execsql_test $tn.6 "
|
||||
SELECT rowid, tokens(ft) FROM ft('y: $prefix')
|
||||
" $expect2]
|
||||
db eval { INSERT INTO ft(ft, rank) VALUES('insttoken', 0) }
|
||||
}
|
||||
}
|
||||
|
||||
do_prefixquery_test 1.$e.1 a*
|
||||
do_prefixquery_test 1.$e.2 b*
|
||||
do_prefixquery_test 1.$e.3 c*
|
||||
do_prefixquery_test 1.$e.4 d*
|
||||
do_prefixquery_test 1.$e.5 e*
|
||||
do_prefixquery_test 1.$e.6 f*
|
||||
do_prefixquery_test 1.$e.7 g*
|
||||
do_prefixquery_test 1.$e.8 h*
|
||||
do_prefixquery_test 1.$e.9 i*
|
||||
do_prefixquery_test 1.$e.10 j*
|
||||
}}
|
||||
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -48,7 +48,7 @@ do_catchsql_test 2.0 {
|
||||
SAVEPOINT two;
|
||||
INSERT INTO ft1 VALUES('b');
|
||||
COMMIT;
|
||||
} {1 {SQL logic error}}
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
reset_db
|
||||
ifcapable fts3 {
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
# 2014 Jan 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 focused on phrase queries.
|
||||
#
|
||||
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5tokendata
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
foreach_detail_mode $testprefix {
|
||||
|
||||
sqlite3_fts5_register_origintext db
|
||||
fts5_aux_test_functions db
|
||||
proc b {x} { string map [list "\0" "."] $x }
|
||||
db func b b
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE VIRTUAL TABLE ft USING fts5(a, b, tokendata=1,
|
||||
tokenize="origintext unicode61", detail=%DETAIL%
|
||||
);
|
||||
CREATE VIRTUAL TABLE vocab USING fts5vocab(ft, instance);
|
||||
}
|
||||
|
||||
do_execsql_test 1.1 {
|
||||
INSERT INTO ft(rowid, a, b) VALUES
|
||||
(1, 'Pedagog Pedal Pedant', 'Peculier Day Today'),
|
||||
(2, 'Pedant pedantic pecked', 'Peck Penalize Pen');
|
||||
|
||||
INSERT INTO ft(rowid, a, b) VALUES
|
||||
(3, 'Penalty Pence Penciled', 'One Two Three'),
|
||||
(4, 'Pedant Pedal Pedant', 'Peculier Day Today');
|
||||
}
|
||||
|
||||
do_execsql_test 1.2 {
|
||||
SELECT DISTINCT b(term) FROM vocab
|
||||
} {
|
||||
day.Day one.One peck.Peck pecked peculier.Peculier pedagog.Pedagog
|
||||
pedal.Pedal pedant.Pedant pedantic pen.Pen penalize.Penalize
|
||||
penalty.Penalty pence.Pence penciled.Penciled three.Three
|
||||
today.Today two.Two
|
||||
}
|
||||
|
||||
do_execsql_test 1.3.1 {
|
||||
SELECT rowid FROM ft('pe*')
|
||||
} {
|
||||
1 2 3 4
|
||||
}
|
||||
|
||||
do_execsql_test 1.3.2 {
|
||||
SELECT rowid FROM ft('pe*') ORDER BY rowid DESC
|
||||
} {
|
||||
4 3 2 1
|
||||
}
|
||||
|
||||
if {"%DETAIL%"!="none"} {
|
||||
do_execsql_test 1.3.3 {
|
||||
SELECT rowid FROM ft WHERE a MATCH 'pe*' ORDER BY rowid DESC
|
||||
} {
|
||||
4 3 2 1
|
||||
}
|
||||
}
|
||||
|
||||
do_execsql_test 1.4 {
|
||||
SELECT rowid, b( fts5_test_insttoken(ft, 0, 0) ) FROM ft('pedant')
|
||||
} {
|
||||
1 pedant.Pedant
|
||||
2 pedant.Pedant
|
||||
4 pedant.Pedant
|
||||
}
|
||||
|
||||
do_execsql_test 1.5 {
|
||||
SELECT rowid, b( fts5_test_insttoken(ft, 0, 0) ) FROM ft('pe*')
|
||||
} {
|
||||
1 pedagog.Pedagog
|
||||
2 pedant.Pedant
|
||||
3 penalty.Penalty
|
||||
4 pedant.Pedant
|
||||
}
|
||||
|
||||
do_execsql_test 1.6 {
|
||||
SELECT rowid, fts5_test_poslist(ft) FROM ft('pe*')
|
||||
} {
|
||||
1 {0.0.0 0.0.1 0.0.2 0.1.0}
|
||||
2 {0.0.0 0.0.1 0.0.2 0.1.0 0.1.1 0.1.2}
|
||||
3 {0.0.0 0.0.1 0.0.2}
|
||||
4 {0.0.0 0.0.1 0.0.2 0.1.0}
|
||||
}
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -342,6 +342,25 @@ do_test 10.3 {
|
||||
}
|
||||
} {}
|
||||
|
||||
do_execsql_test 11.0 {
|
||||
CREATE VIRTUAL TABLE t4 USING fts5(y, tokenize=trigram);
|
||||
}
|
||||
sqlite3_fts5_register_str db
|
||||
do_execsql_test 11.1 {
|
||||
INSERT INTO t4 VALUES( str('') );
|
||||
}
|
||||
|
||||
do_test 12.0 {
|
||||
sqlite3_fts5_tokenize db trigram "abcd"
|
||||
} {abc 0 3 bcd 1 4}
|
||||
|
||||
do_test 12.1 {
|
||||
sqlite3_fts5_tokenize db trigram "a"
|
||||
} {}
|
||||
|
||||
do_test 12.2 {
|
||||
sqlite3_fts5_tokenize db trigram ""
|
||||
} {}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -112,7 +112,7 @@ do_execsql_test 2.1 {
|
||||
|
||||
do_execsql_test 2.2 {
|
||||
SELECT v FROM xyz_config WHERE k='version';
|
||||
} {5}
|
||||
} {4}
|
||||
|
||||
do_execsql_test 2.3 {
|
||||
ROLLBACK TO one;
|
||||
|
||||
+20
-16
@@ -1,19 +1,18 @@
|
||||
|
||||
This directory contains source code for the SQLite "ICU" extension, an
|
||||
integration of the "International Components for Unicode" library with
|
||||
SQLite. Documentation follows.
|
||||
|
||||
1. Features
|
||||
|
||||
|
||||
1.1 SQL Scalars upper() and lower()
|
||||
1.2 Unicode Aware LIKE Operator
|
||||
1.3 ICU Collation Sequences
|
||||
1.4 SQL REGEXP Operator
|
||||
|
||||
|
||||
2. Compilation and Usage
|
||||
|
||||
|
||||
3. Bugs, Problems and Security Issues
|
||||
|
||||
|
||||
3.1 The "case_sensitive_like" Pragma
|
||||
3.2 The SQLITE_MAX_LIKE_PATTERN_LENGTH Macro
|
||||
3.3 Collation Sequence Security Issue
|
||||
@@ -23,10 +22,10 @@ SQLite. Documentation follows.
|
||||
|
||||
1.1 SQL Scalars upper() and lower()
|
||||
|
||||
SQLite's built-in implementations of these two functions only
|
||||
SQLite's built-in implementations of these two functions only
|
||||
provide case mapping for the 26 letters used in the English
|
||||
language. The ICU based functions provided by this extension
|
||||
provide case mapping, where defined, for the full range of
|
||||
provide case mapping, where defined, for the full range of
|
||||
unicode characters.
|
||||
|
||||
ICU provides two types of case mapping, "general" case mapping and
|
||||
@@ -36,7 +35,7 @@ SQLite. Documentation follows.
|
||||
http://www.icu-project.org/userguide/caseMappings.html
|
||||
http://www.icu-project.org/userguide/posix.html#case_mappings
|
||||
|
||||
To utilise "general" case mapping, the upper() or lower() scalar
|
||||
To utilise "general" case mapping, the upper() or lower() scalar
|
||||
functions are invoked with one argument:
|
||||
|
||||
upper('abc') -> 'ABC'
|
||||
@@ -57,7 +56,7 @@ SQLite. Documentation follows.
|
||||
operator understands case equivalence for the 26 letters of the English
|
||||
language alphabet. The implementation of LIKE included in this
|
||||
extension uses the ICU function u_foldCase() to provide case
|
||||
independent comparisons for the full range of unicode characters.
|
||||
independent comparisons for the full range of unicode characters.
|
||||
|
||||
The U_FOLD_CASE_DEFAULT flag is passed to u_foldCase(), meaning the
|
||||
dotless 'I' character used in the Turkish language is considered
|
||||
@@ -66,9 +65,9 @@ SQLite. Documentation follows.
|
||||
|
||||
1.3 ICU Collation Sequences
|
||||
|
||||
A special SQL scalar function, icu_load_collation() is provided that
|
||||
A special SQL scalar function, icu_load_collation() is provided that
|
||||
may be used to register ICU collation sequences with SQLite. It
|
||||
is always called with exactly two arguments, the ICU locale
|
||||
is always called with exactly two arguments, the ICU locale
|
||||
identifying the collation sequence to ICU, and the name of the
|
||||
SQLite collation sequence to create. For example, to create an
|
||||
SQLite collation sequence named "turkish" using Turkish language
|
||||
@@ -87,7 +86,7 @@ SQLite. Documentation follows.
|
||||
australian_penpal_name TEXT COLLATE australian,
|
||||
turkish_penpal_name TEXT COLLATE turkish
|
||||
);
|
||||
|
||||
|
||||
1.4 SQL REGEXP Operator
|
||||
|
||||
This extension provides an implementation of the SQL binary
|
||||
@@ -116,7 +115,7 @@ SQLite. Documentation follows.
|
||||
and use it as a dynamically loadable SQLite extension. To do this
|
||||
using gcc on *nix:
|
||||
|
||||
gcc -fPIC -shared icu.c `pkg-config --libs --cflags icu-uc icu-io` \
|
||||
gcc -fPIC -shared icu.c `pkg-config --libs --cflags icu-io` \
|
||||
-o libSqliteIcu.so
|
||||
|
||||
You may need to add "-I" flags so that gcc can find sqlite3ext.h
|
||||
@@ -124,6 +123,11 @@ SQLite. Documentation follows.
|
||||
loaded into sqlite in the same way as any other dynamically loadable
|
||||
extension.
|
||||
|
||||
As of version 3.48, it can be enabled in the canonical build process
|
||||
by passing one of --with-icu-config or --with-icu-ldflags to the
|
||||
configure script, optionally together with --enable-icu-collations.
|
||||
See the configure --help for more details.
|
||||
|
||||
|
||||
3 BUGS, PROBLEMS AND SECURITY ISSUES
|
||||
|
||||
@@ -144,13 +148,13 @@ SQLite. Documentation follows.
|
||||
SQLITE_MAX_LIKE_PATTERN_LENGTH macro as the maximum length of a
|
||||
pattern in bytes (irrespective of encoding). The default value is
|
||||
defined in internal header file "limits.h".
|
||||
|
||||
The ICU extension LIKE implementation suffers from the same
|
||||
|
||||
The ICU extension LIKE implementation suffers from the same
|
||||
problem and uses the same solution. However, since the ICU extension
|
||||
code does not include the SQLite file "limits.h", modifying
|
||||
the default value therein does not affect the ICU extension.
|
||||
The default value of SQLITE_MAX_LIKE_PATTERN_LENGTH used by
|
||||
the ICU extension LIKE operator is 50000, defined in source
|
||||
the ICU extension LIKE operator is 50000, defined in source
|
||||
file "icu.c".
|
||||
|
||||
3.3 Collation Sequence Security
|
||||
|
||||
+1
-1
@@ -571,7 +571,7 @@ int sqlite3IcuInit(sqlite3 *db){
|
||||
return rc;
|
||||
}
|
||||
|
||||
#if !SQLITE_CORE
|
||||
#ifndef SQLITE_CORE
|
||||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
|
||||
+5
-5
@@ -46,11 +46,11 @@ LSMTESTSRC = $(LSMDIR)/lsm-test/lsmtest1.c $(LSMDIR)/lsm-test/lsmtest2.c \
|
||||
LSMOPTS += -fPIC -DLSM_MUTEX_PTHREADS=1 -I$(LSMDIR) -DHAVE_ZLIB
|
||||
|
||||
lsm.so: $(LSMOBJ)
|
||||
$(TCCX) -shared -fPIC -o lsm.so $(LSMOBJ)
|
||||
$(T.link) -shared -fPIC -o lsm.so $(LSMOBJ)
|
||||
|
||||
%.o: $(LSMDIR)/%.c $(LSMHDR) sqlite3.h
|
||||
$(TCCX) $(LSMOPTS) -c $<
|
||||
|
||||
$(T.link) $(LSMOPTS) -c $<
|
||||
|
||||
lsmtest$(EXE): $(LSMOBJ) $(LSMTESTSRC) $(LSMTESTHDR) sqlite3.o
|
||||
# $(TCPPX) -c $(TOP)/lsm-test/lsmtest_tdb2.cc
|
||||
$(TCCX) $(LSMOPTS) $(LSMTESTSRC) $(LSMOBJ) sqlite3.o -o lsmtest$(EXE) $(THREADLIB) -lz
|
||||
# $(T.link) -c $(TOP)/lsm-test/lsmtest_tdb2.cc
|
||||
$(T.link) $(LSMOPTS) $(LSMTESTSRC) $(LSMOBJ) sqlite3.o -o lsmtest$(EXE) $(THREADLIB) -lz
|
||||
|
||||
+6
-3
@@ -175,15 +175,15 @@ static u8* fromBase64( char *pIn, int ncIn, u8 *pOut ){
|
||||
case ND:
|
||||
/* Treat dark non-digits as pad, but they terminate decode too. */
|
||||
ncIn = 0;
|
||||
deliberate_fall_through;
|
||||
deliberate_fall_through; /* FALLTHRU */
|
||||
case WS:
|
||||
/* Treat whitespace as pad and terminate this group.*/
|
||||
nti = nac;
|
||||
deliberate_fall_through;
|
||||
deliberate_fall_through; /* FALLTHRU */
|
||||
case PC:
|
||||
bdp = 0;
|
||||
--nbo;
|
||||
deliberate_fall_through;
|
||||
deliberate_fall_through; /* FALLTHRU */
|
||||
default: /* bdp is the digit value. */
|
||||
qv = qv<<6 | bdp;
|
||||
break;
|
||||
@@ -192,10 +192,13 @@ static u8* fromBase64( char *pIn, int ncIn, u8 *pOut ){
|
||||
switch( nbo ){
|
||||
case 3:
|
||||
pOut[2] = (qv) & 0xff;
|
||||
deliberate_fall_through; /* FALLTHRU */
|
||||
case 2:
|
||||
pOut[1] = (qv>>8) & 0xff;
|
||||
deliberate_fall_through; /* FALLTHRU */
|
||||
case 1:
|
||||
pOut[0] = (qv>>16) & 0xff;
|
||||
break;
|
||||
}
|
||||
pOut += nbo;
|
||||
}
|
||||
|
||||
@@ -232,12 +232,16 @@ static u8* fromBase85( char *pIn, int ncIn, u8 *pOut ){
|
||||
switch( nbo ){
|
||||
case 4:
|
||||
*pOut++ = (qv >> 24)&0xff;
|
||||
/* FALLTHRU */
|
||||
case 3:
|
||||
*pOut++ = (qv >> 16)&0xff;
|
||||
/* FALLTHRU */
|
||||
case 2:
|
||||
*pOut++ = (qv >> 8)&0xff;
|
||||
/* FALLTHRU */
|
||||
case 1:
|
||||
*pOut++ = qv&0xff;
|
||||
/* FALLTHRU */
|
||||
case 0:
|
||||
break;
|
||||
}
|
||||
|
||||
+6
-1
@@ -588,12 +588,17 @@ static int closureOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Wrapper around sqlite3_free
|
||||
*/
|
||||
static void closureMemFree(closure_avl *p){ sqlite3_free(p); }
|
||||
|
||||
/*
|
||||
** Free up all the memory allocated by a cursor. Set it rLimit to 0
|
||||
** to indicate that it is at EOF.
|
||||
*/
|
||||
static void closureClearCursor(closure_cursor *pCur){
|
||||
closureAvlDestroy(pCur->pClosure, (void(*)(closure_avl*))sqlite3_free);
|
||||
closureAvlDestroy(pCur->pClosure, closureMemFree);
|
||||
sqlite3_free(pCur->zTableName);
|
||||
sqlite3_free(pCur->zIdColumn);
|
||||
sqlite3_free(pCur->zParentColumn);
|
||||
|
||||
+1
-1
@@ -437,7 +437,7 @@ static int writeFile(
|
||||
|
||||
GetSystemTime(¤tTime);
|
||||
SystemTimeToFileTime(¤tTime, &lastAccess);
|
||||
intervals = Int32x32To64(mtime, 10000000) + 116444736000000000;
|
||||
intervals = (mtime*10000000) + 116444736000000000;
|
||||
lastWrite.dwLowDateTime = (DWORD)intervals;
|
||||
lastWrite.dwHighDateTime = intervals >> 32;
|
||||
zUnicodeName = sqlite3_win32_utf8_to_unicode(zFile);
|
||||
|
||||
@@ -484,10 +484,10 @@ int sqlite3_percentile_init(
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
unsigned int i;
|
||||
#if defined(SQLITE3_H) || defined(SQLITE_STATIC_PERCENTILE)
|
||||
(void)pApi; /* Unused parameter */
|
||||
#else
|
||||
#ifdef SQLITE3EXT_H
|
||||
SQLITE_EXTENSION_INIT2(pApi);
|
||||
#else
|
||||
(void)pApi; /* Unused parameter */
|
||||
#endif
|
||||
(void)pzErrMsg; /* Unused parameter */
|
||||
for(i=0; i<sizeof(aPercentFunc)/sizeof(aPercentFunc[0]); i++){
|
||||
|
||||
+2
-1
@@ -656,7 +656,8 @@ static const char *re_subcompile_string(ReCompiled *p){
|
||||
** regular expression. Applications should invoke this routine once
|
||||
** for every call to re_compile() to avoid memory leaks.
|
||||
*/
|
||||
static void re_free(ReCompiled *pRe){
|
||||
static void re_free(void *p){
|
||||
ReCompiled *pRe = (ReCompiled*)p;
|
||||
if( pRe ){
|
||||
sqlite3_free(pRe->aOp);
|
||||
sqlite3_free(pRe->aArg);
|
||||
|
||||
+1
-1
@@ -659,7 +659,7 @@ static int seriesBestIndex(
|
||||
continue;
|
||||
}
|
||||
if( pConstraint->iColumn<SERIES_COLUMN_START ){
|
||||
if( pConstraint->iColumn==SERIES_COLUMN_VALUE ){
|
||||
if( pConstraint->iColumn==SERIES_COLUMN_VALUE && pConstraint->usable ){
|
||||
switch( op ){
|
||||
case SQLITE_INDEX_CONSTRAINT_EQ:
|
||||
case SQLITE_INDEX_CONSTRAINT_IS: {
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@
|
||||
**
|
||||
** This SQLite extension implements functions that compute SHA3 hashes
|
||||
** in the way described by the (U.S.) NIST FIPS 202 SHA-3 Standard.
|
||||
** Two SQL functions are implemented:
|
||||
** Three SQL functions are implemented:
|
||||
**
|
||||
** sha3(X,SIZE)
|
||||
** sha3_agg(Y,SIZE)
|
||||
|
||||
+51
-22
@@ -46,6 +46,11 @@
|
||||
** use O_U8TEXT when writing to the Windows console (or anything
|
||||
** else for which _isatty() returns true) and to use O_BINARY or O_TEXT
|
||||
** for all other output channels.
|
||||
**
|
||||
** The SQLITE_USE_W32_FOR_CONSOLE_IO macro is also available. If
|
||||
** defined, it forces the use of Win32 APIs for all console I/O, both
|
||||
** input and output. This is necessary for some non-Microsoft run-times
|
||||
** that implement stdio differently from Microsoft/Visual-Studio.
|
||||
*/
|
||||
#if defined(SQLITE_U8TEXT_ONLY)
|
||||
# define UseWtextForOutput(fd) 1
|
||||
@@ -96,8 +101,8 @@ FILE *sqlite3_fopen(const char *zFilename, const char *zMode){
|
||||
|
||||
sz1 = (int)strlen(zFilename);
|
||||
sz2 = (int)strlen(zMode);
|
||||
b1 = malloc( (sz1+1)*sizeof(b1[0]) );
|
||||
b2 = malloc( (sz2+1)*sizeof(b1[0]) );
|
||||
b1 = sqlite3_malloc( (sz1+1)*sizeof(b1[0]) );
|
||||
b2 = sqlite3_malloc( (sz2+1)*sizeof(b1[0]) );
|
||||
if( b1 && b2 ){
|
||||
sz1 = MultiByteToWideChar(CP_UTF8, 0, zFilename, sz1, b1, sz1);
|
||||
b1[sz1] = 0;
|
||||
@@ -105,8 +110,8 @@ FILE *sqlite3_fopen(const char *zFilename, const char *zMode){
|
||||
b2[sz2] = 0;
|
||||
fp = _wfopen(b1, b2);
|
||||
}
|
||||
free(b1);
|
||||
free(b2);
|
||||
sqlite3_free(b1);
|
||||
sqlite3_free(b2);
|
||||
simBinaryOther = 0;
|
||||
return fp;
|
||||
}
|
||||
@@ -122,8 +127,8 @@ FILE *sqlite3_popen(const char *zCommand, const char *zMode){
|
||||
|
||||
sz1 = (int)strlen(zCommand);
|
||||
sz2 = (int)strlen(zMode);
|
||||
b1 = malloc( (sz1+1)*sizeof(b1[0]) );
|
||||
b2 = malloc( (sz2+1)*sizeof(b1[0]) );
|
||||
b1 = sqlite3_malloc( (sz1+1)*sizeof(b1[0]) );
|
||||
b2 = sqlite3_malloc( (sz2+1)*sizeof(b1[0]) );
|
||||
if( b1 && b2 ){
|
||||
sz1 = MultiByteToWideChar(CP_UTF8, 0, zCommand, sz1, b1, sz1);
|
||||
b1[sz1] = 0;
|
||||
@@ -131,8 +136,8 @@ FILE *sqlite3_popen(const char *zCommand, const char *zMode){
|
||||
b2[sz2] = 0;
|
||||
fp = _wpopen(b1, b2);
|
||||
}
|
||||
free(b1);
|
||||
free(b2);
|
||||
sqlite3_free(b1);
|
||||
sqlite3_free(b2);
|
||||
return fp;
|
||||
}
|
||||
|
||||
@@ -146,12 +151,22 @@ char *sqlite3_fgets(char *buf, int sz, FILE *in){
|
||||
** that into UTF-8. Otherwise, non-ASCII characters all get translated
|
||||
** into '?'.
|
||||
*/
|
||||
wchar_t *b1 = malloc( sz*sizeof(wchar_t) );
|
||||
wchar_t *b1 = sqlite3_malloc( sz*sizeof(wchar_t) );
|
||||
if( b1==0 ) return 0;
|
||||
_setmode(_fileno(in), IsConsole(in) ? _O_WTEXT : _O_U8TEXT);
|
||||
if( fgetws(b1, sz/4, in)==0 ){
|
||||
sqlite3_free(b1);
|
||||
return 0;
|
||||
#ifdef SQLITE_USE_W32_FOR_CONSOLE_IO
|
||||
DWORD nRead = 0;
|
||||
if( IsConsole(in)
|
||||
&& ReadConsoleW(GetStdHandle(STD_INPUT_HANDLE), b1, sz-1, &nRead, 0)
|
||||
){
|
||||
b1[nRead] = 0;
|
||||
}else
|
||||
#endif
|
||||
{
|
||||
_setmode(_fileno(in), IsConsole(in) ? _O_WTEXT : _O_U8TEXT);
|
||||
if( fgetws(b1, sz/4, in)==0 ){
|
||||
sqlite3_free(b1);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
WideCharToMultiByte(CP_UTF8, 0, b1, -1, buf, sz, 0, 0);
|
||||
sqlite3_free(b1);
|
||||
@@ -207,20 +222,34 @@ int sqlite3_fputs(const char *z, FILE *out){
|
||||
** any translation. */
|
||||
return fputs(z, out);
|
||||
}else{
|
||||
/* When writing to the command-prompt in Windows, it is necessary
|
||||
** to use O_U8TEXT to render Unicode U+0080 and greater. Go ahead
|
||||
** use O_U8TEXT for everything in text mode.
|
||||
/* One must use UTF16 in order to get unicode support when writing
|
||||
** to the console on Windows.
|
||||
*/
|
||||
int sz = (int)strlen(z);
|
||||
wchar_t *b1 = malloc( (sz+1)*sizeof(wchar_t) );
|
||||
wchar_t *b1 = sqlite3_malloc( (sz+1)*sizeof(wchar_t) );
|
||||
if( b1==0 ) return 0;
|
||||
sz = MultiByteToWideChar(CP_UTF8, 0, z, sz, b1, sz);
|
||||
b1[sz] = 0;
|
||||
_setmode(_fileno(out), _O_U8TEXT);
|
||||
if( UseBinaryWText(out) ){
|
||||
piecemealOutput(b1, sz, out);
|
||||
}else{
|
||||
fputws(b1, out);
|
||||
|
||||
#ifdef SQLITE_USE_W32_FOR_CONSOLE_IO
|
||||
DWORD nWr = 0;
|
||||
if( IsConsole(out)
|
||||
&& WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE),b1,sz,&nWr,0)
|
||||
){
|
||||
/* If writing to the console, then the WriteConsoleW() is all we
|
||||
** need to do. */
|
||||
}else
|
||||
#endif
|
||||
{
|
||||
/* As long as SQLITE_USE_W32_FOR_CONSOLE_IO is not defined, or for
|
||||
** non-console I/O even if that macro is defined, write using the
|
||||
** standard library. */
|
||||
_setmode(_fileno(out), _O_U8TEXT);
|
||||
if( UseBinaryWText(out) ){
|
||||
piecemealOutput(b1, sz, out);
|
||||
}else{
|
||||
fputws(b1, out);
|
||||
}
|
||||
}
|
||||
sqlite3_free(b1);
|
||||
return 0;
|
||||
|
||||
+239
-15
@@ -105,7 +105,27 @@
|
||||
** invariants are (1) you must have -DSQLITE_ENABLE_VFSTRACE so that
|
||||
** the shell.c source file will know to include the -vfstrace command-line
|
||||
** option and (2) you must compile and link the three source files
|
||||
** shell,c, test_vfstrace.c, and sqlite3.c.
|
||||
** shell,c, test_vfstrace.c, and sqlite3.c.
|
||||
**
|
||||
** RUNTIME CONTROL OF VFSTRACE OUTPUT
|
||||
**
|
||||
** The application can use the "vfstrace" pragma to control which VFS
|
||||
** APIs are traced. To disable all output:
|
||||
**
|
||||
** PRAGMA vfstrace('-all');
|
||||
**
|
||||
** To enable all output (which is the default setting):
|
||||
**
|
||||
** PRAGMA vfstrace('+all');
|
||||
**
|
||||
** Individual APIs can be enabled or disabled by name, with or without
|
||||
** the initial "x" character. For example, to set up for tracing lock
|
||||
** primatives only:
|
||||
**
|
||||
** PRAGMA vfstrace('-all, +Lock,Unlock,ShmLock');
|
||||
**
|
||||
** The argument to the vfstrace pragma ignores capitalization and any
|
||||
** characters other than alphabetics, '+', and '-'.
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@@ -119,6 +139,8 @@ typedef struct vfstrace_info vfstrace_info;
|
||||
struct vfstrace_info {
|
||||
sqlite3_vfs *pRootVfs; /* The underlying real VFS */
|
||||
int (*xOut)(const char*, void*); /* Send output here */
|
||||
unsigned int mTrace; /* Mask of interfaces to trace */
|
||||
u8 bOn; /* Tracing on/off */
|
||||
void *pOutArg; /* First argument to xOut */
|
||||
const char *zVfsName; /* Name of this trace-VFS */
|
||||
sqlite3_vfs *pTraceVfs; /* Pointer back to the trace VFS */
|
||||
@@ -135,6 +157,39 @@ struct vfstrace_file {
|
||||
sqlite3_file *pReal; /* The real underlying file */
|
||||
};
|
||||
|
||||
/*
|
||||
** Bit values for vfstrace_info.mTrace.
|
||||
*/
|
||||
#define VTR_CLOSE 0x00000001
|
||||
#define VTR_READ 0x00000002
|
||||
#define VTR_WRITE 0x00000004
|
||||
#define VTR_TRUNC 0x00000008
|
||||
#define VTR_SYNC 0x00000010
|
||||
#define VTR_FSIZE 0x00000020
|
||||
#define VTR_LOCK 0x00000040
|
||||
#define VTR_UNLOCK 0x00000080
|
||||
#define VTR_CRL 0x00000100
|
||||
#define VTR_FCTRL 0x00000200
|
||||
#define VTR_SECSZ 0x00000400
|
||||
#define VTR_DEVCHAR 0x00000800
|
||||
#define VTR_SHMLOCK 0x00001000
|
||||
#define VTR_SHMMAP 0x00002000
|
||||
#define VTR_SHMBAR 0x00004000
|
||||
#define VTR_SHMUNMAP 0x00008000
|
||||
#define VTR_OPEN 0x00010000
|
||||
#define VTR_DELETE 0x00020000
|
||||
#define VTR_ACCESS 0x00040000
|
||||
#define VTR_FULLPATH 0x00080000
|
||||
#define VTR_DLOPEN 0x00100000
|
||||
#define VTR_DLERR 0x00200000
|
||||
#define VTR_DLSYM 0x00400000
|
||||
#define VTR_DLCLOSE 0x00800000
|
||||
#define VTR_RAND 0x01000000
|
||||
#define VTR_SLEEP 0x02000000
|
||||
#define VTR_CURTIME 0x04000000
|
||||
#define VTR_LASTERR 0x08000000
|
||||
#define VTR_FETCH 0x10000000 /* Also coverse xUnfetch */
|
||||
|
||||
/*
|
||||
** Method declarations for vfstrace_file.
|
||||
*/
|
||||
@@ -199,11 +254,13 @@ static void vfstrace_printf(
|
||||
){
|
||||
va_list ap;
|
||||
char *zMsg;
|
||||
va_start(ap, zFormat);
|
||||
zMsg = sqlite3_vmprintf(zFormat, ap);
|
||||
va_end(ap);
|
||||
pInfo->xOut(zMsg, pInfo->pOutArg);
|
||||
sqlite3_free(zMsg);
|
||||
if( pInfo->bOn ){
|
||||
va_start(ap, zFormat);
|
||||
zMsg = sqlite3_vmprintf(zFormat, ap);
|
||||
va_end(ap);
|
||||
pInfo->xOut(zMsg, pInfo->pOutArg);
|
||||
sqlite3_free(zMsg);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -302,6 +359,13 @@ static void strappend(char *z, int *pI, const char *zAppend){
|
||||
*pI = i;
|
||||
}
|
||||
|
||||
/*
|
||||
** Turn tracing output on or off according to mMask.
|
||||
*/
|
||||
static void vfstraceOnOff(vfstrace_info *pInfo, unsigned int mMask){
|
||||
pInfo->bOn = (pInfo->mTrace & mMask)!=0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Close an vfstrace-file.
|
||||
*/
|
||||
@@ -309,6 +373,7 @@ static int vfstraceClose(sqlite3_file *pFile){
|
||||
vfstrace_file *p = (vfstrace_file *)pFile;
|
||||
vfstrace_info *pInfo = p->pInfo;
|
||||
int rc;
|
||||
vfstraceOnOff(pInfo, VTR_CLOSE);
|
||||
vfstrace_printf(pInfo, "%s.xClose(%s)", pInfo->zVfsName, p->zFName);
|
||||
rc = p->pReal->pMethods->xClose(p->pReal);
|
||||
vfstrace_print_errcode(pInfo, " -> %s\n", rc);
|
||||
@@ -331,6 +396,7 @@ static int vfstraceRead(
|
||||
vfstrace_file *p = (vfstrace_file *)pFile;
|
||||
vfstrace_info *pInfo = p->pInfo;
|
||||
int rc;
|
||||
vfstraceOnOff(pInfo, VTR_READ);
|
||||
vfstrace_printf(pInfo, "%s.xRead(%s,n=%d,ofst=%lld)",
|
||||
pInfo->zVfsName, p->zFName, iAmt, iOfst);
|
||||
rc = p->pReal->pMethods->xRead(p->pReal, zBuf, iAmt, iOfst);
|
||||
@@ -350,6 +416,7 @@ static int vfstraceWrite(
|
||||
vfstrace_file *p = (vfstrace_file *)pFile;
|
||||
vfstrace_info *pInfo = p->pInfo;
|
||||
int rc;
|
||||
vfstraceOnOff(pInfo, VTR_WRITE);
|
||||
vfstrace_printf(pInfo, "%s.xWrite(%s,n=%d,ofst=%lld)",
|
||||
pInfo->zVfsName, p->zFName, iAmt, iOfst);
|
||||
rc = p->pReal->pMethods->xWrite(p->pReal, zBuf, iAmt, iOfst);
|
||||
@@ -364,6 +431,7 @@ static int vfstraceTruncate(sqlite3_file *pFile, sqlite_int64 size){
|
||||
vfstrace_file *p = (vfstrace_file *)pFile;
|
||||
vfstrace_info *pInfo = p->pInfo;
|
||||
int rc;
|
||||
vfstraceOnOff(pInfo, VTR_TRUNC);
|
||||
vfstrace_printf(pInfo, "%s.xTruncate(%s,%lld)", pInfo->zVfsName, p->zFName,
|
||||
size);
|
||||
rc = p->pReal->pMethods->xTruncate(p->pReal, size);
|
||||
@@ -388,6 +456,7 @@ static int vfstraceSync(sqlite3_file *pFile, int flags){
|
||||
if( flags & ~(SQLITE_SYNC_FULL|SQLITE_SYNC_DATAONLY) ){
|
||||
sqlite3_snprintf(sizeof(zBuf)-i, &zBuf[i], "|0x%x", flags);
|
||||
}
|
||||
vfstraceOnOff(pInfo, VTR_SYNC);
|
||||
vfstrace_printf(pInfo, "%s.xSync(%s,%s)", pInfo->zVfsName, p->zFName,
|
||||
&zBuf[1]);
|
||||
rc = p->pReal->pMethods->xSync(p->pReal, flags);
|
||||
@@ -402,6 +471,7 @@ static int vfstraceFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
|
||||
vfstrace_file *p = (vfstrace_file *)pFile;
|
||||
vfstrace_info *pInfo = p->pInfo;
|
||||
int rc;
|
||||
vfstraceOnOff(pInfo, VTR_FSIZE);
|
||||
vfstrace_printf(pInfo, "%s.xFileSize(%s)", pInfo->zVfsName, p->zFName);
|
||||
rc = p->pReal->pMethods->xFileSize(p->pReal, pSize);
|
||||
vfstrace_print_errcode(pInfo, " -> %s,", rc);
|
||||
@@ -430,6 +500,7 @@ static int vfstraceLock(sqlite3_file *pFile, int eLock){
|
||||
vfstrace_file *p = (vfstrace_file *)pFile;
|
||||
vfstrace_info *pInfo = p->pInfo;
|
||||
int rc;
|
||||
vfstraceOnOff(pInfo, VTR_LOCK);
|
||||
vfstrace_printf(pInfo, "%s.xLock(%s,%s)", pInfo->zVfsName, p->zFName,
|
||||
lockName(eLock));
|
||||
rc = p->pReal->pMethods->xLock(p->pReal, eLock);
|
||||
@@ -444,6 +515,7 @@ static int vfstraceUnlock(sqlite3_file *pFile, int eLock){
|
||||
vfstrace_file *p = (vfstrace_file *)pFile;
|
||||
vfstrace_info *pInfo = p->pInfo;
|
||||
int rc;
|
||||
vfstraceOnOff(pInfo, VTR_UNLOCK);
|
||||
vfstrace_printf(pInfo, "%s.xUnlock(%s,%s)", pInfo->zVfsName, p->zFName,
|
||||
lockName(eLock));
|
||||
rc = p->pReal->pMethods->xUnlock(p->pReal, eLock);
|
||||
@@ -458,6 +530,7 @@ static int vfstraceCheckReservedLock(sqlite3_file *pFile, int *pResOut){
|
||||
vfstrace_file *p = (vfstrace_file *)pFile;
|
||||
vfstrace_info *pInfo = p->pInfo;
|
||||
int rc;
|
||||
vfstraceOnOff(pInfo, VTR_CRL);
|
||||
vfstrace_printf(pInfo, "%s.xCheckReservedLock(%s,%d)",
|
||||
pInfo->zVfsName, p->zFName);
|
||||
rc = p->pReal->pMethods->xCheckReservedLock(p->pReal, pResOut);
|
||||
@@ -477,6 +550,7 @@ static int vfstraceFileControl(sqlite3_file *pFile, int op, void *pArg){
|
||||
char zBuf2[100];
|
||||
char *zOp;
|
||||
char *zRVal = 0;
|
||||
vfstraceOnOff(pInfo, VTR_FCTRL);
|
||||
switch( op ){
|
||||
case SQLITE_FCNTL_LOCKSTATE: zOp = "LOCKSTATE"; break;
|
||||
case SQLITE_GET_LOCKPROXYFILE: zOp = "GET_LOCKPROXYFILE"; break;
|
||||
@@ -505,6 +579,80 @@ static int vfstraceFileControl(sqlite3_file *pFile, int op, void *pArg){
|
||||
case SQLITE_FCNTL_POWERSAFE_OVERWRITE: zOp = "POWERSAFE_OVERWRITE"; break;
|
||||
case SQLITE_FCNTL_PRAGMA: {
|
||||
const char *const* a = (const char*const*)pArg;
|
||||
if( a[1] && strcmp(a[1],"vfstrace")==0 && a[2] ){
|
||||
const u8 *zArg = (const u8*)a[2];
|
||||
if( zArg[0]>='0' && zArg[0]<=9 ){
|
||||
pInfo->mTrace = (sqlite3_uint64)strtoll(a[2], 0, 0);
|
||||
}else{
|
||||
static const struct {
|
||||
const char *z;
|
||||
unsigned int m;
|
||||
} aKw[] = {
|
||||
{ "all", 0xffffffff },
|
||||
{ "close", VTR_CLOSE },
|
||||
{ "read", VTR_READ },
|
||||
{ "write", VTR_WRITE },
|
||||
{ "truncate", VTR_TRUNC },
|
||||
{ "sync", VTR_SYNC },
|
||||
{ "filesize", VTR_FSIZE },
|
||||
{ "lock", VTR_LOCK },
|
||||
{ "unlock", VTR_UNLOCK },
|
||||
{ "checkreservedlock", VTR_CRL },
|
||||
{ "filecontrol", VTR_FCTRL },
|
||||
{ "sectorsize", VTR_SECSZ },
|
||||
{ "devicecharacteristics", VTR_DEVCHAR },
|
||||
{ "shmlock", VTR_SHMLOCK },
|
||||
{ "shmmap", VTR_SHMMAP },
|
||||
{ "shmummap", VTR_SHMUNMAP },
|
||||
{ "shmbarrier", VTR_SHMBAR },
|
||||
{ "open", VTR_OPEN },
|
||||
{ "delete", VTR_DELETE },
|
||||
{ "access", VTR_ACCESS },
|
||||
{ "fullpathname", VTR_FULLPATH },
|
||||
{ "dlopen", VTR_DLOPEN },
|
||||
{ "dlerror", VTR_DLERR },
|
||||
{ "dlsym", VTR_DLSYM },
|
||||
{ "dlclose", VTR_DLCLOSE },
|
||||
{ "randomness", VTR_RAND },
|
||||
{ "sleep", VTR_SLEEP },
|
||||
{ "currenttime", VTR_CURTIME },
|
||||
{ "currenttimeint64", VTR_CURTIME },
|
||||
{ "getlasterror", VTR_LASTERR },
|
||||
{ "fetch", VTR_FETCH },
|
||||
};
|
||||
int onOff = 1;
|
||||
while( zArg[0] ){
|
||||
int jj, n;
|
||||
while( zArg[0]!=0 && zArg[0]!='-' && zArg[0]!='+'
|
||||
&& !isalpha(zArg[0]) ) zArg++;
|
||||
if( zArg[0]==0 ) break;
|
||||
if( zArg[0]=='-' ){
|
||||
onOff = 0;
|
||||
zArg++;
|
||||
}else if( zArg[0]=='+' ){
|
||||
onOff = 1;
|
||||
zArg++;
|
||||
}
|
||||
while( !isalpha(zArg[0]) ){
|
||||
if( zArg[0]==0 ) break;
|
||||
zArg++;
|
||||
}
|
||||
if( zArg[0]=='x' && isalpha(zArg[1]) ) zArg++;
|
||||
for(n=0; isalpha(zArg[n]); n++){}
|
||||
for(jj=0; jj<(int)(sizeof(aKw)/sizeof(aKw[0])); jj++){
|
||||
if( sqlite3_strnicmp(aKw[jj].z,(const char*)zArg,n)==0 ){
|
||||
if( onOff ){
|
||||
pInfo->mTrace |= aKw[jj].m;
|
||||
}else{
|
||||
pInfo->mTrace &= ~aKw[jj].m;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
zArg += n;
|
||||
}
|
||||
}
|
||||
}
|
||||
sqlite3_snprintf(sizeof(zBuf), zBuf, "PRAGMA,[%s,%s]",a[1],a[2]);
|
||||
zOp = zBuf;
|
||||
break;
|
||||
@@ -600,6 +748,7 @@ static int vfstraceSectorSize(sqlite3_file *pFile){
|
||||
vfstrace_file *p = (vfstrace_file *)pFile;
|
||||
vfstrace_info *pInfo = p->pInfo;
|
||||
int rc;
|
||||
vfstraceOnOff(pInfo, VTR_SECSZ);
|
||||
vfstrace_printf(pInfo, "%s.xSectorSize(%s)", pInfo->zVfsName, p->zFName);
|
||||
rc = p->pReal->pMethods->xSectorSize(p->pReal);
|
||||
vfstrace_printf(pInfo, " -> %d\n", rc);
|
||||
@@ -613,6 +762,7 @@ static int vfstraceDeviceCharacteristics(sqlite3_file *pFile){
|
||||
vfstrace_file *p = (vfstrace_file *)pFile;
|
||||
vfstrace_info *pInfo = p->pInfo;
|
||||
int rc;
|
||||
vfstraceOnOff(pInfo, VTR_DEVCHAR);
|
||||
vfstrace_printf(pInfo, "%s.xDeviceCharacteristics(%s)",
|
||||
pInfo->zVfsName, p->zFName);
|
||||
rc = p->pReal->pMethods->xDeviceCharacteristics(p->pReal);
|
||||
@@ -624,11 +774,22 @@ static int vfstraceDeviceCharacteristics(sqlite3_file *pFile){
|
||||
** Shared-memory operations.
|
||||
*/
|
||||
static int vfstraceShmLock(sqlite3_file *pFile, int ofst, int n, int flags){
|
||||
static const char *azLockName[] = {
|
||||
"WRITE",
|
||||
"CKPT",
|
||||
"RECOVER",
|
||||
"READ0",
|
||||
"READ1",
|
||||
"READ2",
|
||||
"READ3",
|
||||
"READ4",
|
||||
};
|
||||
vfstrace_file *p = (vfstrace_file *)pFile;
|
||||
vfstrace_info *pInfo = p->pInfo;
|
||||
int rc;
|
||||
char zLck[100];
|
||||
int i = 0;
|
||||
vfstraceOnOff(pInfo, VTR_SHMLOCK);
|
||||
memcpy(zLck, "|0", 3);
|
||||
if( flags & SQLITE_SHM_UNLOCK ) strappend(zLck, &i, "|UNLOCK");
|
||||
if( flags & SQLITE_SHM_LOCK ) strappend(zLck, &i, "|LOCK");
|
||||
@@ -637,8 +798,15 @@ static int vfstraceShmLock(sqlite3_file *pFile, int ofst, int n, int flags){
|
||||
if( flags & ~(0xf) ){
|
||||
sqlite3_snprintf(sizeof(zLck)-i, &zLck[i], "|0x%x", flags);
|
||||
}
|
||||
vfstrace_printf(pInfo, "%s.xShmLock(%s,ofst=%d,n=%d,%s)",
|
||||
pInfo->zVfsName, p->zFName, ofst, n, &zLck[1]);
|
||||
if( ofst>=0 && ofst<(int)(sizeof(azLockName)/sizeof(azLockName[0])) ){
|
||||
vfstrace_printf(pInfo, "%s.xShmLock(%s,ofst=%d(%s),n=%d,%s)",
|
||||
pInfo->zVfsName, p->zFName, ofst, azLockName[ofst],
|
||||
n, &zLck[1]);
|
||||
}else{
|
||||
vfstrace_printf(pInfo, "%s.xShmLock(%s,ofst=5d,n=%d,%s)",
|
||||
pInfo->zVfsName, p->zFName, ofst,
|
||||
n, &zLck[1]);
|
||||
}
|
||||
rc = p->pReal->pMethods->xShmLock(p->pReal, ofst, n, flags);
|
||||
vfstrace_print_errcode(pInfo, " -> %s\n", rc);
|
||||
return rc;
|
||||
@@ -653,6 +821,7 @@ static int vfstraceShmMap(
|
||||
vfstrace_file *p = (vfstrace_file *)pFile;
|
||||
vfstrace_info *pInfo = p->pInfo;
|
||||
int rc;
|
||||
vfstraceOnOff(pInfo, VTR_SHMMAP);
|
||||
vfstrace_printf(pInfo, "%s.xShmMap(%s,iRegion=%d,szRegion=%d,isWrite=%d,*)",
|
||||
pInfo->zVfsName, p->zFName, iRegion, szRegion, isWrite);
|
||||
rc = p->pReal->pMethods->xShmMap(p->pReal, iRegion, szRegion, isWrite, pp);
|
||||
@@ -662,6 +831,7 @@ static int vfstraceShmMap(
|
||||
static void vfstraceShmBarrier(sqlite3_file *pFile){
|
||||
vfstrace_file *p = (vfstrace_file *)pFile;
|
||||
vfstrace_info *pInfo = p->pInfo;
|
||||
vfstraceOnOff(pInfo, VTR_SHMBAR);
|
||||
vfstrace_printf(pInfo, "%s.xShmBarrier(%s)\n", pInfo->zVfsName, p->zFName);
|
||||
p->pReal->pMethods->xShmBarrier(p->pReal);
|
||||
}
|
||||
@@ -669,13 +839,35 @@ static int vfstraceShmUnmap(sqlite3_file *pFile, int delFlag){
|
||||
vfstrace_file *p = (vfstrace_file *)pFile;
|
||||
vfstrace_info *pInfo = p->pInfo;
|
||||
int rc;
|
||||
vfstraceOnOff(pInfo, VTR_SHMUNMAP);
|
||||
vfstrace_printf(pInfo, "%s.xShmUnmap(%s,delFlag=%d)",
|
||||
pInfo->zVfsName, p->zFName, delFlag);
|
||||
rc = p->pReal->pMethods->xShmUnmap(p->pReal, delFlag);
|
||||
vfstrace_print_errcode(pInfo, " -> %s\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int vfstraceFetch(sqlite3_file *pFile, i64 iOff, int nAmt, void **pptr){
|
||||
vfstrace_file *p = (vfstrace_file *)pFile;
|
||||
vfstrace_info *pInfo = p->pInfo;
|
||||
int rc;
|
||||
vfstraceOnOff(pInfo, VTR_FETCH);
|
||||
vfstrace_printf(pInfo, "%s.xFetch(%s,iOff=%lld,nAmt=%d,p=%p)",
|
||||
pInfo->zVfsName, p->zFName, iOff, nAmt, *pptr);
|
||||
rc = p->pReal->pMethods->xFetch(p->pReal, iOff, nAmt, pptr);
|
||||
vfstrace_print_errcode(pInfo, " -> %s\n", rc);
|
||||
return rc;
|
||||
}
|
||||
static int vfstraceUnfetch(sqlite3_file *pFile, i64 iOff, void *ptr){
|
||||
vfstrace_file *p = (vfstrace_file *)pFile;
|
||||
vfstrace_info *pInfo = p->pInfo;
|
||||
int rc;
|
||||
vfstraceOnOff(pInfo, VTR_FETCH);
|
||||
vfstrace_printf(pInfo, "%s.xUnfetch(%s,iOff=%lld,p=%p)",
|
||||
pInfo->zVfsName, p->zFName, iOff, ptr);
|
||||
rc = p->pReal->pMethods->xUnfetch(p->pReal, iOff, ptr);
|
||||
vfstrace_print_errcode(pInfo, " -> %s\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
@@ -696,6 +888,7 @@ static int vfstraceOpen(
|
||||
p->zFName = zName ? fileTail(zName) : "<temp>";
|
||||
p->pReal = (sqlite3_file *)&p[1];
|
||||
rc = pRoot->xOpen(pRoot, zName, p->pReal, flags, pOutFlags);
|
||||
vfstraceOnOff(pInfo, VTR_OPEN);
|
||||
vfstrace_printf(pInfo, "%s.xOpen(%s,flags=0x%x)",
|
||||
pInfo->zVfsName, p->zFName, flags);
|
||||
if( p->pReal->pMethods ){
|
||||
@@ -721,6 +914,10 @@ static int vfstraceOpen(
|
||||
pNew->xShmBarrier = pSub->xShmBarrier ? vfstraceShmBarrier : 0;
|
||||
pNew->xShmUnmap = pSub->xShmUnmap ? vfstraceShmUnmap : 0;
|
||||
}
|
||||
if( pNew->iVersion>=3 ){
|
||||
pNew->xFetch = pSub->xFetch ? vfstraceFetch : 0;
|
||||
pNew->xUnfetch = pSub->xUnfetch ? vfstraceUnfetch : 0;
|
||||
}
|
||||
pFile->pMethods = pNew;
|
||||
}
|
||||
vfstrace_print_errcode(pInfo, " -> %s", rc);
|
||||
@@ -741,6 +938,7 @@ static int vfstraceDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
|
||||
vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
|
||||
sqlite3_vfs *pRoot = pInfo->pRootVfs;
|
||||
int rc;
|
||||
vfstraceOnOff(pInfo, VTR_DELETE);
|
||||
vfstrace_printf(pInfo, "%s.xDelete(\"%s\",%d)",
|
||||
pInfo->zVfsName, zPath, dirSync);
|
||||
rc = pRoot->xDelete(pRoot, zPath, dirSync);
|
||||
@@ -761,6 +959,7 @@ static int vfstraceAccess(
|
||||
vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
|
||||
sqlite3_vfs *pRoot = pInfo->pRootVfs;
|
||||
int rc;
|
||||
vfstraceOnOff(pInfo, VTR_ACCESS);
|
||||
vfstrace_printf(pInfo, "%s.xAccess(\"%s\",%d)",
|
||||
pInfo->zVfsName, zPath, flags);
|
||||
rc = pRoot->xAccess(pRoot, zPath, flags, pResOut);
|
||||
@@ -783,6 +982,7 @@ static int vfstraceFullPathname(
|
||||
vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
|
||||
sqlite3_vfs *pRoot = pInfo->pRootVfs;
|
||||
int rc;
|
||||
vfstraceOnOff(pInfo, VTR_FULLPATH);
|
||||
vfstrace_printf(pInfo, "%s.xFullPathname(\"%s\")",
|
||||
pInfo->zVfsName, zPath);
|
||||
rc = pRoot->xFullPathname(pRoot, zPath, nOut, zOut);
|
||||
@@ -797,6 +997,7 @@ static int vfstraceFullPathname(
|
||||
static void *vfstraceDlOpen(sqlite3_vfs *pVfs, const char *zPath){
|
||||
vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
|
||||
sqlite3_vfs *pRoot = pInfo->pRootVfs;
|
||||
vfstraceOnOff(pInfo, VTR_DLOPEN);
|
||||
vfstrace_printf(pInfo, "%s.xDlOpen(\"%s\")\n", pInfo->zVfsName, zPath);
|
||||
return pRoot->xDlOpen(pRoot, zPath);
|
||||
}
|
||||
@@ -809,6 +1010,7 @@ static void *vfstraceDlOpen(sqlite3_vfs *pVfs, const char *zPath){
|
||||
static void vfstraceDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){
|
||||
vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
|
||||
sqlite3_vfs *pRoot = pInfo->pRootVfs;
|
||||
vfstraceOnOff(pInfo, VTR_DLERR);
|
||||
vfstrace_printf(pInfo, "%s.xDlError(%d)", pInfo->zVfsName, nByte);
|
||||
pRoot->xDlError(pRoot, nByte, zErrMsg);
|
||||
vfstrace_printf(pInfo, " -> \"%s\"", zErrMsg);
|
||||
@@ -830,7 +1032,8 @@ static void (*vfstraceDlSym(sqlite3_vfs *pVfs,void *p,const char *zSym))(void){
|
||||
static void vfstraceDlClose(sqlite3_vfs *pVfs, void *pHandle){
|
||||
vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
|
||||
sqlite3_vfs *pRoot = pInfo->pRootVfs;
|
||||
vfstrace_printf(pInfo, "%s.xDlOpen()\n", pInfo->zVfsName);
|
||||
vfstraceOnOff(pInfo, VTR_DLCLOSE);
|
||||
vfstrace_printf(pInfo, "%s.xDlClose()\n", pInfo->zVfsName);
|
||||
pRoot->xDlClose(pRoot, pHandle);
|
||||
}
|
||||
|
||||
@@ -841,6 +1044,7 @@ static void vfstraceDlClose(sqlite3_vfs *pVfs, void *pHandle){
|
||||
static int vfstraceRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
|
||||
vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
|
||||
sqlite3_vfs *pRoot = pInfo->pRootVfs;
|
||||
vfstraceOnOff(pInfo, VTR_RAND);
|
||||
vfstrace_printf(pInfo, "%s.xRandomness(%d)\n", pInfo->zVfsName, nByte);
|
||||
return pRoot->xRandomness(pRoot, nByte, zBufOut);
|
||||
}
|
||||
@@ -852,6 +1056,8 @@ static int vfstraceRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
|
||||
static int vfstraceSleep(sqlite3_vfs *pVfs, int nMicro){
|
||||
vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
|
||||
sqlite3_vfs *pRoot = pInfo->pRootVfs;
|
||||
vfstraceOnOff(pInfo, VTR_SLEEP);
|
||||
vfstrace_printf(pInfo, "%s.xSleep(%d)\n", pInfo->zVfsName, nMicro);
|
||||
return pRoot->xSleep(pRoot, nMicro);
|
||||
}
|
||||
|
||||
@@ -861,21 +1067,37 @@ static int vfstraceSleep(sqlite3_vfs *pVfs, int nMicro){
|
||||
static int vfstraceCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
|
||||
vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
|
||||
sqlite3_vfs *pRoot = pInfo->pRootVfs;
|
||||
return pRoot->xCurrentTime(pRoot, pTimeOut);
|
||||
int rc;
|
||||
vfstraceOnOff(pInfo, VTR_CURTIME);
|
||||
vfstrace_printf(pInfo, "%s.xCurrentTime()", pInfo->zVfsName);
|
||||
rc = pRoot->xCurrentTime(pRoot, pTimeOut);
|
||||
vfstrace_printf(pInfo, " -> %.17g\n", *pTimeOut);
|
||||
return rc;
|
||||
}
|
||||
static int vfstraceCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *pTimeOut){
|
||||
vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
|
||||
sqlite3_vfs *pRoot = pInfo->pRootVfs;
|
||||
return pRoot->xCurrentTimeInt64(pRoot, pTimeOut);
|
||||
int rc;
|
||||
vfstraceOnOff(pInfo, VTR_CURTIME);
|
||||
vfstrace_printf(pInfo, "%s.xCurrentTimeInt64()", pInfo->zVfsName);
|
||||
rc = pRoot->xCurrentTimeInt64(pRoot, pTimeOut);
|
||||
vfstrace_printf(pInfo, " -> %lld\n", *pTimeOut);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return th3 most recent error code and message
|
||||
** Return the most recent error code and message
|
||||
*/
|
||||
static int vfstraceGetLastError(sqlite3_vfs *pVfs, int iErr, char *zErr){
|
||||
static int vfstraceGetLastError(sqlite3_vfs *pVfs, int nErr, char *zErr){
|
||||
vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
|
||||
sqlite3_vfs *pRoot = pInfo->pRootVfs;
|
||||
return pRoot->xGetLastError(pRoot, iErr, zErr);
|
||||
int rc;
|
||||
vfstraceOnOff(pInfo, VTR_LASTERR);
|
||||
vfstrace_printf(pInfo, "%s.xGetLastError(%d,zBuf)", pInfo->zVfsName, nErr);
|
||||
if( nErr ) zErr[0] = 0;
|
||||
rc = pRoot->xGetLastError(pRoot, nErr, zErr);
|
||||
vfstrace_printf(pInfo, " -> zBuf[] = \"%s\", rc = %d\n", nErr?zErr:"", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -969,6 +1191,8 @@ int vfstrace_register(
|
||||
pInfo->pOutArg = pOutArg;
|
||||
pInfo->zVfsName = pNew->zName;
|
||||
pInfo->pTraceVfs = pNew;
|
||||
pInfo->mTrace = 0xffffffff;
|
||||
pInfo->bOn = 1;
|
||||
vfstrace_printf(pInfo, "%s.enabled_for(\"%s\")\n",
|
||||
pInfo->zVfsName, pRoot->zName);
|
||||
return sqlite3_vfs_register(pNew, makeDefault);
|
||||
|
||||
@@ -525,7 +525,6 @@ do_test 7.1 {
|
||||
} {1 {file is not a database}}
|
||||
|
||||
reset_db
|
||||
breakpoint
|
||||
do_test 8.0 {
|
||||
sqlite3 db {}
|
||||
db deserialize [decode_hexdb {
|
||||
@@ -552,5 +551,58 @@ do_test 8.1 {
|
||||
list [catch { $R finish } msg] $msg
|
||||
} {0 {}}
|
||||
|
||||
reset_db
|
||||
do_test 9.0 {
|
||||
sqlite3 db {}
|
||||
db deserialize [decode_hexdb {
|
||||
| size 16384 pagesize 4096t 0
|
||||
| 0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00
|
||||
| 16: 10 00 01 01 00 40 20 20 00 00 00 00 00 00 00 06 ........
|
||||
| 32: 00 00 00 0r 00 00 00 00 00 00 00 06 00 00 00 04 ..
|
||||
| 48: 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 ........
|
||||
| 96: 00 00 00 00 0d 00 00 00 06 0d e2 00 0f c4 0f 6a .......j
|
||||
| 112: 0e fc 0e 9d 0e 3d 0d e2 00 00 00 00 00 00 00 00 .
|
||||
| 3552: 00 00 59 06 06 17 21 21 01 7f 74 61 62 6c 65 74 ..tablet
|
||||
| 3568: 74 74 5f 63 6f 6e 66 69 67 74 74 74 5f 63 6f 6econ
|
||||
| 3584: 66 69 67 06 43 52 45 41 54 45 20 54 41 42 4c 45
|
||||
| 3616: 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 76 29 20 )
|
||||
| 3632: 57 49 54 48 4f 55 54 20 52 4f 57 49 44 5e 05 07 WOWID^..
|
||||
| 3648: 17 23 23 01 81 03 74 61 62 6c 65 74 74 74 5f 6tt_d
|
||||
| 3664: 6f 63 73 69 7a 65 74 74 74 5f 64 6f 63 73 69 7a z
|
||||
| 3680: 65 05 43 52 45 41 54 45 20 54 41 42 4c 45 20 27 e.ABLE '
|
||||
| 3696: 74 74 74 5f 64 6f 63 73 69 7a 65 27 28 69 64 20id
|
||||
| 3712: 49 4e 54 45 47 45 52 20 50 52 49 4d 41 52 59 20
|
||||
| 3728: 4b 45 59 2c 20 73 7a 20 42 4c 4f 42 29 5d 04 07 KEYB)]..
|
||||
| 3744: 17 23 23 01 81 B1 74 61 62 6c 65 74 74 74 5f 63 _c
|
||||
| 3760: 6f 6e 74 65 6e 74 74 74 74 5f 63 6f 6e 74 65 6e o_conten
|
||||
| 3776: 7 04 01 03 00 011 54 45 20 54 41 42 4c 45 20 27 t.CRLE '
|
||||
| 3792: 74 74 74 5f 63 6f 6e 74 65 6e 74 27 28 69 64 20
|
||||
| 3808: 49 4e 54 45 47 45 52 20 50 52 49 4d 41 52 59 20 INIMARY
|
||||
| 3904: 6f 2c 20 50 52 49 4d 41 52 59 20 4b 45 59 28 7EY(s
|
||||
| 3920: 65 67 69 64 2c 20 74 65 72 6d 29 29 20 57 49 54 T
|
||||
| 3936: 48 4f 55 54 20 52 4f 57 49 4 58 58 02 07 17 1d 1d ..
|
||||
| 3952: 01 81 03 74 61 62 6c 65 74 74 74 5f 64 61 74 61 .tt_data
|
||||
| 3968: 74 74 74 5f 64 61 74 61 02 43 52 45 41 54 45 2ATE
|
||||
| 3984: 54 41 42 4c 45 20 27 74 74 74 5f 64 61 74 61 27 '
|
||||
| 4000: 28 69 64 20 49 4e 54 45 47 45 52 20 50 52 49 4d (iR PRIM
|
||||
| 4016: 41 52 59 20 4b 45 59 2c 20 62 6c 6f 63 6b 20 42k B
|
||||
| 4032: 4c 4f 42 29 3a 01 06 17 13 13 08 5f 74 61 62 6c
|
||||
| 4048: 65 74 74 74 74 74 74 43 52 45 41 54 45 20 56 49 ettTE VI
|
||||
| 4064: 52 54 55 41 4c 20 54 41 42 4c 45 20 74 74 74 20 t
|
||||
| 4080: 55 53 49 4e 47 20 66 74 73 35 28 61 2c 20 62 29 U5(a, b)
|
||||
| page 4 offset 12288
|
||||
| 0: 0a 00 00 00 03 0f ea 00 0f fa 0f f2 0f ea 00 00 ........
|
||||
| 4064: 00 00 00 00 00 00 00 00 00 00 07 04 01 01 01 05 ..
|
||||
| 4080: 06 03 07 04 01 01 01 03 04 02 05 04 09 01 09 02 ........
|
||||
| end ro2.t
|
||||
}]} {}
|
||||
|
||||
do_test 9.1 {
|
||||
set R [sqlite3_recover_init db main test.db2]
|
||||
catch { $R run }
|
||||
list [catch { $R finish } msg] $msg
|
||||
} {0 {}}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -1825,6 +1825,8 @@ static int recoverWriteDataStep(sqlite3_recover *p){
|
||||
recoverError(p, SQLITE_NOMEM, 0);
|
||||
}
|
||||
p1->nVal = iField+1;
|
||||
}else if( pTab->nCol==0 ){
|
||||
p1->nVal = pTab->nCol;
|
||||
}
|
||||
p1->iPrevCell = iCell;
|
||||
p1->iPrevPage = iPage;
|
||||
|
||||
+2
-2
@@ -3775,8 +3775,8 @@ static void rtreenode(sqlite3_context *ctx, int nArg, sqlite3_value **apArg){
|
||||
sqlite3_str_append(pOut, "}", 1);
|
||||
}
|
||||
errCode = sqlite3_str_errcode(pOut);
|
||||
sqlite3_result_text(ctx, sqlite3_str_finish(pOut), -1, sqlite3_free);
|
||||
sqlite3_result_error_code(ctx, errCode);
|
||||
sqlite3_result_text(ctx, sqlite3_str_finish(pOut), -1, sqlite3_free);
|
||||
}
|
||||
|
||||
/* This routine implements an SQL function that returns the "depth" parameter
|
||||
@@ -4449,7 +4449,7 @@ int sqlite3_rtree_query_callback(
|
||||
);
|
||||
}
|
||||
|
||||
#if !SQLITE_CORE
|
||||
#ifndef SQLITE_CORE
|
||||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
|
||||
@@ -198,7 +198,7 @@ if {[permutation]=="inmemory_journal"} {
|
||||
} else {
|
||||
do_catchsql_test 6.1 {
|
||||
SELECT ( 'elvis' IN(SELECT rtreecheck('t1')) ) FROM (SELECT 1) GROUP BY 1;
|
||||
} {1 {database table is locked}}
|
||||
} {0 0}
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -204,7 +204,9 @@ proc do_conflict_test {tn args} {
|
||||
foreach t $O(-tables) { S attach $t }
|
||||
execsql $O(-sql)
|
||||
set ::xConflict [list]
|
||||
sqlite3changeset_apply db2 [S changeset] xConflict
|
||||
catch {
|
||||
sqlite3changeset_apply db2 [S changeset] xConflict
|
||||
}
|
||||
|
||||
set conflicts [list]
|
||||
foreach c $O(-conflicts) {
|
||||
|
||||
@@ -80,8 +80,10 @@ foreach {tn delrow trans conflictargs conflictret} {
|
||||
8 3 1 {FOREIGN_KEY 1} ABORT
|
||||
} {
|
||||
|
||||
set A(OMIT) {0 {}}
|
||||
set A(ABORT) {1 SQLITE_CONSTRAINT}
|
||||
set A(OMIT,0) {0 {}}
|
||||
set A(OMIT,1) {0 {}}
|
||||
set A(ABORT,0) {1 SQLITE_CONSTRAINT}
|
||||
set A(ABORT,1) {1 SQLITE_CONSTRAINT}
|
||||
do_test 1.2.$tn.1 {
|
||||
populate_db
|
||||
execsql { DELETE FROM p1 WHERE a=($delrow+0) }
|
||||
@@ -89,20 +91,24 @@ foreach {tn delrow trans conflictargs conflictret} {
|
||||
|
||||
set ::xConflict [list]
|
||||
list [catch {sqlite3changeset_apply db $::cc xConflict} msg] $msg
|
||||
} $A($conflictret)
|
||||
} $A($conflictret,$trans)
|
||||
|
||||
do_test 1.2.$tn.2 { set ::xConflict } $conflictargs
|
||||
|
||||
set A(OMIT) {1 1}
|
||||
set A(ABORT) {0 0}
|
||||
set A(OMIT,0) {1 1}
|
||||
set A(OMIT,1) {1 1}
|
||||
set A(ABORT,0) {0 0}
|
||||
set A(ABORT,1) {0 0}
|
||||
|
||||
do_test 1.2.$tn.3 {
|
||||
execsql { SELECT count(*) FROM c1 UNION ALL SELECT count(*) FROM c2 }
|
||||
} $A($conflictret)
|
||||
} $A($conflictret,$trans)
|
||||
|
||||
do_test 1.2.$tn.4 { expr ![sqlite3_get_autocommit db] } $trans
|
||||
do_test 1.2.$tn.5 {
|
||||
if { $trans } { execsql COMMIT }
|
||||
if { $trans && $conflictret=="ABORT" } { execsql COMMIT }
|
||||
} {}
|
||||
catchsql ROLLBACK
|
||||
}
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
|
||||
@@ -201,12 +201,16 @@ proc compare_db {db1 db2} {
|
||||
foreach tbl $lot1 {
|
||||
set col1 [list]
|
||||
set col2 [list]
|
||||
set quoted [list]
|
||||
|
||||
$db1 eval "PRAGMA table_info = $tbl" { lappend col1 $name }
|
||||
$db2 eval "PRAGMA table_info = $tbl" { lappend col2 $name }
|
||||
$db2 eval "PRAGMA table_info = $tbl" {
|
||||
lappend col2 $name
|
||||
lappend quoted "\"[string map {\" \"\"} $name]\""
|
||||
}
|
||||
if {$col1 != $col2} { error "table $tbl schema mismatch" }
|
||||
|
||||
set sql "SELECT * FROM $tbl ORDER BY [join $col1 ,]"
|
||||
set sql "SELECT * FROM $tbl ORDER BY [join $quoted ,]"
|
||||
set data1 [$db1 eval $sql]
|
||||
set data2 [$db2 eval $sql]
|
||||
if {$data1 != $data2} {
|
||||
|
||||
@@ -0,0 +1,191 @@
|
||||
# 2025 Jan 28
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
# This file implements regression tests for SQLite library.
|
||||
#
|
||||
|
||||
if {![info exists testdir]} {
|
||||
set testdir [file join [file dirname [info script]] .. .. test]
|
||||
}
|
||||
source [file join [file dirname [info script]] session_common.tcl]
|
||||
source $testdir/tester.tcl
|
||||
ifcapable !session {finish_test; return}
|
||||
|
||||
set testprefix session_gen
|
||||
|
||||
|
||||
foreach {otn sct} {
|
||||
1 VIRTUAL
|
||||
2 STORED
|
||||
} {
|
||||
eval [string map [list %TYPE% $sct] {
|
||||
reset_db
|
||||
set testprefix $testprefix-$otn
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
|
||||
|
||||
CREATE TABLE t2(a INTEGER PRIMARY KEY, b AS (c+1) %TYPE%, c);
|
||||
|
||||
CREATE TABLE t3(
|
||||
a,
|
||||
b AS (a+10) %TYPE%,
|
||||
c,
|
||||
d AS (c+1) %TYPE%,
|
||||
e,
|
||||
PRIMARY KEY(c, e)
|
||||
) WITHOUT ROWID;
|
||||
|
||||
CREATE TABLE t4(a AS (c*100) %TYPE%, b INTEGER PRIMARY KEY, c);
|
||||
|
||||
CREATE TABLE t5(x, y);
|
||||
}
|
||||
|
||||
foreach {tn sql changeset} {
|
||||
|
||||
0.1 {
|
||||
INSERT INTO t5 VALUES('abc', 'def');
|
||||
} {
|
||||
{INSERT t5 0 X.. {} {i 1 t abc t def}}
|
||||
}
|
||||
0.2 {
|
||||
UPDATE t5 SET y='xyz' WHERE rowid=1;
|
||||
} {
|
||||
{UPDATE t5 0 X.. {i 1 {} {} t def} {{} {} {} {} t xyz}}
|
||||
}
|
||||
0.3 {
|
||||
DELETE FROM t5;
|
||||
} {
|
||||
{DELETE t5 0 X.. {i 1 t abc t xyz} {}}
|
||||
}
|
||||
|
||||
1.1 {
|
||||
INSERT INTO t2 VALUES(1, 2);
|
||||
INSERT INTO t2 VALUES(2, 123);
|
||||
} {
|
||||
{INSERT t2 0 X. {} {i 1 i 2}}
|
||||
{INSERT t2 0 X. {} {i 2 i 123}}
|
||||
}
|
||||
1.2 {
|
||||
UPDATE t2 SET c=456 WHERE a=1
|
||||
} {
|
||||
{UPDATE t2 0 X. {i 1 i 2} {{} {} i 456}}
|
||||
}
|
||||
|
||||
1.3 {
|
||||
DELETE FROM t2 WHERE a=2
|
||||
} {
|
||||
{DELETE t2 0 X. {i 2 i 123} {}}
|
||||
}
|
||||
|
||||
1.4 {
|
||||
UPDATE t2 SET a=15
|
||||
} {
|
||||
{INSERT t2 0 X. {} {i 15 i 456}}
|
||||
{DELETE t2 0 X. {i 1 i 456} {}}
|
||||
}
|
||||
|
||||
2.1 {
|
||||
INSERT INTO t3 VALUES(5, 6, 7);
|
||||
INSERT INTO t3 VALUES(8, 9, 10);
|
||||
} {
|
||||
{INSERT t3 0 .XX {} {i 8 i 9 i 10}}
|
||||
{INSERT t3 0 .XX {} {i 5 i 6 i 7}}
|
||||
}
|
||||
|
||||
2.2 {
|
||||
UPDATE t3 SET a = 505 WHERE (c, e) = (6, 7);
|
||||
} {
|
||||
{UPDATE t3 0 .XX {i 5 i 6 i 7} {i 505 {} {} {} {}}}
|
||||
}
|
||||
|
||||
2.3 {
|
||||
DELETE FROM t3 WHERE (c, e) = (9, 10);
|
||||
} {
|
||||
{DELETE t3 0 .XX {i 8 i 9 i 10} {}}
|
||||
}
|
||||
|
||||
2.4 {
|
||||
UPDATE t3 SET c=1000
|
||||
} {
|
||||
{DELETE t3 0 .XX {i 505 i 6 i 7} {}}
|
||||
{INSERT t3 0 .XX {} {i 505 i 1000 i 7}}
|
||||
}
|
||||
|
||||
3.1 {
|
||||
INSERT INTO t4 VALUES(100, 100);
|
||||
} {
|
||||
{INSERT t4 0 X. {} {i 100 i 100}}
|
||||
}
|
||||
|
||||
} {
|
||||
do_test 1.$tn.1 {
|
||||
sqlite3session S db main
|
||||
S object_config rowid 1
|
||||
S attach *
|
||||
execsql $sql
|
||||
} {}
|
||||
|
||||
do_changeset_test 1.$tn.2 S $changeset
|
||||
|
||||
S delete
|
||||
}
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
|
||||
forcedelete test.db2
|
||||
sqlite3 db2 test.db2
|
||||
|
||||
do_common_sql {
|
||||
CREATE TABLE t0(x INTEGER PRIMARY KEY, y);
|
||||
INSERT INTO t0 VALUES(1, 'one');
|
||||
INSERT INTO t0 VALUES(2, 'two');
|
||||
|
||||
CREATE TABLE t1(a AS (c*10) %TYPE%, b INTEGER PRIMARY KEY, c);
|
||||
INSERT INTO t1 VALUES(1, 5);
|
||||
INSERT INTO t1 VALUES(2, 10);
|
||||
INSERT INTO t1 VALUES(3, 5);
|
||||
|
||||
CREATE TABLE t2(
|
||||
a, b, c AS (a*b) %TYPE%,
|
||||
'k 1', 'k 2', PRIMARY KEY('k 1', 'k 2')
|
||||
) WITHOUT ROWID;
|
||||
INSERT INTO t2 VALUES('a', 'b', 1, 11);
|
||||
INSERT INTO t2 VALUES('A', 'B', 2, 22);
|
||||
INSERT INTO t2 VALUES('Aa', 'Bb', 3, 33);
|
||||
}
|
||||
|
||||
foreach {tn sql} {
|
||||
1.1 { INSERT INTO t0 VALUES(4, 15) }
|
||||
1.2 { INSERT INTO t1 VALUES(4, 15) }
|
||||
1.3 { INSERT INTO t2 VALUES(1, 2, 3, 4) }
|
||||
|
||||
2.1 { UPDATE t1 SET c=100 WHERE b=2 }
|
||||
2.2 { UPDATE t2 SET a=11 }
|
||||
|
||||
3.1 { DELETE FROM t2 WHERE (t2.'k 1') = 2 }
|
||||
3.2 { DELETE FROM t1 }
|
||||
} {
|
||||
do_test 2.$tn.1 {
|
||||
# execsql { PRAGMA vdbe_listing = 1 } db2
|
||||
do_then_apply_sql $sql
|
||||
} {}
|
||||
do_test 2.$tn.2 {
|
||||
compare_db db db2
|
||||
} {}
|
||||
}
|
||||
db2 close
|
||||
|
||||
}]}
|
||||
|
||||
|
||||
|
||||
|
||||
finish_test
|
||||
@@ -0,0 +1,55 @@
|
||||
# 2024 November 04
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
|
||||
if {![info exists testdir]} {
|
||||
set testdir [file join [file dirname [info script]] .. .. test]
|
||||
}
|
||||
source [file join [file dirname [info script]] session_common.tcl]
|
||||
source $testdir/tester.tcl
|
||||
ifcapable !session {finish_test; return}
|
||||
|
||||
if {$::tcl_platform(pointerSize)<8} {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
set testprefix sessionblob
|
||||
|
||||
forcedelete test.db2
|
||||
sqlite3 db2 test.db2
|
||||
|
||||
set NBLOB 2000000
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
|
||||
INSERT INTO t1 VALUES(123, zeroblob($NBLOB));
|
||||
}
|
||||
|
||||
do_test 1.1 {
|
||||
sqlite3session S db main
|
||||
S attach t1
|
||||
} {}
|
||||
|
||||
set b2 [string repeat x 1000]
|
||||
do_test 1.2 {
|
||||
set ::blob [db incrblob t1 b 123]
|
||||
for {set ii 0} {$ii < $NBLOB} {incr ii [string length $b2]} {
|
||||
seek $::blob $ii
|
||||
puts -nonewline $::blob $b2
|
||||
}
|
||||
close $::blob
|
||||
} {}
|
||||
|
||||
S delete
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -59,7 +59,7 @@ do_execsql_test 1.2 {
|
||||
set ::nConflict 0
|
||||
proc conflict {args} {
|
||||
incr ::nConflict
|
||||
return "OMIT"
|
||||
return "ABORT"
|
||||
}
|
||||
|
||||
sqlite3changeset_apply_v2 db $C conflict
|
||||
@@ -82,7 +82,6 @@ do_execsql_test 1.5 {
|
||||
UPDATE p1 SET c=12345 WHERE a = 45;
|
||||
}
|
||||
|
||||
breakpoint
|
||||
sqlite3changeset_apply_v2 -noaction db $C conflict
|
||||
do_execsql_test 1.6 {
|
||||
SELECT * FROM c1
|
||||
@@ -108,4 +107,126 @@ do_execsql_test 1.8 {
|
||||
PRAGMA foreign_key_check
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Check that a changeset that causes an FK violation may not be applied,
|
||||
# even if SQLITE_CHANGESETAPPLY_FKNOACTION is specified.
|
||||
#
|
||||
# UPDATE: Unless the conflict-handler returns OMIT. In that case it can
|
||||
# be committed. See test cases 3.* in this file.
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 2.0 {
|
||||
CREATE TABLE p1(a INTEGER PRIMARY KEY, b, c UNIQUE);
|
||||
INSERT INTO p1 VALUES(1, 1, 'one');
|
||||
INSERT INTO p1 VALUES(2, 2, 'two');
|
||||
|
||||
CREATE TABLE c1(x REFERENCES p1(c) ON DELETE CASCADE);
|
||||
INSERT INTO c1 VALUES('two');
|
||||
}
|
||||
|
||||
db_save
|
||||
|
||||
set C [changeset_from_sql {
|
||||
DELETE FROM p1 WHERE a=2;
|
||||
}]
|
||||
|
||||
db_restore_and_reopen
|
||||
|
||||
do_test 2.1 {
|
||||
sqlite3changeset_apply_v2 -noaction db $C conflict
|
||||
} {}
|
||||
do_execsql_test 2.2 {
|
||||
SELECT * FROM p1
|
||||
} {1 1 one}
|
||||
|
||||
db_restore_and_reopen
|
||||
db eval { PRAGMA foreign_keys = 1 }
|
||||
|
||||
do_test 2.3 {
|
||||
list [catch { sqlite3changeset_apply_v2 -noaction db $C conflict } msg] $msg
|
||||
} {1 SQLITE_CONSTRAINT}
|
||||
do_execsql_test 2.4 {
|
||||
SELECT * FROM p1;
|
||||
} {1 1 one 2 2 two}
|
||||
do_execsql_test 2.5 {
|
||||
SELECT * FROM c1;
|
||||
} {two}
|
||||
|
||||
db_restore_and_reopen
|
||||
db eval { PRAGMA foreign_keys = 1 }
|
||||
|
||||
do_test 2.6 {
|
||||
list [catch {
|
||||
sqlite3changeset_apply_v2 -ignorenoop -noaction db $C conflict
|
||||
} msg] $msg
|
||||
} {1 SQLITE_CONSTRAINT}
|
||||
do_execsql_test 2.7 {
|
||||
SELECT * FROM p1;
|
||||
} {1 1 one 2 2 two}
|
||||
do_execsql_test 2.8 {
|
||||
SELECT * FROM c1;
|
||||
} {two}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 3.0 {
|
||||
CREATE TABLE p1(a INTEGER PRIMARY KEY, b, c UNIQUE);
|
||||
INSERT INTO p1 VALUES(1, 1, 'one');
|
||||
INSERT INTO p1 VALUES(2, 2, 'two');
|
||||
|
||||
CREATE TABLE c1(x REFERENCES p1(c) ON DELETE CASCADE);
|
||||
INSERT INTO c1 VALUES('two');
|
||||
}
|
||||
|
||||
set ::nConflict 0
|
||||
proc conflict {args} {
|
||||
incr ::nConflict
|
||||
return "OMIT"
|
||||
}
|
||||
|
||||
db_save
|
||||
|
||||
set C [changeset_from_sql {
|
||||
DELETE FROM p1 WHERE a=2;
|
||||
}]
|
||||
|
||||
db_restore_and_reopen
|
||||
|
||||
do_test 3.1 {
|
||||
sqlite3changeset_apply_v2 -noaction db $C conflict
|
||||
} {}
|
||||
do_execsql_test 3.2 {
|
||||
SELECT * FROM p1
|
||||
} {1 1 one}
|
||||
|
||||
db_restore_and_reopen
|
||||
db eval { PRAGMA foreign_keys = 1 }
|
||||
|
||||
do_test 3.3 {
|
||||
list [catch { sqlite3changeset_apply_v2 -noaction db $C conflict } msg] $msg
|
||||
} {0 {}}
|
||||
do_execsql_test 3.4 {
|
||||
SELECT * FROM p1;
|
||||
} {1 1 one}
|
||||
do_execsql_test 3.5 {
|
||||
SELECT * FROM c1;
|
||||
} {two}
|
||||
|
||||
db_restore_and_reopen
|
||||
db eval { PRAGMA foreign_keys = 1 }
|
||||
|
||||
do_test 3.6 {
|
||||
list [catch {
|
||||
sqlite3changeset_apply_v2 -ignorenoop -noaction db $C conflict
|
||||
} msg] $msg
|
||||
} {0 {}}
|
||||
do_execsql_test 3.7 {
|
||||
SELECT * FROM p1;
|
||||
} {1 1 one}
|
||||
do_execsql_test 3.8 {
|
||||
SELECT * FROM c1;
|
||||
} {two}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -139,11 +139,13 @@ struct sqlite3_changeset_iter {
|
||||
struct SessionTable {
|
||||
SessionTable *pNext;
|
||||
char *zName; /* Local name of table */
|
||||
int nCol; /* Number of columns in table zName */
|
||||
int nCol; /* Number of non-hidden columns */
|
||||
int nTotalCol; /* Number of columns including hidden */
|
||||
int bStat1; /* True if this is sqlite_stat1 */
|
||||
int bRowid; /* True if this table uses rowid for PK */
|
||||
const char **azCol; /* Column names */
|
||||
const char **azDflt; /* Default value expressions */
|
||||
int *aiIdx; /* Index to pass to xNew/xOld */
|
||||
u8 *abPK; /* Array of primary key flags */
|
||||
int nEntry; /* Total number of entries in hash table */
|
||||
int nChange; /* Size of apChange[] array */
|
||||
@@ -546,22 +548,22 @@ static int sessionPreupdateHash(
|
||||
unsigned int h = 0; /* Hash value to return */
|
||||
int i; /* Used to iterate through columns */
|
||||
|
||||
assert( pTab->nTotalCol==pSession->hook.xCount(pSession->hook.pCtx) );
|
||||
if( pTab->bRowid ){
|
||||
assert( pTab->nCol-1==pSession->hook.xCount(pSession->hook.pCtx) );
|
||||
h = sessionHashAppendI64(h, iRowid);
|
||||
}else{
|
||||
assert( *pbNullPK==0 );
|
||||
assert( pTab->nCol==pSession->hook.xCount(pSession->hook.pCtx) );
|
||||
for(i=0; i<pTab->nCol; i++){
|
||||
if( pTab->abPK[i] ){
|
||||
int rc;
|
||||
int eType;
|
||||
sqlite3_value *pVal;
|
||||
int iIdx = pTab->aiIdx[i];
|
||||
|
||||
if( bNew ){
|
||||
rc = pSession->hook.xNew(pSession->hook.pCtx, i, &pVal);
|
||||
rc = pSession->hook.xNew(pSession->hook.pCtx, iIdx, &pVal);
|
||||
}else{
|
||||
rc = pSession->hook.xOld(pSession->hook.pCtx, i, &pVal);
|
||||
rc = pSession->hook.xOld(pSession->hook.pCtx, iIdx, &pVal);
|
||||
}
|
||||
if( rc!=SQLITE_OK ) return rc;
|
||||
|
||||
@@ -898,6 +900,7 @@ static int sessionPreupdateEqual(
|
||||
sqlite3_value *pVal; /* Value returned by preupdate_new/old */
|
||||
int rc; /* Error code from preupdate_new/old */
|
||||
int eType = *a++; /* Type of value from change record */
|
||||
int iIdx = pTab->aiIdx[iCol];
|
||||
|
||||
/* The following calls to preupdate_new() and preupdate_old() can not
|
||||
** fail. This is because they cache their return values, and by the
|
||||
@@ -906,10 +909,10 @@ static int sessionPreupdateEqual(
|
||||
** this (that the method has already been called). */
|
||||
if( op==SQLITE_INSERT ){
|
||||
/* assert( db->pPreUpdate->pNewUnpacked || db->pPreUpdate->aNew ); */
|
||||
rc = pSession->hook.xNew(pSession->hook.pCtx, iCol, &pVal);
|
||||
rc = pSession->hook.xNew(pSession->hook.pCtx, iIdx, &pVal);
|
||||
}else{
|
||||
/* assert( db->pPreUpdate->pUnpacked ); */
|
||||
rc = pSession->hook.xOld(pSession->hook.pCtx, iCol, &pVal);
|
||||
rc = pSession->hook.xOld(pSession->hook.pCtx, iIdx, &pVal);
|
||||
}
|
||||
assert( rc==SQLITE_OK );
|
||||
(void)rc; /* Suppress warning about unused variable */
|
||||
@@ -1034,9 +1037,11 @@ static int sessionTableInfo(
|
||||
const char *zDb, /* Name of attached database (e.g. "main") */
|
||||
const char *zThis, /* Table name */
|
||||
int *pnCol, /* OUT: number of columns */
|
||||
int *pnTotalCol, /* OUT: number of hidden columns */
|
||||
const char **pzTab, /* OUT: Copy of zThis */
|
||||
const char ***pazCol, /* OUT: Array of column names for table */
|
||||
const char ***pazDflt, /* OUT: Array of default value expressions */
|
||||
int **paiIdx, /* OUT: Array of xNew/xOld indexes */
|
||||
u8 **pabPK, /* OUT: Array of booleans - true for PK col */
|
||||
int *pbRowid /* OUT: True if only PK is a rowid */
|
||||
){
|
||||
@@ -1051,6 +1056,7 @@ static int sessionTableInfo(
|
||||
char **azCol = 0;
|
||||
char **azDflt = 0;
|
||||
u8 *abPK = 0;
|
||||
int *aiIdx = 0;
|
||||
int bRowid = 0; /* Set to true to use rowid as PK */
|
||||
|
||||
assert( pazCol && pabPK );
|
||||
@@ -1058,6 +1064,8 @@ static int sessionTableInfo(
|
||||
*pazCol = 0;
|
||||
*pabPK = 0;
|
||||
*pnCol = 0;
|
||||
if( pnTotalCol ) *pnTotalCol = 0;
|
||||
if( paiIdx ) *paiIdx = 0;
|
||||
if( pzTab ) *pzTab = 0;
|
||||
if( pazDflt ) *pazDflt = 0;
|
||||
|
||||
@@ -1067,9 +1075,9 @@ static int sessionTableInfo(
|
||||
if( rc==SQLITE_OK ){
|
||||
/* For sqlite_stat1, pretend that (tbl,idx) is the PRIMARY KEY. */
|
||||
zPragma = sqlite3_mprintf(
|
||||
"SELECT 0, 'tbl', '', 0, '', 1 UNION ALL "
|
||||
"SELECT 1, 'idx', '', 0, '', 2 UNION ALL "
|
||||
"SELECT 2, 'stat', '', 0, '', 0"
|
||||
"SELECT 0, 'tbl', '', 0, '', 1, 0 UNION ALL "
|
||||
"SELECT 1, 'idx', '', 0, '', 2, 0 UNION ALL "
|
||||
"SELECT 2, 'stat', '', 0, '', 0, 0"
|
||||
);
|
||||
}else if( rc==SQLITE_ERROR ){
|
||||
zPragma = sqlite3_mprintf("");
|
||||
@@ -1077,7 +1085,7 @@ static int sessionTableInfo(
|
||||
return rc;
|
||||
}
|
||||
}else{
|
||||
zPragma = sqlite3_mprintf("PRAGMA '%q'.table_info('%q')", zDb, zThis);
|
||||
zPragma = sqlite3_mprintf("PRAGMA '%q'.table_xinfo('%q')", zDb, zThis);
|
||||
}
|
||||
if( !zPragma ){
|
||||
return SQLITE_NOMEM;
|
||||
@@ -1094,7 +1102,9 @@ static int sessionTableInfo(
|
||||
while( SQLITE_ROW==sqlite3_step(pStmt) ){
|
||||
nByte += sqlite3_column_bytes(pStmt, 1); /* name */
|
||||
nByte += sqlite3_column_bytes(pStmt, 4); /* dflt_value */
|
||||
nDbCol++;
|
||||
if( sqlite3_column_int(pStmt, 6)==0 ){ /* !hidden */
|
||||
nDbCol++;
|
||||
}
|
||||
if( sqlite3_column_int(pStmt, 5) ) bRowid = 0; /* pk */
|
||||
}
|
||||
if( nDbCol==0 ) bRowid = 0;
|
||||
@@ -1103,7 +1113,7 @@ static int sessionTableInfo(
|
||||
rc = sqlite3_reset(pStmt);
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
nByte += nDbCol * (sizeof(const char *)*2 + sizeof(u8) + 1 + 1);
|
||||
nByte += nDbCol * (sizeof(const char *)*2 +sizeof(int)+sizeof(u8) + 1 + 1);
|
||||
pAlloc = sessionMalloc64(pSession, nByte);
|
||||
if( pAlloc==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
@@ -1114,8 +1124,8 @@ static int sessionTableInfo(
|
||||
if( rc==SQLITE_OK ){
|
||||
azCol = (char **)pAlloc;
|
||||
azDflt = (char**)&azCol[nDbCol];
|
||||
pAlloc = (u8 *)&azDflt[nDbCol];
|
||||
abPK = (u8 *)pAlloc;
|
||||
aiIdx = (int*)&azDflt[nDbCol];
|
||||
abPK = (u8 *)&aiIdx[nDbCol];
|
||||
pAlloc = &abPK[nDbCol];
|
||||
if( pzTab ){
|
||||
memcpy(pAlloc, zThis, nThis+1);
|
||||
@@ -1130,27 +1140,32 @@ static int sessionTableInfo(
|
||||
azCol[i] = (char*)pAlloc;
|
||||
pAlloc += nName+1;
|
||||
abPK[i] = 1;
|
||||
aiIdx[i] = -1;
|
||||
i++;
|
||||
}
|
||||
while( SQLITE_ROW==sqlite3_step(pStmt) ){
|
||||
int nName = sqlite3_column_bytes(pStmt, 1);
|
||||
int nDflt = sqlite3_column_bytes(pStmt, 4);
|
||||
const unsigned char *zName = sqlite3_column_text(pStmt, 1);
|
||||
const unsigned char *zDflt = sqlite3_column_text(pStmt, 4);
|
||||
if( sqlite3_column_int(pStmt, 6)==0 ){ /* !hidden */
|
||||
int nName = sqlite3_column_bytes(pStmt, 1);
|
||||
int nDflt = sqlite3_column_bytes(pStmt, 4);
|
||||
const unsigned char *zName = sqlite3_column_text(pStmt, 1);
|
||||
const unsigned char *zDflt = sqlite3_column_text(pStmt, 4);
|
||||
|
||||
if( zName==0 ) break;
|
||||
memcpy(pAlloc, zName, nName+1);
|
||||
azCol[i] = (char *)pAlloc;
|
||||
pAlloc += nName+1;
|
||||
if( zDflt ){
|
||||
memcpy(pAlloc, zDflt, nDflt+1);
|
||||
azDflt[i] = (char *)pAlloc;
|
||||
pAlloc += nDflt+1;
|
||||
}else{
|
||||
azDflt[i] = 0;
|
||||
if( zName==0 ) break;
|
||||
memcpy(pAlloc, zName, nName+1);
|
||||
azCol[i] = (char *)pAlloc;
|
||||
pAlloc += nName+1;
|
||||
if( zDflt ){
|
||||
memcpy(pAlloc, zDflt, nDflt+1);
|
||||
azDflt[i] = (char *)pAlloc;
|
||||
pAlloc += nDflt+1;
|
||||
}else{
|
||||
azDflt[i] = 0;
|
||||
}
|
||||
abPK[i] = sqlite3_column_int(pStmt, 5);
|
||||
aiIdx[i] = sqlite3_column_int(pStmt, 0);
|
||||
i++;
|
||||
}
|
||||
abPK[i] = sqlite3_column_int(pStmt, 5);
|
||||
i++;
|
||||
if( pnTotalCol ) (*pnTotalCol)++;
|
||||
}
|
||||
rc = sqlite3_reset(pStmt);
|
||||
}
|
||||
@@ -1163,6 +1178,7 @@ static int sessionTableInfo(
|
||||
if( pazDflt ) *pazDflt = (const char**)azDflt;
|
||||
*pabPK = abPK;
|
||||
*pnCol = nDbCol;
|
||||
if( paiIdx ) *paiIdx = aiIdx;
|
||||
}else{
|
||||
sessionFree(pSession, azCol);
|
||||
}
|
||||
@@ -1194,7 +1210,8 @@ static int sessionInitTable(
|
||||
u8 *abPK;
|
||||
assert( pTab->azCol==0 || pTab->abPK==0 );
|
||||
rc = sessionTableInfo(pSession, db, zDb,
|
||||
pTab->zName, &pTab->nCol, 0, &pTab->azCol, &pTab->azDflt, &abPK,
|
||||
pTab->zName, &pTab->nCol, &pTab->nTotalCol, 0, &pTab->azCol,
|
||||
&pTab->azDflt, &pTab->aiIdx, &abPK,
|
||||
((pSession==0 || pSession->bImplicitPK) ? &pTab->bRowid : 0)
|
||||
);
|
||||
if( rc==SQLITE_OK ){
|
||||
@@ -1229,15 +1246,17 @@ static int sessionInitTable(
|
||||
*/
|
||||
static int sessionReinitTable(sqlite3_session *pSession, SessionTable *pTab){
|
||||
int nCol = 0;
|
||||
int nTotalCol = 0;
|
||||
const char **azCol = 0;
|
||||
const char **azDflt = 0;
|
||||
int *aiIdx = 0;
|
||||
u8 *abPK = 0;
|
||||
int bRowid = 0;
|
||||
|
||||
assert( pSession->rc==SQLITE_OK );
|
||||
|
||||
pSession->rc = sessionTableInfo(pSession, pSession->db, pSession->zDb,
|
||||
pTab->zName, &nCol, 0, &azCol, &azDflt, &abPK,
|
||||
pTab->zName, &nCol, &nTotalCol, 0, &azCol, &azDflt, &aiIdx, &abPK,
|
||||
(pSession->bImplicitPK ? &bRowid : 0)
|
||||
);
|
||||
if( pSession->rc==SQLITE_OK ){
|
||||
@@ -1260,8 +1279,10 @@ static int sessionReinitTable(sqlite3_session *pSession, SessionTable *pTab){
|
||||
const char **a = pTab->azCol;
|
||||
pTab->azCol = azCol;
|
||||
pTab->nCol = nCol;
|
||||
pTab->nTotalCol = nTotalCol;
|
||||
pTab->azDflt = azDflt;
|
||||
pTab->abPK = abPK;
|
||||
pTab->aiIdx = aiIdx;
|
||||
azCol = a;
|
||||
}
|
||||
if( pSession->bEnableSize ){
|
||||
@@ -1579,7 +1600,7 @@ static int sessionUpdateMaxSize(
|
||||
int ii;
|
||||
for(ii=0; ii<pTab->nCol; ii++){
|
||||
sqlite3_value *p = 0;
|
||||
pSession->hook.xNew(pSession->hook.pCtx, ii, &p);
|
||||
pSession->hook.xNew(pSession->hook.pCtx, pTab->aiIdx[ii], &p);
|
||||
sessionSerializeValue(0, p, &nNew);
|
||||
}
|
||||
}
|
||||
@@ -1599,8 +1620,9 @@ static int sessionUpdateMaxSize(
|
||||
int bChanged = 1;
|
||||
int nOld = 0;
|
||||
int eType;
|
||||
int iIdx = pTab->aiIdx[ii];
|
||||
sqlite3_value *p = 0;
|
||||
pSession->hook.xNew(pSession->hook.pCtx, ii-pTab->bRowid, &p);
|
||||
pSession->hook.xNew(pSession->hook.pCtx, iIdx, &p);
|
||||
if( p==0 ){
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
@@ -1697,11 +1719,11 @@ static void sessionPreupdateOneChange(
|
||||
/* Check the number of columns in this xPreUpdate call matches the
|
||||
** number of columns in the table. */
|
||||
nExpect = pSession->hook.xCount(pSession->hook.pCtx);
|
||||
if( (pTab->nCol-pTab->bRowid)<nExpect ){
|
||||
if( pTab->nTotalCol<nExpect ){
|
||||
if( sessionReinitTable(pSession, pTab) ) return;
|
||||
if( sessionUpdateChanges(pSession, pTab) ) return;
|
||||
}
|
||||
if( (pTab->nCol-pTab->bRowid)!=nExpect ){
|
||||
if( pTab->nTotalCol!=nExpect ){
|
||||
pSession->rc = SQLITE_SCHEMA;
|
||||
return;
|
||||
}
|
||||
@@ -1758,14 +1780,15 @@ static void sessionPreupdateOneChange(
|
||||
|
||||
/* Figure out how large an allocation is required */
|
||||
nByte = sizeof(SessionChange);
|
||||
for(i=0; i<(pTab->nCol-pTab->bRowid); i++){
|
||||
for(i=pTab->bRowid; i<pTab->nCol; i++){
|
||||
int iIdx = pTab->aiIdx[i];
|
||||
sqlite3_value *p = 0;
|
||||
if( op!=SQLITE_INSERT ){
|
||||
/* This may fail if the column has a non-NULL default and was added
|
||||
** using ALTER TABLE ADD COLUMN after this record was created. */
|
||||
rc = pSession->hook.xOld(pSession->hook.pCtx, i, &p);
|
||||
rc = pSession->hook.xOld(pSession->hook.pCtx, iIdx, &p);
|
||||
}else if( pTab->abPK[i] ){
|
||||
TESTONLY(int trc = ) pSession->hook.xNew(pSession->hook.pCtx, i, &p);
|
||||
TESTONLY(int trc = ) pSession->hook.xNew(pSession->hook.pCtx,iIdx,&p);
|
||||
assert( trc==SQLITE_OK );
|
||||
}
|
||||
|
||||
@@ -1800,12 +1823,13 @@ static void sessionPreupdateOneChange(
|
||||
sessionPutI64(&pC->aRecord[1], iRowid);
|
||||
nByte = 9;
|
||||
}
|
||||
for(i=0; i<(pTab->nCol-pTab->bRowid); i++){
|
||||
for(i=pTab->bRowid; i<pTab->nCol; i++){
|
||||
sqlite3_value *p = 0;
|
||||
int iIdx = pTab->aiIdx[i];
|
||||
if( op!=SQLITE_INSERT ){
|
||||
pSession->hook.xOld(pSession->hook.pCtx, i, &p);
|
||||
pSession->hook.xOld(pSession->hook.pCtx, iIdx, &p);
|
||||
}else if( pTab->abPK[i] ){
|
||||
pSession->hook.xNew(pSession->hook.pCtx, i, &p);
|
||||
pSession->hook.xNew(pSession->hook.pCtx, iIdx, &p);
|
||||
}
|
||||
sessionSerializeValue(&pC->aRecord[nByte], p, &nByte);
|
||||
}
|
||||
@@ -2207,7 +2231,8 @@ int sqlite3session_diff(
|
||||
int bRowid = 0;
|
||||
u8 *abPK;
|
||||
const char **azCol = 0;
|
||||
rc = sessionTableInfo(0, db, zFrom, zTbl, &nCol, 0, &azCol, 0, &abPK,
|
||||
rc = sessionTableInfo(0, db, zFrom, zTbl,
|
||||
&nCol, 0, 0, &azCol, 0, 0, &abPK,
|
||||
pSession->bImplicitPK ? &bRowid : 0
|
||||
);
|
||||
if( rc==SQLITE_OK ){
|
||||
@@ -2531,9 +2556,11 @@ static void sessionAppendIdent(
|
||||
char *zOut = (char *)&p->aBuf[p->nBuf];
|
||||
const char *zIn = zStr;
|
||||
*zOut++ = '"';
|
||||
while( *zIn ){
|
||||
if( *zIn=='"' ) *zOut++ = '"';
|
||||
*zOut++ = *(zIn++);
|
||||
if( zIn!=0 ){
|
||||
while( *zIn ){
|
||||
if( *zIn=='"' ) *zOut++ = '"';
|
||||
*zOut++ = *(zIn++);
|
||||
}
|
||||
}
|
||||
*zOut++ = '"';
|
||||
p->nBuf = (int)((u8 *)zOut - p->aBuf);
|
||||
@@ -2784,10 +2811,10 @@ static int sessionSelectStmt(
|
||||
int rc = SQLITE_OK;
|
||||
char *zSql = 0;
|
||||
const char *zSep = "";
|
||||
const char *zCols = bRowid ? SESSIONS_ROWID ", *" : "*";
|
||||
int nSql = -1;
|
||||
int i;
|
||||
|
||||
SessionBuffer cols = {0, 0, 0};
|
||||
SessionBuffer nooptest = {0, 0, 0};
|
||||
SessionBuffer pkfield = {0, 0, 0};
|
||||
SessionBuffer pkvar = {0, 0, 0};
|
||||
@@ -2800,9 +2827,16 @@ static int sessionSelectStmt(
|
||||
sessionAppendStr(&pkvar,
|
||||
"?1, (CASE WHEN ?2=X'' THEN NULL ELSE ?2 END)", &rc
|
||||
);
|
||||
zCols = "tbl, ?2, stat";
|
||||
sessionAppendStr(&cols, "tbl, ?2, stat", &rc);
|
||||
}else{
|
||||
#if 0
|
||||
if( bRowid ){
|
||||
sessionAppendStr(&cols, SESSIONS_ROWID, &rc);
|
||||
}
|
||||
#endif
|
||||
for(i=0; i<nCol; i++){
|
||||
if( cols.nBuf ) sessionAppendStr(&cols, ", ", &rc);
|
||||
sessionAppendIdent(&cols, azCol[i], &rc);
|
||||
if( abPK[i] ){
|
||||
sessionAppendStr(&pkfield, zSep, &rc);
|
||||
sessionAppendStr(&pkvar, zSep, &rc);
|
||||
@@ -2820,7 +2854,7 @@ static int sessionSelectStmt(
|
||||
if( rc==SQLITE_OK ){
|
||||
zSql = sqlite3_mprintf(
|
||||
"SELECT %s%s FROM %Q.%Q WHERE (%s) IS (%s)",
|
||||
zCols, (bIgnoreNoop ? (char*)nooptest.aBuf : ""),
|
||||
(char*)cols.aBuf, (bIgnoreNoop ? (char*)nooptest.aBuf : ""),
|
||||
zDb, zTab, (char*)pkfield.aBuf, (char*)pkvar.aBuf
|
||||
);
|
||||
if( zSql==0 ) rc = SQLITE_NOMEM;
|
||||
@@ -2863,6 +2897,7 @@ static int sessionSelectStmt(
|
||||
sqlite3_free(nooptest.aBuf);
|
||||
sqlite3_free(pkfield.aBuf);
|
||||
sqlite3_free(pkvar.aBuf);
|
||||
sqlite3_free(cols.aBuf);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -5203,7 +5238,8 @@ static int sessionChangesetApply(
|
||||
|
||||
sqlite3changeset_pk(pIter, &abPK, 0);
|
||||
rc = sessionTableInfo(0, db, "main", zNew,
|
||||
&sApply.nCol, &zTab, &sApply.azCol, 0, &sApply.abPK, &sApply.bRowid
|
||||
&sApply.nCol, 0, &zTab, &sApply.azCol, 0, 0,
|
||||
&sApply.abPK, &sApply.bRowid
|
||||
);
|
||||
if( rc!=SQLITE_OK ) break;
|
||||
for(i=0; i<sApply.nCol; i++){
|
||||
@@ -5283,12 +5319,17 @@ static int sessionChangesetApply(
|
||||
}
|
||||
}
|
||||
}
|
||||
sqlite3_exec(db, "PRAGMA defer_foreign_keys = 0", 0, 0, 0);
|
||||
|
||||
{
|
||||
int rc2 = sqlite3_exec(db, "PRAGMA defer_foreign_keys = 0", 0, 0, 0);
|
||||
if( rc==SQLITE_OK ) rc = rc2;
|
||||
}
|
||||
|
||||
if( (flags & SQLITE_CHANGESETAPPLY_NOSAVEPOINT)==0 ){
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3_exec(db, "RELEASE changeset_apply", 0, 0, 0);
|
||||
}else{
|
||||
}
|
||||
if( rc!=SQLITE_OK ){
|
||||
sqlite3_exec(db, "ROLLBACK TO changeset_apply", 0, 0, 0);
|
||||
sqlite3_exec(db, "RELEASE changeset_apply", 0, 0, 0);
|
||||
}
|
||||
|
||||
@@ -719,7 +719,6 @@ static int replace_handler(
|
||||
const char *zTab; /* Name of table conflict is on */
|
||||
int nCol; /* Number of columns in table zTab */
|
||||
int i;
|
||||
int x = 0;
|
||||
|
||||
sqlite3changeset_op(pIter, &zTab, &nCol, &op, 0);
|
||||
|
||||
@@ -728,7 +727,6 @@ static int replace_handler(
|
||||
sqlite3_value *pVal;
|
||||
sqlite3changeset_old(pIter, i, &pVal);
|
||||
sqlite3_value_text16(pVal);
|
||||
x++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -737,7 +735,6 @@ static int replace_handler(
|
||||
sqlite3_value *pVal;
|
||||
sqlite3changeset_new(pIter, i, &pVal);
|
||||
sqlite3_value_text16(pVal);
|
||||
x++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,96 +0,0 @@
|
||||
/*
|
||||
** 2014-09-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 the application interface definitions for the
|
||||
** user-authentication extension feature.
|
||||
**
|
||||
** To compile with the user-authentication feature, append this file to
|
||||
** end of an SQLite amalgamation header file ("sqlite3.h"), then add
|
||||
** the SQLITE_USER_AUTHENTICATION compile-time option. See the
|
||||
** user-auth.txt file in the same source directory as this file for
|
||||
** additional information.
|
||||
*/
|
||||
#ifdef SQLITE_USER_AUTHENTICATION
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
** If a database contains the SQLITE_USER table, then the
|
||||
** sqlite3_user_authenticate() interface must be invoked with an
|
||||
** appropriate username and password prior to enable read and write
|
||||
** access to the database.
|
||||
**
|
||||
** Return SQLITE_OK on success or SQLITE_ERROR if the username/password
|
||||
** combination is incorrect or unknown.
|
||||
**
|
||||
** If the SQLITE_USER table is not present in the database file, then
|
||||
** this interface is a harmless no-op returnning SQLITE_OK.
|
||||
*/
|
||||
int sqlite3_user_authenticate(
|
||||
sqlite3 *db, /* The database connection */
|
||||
const char *zUsername, /* Username */
|
||||
const char *aPW, /* Password or credentials */
|
||||
int nPW /* Number of bytes in aPW[] */
|
||||
);
|
||||
|
||||
/*
|
||||
** The sqlite3_user_add() interface can be used (by an admin user only)
|
||||
** to create a new user. When called on a no-authentication-required
|
||||
** database, this routine converts the database into an authentication-
|
||||
** required database, automatically makes the added user an
|
||||
** administrator, and logs in the current connection as that user.
|
||||
** The sqlite3_user_add() interface only works for the "main" database, not
|
||||
** for any ATTACH-ed databases. Any call to sqlite3_user_add() by a
|
||||
** non-admin user results in an error.
|
||||
*/
|
||||
int sqlite3_user_add(
|
||||
sqlite3 *db, /* Database connection */
|
||||
const char *zUsername, /* Username to be added */
|
||||
const char *aPW, /* Password or credentials */
|
||||
int nPW, /* Number of bytes in aPW[] */
|
||||
int isAdmin /* True to give new user admin privilege */
|
||||
);
|
||||
|
||||
/*
|
||||
** The sqlite3_user_change() interface can be used to change a users
|
||||
** login credentials or admin privilege. Any user can change their own
|
||||
** login credentials. Only an admin user can change another users login
|
||||
** credentials or admin privilege setting. No user may change their own
|
||||
** admin privilege setting.
|
||||
*/
|
||||
int sqlite3_user_change(
|
||||
sqlite3 *db, /* Database connection */
|
||||
const char *zUsername, /* Username to change */
|
||||
const char *aPW, /* New password or credentials */
|
||||
int nPW, /* Number of bytes in aPW[] */
|
||||
int isAdmin /* Modified admin privilege for the user */
|
||||
);
|
||||
|
||||
/*
|
||||
** The sqlite3_user_delete() interface can be used (by an admin user only)
|
||||
** to delete a user. The currently logged-in user cannot be deleted,
|
||||
** which guarantees that there is always an admin user and hence that
|
||||
** the database cannot be converted into a no-authentication-required
|
||||
** database.
|
||||
*/
|
||||
int sqlite3_user_delete(
|
||||
sqlite3 *db, /* Database connection */
|
||||
const char *zUsername /* Username to remove */
|
||||
);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end of the 'extern "C"' block */
|
||||
#endif
|
||||
|
||||
#endif /* SQLITE_USER_AUTHENTICATION */
|
||||
@@ -1,176 +0,0 @@
|
||||
*********************************** NOTICE ************************************
|
||||
* This extension is deprecated. The SQLite developers do not maintain this *
|
||||
* extension. At some point in the future, it might disappear from the source *
|
||||
* tree. *
|
||||
* *
|
||||
* If you are using this extension and think it should be supported moving *
|
||||
* forward, visit the SQLite Forum (https://sqlite.org/forum) and argue your *
|
||||
* case there. *
|
||||
* *
|
||||
* This deprecation notice was added on 2024-01-22. *
|
||||
*******************************************************************************
|
||||
|
||||
Activate the user authentication logic by including the
|
||||
ext/userauth/userauth.c source code file in the build and
|
||||
adding the -DSQLITE_USER_AUTHENTICATION compile-time option.
|
||||
The ext/userauth/sqlite3userauth.h header file is available to
|
||||
applications to define the interface.
|
||||
|
||||
When using the SQLite amalgamation, it is sufficient to append
|
||||
the ext/userauth/userauth.c source file onto the end of the
|
||||
amalgamation.
|
||||
|
||||
The following new APIs are available when user authentication is
|
||||
activated:
|
||||
|
||||
int sqlite3_user_authenticate(
|
||||
sqlite3 *db, /* The database connection */
|
||||
const char *zUsername, /* Username */
|
||||
const char *aPW, /* Password or credentials */
|
||||
int nPW /* Number of bytes in aPW[] */
|
||||
);
|
||||
|
||||
int sqlite3_user_add(
|
||||
sqlite3 *db, /* Database connection */
|
||||
const char *zUsername, /* Username to be added */
|
||||
const char *aPW, /* Password or credentials */
|
||||
int nPW, /* Number of bytes in aPW[] */
|
||||
int isAdmin /* True to give new user admin privilege */
|
||||
);
|
||||
|
||||
int sqlite3_user_change(
|
||||
sqlite3 *db, /* Database connection */
|
||||
const char *zUsername, /* Username to change */
|
||||
const void *aPW, /* Modified password or credentials */
|
||||
int nPW, /* Number of bytes in aPW[] */
|
||||
int isAdmin /* Modified admin privilege for the user */
|
||||
);
|
||||
|
||||
int sqlite3_user_delete(
|
||||
sqlite3 *db, /* Database connection */
|
||||
const char *zUsername /* Username to remove */
|
||||
);
|
||||
|
||||
With this extension, a database can be marked as requiring authentication.
|
||||
By default a database does not require authentication.
|
||||
|
||||
The sqlite3_open(), sqlite3_open16(), and sqlite3_open_v2() interfaces
|
||||
work as before: they open a new database connection. However, if the
|
||||
database being opened requires authentication, then attempts to read
|
||||
or write from the database will fail with an SQLITE_AUTH error until
|
||||
after sqlite3_user_authenticate() has been called successfully. The
|
||||
sqlite3_user_authenticate() call will return SQLITE_OK if the
|
||||
authentication credentials are accepted and SQLITE_ERROR if not.
|
||||
|
||||
Calling sqlite3_user_authenticate() on a no-authentication-required
|
||||
database connection is a harmless no-op.
|
||||
|
||||
If the database is encrypted, then sqlite3_key_v2() must be called first,
|
||||
with the correct decryption key, prior to invoking sqlite3_user_authenticate().
|
||||
|
||||
To recapitulate: When opening an existing unencrypted authentication-
|
||||
required database, the call sequence is:
|
||||
|
||||
sqlite3_open_v2()
|
||||
sqlite3_user_authenticate();
|
||||
/* Database is now usable */
|
||||
|
||||
To open an existing, encrypted, authentication-required database, the
|
||||
call sequence is:
|
||||
|
||||
sqlite3_open_v2();
|
||||
sqlite3_key_v2();
|
||||
sqlite3_user_authenticate();
|
||||
/* Database is now usable */
|
||||
|
||||
When opening a no-authentication-required database, the database
|
||||
connection is treated as if it was authenticated as an admin user.
|
||||
|
||||
When ATTACH-ing new database files to a connection, each newly attached
|
||||
database that is an authentication-required database is checked using
|
||||
the same username and password as supplied to the main database. If that
|
||||
check fails, then the ATTACH command fails with an SQLITE_AUTH error.
|
||||
|
||||
The sqlite3_user_add() interface can be used (by an admin user only)
|
||||
to create a new user. When called on a no-authentication-required
|
||||
database and when A is true, the sqlite3_user_add(D,U,P,N,A) routine
|
||||
converts the database into an authentication-required database and
|
||||
logs in the database connection D as user U with password P,N.
|
||||
To convert a no-authentication-required database into an authentication-
|
||||
required database, the isAdmin parameter must be true. If
|
||||
sqlite3_user_add(D,U,P,N,A) is called on a no-authentication-required
|
||||
database and A is false, then the call fails with an SQLITE_AUTH error.
|
||||
|
||||
Any call to sqlite3_user_add() by a non-admin user results in an error.
|
||||
|
||||
Hence, to create a new, unencrypted, authentication-required database,
|
||||
the call sequence is:
|
||||
|
||||
sqlite3_open_v2();
|
||||
sqlite3_user_add();
|
||||
|
||||
And to create a new, encrypted, authentication-required database, the call
|
||||
sequence is:
|
||||
|
||||
sqlite3_open_v2();
|
||||
sqlite3_key_v2();
|
||||
sqlite3_user_add();
|
||||
|
||||
The sqlite3_user_delete() interface can be used (by an admin user only)
|
||||
to delete a user. The currently logged-in user cannot be deleted,
|
||||
which guarantees that there is always an admin user and hence that
|
||||
the database cannot be converted into a no-authentication-required
|
||||
database.
|
||||
|
||||
The sqlite3_user_change() interface can be used to change a users
|
||||
login credentials or admin privilege. Any user can change their own
|
||||
password. Only an admin user can change another users login
|
||||
credentials or admin privilege setting. No user may change their own
|
||||
admin privilege setting.
|
||||
|
||||
The sqlite3_set_authorizer() callback is modified to take a 7th parameter
|
||||
which is the username of the currently logged in user, or NULL for a
|
||||
no-authentication-required database.
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
Implementation notes:
|
||||
|
||||
An authentication-required database is identified by the presence of a
|
||||
new table:
|
||||
|
||||
CREATE TABLE sqlite_user(
|
||||
uname TEXT PRIMARY KEY,
|
||||
isAdmin BOOLEAN,
|
||||
pw BLOB
|
||||
) WITHOUT ROWID;
|
||||
|
||||
The sqlite_user table is inaccessible (unreadable and unwriteable) to
|
||||
non-admin users and is read-only for admin users. However, if the same
|
||||
database file is opened by a version of SQLite that omits
|
||||
the -DSQLITE_USER_AUTHENTICATION compile-time option, then the sqlite_user
|
||||
table will be readable by anybody and writeable by anybody if
|
||||
the "PRAGMA writable_schema=ON" statement is run first.
|
||||
|
||||
The sqlite_user.pw field is encoded by a built-in SQL function
|
||||
"sqlite_crypt(X,Y)". The two arguments are both BLOBs. The first argument
|
||||
is the plaintext password supplied to the sqlite3_user_authenticate()
|
||||
interface. The second argument is the sqlite_user.pw value and is supplied
|
||||
so that the function can extract the "salt" used by the password encoder.
|
||||
The result of sqlite_crypt(X,Y) is another blob which is the value that
|
||||
ends up being stored in sqlite_user.pw. To verify credentials X supplied
|
||||
by the sqlite3_user_authenticate() routine, SQLite runs:
|
||||
|
||||
sqlite_user.pw == sqlite_crypt(X, sqlite_user.pw)
|
||||
|
||||
To compute an appropriate sqlite_user.pw value from a new or modified
|
||||
password X, sqlite_crypt(X,NULL) is run. A new random salt is selected
|
||||
when the second argument is NULL.
|
||||
|
||||
The built-in version of of sqlite_crypt() uses a simple Ceasar-cypher
|
||||
which prevents passwords from being revealed by searching the raw database
|
||||
for ASCII text, but is otherwise trivally broken. For better password
|
||||
security, the database should be encrypted using the SQLite Encryption
|
||||
Extension or similar technology. Or, the application can use the
|
||||
sqlite3_create_function() interface to provide an alternative
|
||||
implementation of sqlite_crypt() that computes a stronger password hash,
|
||||
perhaps using a cryptographic hash function like SHA1.
|
||||
@@ -1,355 +0,0 @@
|
||||
/*
|
||||
** 2014-09-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 the bulk of the implementation of the
|
||||
** user-authentication extension feature. Some parts of the user-
|
||||
** authentication code are contained within the SQLite core (in the
|
||||
** src/ subdirectory of the main source code tree) but those parts
|
||||
** that could reasonable be separated out are moved into this file.
|
||||
**
|
||||
** To compile with the user-authentication feature, append this file to
|
||||
** end of an SQLite amalgamation, then add the SQLITE_USER_AUTHENTICATION
|
||||
** compile-time option. See the user-auth.txt file in the same source
|
||||
** directory as this file for additional information.
|
||||
*/
|
||||
#ifdef SQLITE_USER_AUTHENTICATION
|
||||
#ifndef SQLITEINT_H
|
||||
# include "sqliteInt.h"
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Prepare an SQL statement for use by the user authentication logic.
|
||||
** Return a pointer to the prepared statement on success. Return a
|
||||
** NULL pointer if there is an error of any kind.
|
||||
*/
|
||||
static sqlite3_stmt *sqlite3UserAuthPrepare(
|
||||
sqlite3 *db,
|
||||
const char *zFormat,
|
||||
...
|
||||
){
|
||||
sqlite3_stmt *pStmt;
|
||||
char *zSql;
|
||||
int rc;
|
||||
va_list ap;
|
||||
u64 savedFlags = db->flags;
|
||||
|
||||
va_start(ap, zFormat);
|
||||
zSql = sqlite3_vmprintf(zFormat, ap);
|
||||
va_end(ap);
|
||||
if( zSql==0 ) return 0;
|
||||
db->flags |= SQLITE_WriteSchema;
|
||||
rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
|
||||
db->flags = savedFlags;
|
||||
sqlite3_free(zSql);
|
||||
if( rc ){
|
||||
sqlite3_finalize(pStmt);
|
||||
pStmt = 0;
|
||||
}
|
||||
return pStmt;
|
||||
}
|
||||
|
||||
/*
|
||||
** Check to see if the sqlite_user table exists in database zDb.
|
||||
*/
|
||||
static int userTableExists(sqlite3 *db, const char *zDb){
|
||||
int rc;
|
||||
sqlite3_mutex_enter(db->mutex);
|
||||
sqlite3BtreeEnterAll(db);
|
||||
if( db->init.busy==0 ){
|
||||
char *zErr = 0;
|
||||
sqlite3Init(db, &zErr);
|
||||
sqlite3DbFree(db, zErr);
|
||||
}
|
||||
rc = sqlite3FindTable(db, "sqlite_user", zDb)!=0;
|
||||
sqlite3BtreeLeaveAll(db);
|
||||
sqlite3_mutex_leave(db->mutex);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Check to see if database zDb has a "sqlite_user" table and if it does
|
||||
** whether that table can authenticate zUser with nPw,zPw. Write one of
|
||||
** the UAUTH_* user authorization level codes into *peAuth and return a
|
||||
** result code.
|
||||
*/
|
||||
static int userAuthCheckLogin(
|
||||
sqlite3 *db, /* The database connection to check */
|
||||
const char *zDb, /* Name of specific database to check */
|
||||
u8 *peAuth /* OUT: One of UAUTH_* constants */
|
||||
){
|
||||
sqlite3_stmt *pStmt;
|
||||
int rc;
|
||||
|
||||
*peAuth = UAUTH_Unknown;
|
||||
if( !userTableExists(db, "main") ){
|
||||
*peAuth = UAUTH_Admin; /* No sqlite_user table. Everybody is admin. */
|
||||
return SQLITE_OK;
|
||||
}
|
||||
if( db->auth.zAuthUser==0 ){
|
||||
*peAuth = UAUTH_Fail;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
pStmt = sqlite3UserAuthPrepare(db,
|
||||
"SELECT pw=sqlite_crypt(?1,pw), isAdmin FROM \"%w\".sqlite_user"
|
||||
" WHERE uname=?2", zDb);
|
||||
if( pStmt==0 ) return SQLITE_NOMEM;
|
||||
sqlite3_bind_blob(pStmt, 1, db->auth.zAuthPW, db->auth.nAuthPW,SQLITE_STATIC);
|
||||
sqlite3_bind_text(pStmt, 2, db->auth.zAuthUser, -1, SQLITE_STATIC);
|
||||
rc = sqlite3_step(pStmt);
|
||||
if( rc==SQLITE_ROW && sqlite3_column_int(pStmt,0) ){
|
||||
*peAuth = sqlite3_column_int(pStmt, 1) + UAUTH_User;
|
||||
}else{
|
||||
*peAuth = UAUTH_Fail;
|
||||
}
|
||||
return sqlite3_finalize(pStmt);
|
||||
}
|
||||
int sqlite3UserAuthCheckLogin(
|
||||
sqlite3 *db, /* The database connection to check */
|
||||
const char *zDb, /* Name of specific database to check */
|
||||
u8 *peAuth /* OUT: One of UAUTH_* constants */
|
||||
){
|
||||
int rc;
|
||||
u8 savedAuthLevel;
|
||||
assert( zDb!=0 );
|
||||
assert( peAuth!=0 );
|
||||
savedAuthLevel = db->auth.authLevel;
|
||||
db->auth.authLevel = UAUTH_Admin;
|
||||
rc = userAuthCheckLogin(db, zDb, peAuth);
|
||||
db->auth.authLevel = savedAuthLevel;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** If the current authLevel is UAUTH_Unknown, the take actions to figure
|
||||
** out what authLevel should be
|
||||
*/
|
||||
void sqlite3UserAuthInit(sqlite3 *db){
|
||||
if( db->auth.authLevel==UAUTH_Unknown ){
|
||||
u8 authLevel = UAUTH_Fail;
|
||||
sqlite3UserAuthCheckLogin(db, "main", &authLevel);
|
||||
db->auth.authLevel = authLevel;
|
||||
if( authLevel<UAUTH_Admin ) db->flags &= ~SQLITE_WriteSchema;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Implementation of the sqlite_crypt(X,Y) function.
|
||||
**
|
||||
** If Y is NULL then generate a new hash for password X and return that
|
||||
** hash. If Y is not null, then generate a hash for password X using the
|
||||
** same salt as the previous hash Y and return the new hash.
|
||||
*/
|
||||
void sqlite3CryptFunc(
|
||||
sqlite3_context *context,
|
||||
int NotUsed,
|
||||
sqlite3_value **argv
|
||||
){
|
||||
const char *zIn;
|
||||
int nIn, ii;
|
||||
u8 *zOut;
|
||||
char zSalt[8];
|
||||
zIn = sqlite3_value_blob(argv[0]);
|
||||
nIn = sqlite3_value_bytes(argv[0]);
|
||||
if( sqlite3_value_type(argv[1])==SQLITE_BLOB
|
||||
&& sqlite3_value_bytes(argv[1])==nIn+sizeof(zSalt)
|
||||
){
|
||||
memcpy(zSalt, sqlite3_value_blob(argv[1]), sizeof(zSalt));
|
||||
}else{
|
||||
sqlite3_randomness(sizeof(zSalt), zSalt);
|
||||
}
|
||||
zOut = sqlite3_malloc( nIn+sizeof(zSalt) );
|
||||
if( zOut==0 ){
|
||||
sqlite3_result_error_nomem(context);
|
||||
}else{
|
||||
memcpy(zOut, zSalt, sizeof(zSalt));
|
||||
for(ii=0; ii<nIn; ii++){
|
||||
zOut[ii+sizeof(zSalt)] = zIn[ii]^zSalt[ii&0x7];
|
||||
}
|
||||
sqlite3_result_blob(context, zOut, nIn+sizeof(zSalt), sqlite3_free);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** If a database contains the SQLITE_USER table, then the
|
||||
** sqlite3_user_authenticate() interface must be invoked with an
|
||||
** appropriate username and password prior to enable read and write
|
||||
** access to the database.
|
||||
**
|
||||
** Return SQLITE_OK on success or SQLITE_ERROR if the username/password
|
||||
** combination is incorrect or unknown.
|
||||
**
|
||||
** If the SQLITE_USER table is not present in the database file, then
|
||||
** this interface is a harmless no-op returnning SQLITE_OK.
|
||||
*/
|
||||
int sqlite3_user_authenticate(
|
||||
sqlite3 *db, /* The database connection */
|
||||
const char *zUsername, /* Username */
|
||||
const char *zPW, /* Password or credentials */
|
||||
int nPW /* Number of bytes in aPW[] */
|
||||
){
|
||||
int rc;
|
||||
u8 authLevel = UAUTH_Fail;
|
||||
db->auth.authLevel = UAUTH_Unknown;
|
||||
sqlite3_free(db->auth.zAuthUser);
|
||||
sqlite3_free(db->auth.zAuthPW);
|
||||
memset(&db->auth, 0, sizeof(db->auth));
|
||||
db->auth.zAuthUser = sqlite3_mprintf("%s", zUsername);
|
||||
if( db->auth.zAuthUser==0 ) return SQLITE_NOMEM;
|
||||
db->auth.zAuthPW = sqlite3_malloc( nPW+1 );
|
||||
if( db->auth.zAuthPW==0 ) return SQLITE_NOMEM;
|
||||
memcpy(db->auth.zAuthPW,zPW,nPW);
|
||||
db->auth.nAuthPW = nPW;
|
||||
rc = sqlite3UserAuthCheckLogin(db, "main", &authLevel);
|
||||
db->auth.authLevel = authLevel;
|
||||
sqlite3ExpirePreparedStatements(db, 0);
|
||||
if( rc ){
|
||||
return rc; /* OOM error, I/O error, etc. */
|
||||
}
|
||||
if( authLevel<UAUTH_User ){
|
||||
return SQLITE_AUTH; /* Incorrect username and/or password */
|
||||
}
|
||||
return SQLITE_OK; /* Successful login */
|
||||
}
|
||||
|
||||
/*
|
||||
** The sqlite3_user_add() interface can be used (by an admin user only)
|
||||
** to create a new user. When called on a no-authentication-required
|
||||
** database, this routine converts the database into an authentication-
|
||||
** required database, automatically makes the added user an
|
||||
** administrator, and logs in the current connection as that user.
|
||||
** The sqlite3_user_add() interface only works for the "main" database, not
|
||||
** for any ATTACH-ed databases. Any call to sqlite3_user_add() by a
|
||||
** non-admin user results in an error.
|
||||
*/
|
||||
int sqlite3_user_add(
|
||||
sqlite3 *db, /* Database connection */
|
||||
const char *zUsername, /* Username to be added */
|
||||
const char *aPW, /* Password or credentials */
|
||||
int nPW, /* Number of bytes in aPW[] */
|
||||
int isAdmin /* True to give new user admin privilege */
|
||||
){
|
||||
sqlite3_stmt *pStmt;
|
||||
int rc;
|
||||
sqlite3UserAuthInit(db);
|
||||
if( db->auth.authLevel<UAUTH_Admin ) return SQLITE_AUTH;
|
||||
if( !userTableExists(db, "main") ){
|
||||
if( !isAdmin ) return SQLITE_AUTH;
|
||||
pStmt = sqlite3UserAuthPrepare(db,
|
||||
"CREATE TABLE sqlite_user(\n"
|
||||
" uname TEXT PRIMARY KEY,\n"
|
||||
" isAdmin BOOLEAN,\n"
|
||||
" pw BLOB\n"
|
||||
") WITHOUT ROWID;");
|
||||
if( pStmt==0 ) return SQLITE_NOMEM;
|
||||
sqlite3_step(pStmt);
|
||||
rc = sqlite3_finalize(pStmt);
|
||||
if( rc ) return rc;
|
||||
}
|
||||
pStmt = sqlite3UserAuthPrepare(db,
|
||||
"INSERT INTO sqlite_user(uname,isAdmin,pw)"
|
||||
" VALUES(%Q,%d,sqlite_crypt(?1,NULL))",
|
||||
zUsername, isAdmin!=0);
|
||||
if( pStmt==0 ) return SQLITE_NOMEM;
|
||||
sqlite3_bind_blob(pStmt, 1, aPW, nPW, SQLITE_STATIC);
|
||||
sqlite3_step(pStmt);
|
||||
rc = sqlite3_finalize(pStmt);
|
||||
if( rc ) return rc;
|
||||
if( db->auth.zAuthUser==0 ){
|
||||
assert( isAdmin!=0 );
|
||||
sqlite3_user_authenticate(db, zUsername, aPW, nPW);
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** The sqlite3_user_change() interface can be used to change a users
|
||||
** login credentials or admin privilege. Any user can change their own
|
||||
** login credentials. Only an admin user can change another users login
|
||||
** credentials or admin privilege setting. No user may change their own
|
||||
** admin privilege setting.
|
||||
*/
|
||||
int sqlite3_user_change(
|
||||
sqlite3 *db, /* Database connection */
|
||||
const char *zUsername, /* Username to change */
|
||||
const char *aPW, /* Modified password or credentials */
|
||||
int nPW, /* Number of bytes in aPW[] */
|
||||
int isAdmin /* Modified admin privilege for the user */
|
||||
){
|
||||
sqlite3_stmt *pStmt;
|
||||
int rc;
|
||||
u8 authLevel;
|
||||
|
||||
authLevel = db->auth.authLevel;
|
||||
if( authLevel<UAUTH_User ){
|
||||
/* Must be logged in to make a change */
|
||||
return SQLITE_AUTH;
|
||||
}
|
||||
if( strcmp(db->auth.zAuthUser, zUsername)!=0 ){
|
||||
if( db->auth.authLevel<UAUTH_Admin ){
|
||||
/* Must be an administrator to change a different user */
|
||||
return SQLITE_AUTH;
|
||||
}
|
||||
}else if( isAdmin!=(authLevel==UAUTH_Admin) ){
|
||||
/* Cannot change the isAdmin setting for self */
|
||||
return SQLITE_AUTH;
|
||||
}
|
||||
db->auth.authLevel = UAUTH_Admin;
|
||||
if( !userTableExists(db, "main") ){
|
||||
/* This routine is a no-op if the user to be modified does not exist */
|
||||
}else{
|
||||
pStmt = sqlite3UserAuthPrepare(db,
|
||||
"UPDATE sqlite_user SET isAdmin=%d, pw=sqlite_crypt(?1,NULL)"
|
||||
" WHERE uname=%Q", isAdmin, zUsername);
|
||||
if( pStmt==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
sqlite3_bind_blob(pStmt, 1, aPW, nPW, SQLITE_STATIC);
|
||||
sqlite3_step(pStmt);
|
||||
rc = sqlite3_finalize(pStmt);
|
||||
}
|
||||
}
|
||||
db->auth.authLevel = authLevel;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** The sqlite3_user_delete() interface can be used (by an admin user only)
|
||||
** to delete a user. The currently logged-in user cannot be deleted,
|
||||
** which guarantees that there is always an admin user and hence that
|
||||
** the database cannot be converted into a no-authentication-required
|
||||
** database.
|
||||
*/
|
||||
int sqlite3_user_delete(
|
||||
sqlite3 *db, /* Database connection */
|
||||
const char *zUsername /* Username to remove */
|
||||
){
|
||||
sqlite3_stmt *pStmt;
|
||||
if( db->auth.authLevel<UAUTH_Admin ){
|
||||
/* Must be an administrator to delete a user */
|
||||
return SQLITE_AUTH;
|
||||
}
|
||||
if( strcmp(db->auth.zAuthUser, zUsername)==0 ){
|
||||
/* Cannot delete self */
|
||||
return SQLITE_AUTH;
|
||||
}
|
||||
if( !userTableExists(db, "main") ){
|
||||
/* This routine is a no-op if the user to be deleted does not exist */
|
||||
return SQLITE_OK;
|
||||
}
|
||||
pStmt = sqlite3UserAuthPrepare(db,
|
||||
"DELETE FROM sqlite_user WHERE uname=%Q", zUsername);
|
||||
if( pStmt==0 ) return SQLITE_NOMEM;
|
||||
sqlite3_step(pStmt);
|
||||
return sqlite3_finalize(pStmt);
|
||||
}
|
||||
|
||||
#endif /* SQLITE_USER_AUTHENTICATION */
|
||||
+130
-118
@@ -32,19 +32,16 @@
|
||||
#
|
||||
# - Emscripten SDK: https://emscripten.org/docs/getting_started/downloads.html
|
||||
# - The bash shell
|
||||
# - GNU make, GNU sed, GNU awk, GNU grep (all in the $PATH)
|
||||
# - GNU make, GNU sed, GNU awk, GNU grep (all in the $PATH and without
|
||||
# a "g" prefix like they have on some non-GNU systems)
|
||||
# - wasm-strip for release builds: https://github.com/WebAssembly/wabt
|
||||
# - InfoZip for 'dist' zip file
|
||||
########################################################################
|
||||
default: all
|
||||
#default: quick
|
||||
SHELL := $(firstword $(shell which bash) $(wildcard /usr/local/bin/bash /usr/bin/bash /bin/bash))
|
||||
ifeq (,$(SHELL))
|
||||
$(error Cannot find the bash shell)
|
||||
endif
|
||||
MAKEFILE := $(lastword $(MAKEFILE_LIST))
|
||||
CLEAN_FILES :=
|
||||
DISTCLEAN_FILES :=
|
||||
DISTCLEAN_FILES := config.make
|
||||
MAKING_CLEAN := $(if $(filter %clean,$(MAKECMDGOALS)),1,0)
|
||||
.PHONY: clean distclean
|
||||
clean:
|
||||
@@ -52,6 +49,67 @@ clean:
|
||||
distclean: clean
|
||||
-rm -f $(DISTCLEAN_FILES)
|
||||
|
||||
|
||||
########################################################################
|
||||
# Special-case builds for which we require certain pre-conditions
|
||||
# which, if not met, may cause warnings or fatal errors in the build.
|
||||
# This also affects the default optimization level flags. Note that
|
||||
# the fiddle targets are in this list because they are used for
|
||||
# generating sqlite.org/fiddle.
|
||||
OPTIMIZED_TARGETS := dist snapshot fiddle fiddle.debug
|
||||
|
||||
ifeq (1,$(MAKING_CLEAN))
|
||||
bin.wasm-strip := echo "not stripping"
|
||||
bin.wasm-opt := irrelevant
|
||||
bin.emcc := irrelevant
|
||||
bin.bash := irrelevant
|
||||
emcc.version := unknown
|
||||
else
|
||||
# Include config.make and perform some bootstrapping...
|
||||
ifeq (,$(wildcard ./config.make))
|
||||
$(error Missing config.make (gets generated by the configure script if the EMSDK is found))
|
||||
endif
|
||||
include ./config.make
|
||||
ifeq (,$(bin.bash))
|
||||
$(error Configure script did not find the bash shell)
|
||||
endif
|
||||
ifeq (,$(bin.emcc))
|
||||
$(error Configure script did not find emcc)
|
||||
endif
|
||||
emcc.version := $(shell $(bin.emcc) --version | sed -n 1p | sed -e 's/^.* \([3-9][^ ]*\) .*$$/\1/;')
|
||||
$(info using emcc version [$(emcc.version)])
|
||||
ifeq (,$(bin.wasm-strip))
|
||||
####################################################################
|
||||
# We need wasm-strip for release builds (see below for why) but
|
||||
# not strictly for non-release builds.
|
||||
$(info WARNING: *******************************************************************)
|
||||
$(info WARNING: Builds using -Oz will minify WASM-exported names, breaking)
|
||||
$(info WARNING: _All The Things_. The workaround for that is to build)
|
||||
$(info WARNING: with -g3 (which explodes the file size) and then strip the debug)
|
||||
$(info WARNING: info after compilation, using wasm-strip, to shrink the wasm file.)
|
||||
$(info WARNING: wasm-strip was not found in the PATH so we cannot strip those.)
|
||||
$(info WARNING: If this build uses any optimization level higher than -O1 then)
|
||||
$(info WARNING: the ***resulting JS code WILL NOT BE USABLE***.)
|
||||
$(info WARNING: wasm-strip is part of the wabt package:)
|
||||
$(info WARNING: https://github.com/WebAssembly/wabt)
|
||||
$(info WARNING: on Ubuntu-like systems it can be installed with:)
|
||||
$(info WARNING: sudo apt install wabt)
|
||||
$(info WARNING: *******************************************************************)
|
||||
ifneq (,$(filter $(OPTIMIZED_TARGETS),$(MAKECMDGOALS)))
|
||||
$(error Cannot make release-quality binary because wasm-strip is not available.)
|
||||
endif
|
||||
bin.wasm-strip := echo "not wasm-stripping"
|
||||
endif
|
||||
ifeq (,$(filter $(OPTIMIZED_TARGETS),$(MAKECMDGOALS)))
|
||||
$(info ==============================================================)
|
||||
$(info == Development build. Make one of (dist, snapshot) for a)
|
||||
$(info == smaller release build.)
|
||||
$(info ==============================================================)
|
||||
endif
|
||||
endif
|
||||
# ^^^ end of are-we-MAKING_CLEAN
|
||||
maybe-wasm-strip := $(bin.wasm-strip)
|
||||
|
||||
########################################################################
|
||||
# JS_BUILD_NAMES exists for documentation purposes only. It enumerates
|
||||
# the core build styles:
|
||||
@@ -107,7 +165,7 @@ dir.wasmfs := $(dir.dout)
|
||||
|
||||
MKDIR.bld := $(dir.tmp)
|
||||
$(MKDIR.bld):
|
||||
-mkdir -p $@ $(dir.dout)
|
||||
@mkdir -p $@ $(dir.dout)
|
||||
|
||||
CLEAN_FILES += *~ $(dir.jacc)/*~ $(dir.api)/*~ $(dir.common)/*~ $(dir.fiddle)/*~ \
|
||||
$(dir.fiddle-debug)/* $(dir.dout)/* $(dir.tmp)/*
|
||||
@@ -133,13 +191,15 @@ sqlite3.canonical.c := $(dir.top)/sqlite3.c
|
||||
sqlite3.c ?= $(firstword $(wildcard $(dir.top)/sqlite3-see.c) $(sqlite3.canonical.c))
|
||||
sqlite3.h := $(dir.top)/sqlite3.h
|
||||
|
||||
ifneq (1,$(MAKING_CLEAN))
|
||||
ifeq (,$(shell grep sqlite3_activate_see $(sqlite3.c)))
|
||||
ifeq (1,$(MAKING_CLEAN))
|
||||
SQLITE_C_IS_SEE := 0
|
||||
else
|
||||
SQLITE_C_IS_SEE := 1
|
||||
$(info This is an SEE build)
|
||||
endif
|
||||
ifeq (,$(shell grep sqlite3_activate_see $(sqlite3.c)))
|
||||
SQLITE_C_IS_SEE := 0
|
||||
else
|
||||
SQLITE_C_IS_SEE := 1
|
||||
$(info This is an SEE build)
|
||||
endif
|
||||
endif
|
||||
|
||||
########################################################################@
|
||||
@@ -151,65 +211,6 @@ $(sqlite3.h):
|
||||
$(MAKE) -C $(dir.top) sqlite3.c
|
||||
$(sqlite3.c): $(sqlite3.h)
|
||||
|
||||
########################################################################
|
||||
# Special-case builds for which we require certain pre-conditions
|
||||
# which, if not met, may cause warnings or fatal errors in the build.
|
||||
# This also affects the default optimization level flags. Note that
|
||||
# the fiddle targets are in this list because they are used for
|
||||
# generating sqlite.org/fiddle.
|
||||
OPTIMIZED_TARGETS := dist snapshot fiddle fiddle.debug
|
||||
|
||||
ifneq (1,$(MAKING_CLEAN))
|
||||
ifeq (,$(filter $(OPTIMIZED_TARGETS),$(MAKECMDGOALS)))
|
||||
$(info ==============================================================)
|
||||
$(info == Development build. Make one of (dist, snapshot) for a)
|
||||
$(info == smaller release build.)
|
||||
$(info ==============================================================)
|
||||
endif
|
||||
endif
|
||||
|
||||
########################################################################
|
||||
# Find emcc (Emscripten compiler)...
|
||||
ifeq (1,$(MAKING_CLEAN))
|
||||
emcc.bin := echo
|
||||
emcc.version := unknown
|
||||
else
|
||||
emcc.bin := $(dir.tool)/emcc.sh
|
||||
ifeq (,$(wildcard $(emcc.bin)))
|
||||
$(error Configure script did not find emcc.)
|
||||
endif
|
||||
emcc.version := $(shell $(emcc.bin) --version | sed -n 1p | sed -e 's/^.* \([3-9][^ ]*\) .*$$/\1/;')
|
||||
$(info using emcc version [$(emcc.version)])
|
||||
endif
|
||||
#########################################################################
|
||||
# Find wasm-strip, which we need for release builds (see below for
|
||||
# why) but not strictly for non-release builds.
|
||||
ifeq (1,$(MAKING_CLEAN))
|
||||
wasm-strip-bin := irrelevant
|
||||
else
|
||||
wasm-strip.bin ?= $(shell which wasm-strip 2>/dev/null)
|
||||
ifeq (,$(wasm-strip.bin))
|
||||
$(info WARNING: *******************************************************************)
|
||||
$(info WARNING: Builds using -O2/-O3/-Os/-Oz will minify WASM-exported names,)
|
||||
$(info WARNING: breaking _All The Things_. The workaround for that is to build)
|
||||
$(info WARNING: with -g3 (which explodes the file size) and then strip the debug)
|
||||
$(info WARNING: info after compilation, using wasm-strip, to shrink the wasm file.)
|
||||
$(info WARNING: wasm-strip was not found in the PATH so we cannot strip those.)
|
||||
$(info WARNING: If this build uses any optimization level higher than -O1 then)
|
||||
$(info WARNING: the ***resulting JS code WILL NOT BE USABLE***.)
|
||||
$(info WARNING: wasm-strip is part of the wabt package:)
|
||||
$(info WARNING: https://github.com/WebAssembly/wabt)
|
||||
$(info WARNING: on Ubuntu-like systems it can be installed with:)
|
||||
$(info WARNING: sudo apt install wabt)
|
||||
$(info WARNING: *******************************************************************)
|
||||
ifneq (,$(filter $(OPTIMIZED_TARGETS),$(MAKECMDGOALS)))
|
||||
$(error Cannot make release-quality binary because wasm-strip is not available.)
|
||||
endif
|
||||
wasm-strip.bin := echo "not wasm-stripping"
|
||||
endif
|
||||
endif
|
||||
maybe-wasm-strip := $(wasm-strip.bin)
|
||||
|
||||
########################################################################
|
||||
# barebones=1 disables all "extraneous" stuff from sqlite3-wasm.c, the
|
||||
# goal being to create a WASM file with only the core APIs.
|
||||
@@ -376,20 +377,7 @@ $(bin.stripccomments): $(bin.stripccomments).c $(MAKEFILE)
|
||||
DISTCLEAN_FILES += $(bin.stripccomments)
|
||||
|
||||
########################################################################
|
||||
# bin.mkwb is used for generating some of the makefile code for the
|
||||
# various wasm builds. It used to be generated in this makefile via a
|
||||
# difficult-to-read/maintain block of $(eval)'d code. Attempts were
|
||||
# made to generate it from tcl and bash (shell) but having to escape
|
||||
# the $ references in those languages made it just as illegible as the
|
||||
# native makefile code. Somewhat surprisingly, moving that code generation
|
||||
# to C makes it slightly less illegible than the previous 3 options.
|
||||
bin.mkwb := ./mkwasmbuilds
|
||||
$(bin.mkwb): $(bin.mkwb).c $(MAKEFILE)
|
||||
$(CC) -o $@ $<
|
||||
DISTCLEAN_FILES += $(bin.mkwb)
|
||||
|
||||
########################################################################
|
||||
# C-PP.FILTER: a $(call)able to transform $(1) to $(2) via:
|
||||
# SQLITE.CALL.C-PP.FILTER: a $(call)able to transform $(1) to $(2) via:
|
||||
#
|
||||
# ./c-pp -f $(1) -o $(2) $(3)
|
||||
#
|
||||
@@ -419,7 +407,7 @@ DISTCLEAN_FILES += $(bin.mkwb)
|
||||
# JS/WASM build. They are solely for use with $(bin.c-pp) itself.
|
||||
#
|
||||
# -D... flags which should be included in all invocations should be
|
||||
# appended to $(C-PP.FILTER.global).
|
||||
# appended to $(SQLITE.CALL.C-PP.FILTER.global).
|
||||
bin.c-pp := ./c-pp
|
||||
$(bin.c-pp): c-pp.c $(sqlite3.c) $(MAKEFILE)
|
||||
$(CC) -O0 -o $@ c-pp.c $(sqlite3.c) '-DCMPP_DEFAULT_DELIM="//#"' -I$(dir.top) \
|
||||
@@ -427,20 +415,21 @@ $(bin.c-pp): c-pp.c $(sqlite3.c) $(MAKEFILE)
|
||||
-DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_WAL -DSQLITE_THREADSAFE=0 \
|
||||
-DSQLITE_TEMP_STORE=3
|
||||
DISTCLEAN_FILES += $(bin.c-pp)
|
||||
C-PP.FILTER.global ?=
|
||||
SQLITE.CALL.C-PP.FILTER.global ?=
|
||||
ifeq (1,$(SQLITE_C_IS_SEE))
|
||||
C-PP.FILTER.global += -Denable-see
|
||||
SQLITE.CALL.C-PP.FILTER.global += -Denable-see
|
||||
endif
|
||||
define C-PP.FILTER
|
||||
define SQLITE.CALL.C-PP.FILTER
|
||||
# Create $2 from $1 using $(bin.c-pp)
|
||||
# $1 = Input file: c-pp -f $(1).js
|
||||
# $2 = Output file: c-pp -o $(2).js
|
||||
# $3 = optional c-pp -D... flags
|
||||
$(2): $(1) $$(MAKEFILE) $$(bin.c-pp)
|
||||
$$(bin.c-pp) -f $(1) -o $$@ $(3) $(C-PP.FILTER.global)
|
||||
$(2): $(1) $$(MAKEFILE_LIST) $$(bin.c-pp)
|
||||
@mkdir -p $$(dir $$@)
|
||||
$$(bin.c-pp) -f $(1) -o $$@ $(3) $(SQLITE.CALL.C-PP.FILTER.global)
|
||||
#CLEAN_FILES += $(2)
|
||||
endef
|
||||
# /end C-PP.FILTER
|
||||
# /end SQLITE.CALL.C-PP.FILTER
|
||||
########################################################################
|
||||
|
||||
# cflags.common = C compiler flags for all builds
|
||||
@@ -618,7 +607,6 @@ emcc.cflags += -I. -I$(dir.top)
|
||||
########################################################################
|
||||
# emcc flags specific to building .js/.wasm files...
|
||||
emcc.jsflags := -fPIC
|
||||
emcc.jsflags += --minify 0
|
||||
emcc.jsflags += --no-entry
|
||||
emcc.jsflags += -sWASM_BIGINT=$(emcc.WASM_BIGINT)
|
||||
emcc.jsflags += -sMODULARIZE
|
||||
@@ -631,6 +619,12 @@ emcc.exportedRuntimeMethods := \
|
||||
emcc.jsflags += $(emcc.exportedRuntimeMethods)
|
||||
emcc.jsflags += -sUSE_CLOSURE_COMPILER=0
|
||||
emcc.jsflags += -sIMPORTED_MEMORY
|
||||
ifeq (,$(filter -O0,$(emcc_opt)))
|
||||
emcc.assert ?= 0
|
||||
else
|
||||
emcc.assert ?= 2
|
||||
endif
|
||||
emcc.jsflags += -sASSERTIONS=$(emcc.assert)
|
||||
emcc.jsflags += -sSTRICT_JS=0
|
||||
# STRICT_JS disabled due to:
|
||||
# https://github.com/emscripten-core/emscripten/issues/18610
|
||||
@@ -826,7 +820,7 @@ sqlite3-wasmfs.cfiles := $(sqlite3-wasm.cfiles)
|
||||
########################################################################
|
||||
|
||||
########################################################################
|
||||
# SQLITE3.xJS.ESM-EXPORT-DEFAULT is used by mkwasmbuilds.c and the
|
||||
# SQLITE.CALL.xJS.ESM-EXPORT-DEFAULT is used by mkwasmbuilds.c and the
|
||||
# wasmfs build. $1 is 1 if the build mode needs this workaround
|
||||
# (modes: esm, bundler-friendly, node) and 0 if not (vanilla). $2 must
|
||||
# be 0 for all builds except sqlite3-wasmfs.mjs, in which case it must
|
||||
@@ -847,9 +841,9 @@ sqlite3-wasmfs.cfiles := $(sqlite3-wasm.cfiles)
|
||||
#
|
||||
# Maintenance reminder: Mac sed works differently than GNU sed, so we
|
||||
# use awk instead of sed for this.
|
||||
define SQLITE3.xJS.ESM-EXPORT-DEFAULT
|
||||
define SQLITE.CALL.xJS.ESM-EXPORT-DEFAULT
|
||||
if [ x1 = x$(1) ]; then \
|
||||
echo "Fragile workaround for emscripten/issues/18237. See SQLITE3.xJS.ESM-EXPORT-DEFAULT."; \
|
||||
echo "Fragile workaround for emscripten/issues/18237. See SQLITE.CALL.xJS.ESM-EXPORT-DEFAULT."; \
|
||||
{\
|
||||
awk '/^export default/ && !f{f=1; next} 1' $@ > $@.tmp && mv $@.tmp $@; \
|
||||
} || exit $$?; \
|
||||
@@ -873,14 +867,6 @@ sqlite3-node.mjs := $(dir.dout)/sqlite3-node.mjs
|
||||
sqlite3-api-wasmfs.mjs := $(dir.tmp)/sqlite3-api-wasmfs.mjs
|
||||
sqlite3-wasmfs.mjs := $(dir.wasmfs)/sqlite3-wasmfs.mjs
|
||||
EXPORTED_FUNCTIONS.fiddle := $(dir.tmp)/EXPORTED_FUNCTIONS.fiddle
|
||||
ifneq (1,$(MAKING_CLEAN))
|
||||
.wasmbuilds.make: $(bin.mkwb)
|
||||
@rm -f $@
|
||||
$(bin.mkwb) > $@
|
||||
@chmod -w $@
|
||||
-include .wasmbuilds.make
|
||||
endif
|
||||
DISTCLEAN_FILES += .wasmbuilds.make
|
||||
|
||||
# The various -D... values used by *.c-pp.js include:
|
||||
#
|
||||
@@ -930,22 +916,47 @@ sqlite3-worker1-promiser.js := $(dir.dout)/sqlite3-worker1-promiser.js
|
||||
sqlite3-worker1-promiser.mjs := $(dir.dout)/sqlite3-worker1-promiser.mjs
|
||||
sqlite3-worker1-bundler-friendly.mjs := $(dir.dout)/sqlite3-worker1-bundler-friendly.mjs
|
||||
sqlite3-worker1-promiser-bundler-friendly.js := $(dir.dout)/sqlite3-worker1-promiser-bundler-friendly.js
|
||||
$(eval $(call C-PP.FILTER,$(sqlite3-worker1.js.in),$(sqlite3-worker1.js)))
|
||||
$(eval $(call C-PP.FILTER,$(sqlite3-worker1.js.in),$(sqlite3-worker1-bundler-friendly.mjs),\
|
||||
|
||||
ifneq (1,$(MAKING_CLEAN))
|
||||
# This block MUST come between the above definitions of
|
||||
# sqlite3-...js/mjs and the $(eval) calls below this block which use
|
||||
# SQLITE.CALL.C-PP.FILTER.
|
||||
########################################################################
|
||||
# bin.mkwb is used for generating some of the makefile code for the
|
||||
# various wasm builds. It used to be generated in this makefile via a
|
||||
# difficult-to-read/maintain block of $(eval)'d code. Attempts were
|
||||
# made to generate it from tcl and bash (shell) but having to escape
|
||||
# the $ references in those languages made it just as illegible as the
|
||||
# native makefile code. Somewhat surprisingly, moving that code generation
|
||||
# to C makes it slightly less illegible than the previous 3 options.
|
||||
bin.mkwb := ./mkwasmbuilds
|
||||
$(bin.mkwb): $(bin.mkwb).c $(MAKEFILE)
|
||||
$(CC) -o $@ $<
|
||||
DISTCLEAN_FILES += $(bin.mkwb)
|
||||
.wasmbuilds.make: $(bin.mkwb)
|
||||
@rm -f $@
|
||||
$(bin.mkwb) > $@
|
||||
@chmod -w $@
|
||||
-include .wasmbuilds.make
|
||||
endif
|
||||
DISTCLEAN_FILES += .wasmbuilds.make
|
||||
|
||||
$(eval $(call SQLITE.CALL.C-PP.FILTER,$(sqlite3-worker1.js.in),$(sqlite3-worker1.js)))
|
||||
$(eval $(call SQLITE.CALL.C-PP.FILTER,$(sqlite3-worker1.js.in),$(sqlite3-worker1-bundler-friendly.mjs),\
|
||||
$(c-pp.D.sqlite3-bundler-friendly)))
|
||||
$(eval $(call C-PP.FILTER,$(sqlite3-worker1-promiser.js.in),$(sqlite3-worker1-promiser.js)))
|
||||
$(eval $(call C-PP.FILTER,$(sqlite3-worker1-promiser.js.in),\
|
||||
$(eval $(call SQLITE.CALL.C-PP.FILTER,$(sqlite3-worker1-promiser.js.in),$(sqlite3-worker1-promiser.js)))
|
||||
$(eval $(call SQLITE.CALL.C-PP.FILTER,$(sqlite3-worker1-promiser.js.in),\
|
||||
$(sqlite3-worker1-promiser-bundler-friendly.js),\
|
||||
$(c-pp.D.sqlite3-bundler-friendly)))
|
||||
$(eval $(call C-PP.FILTER,$(sqlite3-worker1-promiser.js.in),$(sqlite3-worker1-promiser.mjs),\
|
||||
$(eval $(call SQLITE.CALL.C-PP.FILTER,$(sqlite3-worker1-promiser.js.in),$(sqlite3-worker1-promiser.mjs),\
|
||||
-Dtarget=es6-module -Dtarget=es6-bundler-friendly))
|
||||
$(sqlite3-bundler-friendly.mjs): $(sqlite3-worker1-bundler-friendly.mjs) \
|
||||
$(sqlite3-worker1-promiser-bundler-friendly.js)
|
||||
$(eval $(call C-PP.FILTER,demo-worker1-promiser.c-pp.js,demo-worker1-promiser.js))
|
||||
$(eval $(call C-PP.FILTER,demo-worker1-promiser.c-pp.js,demo-worker1-promiser.mjs,\
|
||||
$(eval $(call SQLITE.CALL.C-PP.FILTER,demo-worker1-promiser.c-pp.js,demo-worker1-promiser.js))
|
||||
$(eval $(call SQLITE.CALL.C-PP.FILTER,demo-worker1-promiser.c-pp.js,demo-worker1-promiser.mjs,\
|
||||
-Dtarget=es6-module))
|
||||
$(eval $(call C-PP.FILTER,demo-worker1-promiser.c-pp.html,demo-worker1-promiser.html))
|
||||
$(eval $(call C-PP.FILTER,demo-worker1-promiser.c-pp.html,demo-worker1-promiser-esm.html,\
|
||||
$(eval $(call SQLITE.CALL.C-PP.FILTER,demo-worker1-promiser.c-pp.html,demo-worker1-promiser.html))
|
||||
$(eval $(call SQLITE.CALL.C-PP.FILTER,demo-worker1-promiser.c-pp.html,demo-worker1-promiser-esm.html,\
|
||||
-Dtarget=es6-module))
|
||||
all: $(sqlite3-worker1.js) \
|
||||
$(sqlite3-worker1-promiser.js) $(sqlite3-worker1-promiser.mjs)
|
||||
@@ -1042,7 +1053,7 @@ $(speedtest1.js): $(MAKEFILE) $(speedtest1.cfiles) \
|
||||
$(pre-post-speedtest1-vanilla.deps) \
|
||||
$(EXPORTED_FUNCTIONS.speedtest1)
|
||||
@echo "Building $@ ..."
|
||||
$(emcc.bin) \
|
||||
$(bin.emcc) \
|
||||
$(emcc.speedtest1) \
|
||||
$(emcc.speedtest1.common) \
|
||||
$(emcc.flags.speedtest1-vanilla) $(pre-post-speedtest1-vanilla.flags) \
|
||||
@@ -1052,6 +1063,7 @@ $(speedtest1.js): $(MAKEFILE) $(speedtest1.cfiles) \
|
||||
$(speedtest1.exit-runtime0) \
|
||||
-o $@ $(speedtest1.cfiles) -lm
|
||||
$(maybe-wasm-strip) $(speedtest1.wasm)
|
||||
sed -i -e '/^var _sqlite3.*createExportWrapper/d' $@
|
||||
chmod -x $(speedtest1.wasm)
|
||||
ls -la $@ $(speedtest1.wasm)
|
||||
|
||||
@@ -1077,10 +1089,10 @@ all: speedtest1
|
||||
# tester1.mjs: cases 3 and 4
|
||||
#
|
||||
# To create those, we filter tester1.c-pp.js with $(bin.c-pp)...
|
||||
$(eval $(call C-PP.FILTER,tester1.c-pp.js,tester1.js))
|
||||
$(eval $(call C-PP.FILTER,tester1.c-pp.js,tester1.mjs,$(c-pp.D.sqlite3-esm)))
|
||||
$(eval $(call C-PP.FILTER,tester1.c-pp.html,tester1.html))
|
||||
$(eval $(call C-PP.FILTER,tester1.c-pp.html,tester1-esm.html,$(c-pp.D.sqlite3-esm)))
|
||||
$(eval $(call SQLITE.CALL.C-PP.FILTER,tester1.c-pp.js,tester1.js))
|
||||
$(eval $(call SQLITE.CALL.C-PP.FILTER,tester1.c-pp.js,tester1.mjs,$(c-pp.D.sqlite3-esm)))
|
||||
$(eval $(call SQLITE.CALL.C-PP.FILTER,tester1.c-pp.html,tester1.html))
|
||||
$(eval $(call SQLITE.CALL.C-PP.FILTER,tester1.c-pp.html,tester1-esm.html,$(c-pp.D.sqlite3-esm)))
|
||||
tester1: tester1.js tester1.mjs tester1.html tester1-esm.html
|
||||
# Note that we do not include $(sqlite3-bundler-friendly.mjs) in this
|
||||
# because bundlers are client-specific.
|
||||
|
||||
@@ -31,16 +31,20 @@ build:
|
||||
use of and is not demonstrated here.
|
||||
|
||||
Browsers will not serve WASM files from file:// URLs, so the test and
|
||||
demonstration apps require a web server and that server must include
|
||||
the following headers in its response when serving the files:
|
||||
demonstration apps require a web server and that server must, for the
|
||||
OPFS[^1]-related features, include the following headers in its response
|
||||
when serving the files:
|
||||
|
||||
Cross-Origin-Opener-Policy: same-origin
|
||||
Cross-Origin-Embedder-Policy: require-corp
|
||||
|
||||
The core library will function without those headers but certain
|
||||
features, most notably OPFS storage, will not be available.
|
||||
Most functionality will work without those headers but the OPFS[^1]
|
||||
storage capability will not be available without them.
|
||||
|
||||
One simple way to get the demo apps up and running on Unix-style
|
||||
systems is to install althttpd (https://sqlite.org/althttpd) and run:
|
||||
|
||||
althttpd --enable-sab --page index.html
|
||||
|
||||
|
||||
[^1]: https://developer.mozilla.org/en-US/docs/Web/API/File_System_API/Origin_private_file_system
|
||||
|
||||
+36
-10
@@ -29,8 +29,16 @@ $ ./emsdk install latest
|
||||
$ ./emsdk activate latest
|
||||
```
|
||||
|
||||
The following needs to be run for each shell instance which needs the
|
||||
`emcc` compiler:
|
||||
(Sidebar: Emscripten updates can and do _change things_, i.e. _break
|
||||
things_, so it's considered _required practice_ to test thoroughly
|
||||
after upgrading it! Our build process makes no guarantees about which
|
||||
Emscripten version(s) will or won't work, but it's important that
|
||||
production builds are built using a compatible version. During active
|
||||
development, the EMSDK is frequently updated, the goal being to keep
|
||||
`sqlite3.wasm` working with "the latest" EMSDK.)
|
||||
|
||||
The SQLite configure script will search for the EMSDK. One way
|
||||
to ensure that it finds it is:
|
||||
|
||||
```
|
||||
# Activate PATH and other environment variables in the current terminal:
|
||||
@@ -38,15 +46,27 @@ $ source ./emsdk_env.sh
|
||||
|
||||
$ which emcc
|
||||
/path/to/emsdk/upstream/emscripten/emcc
|
||||
|
||||
$ ./configure ...
|
||||
```
|
||||
|
||||
Optionally, add that to your login shell's resource file (`~/.bashrc`
|
||||
or equivalent).
|
||||
Optionally, add that `source` part to your login shell's resource file
|
||||
(`~/.bashrc` or equivalent).
|
||||
|
||||
That `env` script needs to be sourced for building this application
|
||||
from the top of the sqlite3 build tree:
|
||||
Another way is to pass the EMSDK dir to configure:
|
||||
|
||||
```
|
||||
$ ./configure --with-emsdk=/path/to/emsdk
|
||||
```
|
||||
|
||||
The build tree uses a small wrapper for invoking the `emcc` (the
|
||||
Emscripten compiler): `tool/emcc.sh` is generated from
|
||||
`tool/emcc.sh.in` using the EMSDK path found by the configure process.
|
||||
|
||||
With that in place, the most common build approaches are:
|
||||
|
||||
```
|
||||
# From the top of the tree:
|
||||
$ make fiddle
|
||||
```
|
||||
|
||||
@@ -57,7 +77,7 @@ $ cd ext/wasm
|
||||
$ make
|
||||
```
|
||||
|
||||
That will generate the a number of files required for a handful of
|
||||
Those will generate the a number of files required for a handful of
|
||||
test and demo applications which can be accessed via
|
||||
`index.html`. WASM content cannot, due to XMLHttpRequest security
|
||||
limitations, be loaded if the containing HTML file is opened directly
|
||||
@@ -68,16 +88,21 @@ needs to be served via an HTTP server. For example, using
|
||||
```
|
||||
$ cd ext/wasm
|
||||
$ althttpd --enable-sab --max-age 1 --page index.html
|
||||
# Or, more simply, from the ext/wasm dir:
|
||||
$ make httpd
|
||||
```
|
||||
|
||||
That will open the system's browser and run the index page, from which
|
||||
all of the test and demo applications can be accessed.
|
||||
That will open the system's browser and visit the index page, from
|
||||
which (almost) all of the test and demo applications can be accessed.
|
||||
(`ext/wasm/SQLTester` is not listed in that page because it's only of
|
||||
real utility when it's used in conjunction with the project's
|
||||
proprietary test suite, which most users don't have access to.)
|
||||
|
||||
Note that when serving this app via [althttpd][], it must be a version
|
||||
from 2022-09-26 or newer so that it recognizes the `--enable-sab`
|
||||
flag, which causes althttpd to emit two HTTP response headers which
|
||||
are required to enable JavaScript's `SharedArrayBuffer` and `Atomics`
|
||||
APIs. Those APIs are required in order to enable the OPFS-related
|
||||
APIs. Those APIs are required in order to enable the [OPFS][]-related
|
||||
features in the apps which use them.
|
||||
|
||||
# Testing on a remote machine that is accessed via SSH
|
||||
@@ -104,3 +129,4 @@ be tunneled using SSH.
|
||||
[emscripten]: https://emscripten.org
|
||||
[althttpd]: https://sqlite.org/althttpd
|
||||
[SharedArrayBuffer]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer
|
||||
[OPFS]: https://developer.mozilla.org/en-US/docs/Web/API/File_System_API/Origin_private_file_system
|
||||
|
||||
+14
-10
@@ -85,17 +85,18 @@ browser client:
|
||||
Installs the `sqlite3.vtab` namespace, which contain helpers for use
|
||||
by downstream code which creates `sqlite3_module` implementations.
|
||||
- **`sqlite3-vfs-opfs.c-pp.js`**\
|
||||
is an sqlite3 VFS implementation which supports the Origin-Private
|
||||
FileSystem (OPFS) as a storage layer to provide persistent storage
|
||||
for database files in a browser. It requires...
|
||||
is an sqlite3 VFS implementation which supports the [Origin-Private
|
||||
FileSystem (OPFS)][OPFS] as a storage layer to provide persistent
|
||||
storage for database files in a browser. It requires...
|
||||
- **`sqlite3-opfs-async-proxy.js`**\
|
||||
is the asynchronous backend part of the OPFS proxy. It speaks
|
||||
directly to the (async) OPFS API and channels those results back
|
||||
to its synchronous counterpart. This file, because it must be
|
||||
started in its own Worker, is not part of the amalgamation.
|
||||
is the asynchronous backend part of the [OPFS][] proxy. It
|
||||
speaks directly to the (async) OPFS API and channels those
|
||||
results back to its synchronous counterpart. This file, because
|
||||
it must be started in its own Worker, is not part of the
|
||||
amalgamation.
|
||||
- **`sqlite3-vfs-opfs-sahpool.c-pp.js`**\
|
||||
is another sqlite3 VFS supporting the OPFS, but uses a completely
|
||||
different approach that the above-listed one.
|
||||
is another sqlite3 VFS supporting the [OPFS][], but uses a
|
||||
completely different approach that the above-listed one.
|
||||
- **`sqlite3-api-cleanup.js`**\
|
||||
The previous files do not immediately extend the library. Instead
|
||||
they add callback functions to be called during its
|
||||
@@ -152,7 +153,7 @@ into the build-generated `sqlite3.js` along with `sqlite3-api.js`.
|
||||
flag. This file overwrites the Emscripten-installed
|
||||
`sqlite3InitModule()` function with one which, after the module is
|
||||
loaded, also initializes the asynchronous parts of the sqlite3
|
||||
module. For example, the OPFS VFS support.
|
||||
module. For example, the [OPFS][] VFS support.
|
||||
|
||||
<a id='c-pp'></a>
|
||||
Preprocessing of Source Files
|
||||
@@ -164,3 +165,6 @@ builds. The preprocessor application itself is in
|
||||
[`c-pp.c`](/file/ext/wasm/c-pp.c) and the complete technical details
|
||||
of such preprocessing are maintained in
|
||||
[`GNUMakefile`](/file/ext/wasm/GNUmakefile).
|
||||
|
||||
|
||||
[OPFS]: https://developer.mozilla.org/en-US/docs/Web/API/File_System_API/Origin_private_file_system
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
const toExportForESM =
|
||||
//#endif
|
||||
(function(){
|
||||
//console.warn("this is extern-post-js");
|
||||
/**
|
||||
In order to hide the sqlite3InitModule()'s resulting
|
||||
Emscripten module from downstream clients (and simplify our
|
||||
@@ -62,6 +63,16 @@ const toExportForESM =
|
||||
globalThis.sqlite3InitModule = function ff(...args){
|
||||
//console.warn("Using replaced sqlite3InitModule()",globalThis.location);
|
||||
return originalInit(...args).then((EmscriptenModule)=>{
|
||||
//console.warn("originalInit() then() arg =",EmscriptenModule);
|
||||
//console.warn("initModuleState =",initModuleState);
|
||||
EmscriptenModule.runSQLite3PostLoadInit(EmscriptenModule);
|
||||
const s = EmscriptenModule.sqlite3;
|
||||
s.scriptInfo = initModuleState;
|
||||
//console.warn("sqlite3.scriptInfo =",s.scriptInfo);
|
||||
if(ff.__isUnderTest) s.__isUnderTest = true;
|
||||
const f = s.asyncPostInit;
|
||||
delete s.asyncPostInit;
|
||||
const rv = f();
|
||||
//#if wasmfs
|
||||
if('undefined'!==typeof WorkerGlobalScope &&
|
||||
EmscriptenModule['ENVIRONMENT_IS_PTHREAD']){
|
||||
@@ -74,14 +85,7 @@ const toExportForESM =
|
||||
return EmscriptenModule;
|
||||
}
|
||||
//#endif
|
||||
//console.warn("sqlite3InitModule() returning sqlite3 object.");
|
||||
const s = EmscriptenModule.sqlite3;
|
||||
s.scriptInfo = initModuleState;
|
||||
//console.warn("sqlite3.scriptInfo =",s.scriptInfo);
|
||||
if(ff.__isUnderTest) s.__isUnderTest = true;
|
||||
const f = s.asyncPostInit;
|
||||
delete s.asyncPostInit;
|
||||
return f();
|
||||
return rv;
|
||||
}).catch((e)=>{
|
||||
console.error("Exception loading sqlite3 module:",e);
|
||||
throw e;
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
/* The current function scope was opened via post-js-header.js, which
|
||||
gets prepended to this at build-time. This file closes that
|
||||
scope. */
|
||||
})/*postRun.push(...)*/;
|
||||
//console.warn("This is the end of the Module.runSQLite3PostLoadInit handler.");
|
||||
}/*Module.runSQLite3PostLoadInit()*/;
|
||||
//console.warn("This is the end of the setup of the (pending) Module.runSQLite3PostLoadInit");
|
||||
|
||||
@@ -7,22 +7,27 @@
|
||||
installs will be run after the WASM module is loaded, at which
|
||||
point the sqlite3 JS API bits will get set up.
|
||||
*/
|
||||
if(!Module.postRun) Module.postRun = [];
|
||||
Module.postRun.push(function(Module/*the Emscripten-style module object*/){
|
||||
Module.runSQLite3PostLoadInit = function(EmscriptenModule/*the Emscripten-style module object*/){
|
||||
/** ^^^ Don't use Module.postRun, as that runs a different time
|
||||
depending on whether this file is built with emcc 3.1.x or
|
||||
4.0.x. This function name is intentionally obnoxiously verbose to
|
||||
ensure that we don't collide with current and future Emscripten
|
||||
symbol names. */
|
||||
'use strict';
|
||||
//console.warn("This is the start of Module.runSQLite3PostLoadInit()");
|
||||
/* This function will contain at least the following:
|
||||
|
||||
- post-js-header.js (this file)
|
||||
- post-js-header.js => this file
|
||||
- sqlite3-api-prologue.js => Bootstrapping bits to attach the rest to
|
||||
- common/whwasmutil.js => Replacements for much of Emscripten's glue
|
||||
- jaccwaby/jaccwabyt.js => Jaccwabyt (C/JS struct binding)
|
||||
- jaccwabyt/jaccwabyt.js => Jaccwabyt (C/JS struct binding)
|
||||
- sqlite3-api-glue.js => glues previous parts together
|
||||
- sqlite3-api-oo.js => SQLite3 OO API #1
|
||||
- sqlite3-api-oo1.js => SQLite3 OO API #1
|
||||
- sqlite3-api-worker1.js => Worker-based API
|
||||
- sqlite3-vfs-helper.c-pp.js => Utilities for VFS impls
|
||||
- sqlite3-vtab-helper.c-pp.js => Utilities for virtual table impls
|
||||
- sqlite3-vfs-opfs.c-pp.js => OPFS VFS
|
||||
- sqlite3-vfs-opfs.c-pp.js => OPFS VFS
|
||||
- sqlite3-vfs-opfs-sahpool.c-pp.js => OPFS SAHPool VFS
|
||||
- sqlite3-api-cleanup.js => final API cleanup
|
||||
- post-js-footer.js => closes this postRun() function
|
||||
- post-js-footer.js => closes this function
|
||||
*/
|
||||
|
||||
@@ -14,6 +14,9 @@
|
||||
intended to be appended after all other sqlite3-api-*.js files so
|
||||
that it can finalize any setup and clean up any global symbols
|
||||
temporarily used for setting up the API's various subsystems.
|
||||
|
||||
In Emscripten builds it's run in the context of a Module.postRun
|
||||
handler.
|
||||
*/
|
||||
'use strict';
|
||||
if('undefined' !== typeof Module){ // presumably an Emscripten build
|
||||
|
||||
@@ -228,13 +228,49 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
}),
|
||||
'*'
|
||||
]],
|
||||
/**
|
||||
We do not have a way to automatically clean up destructors
|
||||
which are automatically converted from JS functions via the
|
||||
final argument to sqlite3_set_auxdata(). Because of that,
|
||||
automatic function conversion is not supported for this
|
||||
function. Clients should use wasm.installFunction() to create
|
||||
such callbacks, then pass that pointer to
|
||||
sqlite3_set_auxdata(). Relying on automated conversions here
|
||||
would lead to leaks of JS/WASM proxy functions because
|
||||
sqlite3_set_auxdata() is frequently called in UDFs.
|
||||
|
||||
The sqlite3.oo1.DB class's onclose handlers can be used for this
|
||||
purpose. For example:
|
||||
|
||||
const pAuxDtor = wasm.installFunction('v(p)', function(ptr){
|
||||
//free ptr
|
||||
});
|
||||
myDb.onclose = {
|
||||
after: ()=>{
|
||||
wasm.uninstallFunction(pAuxDtor);
|
||||
}
|
||||
};
|
||||
|
||||
Then pass pAuxDtor as the final argument to appropriate
|
||||
sqlite3_set_auxdata() calls.
|
||||
|
||||
Note that versions prior to 3.49.0 ostensibly had automatic
|
||||
function conversion here but a typo prevented it from
|
||||
working. Rather than fix it, it was removed because testing the
|
||||
fix brought the huge potential for memory leaks to the
|
||||
forefront.
|
||||
*/
|
||||
["sqlite3_set_auxdata", undefined, [
|
||||
"sqlite3_context*", "int", "*",
|
||||
new wasm.xWrap.FuncPtrAdapter({
|
||||
name: 'xDestroyAuxData',
|
||||
signature: 'v(*)',
|
||||
contextKey: (argv, argIndex)=>argv[0/* sqlite3_context* */]
|
||||
})
|
||||
true
|
||||
? "*"
|
||||
: new wasm.xWrap.FuncPtrAdapter({
|
||||
/* If we can find a way to automate their cleanup, JS functions can
|
||||
be auto-converted with this. */
|
||||
name: 'xDestroyAuxData',
|
||||
signature: 'v(p)',
|
||||
contextKey: (argv, argIndex)=>argv[0/* sqlite3_context* */]
|
||||
})
|
||||
]],
|
||||
["sqlite3_shutdown", undefined],
|
||||
["sqlite3_sourceid", "string"],
|
||||
@@ -1047,6 +1083,10 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
'sqlite3_set_authorizer',
|
||||
'sqlite3_trace_v2',
|
||||
'sqlite3_update_hook'
|
||||
/*
|
||||
We do not yet have a way to clean up automatically-converted
|
||||
sqlite3_set_auxdata() finalizers.
|
||||
*/
|
||||
]) {
|
||||
const x = wasm.exports[name];
|
||||
if( !x ){
|
||||
|
||||
@@ -12,12 +12,12 @@
|
||||
|
||||
This file is intended to be combined at build-time with other
|
||||
related code, most notably a header and footer which wraps this
|
||||
whole file into an Emscripten Module.postRun() handler. The sqlite3
|
||||
JS API has no hard requirements on Emscripten and does not expose
|
||||
any Emscripten APIs to clients. It is structured such that its build
|
||||
can be tweaked to include it in arbitrary WASM environments which
|
||||
can supply the necessary underlying features (e.g. a POSIX file I/O
|
||||
layer).
|
||||
whole file into a single callback which can be run after Emscripten
|
||||
loads the corresponding WASM module. The sqlite3 JS API has no hard
|
||||
requirements on Emscripten and does not expose any Emscripten APIs
|
||||
to clients. It is structured such that its build can be tweaked to
|
||||
include it in arbitrary WASM environments which can supply the
|
||||
necessary underlying features (e.g. a POSIX file I/O layer).
|
||||
|
||||
Main project home page: https://sqlite.org
|
||||
|
||||
@@ -1712,41 +1712,48 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
|
||||
missing or falsy pointer argument as 0.
|
||||
*/
|
||||
capi.sqlite3_db_config = function(pDb, op, ...args){
|
||||
if(!this.s){
|
||||
this.s = wasm.xWrap('sqlite3__wasm_db_config_s','int',
|
||||
['sqlite3*', 'int', 'string:static']
|
||||
/* MAINDBNAME requires a static string */);
|
||||
this.pii = wasm.xWrap('sqlite3__wasm_db_config_pii', 'int',
|
||||
['sqlite3*', 'int', '*','int', 'int']);
|
||||
this.ip = wasm.xWrap('sqlite3__wasm_db_config_ip','int',
|
||||
['sqlite3*', 'int', 'int','*']);
|
||||
}
|
||||
switch(op){
|
||||
case capi.SQLITE_DBCONFIG_ENABLE_FKEY:
|
||||
case capi.SQLITE_DBCONFIG_ENABLE_TRIGGER:
|
||||
case capi.SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER:
|
||||
case capi.SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION:
|
||||
case capi.SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE:
|
||||
case capi.SQLITE_DBCONFIG_ENABLE_QPSG:
|
||||
case capi.SQLITE_DBCONFIG_TRIGGER_EQP:
|
||||
case capi.SQLITE_DBCONFIG_RESET_DATABASE:
|
||||
case capi.SQLITE_DBCONFIG_DEFENSIVE:
|
||||
case capi.SQLITE_DBCONFIG_WRITABLE_SCHEMA:
|
||||
case capi.SQLITE_DBCONFIG_LEGACY_ALTER_TABLE:
|
||||
case capi.SQLITE_DBCONFIG_DQS_DML:
|
||||
case capi.SQLITE_DBCONFIG_DQS_DDL:
|
||||
case capi.SQLITE_DBCONFIG_ENABLE_VIEW:
|
||||
case capi.SQLITE_DBCONFIG_LEGACY_FILE_FORMAT:
|
||||
case capi.SQLITE_DBCONFIG_TRUSTED_SCHEMA:
|
||||
case capi.SQLITE_DBCONFIG_STMT_SCANSTATUS:
|
||||
case capi.SQLITE_DBCONFIG_REVERSE_SCANORDER:
|
||||
return this.ip(pDb, op, args[0], args[1] || 0);
|
||||
case capi.SQLITE_DBCONFIG_LOOKASIDE:
|
||||
return this.pii(pDb, op, args[0], args[1], args[2]);
|
||||
case capi.SQLITE_DBCONFIG_MAINDBNAME:
|
||||
return this.s(pDb, op, args[0]);
|
||||
default:
|
||||
return capi.SQLITE_MISUSE;
|
||||
case capi.SQLITE_DBCONFIG_ENABLE_FKEY:
|
||||
case capi.SQLITE_DBCONFIG_ENABLE_TRIGGER:
|
||||
case capi.SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER:
|
||||
case capi.SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION:
|
||||
case capi.SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE:
|
||||
case capi.SQLITE_DBCONFIG_ENABLE_QPSG:
|
||||
case capi.SQLITE_DBCONFIG_TRIGGER_EQP:
|
||||
case capi.SQLITE_DBCONFIG_RESET_DATABASE:
|
||||
case capi.SQLITE_DBCONFIG_DEFENSIVE:
|
||||
case capi.SQLITE_DBCONFIG_WRITABLE_SCHEMA:
|
||||
case capi.SQLITE_DBCONFIG_LEGACY_ALTER_TABLE:
|
||||
case capi.SQLITE_DBCONFIG_DQS_DML:
|
||||
case capi.SQLITE_DBCONFIG_DQS_DDL:
|
||||
case capi.SQLITE_DBCONFIG_ENABLE_VIEW:
|
||||
case capi.SQLITE_DBCONFIG_LEGACY_FILE_FORMAT:
|
||||
case capi.SQLITE_DBCONFIG_TRUSTED_SCHEMA:
|
||||
case capi.SQLITE_DBCONFIG_STMT_SCANSTATUS:
|
||||
case capi.SQLITE_DBCONFIG_REVERSE_SCANORDER:
|
||||
case capi.SQLITE_DBCONFIG_ENABLE_ATTACH_CREATE:
|
||||
case capi.SQLITE_DBCONFIG_ENABLE_ATTACH_WRITE:
|
||||
case capi.SQLITE_DBCONFIG_ENABLE_COMMENTS:
|
||||
if( !this.ip ){
|
||||
this.ip = wasm.xWrap('sqlite3__wasm_db_config_ip','int',
|
||||
['sqlite3*', 'int', 'int', '*']);
|
||||
}
|
||||
return this.ip(pDb, op, args[0], args[1] || 0);
|
||||
case capi.SQLITE_DBCONFIG_LOOKASIDE:
|
||||
if( !this.pii ){
|
||||
this.pii = wasm.xWrap('sqlite3__wasm_db_config_pii', 'int',
|
||||
['sqlite3*', 'int', '*', 'int', 'int']);
|
||||
}
|
||||
return this.pii(pDb, op, args[0], args[1], args[2]);
|
||||
case capi.SQLITE_DBCONFIG_MAINDBNAME:
|
||||
if(!this.s){
|
||||
this.s = wasm.xWrap('sqlite3__wasm_db_config_s','int',
|
||||
['sqlite3*', 'int', 'string:static']
|
||||
/* MAINDBNAME requires a static string */);
|
||||
}
|
||||
return this.s(pDb, op, args[0]);
|
||||
default:
|
||||
return capi.SQLITE_MISUSE;
|
||||
}
|
||||
}.bind(Object.create(null));
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user