Compare commits
633 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 2b041fb97a | |||
| b7ceffdadf | |||
| 66b3ed318b | |||
| 878db7b099 | |||
| 7119a6c16b | |||
| 95f35b64da | |||
| 62d96919f6 | |||
| 2a9254cf2c | |||
| 9e59c06fb1 | |||
| 853520ddbf | |||
| 38b4158aba | |||
| 8f1f9ef09f | |||
| 8cd30e3f5b | |||
| f4382b2415 | |||
| 18e2ace468 | |||
| 697c3fb25b | |||
| 63558eae54 | |||
| 6ba175f0c8 | |||
| a55901a27c | |||
| 0be2dd9a1b | |||
| 29057f3d18 | |||
| 57b32ef924 | |||
| 3c90b86372 | |||
| 4e34558f1b | |||
| 118ac6a7ad | |||
| 7d24e6b080 | |||
| 415acd09d7 | |||
| 1d9db01065 | |||
| 253695caf3 | |||
| 5e419c1048 | |||
| 38f2c5f81c | |||
| 8a894cd804 | |||
| 7f0e0c7dbf | |||
| db467f5777 | |||
| f8305e4616 | |||
| 8513eb6ba8 | |||
| 0e8cbd5e78 | |||
| 704561f346 | |||
| ae2a4acf8d | |||
| 38b31a93b3 | |||
| eaa50b8660 | |||
| 87dce45f96 | |||
| ff60709d68 | |||
| 3b204ec8bb | |||
| 61e3067529 | |||
| d70fbffc1a | |||
| f8cafd7b11 | |||
| a95620c141 | |||
| d87a4f8bdd | |||
| dbff02abc5 | |||
| 11e1defc8f | |||
| 3d56d59adc | |||
| 7154803d4c | |||
| df9b488799 | |||
| 15e05eab32 | |||
| 9d3047bd0d | |||
| 2b30518804 | |||
| 33f0a3ed13 | |||
| 762946b236 | |||
| 8550e4a9f8 | |||
| 99f50dd219 | |||
| 7316b6c072 | |||
| d61d934f9b | |||
| d0d3182fa8 | |||
| e92f8e565b | |||
| 5c6dc45a10 | |||
| 74c8e234cd | |||
| 5735921b0f | |||
| 6677cfeda7 | |||
| 40b831851e | |||
| 6df1de1c73 | |||
| 0b8c8c861b | |||
| f7c96ee98b | |||
| 165daef043 | |||
| f1fb5ce10f | |||
| dc3bec34a6 | |||
| 2a4a4ec408 | |||
| 79254dc363 | |||
| 0c8144ab4f | |||
| 27119c56bd | |||
| a9c8f7cf34 | |||
| 923423c16f | |||
| 7a41b48cf9 | |||
| 38b26d82e6 | |||
| cd889c7a88 | |||
| 882aba4090 | |||
| 9c2f068ebd | |||
| dbab768d07 | |||
| a40f6eb80e | |||
| a8cf79e322 | |||
| 5600adf1b1 | |||
| cf25c16a54 | |||
| 8755e695c5 | |||
| f1c750e4ca | |||
| 6946a7fa50 | |||
| bc97630313 | |||
| c43d16d69a | |||
| deb6a60a84 | |||
| c4e84b7295 | |||
| 56a0480540 | |||
| dc181d41d5 | |||
| 934e796e43 | |||
| 6ffcdb1856 | |||
| 4987c5c3c2 | |||
| 21e7816e65 | |||
| 6aedd6d9fc | |||
| 7bd230cf4d | |||
| bb4d2edf10 | |||
| 109025c0a4 | |||
| 3c72072a6f | |||
| c81ab76cd9 | |||
| fd486258a0 | |||
| 940cdc94f3 | |||
| 23a16c8387 | |||
| e6e49bfef2 | |||
| 06638117bb | |||
| 22cd1eec5a | |||
| 7c6f2880aa | |||
| 70989b6f59 | |||
| ef7c692baf | |||
| da52f11250 | |||
| 7a29505e57 | |||
| d281889ac8 | |||
| a955ec806a | |||
| b5df31d15f | |||
| b9a6e42a55 | |||
| 1c30df3598 | |||
| ca447020ae | |||
| 7aa01a0ffc | |||
| 5d5d6194c9 | |||
| c97ad9b4e1 | |||
| 41155d8885 | |||
| df2d14b86e | |||
| a239ece378 | |||
| c1042cd133 | |||
| 65b1244781 | |||
| 49af3dfbf4 | |||
| a5315a6ece | |||
| f138110dfd | |||
| ad8ec9db63 | |||
| 129767958a | |||
| 90fa4c7b2c | |||
| 3196c349d1 | |||
| 0337b9a628 | |||
| 6cb12337b9 | |||
| c589d5ab06 | |||
| 28db1a68ba | |||
| 11397ce104 | |||
| 494ba30c9b | |||
| 6a18c9e06a | |||
| ccd34894e1 | |||
| c1547d1f7a | |||
| 50ca8af6f2 | |||
| 8db3fc5488 | |||
| ba5994b181 | |||
| 3341f5ce85 | |||
| d6b56d65a8 | |||
| 4f2f91bf08 | |||
| 242e064978 | |||
| 4a90f81a6d | |||
| a88d61824d | |||
| af43eddc23 | |||
| b5b4ca2a11 | |||
| c3c645ef46 | |||
| f5a9b58c8b | |||
| ce018f5bb3 | |||
| 1a7cfbebb0 | |||
| db05c66a16 | |||
| 71475478a1 | |||
| c8edf07ca7 | |||
| d9bc2bb638 | |||
| 3c39f1f5d6 | |||
| dac0d0b310 | |||
| 4a972bc1b8 | |||
| 8aa9135f2c | |||
| fcd65efcf1 | |||
| c013fa50db | |||
| 1321ea5010 | |||
| 87ebadbf4e | |||
| cc902fd25e | |||
| 306a8dcf3e | |||
| 838d2d3078 | |||
| 1d5a12e6a5 | |||
| f9eff9052d | |||
| 58b08d7702 | |||
| 27095fc4a5 | |||
| 7766c9943e | |||
| 789da35848 | |||
| 8d4edd0d67 | |||
| 5804da0218 | |||
| d55ab84451 | |||
| 889ce8ee90 | |||
| be1fdbd272 | |||
| 9904d824b8 | |||
| 5b5625f679 | |||
| 59b171172f | |||
| 4cc86b6e92 | |||
| 91937a6961 | |||
| 01972f55fe | |||
| fb7d0c3c01 | |||
| 8c58fd78c3 | |||
| 5648d717b1 | |||
| a0651b3707 | |||
| bb36d55e63 | |||
| 0766cbf511 | |||
| 692c160360 | |||
| ff176231da | |||
| 27c680cc69 | |||
| ff4ad29d05 | |||
| 781163aa9d | |||
| 6ad4e9fd2a | |||
| 1c8ed5fa43 | |||
| 1521ca4c20 | |||
| 127812e645 | |||
| 18557fdeb5 | |||
| 922cf3e2e4 | |||
| 5a18c1f9cd | |||
| aa2258e35b | |||
| f5b1c3da36 | |||
| dd9a7e4540 | |||
| 901b671455 | |||
| b204b6aa7b | |||
| 8797bd695f | |||
| 6c796631fc | |||
| 408a34925d | |||
| ef2401f669 | |||
| b651084713 | |||
| 21363ac78d | |||
| f87a54ab41 | |||
| 52d0310256 | |||
| 342984075b | |||
| 65a46af7ae | |||
| f0f240c0d8 | |||
| db79dd1f88 | |||
| b8123415b2 | |||
| 2ed4f5016a | |||
| 42f997d768 | |||
| 743188642d | |||
| 235b5d0ac5 | |||
| 41ebf965cd | |||
| 189c41221d | |||
| 7c5a829025 | |||
| 3f138e1d8f | |||
| ff7200e75b | |||
| 78f9ba9774 | |||
| 8ff952773d | |||
| a7384e0de2 | |||
| 797fcb8433 | |||
| 7dad9b4297 | |||
| 3e38aa0821 | |||
| a4a8e91022 | |||
| 10e54e365a | |||
| 29d5e43ad4 | |||
| 1286677773 | |||
| 8c411f7fce | |||
| 9b118de9d5 | |||
| 195ef6baca | |||
| 7978910f85 | |||
| ff6ab9dd2b | |||
| 5af9fd53f4 | |||
| 4a9a5cbbe9 | |||
| 6010980914 | |||
| fe4ed96006 | |||
| 4098aa5d19 | |||
| 555aaa432c | |||
| 5eba4281b0 | |||
| c5900bfd59 | |||
| c60c928717 | |||
| 8f924f0530 | |||
| 610a5bafe2 | |||
| 8bc2647e0c | |||
| 1107b4b9cf | |||
| caa7a62591 | |||
| 0c8c9a64b3 | |||
| 679f5d458e | |||
| 1193e4679d | |||
| 35c6f58dce | |||
| 6e7a0c2d86 | |||
| 5529ec74da | |||
| 6d02d2647b | |||
| 5cd01c30b4 | |||
| c76520c5b9 | |||
| 92d317f787 | |||
| eaa560f3fc | |||
| e9b919d550 | |||
| 210f6f89be | |||
| 575a7b85f5 | |||
| f2b21a5f57 | |||
| 3a799b3e4e | |||
| 133f930e61 | |||
| 5c85ddc3d7 | |||
| 0a83dac31c | |||
| 4a36d30493 | |||
| e317e7f4b4 | |||
| 8517b7d2b6 | |||
| b2d590c5f9 | |||
| dcea6335c7 | |||
| 9e88d4bb8a | |||
| eb48fddac7 | |||
| 698386ca2c | |||
| ea9a25e500 | |||
| 0c059b598d | |||
| 490661fd96 | |||
| bb99e73ef5 | |||
| 58c5a95c07 | |||
| 1bed50d424 | |||
| 24b1d7a0c8 | |||
| 91db27aff5 | |||
| f971c15b1f | |||
| a51de65758 | |||
| 5cc7f4b580 | |||
| a1291e79d3 | |||
| b030bc6980 | |||
| 5addf9f111 | |||
| d888e79bb8 | |||
| 3f91c05e5d | |||
| 47ce12d239 | |||
| 5bd8cc7dd5 | |||
| ed1b616f4a | |||
| a7382d3523 | |||
| 15fef79a29 | |||
| ff79000f28 | |||
| 8e3042b565 | |||
| ad2bcef112 | |||
| 3f80dbd51e | |||
| 096c22ad5e | |||
| d3b58968a9 | |||
| f15c80d80f | |||
| e388fc7367 | |||
| c97cdbe523 | |||
| 4400b0ac45 | |||
| 3bad3d6964 | |||
| f504cc761b | |||
| 9015b8822d | |||
| 262addd9ab | |||
| a28a784ef4 | |||
| 15669d302d | |||
| 1c2ad465c6 | |||
| 780187f090 | |||
| 3302bf4dbd | |||
| 1631c64f78 | |||
| 8174305e17 | |||
| 064b681e9b | |||
| 8f14c45197 | |||
| b4afecc626 | |||
| 07f215ad9e | |||
| 53bef48fbe | |||
| 2ec78c0e4b | |||
| b16c2980b3 | |||
| fe225745fc | |||
| 4f2144dac0 | |||
| b18d851119 | |||
| 4eabec5b18 | |||
| 171c944345 | |||
| 8bd5ff4f32 | |||
| faf10c521f | |||
| 71e2bdb2b4 | |||
| 04416ddc51 | |||
| 6326e30f86 | |||
| c855df67a4 | |||
| aecfb0a3b3 | |||
| f73912694b | |||
| d109de8f84 | |||
| 9d82438dcb | |||
| a592883d87 | |||
| 1ffd7ed54f | |||
| a0a1fb876f | |||
| 7acf972c59 | |||
| 441993200e | |||
| 7052c67c36 | |||
| 55a4bea72a | |||
| 0b9efaffd7 | |||
| 6f9b37b35b | |||
| c636e124df | |||
| db8939f481 | |||
| bdc4ffacec | |||
| f7623a0871 | |||
| 2e32cbc4a5 | |||
| be3778dee2 | |||
| 74d5faec93 | |||
| 8ee747dda5 | |||
| 20ff50ad10 | |||
| 9b183a234c | |||
| d3bb31b931 | |||
| 9958c51a5d | |||
| 64ef4582c2 | |||
| 68d700cac6 | |||
| bee10b987c | |||
| 42123a294d | |||
| 635c6b8086 | |||
| 615fc1f083 | |||
| a61f11f307 | |||
| 42305fc126 | |||
| 6c23f1941b | |||
| 0cf237c5b0 | |||
| 6357d35da9 | |||
| 9e278d7ec0 | |||
| ba384470c4 | |||
| 5b070cfa0f | |||
| c4c2589ff0 | |||
| 6172e4355f | |||
| 3d24637325 | |||
| 8960c02b91 | |||
| 2143714d9f | |||
| f1bf103e4e | |||
| 6adbdac676 | |||
| 75bdf00e89 | |||
| f13e2d22fe | |||
| 076bd5758b | |||
| 105c20648e | |||
| fdda1cbe0c | |||
| 1d8cde9d56 | |||
| 51b3b402c4 | |||
| 8cf7bd5448 | |||
| 199f091a95 | |||
| d8295c8674 | |||
| 68ba3980d5 | |||
| e042988dc0 | |||
| 98526f906e | |||
| bb6d32ae71 | |||
| c98d42e802 | |||
| 99623a83aa | |||
| e9540e2881 | |||
| c7cbcfbbbd | |||
| 9175b18226 | |||
| 709cb313cf | |||
| 063a2b338c | |||
| 718c5ff551 | |||
| 9e72ea5ddc | |||
| fd70ca40cc | |||
| 01f07a61e4 | |||
| f8ed7db472 | |||
| 6975fc56f7 | |||
| 41caf1cdfa | |||
| f6ec2b5946 | |||
| e15d5de0a6 | |||
| cf2710e0b6 | |||
| 941602ae4f | |||
| 34e4c6f732 | |||
| 2fbb3fb532 | |||
| df9471b1b5 | |||
| bd1402487b | |||
| 4703b7d092 | |||
| 404ddadbd4 | |||
| fd6beda14b | |||
| 48f5e52728 | |||
| b458cbb601 | |||
| 6593b340ff | |||
| 0de7da1998 | |||
| 6d98c55b56 | |||
| e3eefe00dd | |||
| ecaa021759 | |||
| 7d24afa0de | |||
| 077f9b14f1 | |||
| c5a0ed7b43 | |||
| 8741ca0819 | |||
| 586b2b2a54 | |||
| e1b55a5af9 | |||
| 0507e6e388 | |||
| 9c3eef8c0d | |||
| af35432400 | |||
| cadfdd4e09 | |||
| 5ef9c89977 | |||
| d72ca8f810 | |||
| 2f755cdc3a | |||
| 4c86b2db0f | |||
| 1344b540d9 | |||
| 5b7048d5af | |||
| 7da33383c7 | |||
| c327bd0354 | |||
| 1085eee098 | |||
| eccb42eb0e | |||
| bb24c75b41 | |||
| 54bfc9435f | |||
| d79ce8a459 | |||
| 7c6256234c | |||
| c34ff12c59 | |||
| d60a503b4c | |||
| 05665e9de9 | |||
| efe474af97 | |||
| 6fa46d0e06 | |||
| 2386943f19 | |||
| 18970dac18 | |||
| 38af125238 | |||
| b23f92b286 | |||
| eeb8506c18 | |||
| d081df0a5d | |||
| 09d8e696dc | |||
| 20c118faec | |||
| fefe24ddf8 | |||
| 09f87094bd | |||
| ee8f926027 | |||
| 4ed784d1e8 | |||
| a7f3b0f85b | |||
| c598fdd10c | |||
| 0e7a7e57cc | |||
| 4aaf45e246 | |||
| 89b04f3786 | |||
| 31079226f7 | |||
| 7c492a250b | |||
| e6d3c57204 | |||
| 294cd87afc | |||
| 18ec0d4a34 | |||
| bebe2d8be8 | |||
| 3731703dbb | |||
| 2526668556 | |||
| 33087dbf30 | |||
| b8337932b3 | |||
| 00208479fd | |||
| f765aec406 | |||
| e212493358 | |||
| df903fe056 | |||
| 0462499051 | |||
| 79dac84b31 | |||
| b834f629cc | |||
| c83386cbe5 | |||
| 0445cd1020 | |||
| fa0763eb34 | |||
| c72953a4bc | |||
| c4439fb134 | |||
| 61f2ee6ab8 | |||
| 1550771a6a | |||
| 9a1a4822e8 | |||
| a0693f21fc | |||
| 433af7ab93 | |||
| 32ca0dbcdf | |||
| 12b205c637 | |||
| 4f59d09648 | |||
| f722d91fa8 | |||
| 5d783d5c84 | |||
| e09e451a48 | |||
| 325420616f | |||
| 0e4afddadf | |||
| 7e60106d15 | |||
| 8292aa7a18 | |||
| a8c43830f2 | |||
| 0e93237b17 | |||
| f0c9bc596e | |||
| 788ade3487 | |||
| 538ad6ce58 | |||
| d1122a4c0f | |||
| a40cae7802 | |||
| e871779f7e | |||
| 11a088b7eb | |||
| 07305e3a3a | |||
| ebf9702b34 | |||
| f4744ff1ff | |||
| cbea8d5c3f | |||
| 0f78aafec8 | |||
| 1002bcff43 | |||
| 1aa94b5821 | |||
| 5b80dbe6b3 | |||
| c52c00f670 | |||
| e8ba446a9a | |||
| 2eb9adb564 | |||
| 5b9b7cba22 | |||
| 0901571f0a | |||
| 9c0d777a9f | |||
| 72814933b9 | |||
| 01508c814c | |||
| aeb62886c5 | |||
| d059774365 | |||
| 9b4e7898d7 | |||
| 78bc1339ac | |||
| 2ae4531c89 | |||
| f3ea92cceb | |||
| 2ad1e92858 | |||
| 19ca99eea4 | |||
| 8d5fe073d2 | |||
| b11daa50f9 | |||
| b95c1d0ac9 | |||
| 6c290ccd49 | |||
| 4c3ab545a9 | |||
| 297472a2fc | |||
| d3a4dbe4b8 | |||
| 84a231eb61 | |||
| 3afd5b6d65 | |||
| 99ac2324aa | |||
| 317b7416a6 | |||
| d591a5b93d | |||
| fed13d50a9 | |||
| ec14ef80b0 | |||
| ddc6bd9f21 | |||
| 23afc2c4ec | |||
| c859f0267c | |||
| f8e195159f | |||
| 0868d58e2c | |||
| dfa6289153 | |||
| 35b771e221 | |||
| 5b27ecafbc | |||
| b065eceb56 | |||
| 99200b2f07 | |||
| 14602eafa7 | |||
| 0309fb919a | |||
| 3ac612dd7d | |||
| 642e950e63 | |||
| 6e6dfd6a23 | |||
| 46435a04fd | |||
| 5d8daf184d | |||
| 0a42e9913b | |||
| 4f2f6c74ca | |||
| 2469350ad9 | |||
| 2c26adb873 | |||
| db2a33a3dd | |||
| 5749e1ee43 | |||
| d737feeacf | |||
| 0526db32e2 | |||
| 06915d0145 | |||
| 0221cacea7 | |||
| 6f4e5ee4c9 | |||
| 1d40237bc8 | |||
| ae7ede4a4f | |||
| 366b419d00 | |||
| c494fdb580 | |||
| b6d108f0b3 | |||
| 495ce22d49 | |||
| 73a50fa42c | |||
| d21d5b21db | |||
| 1278ac411c | |||
| d59afcfbfe | |||
| 0389d5f8d0 | |||
| ac94cf3ece | |||
| 5b613ed41b | |||
| fa4c4247a5 | |||
| 1152def76e | |||
| 660322f96f | |||
| 05c6d13027 | |||
| 6951c49779 | |||
| ed27183d83 | |||
| 8181cc6c10 | |||
| de6a4be9b5 | |||
| 3a39c44c21 | |||
| 20728a599e |
+128
-60
@@ -83,9 +83,13 @@ TEMP_STORE = -DSQLITE_TEMP_STORE=@TEMP_STORE@
|
||||
# based on configuration. (-DSQLITE_OMIT*, -DSQLITE_ENABLE*).
|
||||
# The same set of OMIT and ENABLE flags should be passed to the
|
||||
# LEMON parser generator and the mkkeywordhash tool as well.
|
||||
OPT_FEATURE_FLAGS = @OPT_FEATURE_FLAGS@
|
||||
#
|
||||
# Add OPTIONS=... on the command line to append additional options
|
||||
# to the OPT_FEATURE_FLAGS.
|
||||
#
|
||||
OPT_FEATURE_FLAGS = @OPT_FEATURE_FLAGS@ $(OPTIONS)
|
||||
|
||||
TCC += $(OPT_FEATURE_FLAGS)
|
||||
TCC += $(OPT_FEATURE_FLAGS)
|
||||
|
||||
# Add in any optional parameters specified on the make commane line
|
||||
# ie. make "OPTS=-DSQLITE_ENABLE_FOO=1 -DSQLITE_OMIT_FOO=1".
|
||||
@@ -117,14 +121,15 @@ HAVE_TCL = @HAVE_TCL@
|
||||
#
|
||||
TCLSH_CMD = @TCLSH_CMD@
|
||||
|
||||
# Additional options when running tests using testrunner.tcl
|
||||
# This is usually either blank, or else --status
|
||||
#
|
||||
TSTRNNR_OPTS = @TSTRNNR_OPTS@
|
||||
|
||||
# Where do we want to install the tcl plugin
|
||||
#
|
||||
TCLLIBDIR = @TCLLIBDIR@
|
||||
|
||||
# The suffix used on shared libraries. Ex: ".dll", ".so", ".dylib"
|
||||
#
|
||||
SHLIB_SUFFIX = @TCL_SHLIB_SUFFIX@
|
||||
|
||||
# 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
|
||||
# CFLAGS / LDFLAGS, because libtool wants to use CFLAGS when linking, which
|
||||
@@ -454,6 +459,7 @@ TESTSRC += \
|
||||
$(TOP)/ext/misc/remember.c \
|
||||
$(TOP)/ext/misc/series.c \
|
||||
$(TOP)/ext/misc/spellfix.c \
|
||||
$(TOP)/ext/misc/stmtrand.c \
|
||||
$(TOP)/ext/misc/totype.c \
|
||||
$(TOP)/ext/misc/unionvtab.c \
|
||||
$(TOP)/ext/misc/wholenumber.c \
|
||||
@@ -644,6 +650,7 @@ FUZZCHECK_SRC += $(TOP)/test/fuzzinvariants.c
|
||||
FUZZCHECK_SRC += $(TOP)/ext/recover/dbdata.c
|
||||
FUZZCHECK_SRC += $(TOP)/ext/recover/sqlite3recover.c
|
||||
FUZZCHECK_SRC += $(TOP)/test/vt02.c
|
||||
FUZZCHECK_SRC += $(TOP)/ext/misc/percentile.c
|
||||
FUZZCHECK_SRC += $(TOP)/ext/misc/randomjson.c
|
||||
DBFUZZ_OPT =
|
||||
ST_OPT = -DSQLITE_OS_KV_OPTIONAL
|
||||
@@ -654,11 +661,16 @@ SQLITE3_SHELL_TARGET_ = sqlite3$(TEXE)
|
||||
SQLITE3_SHELL_TARGET_1 =
|
||||
SQLITE3_SHELL_TARGET = $(SQLITE3_SHELL_TARGET_@HAVE_WASI_SDK@)
|
||||
|
||||
# Use $(libtclsqlite3.la_$(HAVE_TCL)) to resolve to either
|
||||
# libtclsqlite3.la or an empty value.
|
||||
libtclsqlite3.la_0 =
|
||||
libtclsqlite3.la_1 = libtclsqlite3.la
|
||||
|
||||
# This is the default Makefile target. The objects listed here
|
||||
# are what get build when you type just "make" with no arguments.
|
||||
#
|
||||
all: sqlite3.h libsqlite3.la $(SQLITE3_SHELL_TARGET) \
|
||||
$(HAVE_TCL:1=libtclsqlite3.la)
|
||||
$(libtclsqlite3.la_$(HAVE_TCL))
|
||||
|
||||
Makefile: $(TOP)/Makefile.in
|
||||
./config.status
|
||||
@@ -682,12 +694,26 @@ sqlite3$(TEXE): shell.c sqlite3.c
|
||||
shell.c sqlite3.c \
|
||||
$(LIBREADLINE) $(TLIBS) -rpath "$(libdir)"
|
||||
|
||||
sqldiff$(TEXE): $(TOP)/tool/sqldiff.c sqlite3.lo sqlite3.h
|
||||
$(LTLINK) -o $@ $(TOP)/tool/sqldiff.c sqlite3.lo $(TLIBS)
|
||||
sqldiff$(TEXE): $(TOP)/tool/sqldiff.c $(TOP)/ext/misc/sqlite3_stdio.h sqlite3.lo sqlite3.h
|
||||
$(LTLINK) -I$(TOP)/ext/misc -o $@ $(TOP)/tool/sqldiff.c sqlite3.lo $(TLIBS)
|
||||
|
||||
dbhash$(TEXE): $(TOP)/tool/dbhash.c sqlite3.lo sqlite3.h
|
||||
$(LTLINK) -o $@ $(TOP)/tool/dbhash.c sqlite3.lo $(TLIBS)
|
||||
|
||||
RSYNC_SRC = \
|
||||
$(TOP)/tool/sqlite3-rsync.c \
|
||||
sqlite3.c
|
||||
|
||||
RSYNC_OPT = \
|
||||
-DSQLITE_ENABLE_DBPAGE_VTAB \
|
||||
-USQLITE_THREADSAFE \
|
||||
-DSQLITE_THREADSAFE=0 \
|
||||
-DSQLITE_OMIT_LOAD_EXTENSION \
|
||||
-DSQLITE_OMIT_DEPRECATED
|
||||
|
||||
sqlite3-rsync$(TEXE): $(RSYNC_SRC)
|
||||
$(TCC) -o $@ $(RSYNC_OPT) $(RSYNC_SRC) $(TLIBS)
|
||||
|
||||
scrub$(TEXE): $(TOP)/ext/misc/scrub.c sqlite3.lo
|
||||
$(LTLINK) -o $@ -I. -DSCRUB_STANDALONE \
|
||||
$(TOP)/ext/misc/scrub.c sqlite3.lo $(TLIBS)
|
||||
@@ -799,6 +825,10 @@ has_tclsh85:
|
||||
sh $(TOP)/tool/cktclsh.sh 8.5 $(TCLSH_CMD)
|
||||
touch has_tclsh85
|
||||
|
||||
has_tclconfig:
|
||||
@ if test x"$(HAVE_TCL)" != "x1"; then echo 'ERROR: Requires access to "tclConfig.sh" which "configure" was not able to locate'; exit 1; fi
|
||||
touch has_tclconfig
|
||||
|
||||
|
||||
# This target creates a directory named "tsrc" and fills it with
|
||||
# copies of all of the C source code and header files needed to
|
||||
@@ -1121,7 +1151,7 @@ tclsqlite-shell.lo: $(TOP)/src/tclsqlite.c $(HDR)
|
||||
tclsqlite-stubs.lo: $(TOP)/src/tclsqlite.c $(HDR)
|
||||
$(LTCOMPILE) -DUSE_TCL_STUBS=1 -o $@ -c $(TOP)/src/tclsqlite.c
|
||||
|
||||
tclsqlite3$(TEXE): tclsqlite-shell.lo libsqlite3.la
|
||||
tclsqlite3$(TEXE): has_tclconfig tclsqlite-shell.lo libsqlite3.la
|
||||
$(LTLINK) -o $@ tclsqlite-shell.lo \
|
||||
libsqlite3.la $(LIBTCL)
|
||||
|
||||
@@ -1157,8 +1187,6 @@ keywordhash.h: $(TOP)/tool/mkkeywordhash.c
|
||||
# Source and header files that shell.c depends on
|
||||
SHELL_DEP = \
|
||||
$(TOP)/src/shell.c.in \
|
||||
$(TOP)/ext/consio/console_io.c \
|
||||
$(TOP)/ext/consio/console_io.h \
|
||||
$(TOP)/ext/expert/sqlite3expert.c \
|
||||
$(TOP)/ext/expert/sqlite3expert.h \
|
||||
$(TOP)/ext/intck/sqlite3intck.c \
|
||||
@@ -1172,11 +1200,16 @@ SHELL_DEP = \
|
||||
$(TOP)/ext/misc/ieee754.c \
|
||||
$(TOP)/ext/misc/memtrace.c \
|
||||
$(TOP)/ext/misc/pcachetrace.c \
|
||||
$(TOP)/ext/misc/percentile.c \
|
||||
$(TOP)/ext/misc/regexp.c \
|
||||
$(TOP)/ext/misc/series.c \
|
||||
$(TOP)/ext/misc/sha1.c \
|
||||
$(TOP)/ext/misc/shathree.c \
|
||||
$(TOP)/ext/misc/sqlar.c \
|
||||
$(TOP)/ext/misc/sqlite3_stdio.c \
|
||||
$(TOP)/ext/misc/sqlite3_stdio.h \
|
||||
$(TOP)/ext/misc/uint.c \
|
||||
$(TOP)/ext/misc/vfstrace.c \
|
||||
$(TOP)/ext/misc/zipfile.c \
|
||||
$(TOP)/ext/recover/dbdata.c \
|
||||
$(TOP)/ext/recover/sqlite3recover.c \
|
||||
@@ -1308,7 +1341,7 @@ TESTFIXTURE_SRC1 = sqlite3.c
|
||||
TESTFIXTURE_SRC = $(TESTSRC) $(TOP)/src/tclsqlite.c
|
||||
TESTFIXTURE_SRC += $(TESTFIXTURE_SRC$(USE_AMALGAMATION))
|
||||
|
||||
testfixture$(TEXE): has_tclsh85 $(TESTFIXTURE_SRC)
|
||||
testfixture$(TEXE): has_tclconfig has_tclsh85 $(TESTFIXTURE_SRC)
|
||||
$(LTLINK) -DSQLITE_NO_SYNC=1 $(TEMP_STORE) $(TESTFIXTURE_FLAGS) \
|
||||
-o $@ $(TESTFIXTURE_SRC) $(LIBTCL) $(TLIBS)
|
||||
|
||||
@@ -1357,15 +1390,20 @@ tcltest: ./testfixture$(TEXE)
|
||||
testrunner: testfixture$(TEXE)
|
||||
./testfixture$(TEXE) $(TOP)/test/testrunner.tcl
|
||||
|
||||
# Runs both fuzztest and testrunner, consecutively.
|
||||
# This is the testing target preferred by the core SQLite developers.
|
||||
# It runs tests under a standard configuration, regardless of how
|
||||
# ./configure was run. The devs run "make devtest" prior to each
|
||||
# check-in, at a minimum. Probably other tests too, but at least this
|
||||
# one.
|
||||
#
|
||||
devtest: srctree-check testfixture$(TEXE) fuzztest testrunner
|
||||
devtest: srctree-check sourcetest
|
||||
$(TCLSH_CMD) $(TOP)/test/testrunner.tcl mdevtest $(TSTRNNR_OPTS)
|
||||
|
||||
mdevtest: srctree-check has_tclsh85
|
||||
$(TCLSH_CMD) $(TOP)/test/testrunner.tcl mdevtest
|
||||
$(TCLSH_CMD) $(TOP)/test/testrunner.tcl mdevtest $(TSTRNNR_OPTS)
|
||||
|
||||
sdevtest: has_tclsh85
|
||||
$(TCLSH_CMD) $(TOP)/test/testrunner.tcl sdevtest
|
||||
$(TCLSH_CMD) $(TOP)/test/testrunner.tcl sdevtest $(TSTRNNR_OPTS)
|
||||
|
||||
# Validate that various generated files in the source tree
|
||||
# are up-to-date.
|
||||
@@ -1375,16 +1413,19 @@ srctree-check: $(TOP)/tool/srctree-check.tcl
|
||||
|
||||
# Testing for a release
|
||||
#
|
||||
releasetest: srctree-check testfixture$(TEXE)
|
||||
./testfixture$(TEXE) $(TOP)/test/testrunner.tcl release
|
||||
releasetest: srctree-check has_tclsh85 verify-source
|
||||
$(TCLSH_CMD) $(TOP)/test/testrunner.tcl release $(TSTRNNR_OPTS)
|
||||
|
||||
# Minimal testing that runs in less than 3 minutes
|
||||
#
|
||||
quicktest: ./testfixture$(TEXE)
|
||||
./testfixture$(TEXE) $(TOP)/test/extraquick.test $(TESTOPTS)
|
||||
|
||||
# This is the common case. Run many tests that do not take too long,
|
||||
# including fuzzcheck, sqlite3_analyzer, and sqldiff tests.
|
||||
# Try to run tests on whatever options are specified by the
|
||||
# ./configure. The developers seldom use this target. Instead
|
||||
# they use "make devtest" which runs tests on a standard set of
|
||||
# options regardless of how SQLite is configured. This "test"
|
||||
# target is provided for legacy only.
|
||||
#
|
||||
test: srctree-check fuzztest sourcetest $(TESTPROGS) tcltest
|
||||
|
||||
@@ -1401,19 +1442,19 @@ valgrindtest: $(TESTPROGS) valgrindfuzz
|
||||
smoketest: $(TESTPROGS) fuzzcheck$(TEXE)
|
||||
./testfixture$(TEXE) $(TOP)/test/main.test $(TESTOPTS)
|
||||
|
||||
shelltest: $(TESTPROGS)
|
||||
./testfixture$(TEXT) $(TOP)/test/permutations.test shell
|
||||
shelltest:
|
||||
$(TCLSH_CMD) $(TOP)/test/testrunner.tcl release shell
|
||||
|
||||
sqlite3_analyzer.c: sqlite3.c $(TOP)/src/tclsqlite.c $(TOP)/tool/spaceanal.tcl $(TOP)/tool/mkccode.tcl $(TOP)/tool/sqlite3_analyzer.c.in has_tclsh85
|
||||
$(TCLSH_CMD) $(TOP)/tool/mkccode.tcl $(TOP)/tool/sqlite3_analyzer.c.in >sqlite3_analyzer.c
|
||||
|
||||
sqlite3_analyzer$(TEXE): sqlite3_analyzer.c
|
||||
sqlite3_analyzer$(TEXE): has_tclconfig sqlite3_analyzer.c
|
||||
$(LTLINK) sqlite3_analyzer.c -o $@ $(LIBTCL) $(TLIBS)
|
||||
|
||||
sqltclsh.c: sqlite3.c $(TOP)/src/tclsqlite.c $(TOP)/tool/sqltclsh.tcl $(TOP)/ext/misc/appendvfs.c $(TOP)/tool/mkccode.tcl $(TOP)/tool/sqltclsh.c.in has_tclsh85
|
||||
$(TCLSH_CMD) $(TOP)/tool/mkccode.tcl $(TOP)/tool/sqltclsh.c.in >sqltclsh.c
|
||||
|
||||
sqltclsh$(TEXE): sqltclsh.c
|
||||
sqltclsh$(TEXE): has_tclconfig sqltclsh.c
|
||||
$(LTLINK) sqltclsh.c -o $@ $(LIBTCL) $(TLIBS)
|
||||
|
||||
sqlite3_expert$(TEXE): $(TOP)/ext/expert/sqlite3expert.h $(TOP)/ext/expert/sqlite3expert.c $(TOP)/ext/expert/expert.c sqlite3.c
|
||||
@@ -1432,7 +1473,7 @@ CHECKER_DEPS =\
|
||||
sqlite3_checker.c: $(CHECKER_DEPS) has_tclsh85
|
||||
$(TCLSH_CMD) $(TOP)/tool/mkccode.tcl $(TOP)/ext/repair/sqlite3_checker.c.in >$@
|
||||
|
||||
sqlite3_checker$(TEXE): sqlite3_checker.c
|
||||
sqlite3_checker$(TEXE): has_tclconfig sqlite3_checker.c
|
||||
$(LTLINK) sqlite3_checker.c -o $@ $(LIBTCL) $(TLIBS)
|
||||
|
||||
dbdump$(TEXE): $(TOP)/ext/misc/dbdump.c sqlite3.lo
|
||||
@@ -1546,7 +1587,12 @@ lib_install: libsqlite3.la
|
||||
$(INSTALL) -d $(DESTDIR)$(libdir)
|
||||
$(LTINSTALL) libsqlite3.la $(DESTDIR)$(libdir)
|
||||
|
||||
install: sqlite3$(TEXE) lib_install sqlite3.h sqlite3.pc ${HAVE_TCL:1=tcl_install}
|
||||
# Use $(tcl_install_$(HAVE_TCL)) to resolve to either tcl_install or
|
||||
# an empty value.
|
||||
tcl_install_0 =
|
||||
tcl_install_1 = tcl_install
|
||||
|
||||
install: sqlite3$(TEXE) lib_install sqlite3.h sqlite3.pc $(tcl_install_$(HAVE_TCL))
|
||||
$(INSTALL) -d $(DESTDIR)$(bindir)
|
||||
$(LTINSTALL) sqlite3$(TEXE) $(DESTDIR)$(bindir)
|
||||
$(INSTALL) -d $(DESTDIR)$(includedir)
|
||||
@@ -1557,49 +1603,71 @@ install: sqlite3$(TEXE) lib_install sqlite3.h sqlite3.pc ${HAVE_TCL:1=tcl_instal
|
||||
|
||||
pkgIndex.tcl:
|
||||
echo 'package ifneeded sqlite3 $(RELEASE) [list load [file join $$dir libtclsqlite3[info sharedlibextension]] sqlite3]' > $@
|
||||
|
||||
tcl_install: lib_install libtclsqlite3.la pkgIndex.tcl
|
||||
$(INSTALL) -d $(DESTDIR)$(TCLLIBDIR)
|
||||
$(LTINSTALL) libtclsqlite3.la $(DESTDIR)$(TCLLIBDIR)
|
||||
rm -f $(DESTDIR)$(TCLLIBDIR)/libtclsqlite3.la $(DESTDIR)$(TCLLIBDIR)/libtclsqlite3.a
|
||||
$(INSTALL) -m 0644 pkgIndex.tcl $(DESTDIR)$(TCLLIBDIR)
|
||||
|
||||
clean:
|
||||
rm -f *.lo *.la *.o sqlite3$(TEXE) libsqlite3.la
|
||||
rm -f sqlite3.h opcodes.*
|
||||
rm -rf .libs .deps
|
||||
rm -f lemon$(BEXE) lempar.c parse.* sqlite*.tar.gz
|
||||
rm -f mkkeywordhash$(BEXE) keywordhash.h
|
||||
rm -f mksourceid$(BEXE)
|
||||
rm -f *.da *.bb *.bbg gmon.out
|
||||
rm -rf tsrc .target_source
|
||||
rm -f tclsqlite3$(TEXE)
|
||||
rm -f testfixture$(TEXE) test.db
|
||||
# Build the SQLite TCL extension in a way that make it compatible
|
||||
# with whatever version of TCL is running as $TCLSH_CMD, possibly defined
|
||||
# by --with-tclsh=
|
||||
#
|
||||
tclextension: tclsqlite3.c
|
||||
$(TCLSH_CMD) $(TOP)/tool/buildtclext.tcl --build-only --cc $(CC) $(CFLAGS) $(OPT_FEATURE_FLAGS) $(OPTS)
|
||||
|
||||
# Install the SQLite TCL extension in a way that is appropriate for $TCLSH_CMD
|
||||
# to find it.
|
||||
#
|
||||
tclextension-install: tclsqlite3.c
|
||||
$(TCLSH_CMD) $(TOP)/tool/buildtclext.tcl --cc $(CC) $(CFLAGS) $(OPT_FEATURE_FLAGS) $(OPTS)
|
||||
|
||||
# Install the SQLite TCL extension that is used by $TCLSH_CMD
|
||||
#
|
||||
tclextension-uninstall:
|
||||
$(TCLSH_CMD) $(TOP)/tool/buildtclext.tcl --uninstall
|
||||
|
||||
# List all installed the SQLite TCL extension that is are accessible
|
||||
# by $TCLSH_CMD, included prior versions.
|
||||
#
|
||||
tclextension-list:
|
||||
$(TCLSH_CMD) $(TOP)/tool/buildtclext.tcl --info
|
||||
|
||||
|
||||
# Remove build products sufficient so that subsequent makes will recompile
|
||||
# everything from scratch. Do not remove:
|
||||
#
|
||||
# * test results and test logs
|
||||
# * output from ./configure
|
||||
#
|
||||
tidy:
|
||||
rm -f *.lo *.la *.o *.c *.da *.bb *.bbg gmon.* *.rws sqlite3$(TEXE)
|
||||
rm -f fts5.h keywordhash.h opcodes.h sqlite3.h sqlite3ext.h sqlite3session.h
|
||||
rm -rf .libs .deps tsrc .target_source
|
||||
rm -f lemon$(BEXE) sqlite*.tar.gz
|
||||
rm -f mkkeywordhash$(BEXE) mksourceid$(BEXE)
|
||||
rm -f parse.* fts5parse.*
|
||||
rm -f tclsqlite3$(TEXE) $(TESTPROGS)
|
||||
rm -f LogEst$(TEXE) fts3view$(TEXE) rollback-test$(TEXE) showdb$(TEXE)
|
||||
rm -f showjournal$(TEXE) showstat4$(TEXE) showwal$(TEXE) speedtest1$(TEXE)
|
||||
rm -f wordcount$(TEXE) changeset$(TEXE)
|
||||
rm -f version-info$(TEXT)
|
||||
rm -f sqlite3.dll sqlite3.lib sqlite3.exp sqlite3.def
|
||||
rm -f sqlite3.c
|
||||
rm -f sqlite3rc.h
|
||||
rm -f shell.c sqlite3ext.h
|
||||
rm -f sqlite3_analyzer$(TEXE) sqlite3_analyzer.c
|
||||
rm -f sqlite-*-output.vsix
|
||||
rm -f mptester mptester.exe
|
||||
rm -f rbu rbu.exe
|
||||
rm -f srcck1 srcck1.exe
|
||||
rm -f fuzzershell fuzzershell.exe
|
||||
rm -f fuzzcheck fuzzcheck.exe
|
||||
rm -f sqldiff sqldiff.exe
|
||||
rm -f dbhash dbhash.exe
|
||||
rm -f fts5.* fts5parse.*
|
||||
rm -f threadtest5
|
||||
rm -f src-verify
|
||||
rm -f custom.rws
|
||||
rm -f has_tclsh84 has_tclsh85
|
||||
rm -f wordcount$(TEXE) changeset$(TEXE) version-info$(TEXE)
|
||||
rm -f *.dll *.lib *.exp *.def *.pc *.vsix *.so *.dylib pkgIndex.tcl
|
||||
rm -f sqlite3_analyzer$(TEXE) sqlite3-rsync$(TEXE)
|
||||
rm -f mptester$(TEXE) rbu$(TEXE) srcck1$(TEXE)
|
||||
rm -f fuzzershell$(TEXE) fuzzcheck$(TEXE) sqldiff$(TEXE) dbhash$(TEXE)
|
||||
rm -f threadtest5$(TEXE)
|
||||
rm -f src-verify has_tclsh*
|
||||
|
||||
# Removes build products and test logs. Retains ./configure outputs.
|
||||
#
|
||||
clean: tidy
|
||||
rm -rf omittest* testrunner* testdir*
|
||||
|
||||
# Clean up everything. No exceptions.
|
||||
#
|
||||
distclean: clean
|
||||
rm -f sqlite_cfg.h config.log config.status libtool Makefile sqlite3.pc \
|
||||
$(TESTPROGS)
|
||||
rm -f sqlite_cfg.h config.log config.status Makefile $(LIBTOOL)
|
||||
|
||||
#
|
||||
# Windows section
|
||||
|
||||
+72
-12
@@ -379,6 +379,7 @@ SQLITE_TCL_DEP =
|
||||
# the Windows platform.
|
||||
#
|
||||
!IFNDEF OPT_FEATURE_FLAGS
|
||||
OPT_FEATURE_FLAGS = $(OPT_XTRA)
|
||||
!IF $(MINIMAL_AMALGAMATION)==0
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_FTS3=1
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_FTS5=1
|
||||
@@ -392,6 +393,14 @@ OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_BYTECODE_VTAB=1
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_COLUMN_METADATA=1
|
||||
!ENDIF
|
||||
|
||||
# Additional feature-options above and beyond what are normally used can be
|
||||
# be added using OPTIONS=.... on the command-line. These values are
|
||||
# appended to the OPT_FEATURE_FLAGS variable.
|
||||
#
|
||||
!IFDEF OPTIONS
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) $(OPTIONS)
|
||||
!ENDIF
|
||||
|
||||
# Should the session extension be enabled? If so, add compilation options
|
||||
# to enable it.
|
||||
#
|
||||
@@ -929,7 +938,7 @@ TCLSUFFIX =
|
||||
!ENDIF
|
||||
|
||||
!IFNDEF TCLDIR
|
||||
TCLDIR = $(TOP)\compat\tcl
|
||||
TCLDIR = C:\Tcl
|
||||
!ENDIF
|
||||
|
||||
!IFNDEF TCLINCDIR
|
||||
@@ -1596,6 +1605,7 @@ TESTEXT = \
|
||||
$(TOP)\ext\misc\remember.c \
|
||||
$(TOP)\ext\misc\series.c \
|
||||
$(TOP)\ext\misc\spellfix.c \
|
||||
$(TOP)\ext\misc\stmtrand.c \
|
||||
$(TOP)\ext\misc\totype.c \
|
||||
$(TOP)\ext\misc\unionvtab.c \
|
||||
$(TOP)\ext\misc\wholenumber.c \
|
||||
@@ -1757,6 +1767,7 @@ FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\test\fuzzinvariants.c
|
||||
FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\test\vt02.c
|
||||
FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\ext\recover\dbdata.c
|
||||
FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\ext\recover\sqlite3recover.c
|
||||
FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\ext\misc\percentile.c
|
||||
FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\ext\misc\randomjson.c
|
||||
|
||||
OSSSHELL_SRC = $(TOP)\test\ossshell.c $(TOP)\test\ossfuzz.c
|
||||
@@ -1819,6 +1830,19 @@ pkgIndex.tcl: $(TOP)\VERSION
|
||||
|
||||
$(SQLITE3TCLDLL): libtclsqlite3.lib $(LIBRESOBJS) tclsqlite3.def pkgIndex.tcl
|
||||
$(LD) $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) /DLL /DEF:tclsqlite3.def /OUT:$@ libtclsqlite3.lib $(LIBRESOBJS) $(LTLIBS) $(TLIBS)
|
||||
|
||||
tclextension: $(SQLITE3TCLDLL)
|
||||
|
||||
tclextension-install: $(SQLITE3TCLDLL)
|
||||
$(TCLSH_CMD) $(TOP)\tool\buildtclext.tcl --install-only
|
||||
|
||||
tclextension-uninstall:
|
||||
$(TCLSH_CMD) $(TOP)\tool\buildtclext.tcl --uninstall
|
||||
|
||||
tclextension-list:
|
||||
$(TCLSH_CMD) $(TOP)\tool\buildtclext.tcl --info
|
||||
|
||||
|
||||
# <</mark>>
|
||||
|
||||
$(SQLITE3DLL): $(LIBOBJ) $(LIBRESOBJS) $(CORE_LINK_DEP)
|
||||
@@ -1837,12 +1861,25 @@ $(SQLITE3EXE): shell.c $(SHELL_CORE_DEP) $(LIBRESOBJS) $(SHELL_CORE_SRC) $(SQLIT
|
||||
/link $(SQLITE3EXEPDB) $(LDFLAGS) $(LTLINKOPTS) $(SHELL_LINK_OPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LIBREADLINE) $(LTLIBS) $(TLIBS)
|
||||
|
||||
# <<mark>>
|
||||
sqldiff.exe: $(TOP)\tool\sqldiff.c $(TOP)\ext\consio\console_io.h $(TOP)\ext\consio\console_io.c $(SQLITE3C) $(SQLITE3H) $(LIBRESOBJS)
|
||||
$(LTLINK) $(NO_WARN) -I$(TOP)\ext\consio $(TOP)\tool\sqldiff.c $(TOP)\ext\consio\console_io.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS) $(LIBRESOBJS)
|
||||
sqldiff.exe: $(TOP)\tool\sqldiff.c $(TOP)\ext\misc\sqlite3_stdio.h $(TOP)\ext\misc\sqlite3_stdio.c $(SQLITE3C) $(SQLITE3H) $(LIBRESOBJS)
|
||||
$(LTLINK) $(NO_WARN) -I$(TOP)\ext\misc $(TOP)\tool\sqldiff.c $(TOP)\ext\misc\sqlite3_stdio.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS) $(LIBRESOBJS)
|
||||
|
||||
dbhash.exe: $(TOP)\tool\dbhash.c $(SQLITE3C) $(SQLITE3H)
|
||||
$(LTLINK) $(NO_WARN) $(TOP)\tool\dbhash.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
||||
|
||||
RSYNC_SRC = \
|
||||
$(TOP)\tool\sqlite3-rsync.c \
|
||||
$(SQLITE3C)
|
||||
|
||||
RSYNC_OPT = \
|
||||
-DSQLITE_ENABLE_DBPAGE_VTAB \
|
||||
-DSQLITE_THREADSAFE=0 \
|
||||
-DSQLITE_OMIT_LOAD_EXTENSION \
|
||||
-DSQLITE_OMIT_DEPRECATED
|
||||
|
||||
sqlite3-rsync.exe: $(RSYNC_SRC) $(LIBRESOBJS)
|
||||
$(LTLINK) $(RSYNC_OPT) $(NO_WARN) $(RSYNC_SRC) /link $(LDFLAGS) $(LTLINKOPTS) $(LIBRESOBJS)
|
||||
|
||||
scrub.exe: $(TOP)\ext\misc\scrub.c $(SQLITE3C) $(SQLITE3H)
|
||||
$(LTLINK) $(NO_WARN) -DSCRUB_STANDALONE=1 $(TOP)\ext\misc\scrub.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
||||
|
||||
@@ -1870,6 +1907,10 @@ fuzzcheck.exe: $(FUZZCHECK_SRC) $(SQLITE3C) $(SQLITE3H)
|
||||
fuzzcheck-asan.exe: $(FUZZCHECK_SRC) $(SQLITE3C) $(SQLITE3H)
|
||||
$(LTLINK) $(NO_WARN) /fsanitize=address $(FUZZCHECK_OPTS) $(FUZZCHECK_SRC) $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
||||
|
||||
run-fuzzcheck: fuzzcheck.exe fuzzcheck-asan.exe
|
||||
fuzzcheck --spinner $(FUZZDB)
|
||||
fuzzcheck-asan --spinner $(FUZZDB)
|
||||
|
||||
ossshell.exe: $(OSSSHELL_SRC) $(SQLITE3C) $(SQLITE3H)
|
||||
$(LTLINK) $(NO_WARN) $(FUZZCHECK_OPTS) $(OSSSHELL_SRC) $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
||||
|
||||
@@ -2275,8 +2316,6 @@ keywordhash.h: $(TOP)\tool\mkkeywordhash.c mkkeywordhash.exe
|
||||
# Source and header files that shell.c depends on
|
||||
SHELL_DEP = \
|
||||
$(TOP)\src\shell.c.in \
|
||||
$(TOP)\ext\consio\console_io.c \
|
||||
$(TOP)\ext\consio\console_io.h \
|
||||
$(TOP)\ext\expert\sqlite3expert.c \
|
||||
$(TOP)\ext\expert\sqlite3expert.h \
|
||||
$(TOP)\ext\intck\sqlite3intck.c \
|
||||
@@ -2290,11 +2329,16 @@ SHELL_DEP = \
|
||||
$(TOP)\ext\misc\ieee754.c \
|
||||
$(TOP)\ext\misc\memtrace.c \
|
||||
$(TOP)\ext\misc\pcachetrace.c \
|
||||
$(TOP)\ext\misc\percentile.c \
|
||||
$(TOP)\ext\misc\regexp.c \
|
||||
$(TOP)\ext\misc\series.c \
|
||||
$(TOP)\ext\misc\sha1.c \
|
||||
$(TOP)\ext\misc\shathree.c \
|
||||
$(TOP)\ext\misc\sqlar.c \
|
||||
$(TOP)\ext\misc\sqlite3_stdio.c \
|
||||
$(TOP)\ext\misc\sqlite3_stdio.h \
|
||||
$(TOP)\ext\misc\uint.c \
|
||||
$(TOP)\ext\misc\vfstrace.c \
|
||||
$(TOP)\ext\misc\zipfile.c \
|
||||
$(TOP)\ext\recover\dbdata.c \
|
||||
$(TOP)\ext\recover\sqlite3recover.c \
|
||||
@@ -2521,6 +2565,13 @@ queryplantest: testfixture.exe shell
|
||||
fuzztest: fuzzcheck.exe
|
||||
.\fuzzcheck.exe $(FUZZDATA)
|
||||
|
||||
# Legacy testing target for third-party integrators. The SQLite
|
||||
# developers seldom use this target themselves. Instead
|
||||
# they use "nmake /f Makefile.msc devtest" which runs tests on
|
||||
# a standard set of options
|
||||
#
|
||||
test: $(TESTPROGS) sourcetest fuzztest tcltest
|
||||
|
||||
# Minimal testing that runs in less than 3 minutes (on a fast machine)
|
||||
#
|
||||
quicktest: testfixture.exe sourcetest
|
||||
@@ -2530,7 +2581,6 @@ quicktest: testfixture.exe sourcetest
|
||||
# This is the common case. Run many tests that do not take too long,
|
||||
# including fuzzcheck, sqlite3_analyzer, and sqldiff tests.
|
||||
#
|
||||
test: $(TESTPROGS) sourcetest fuzztest tcltest
|
||||
|
||||
# The veryquick.test TCL tests.
|
||||
#
|
||||
@@ -2544,17 +2594,27 @@ tcltest: testfixture.exe
|
||||
testrunner: testfixture.exe
|
||||
.\testfixture.exe $(TOP)\test\testrunner.tcl
|
||||
|
||||
# Runs both fuzztest and testrunner, consecutively.
|
||||
# This is the testing target preferred by the core SQLite developers.
|
||||
# It runs tests under a standard configuration. The devs run
|
||||
# "nmake /f Makefile.msc devtest" prior to each check-in, at a minimum.
|
||||
# Probably other tests too, but at least this one.
|
||||
#
|
||||
devtest: testfixture.exe fuzztest testrunner
|
||||
devtest: srctree-check sourcetest
|
||||
$(TCLSH_CMD) $(TOP)\test\testrunner.tcl mdevtest
|
||||
|
||||
mdevtest:
|
||||
$(TCLSH_CMD) $(TOP)\test\testrunner.tcl mdevtest
|
||||
|
||||
# Validate that various generated files in the source tree
|
||||
# are up-to-date.
|
||||
#
|
||||
srctree-check: $(TOP)\tool\srctree-check.tcl
|
||||
$(TCLSH_CMD) $(TOP)\tool\srctree-check.tcl
|
||||
|
||||
# Testing for a release
|
||||
#
|
||||
releasetest: testfixture.exe
|
||||
testfixture.exe $(TOP)\test\testrunner.tcl release
|
||||
releasetest:
|
||||
$(TCLSH_CMD) $(TOP)\test\testrunner.tcl release
|
||||
|
||||
|
||||
smoketest: $(TESTPROGS)
|
||||
@@ -2564,7 +2624,7 @@ smoketest: $(TESTPROGS)
|
||||
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\consio\console_io.h $(TOP)\ext\consio\console_io.c $(SQLITE_TCL_DEP)
|
||||
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 > $@
|
||||
|
||||
sqlite3_analyzer.exe: sqlite3_analyzer.c $(LIBRESOBJS)
|
||||
@@ -2719,7 +2779,7 @@ clean:
|
||||
del /Q sqlite3.c sqlite3-*.c sqlite3.h 2>NUL
|
||||
del /Q sqlite3rc.h 2>NUL
|
||||
del /Q shell.c sqlite3ext.h sqlite3session.h 2>NUL
|
||||
del /Q sqlite3_analyzer.exe sqlite3_analyzer.c 2>NUL
|
||||
del /Q sqlite3_analyzer.exe sqlite3_analyzer.c sqlite3-rsync.exe 2>NUL
|
||||
del /Q sqlite-*-output.vsix 2>NUL
|
||||
del /Q fuzzershell.exe fuzzcheck.exe sqldiff.exe dbhash.exe 2>NUL
|
||||
del /Q sqltclsh.* 2>NUL
|
||||
|
||||
@@ -1,14 +1,19 @@
|
||||
<h1 align="center">SQLite Source Repository</h1>
|
||||
|
||||
This repository contains the complete source code for the
|
||||
[SQLite database engine](https://sqlite.org/). Some test scripts
|
||||
are also included. However, many other test scripts
|
||||
[SQLite database engine](https://sqlite.org/), including
|
||||
many test scripts. However, other test scripts
|
||||
and most of the documentation are managed separately.
|
||||
|
||||
See the [on-line documentation](https://sqlite.org/) for more information
|
||||
about what SQLite is and how it works from a user's perspective. This
|
||||
README file is about the source code that goes into building SQLite,
|
||||
not about how SQLite is used.
|
||||
|
||||
## Version Control
|
||||
|
||||
SQLite sources are managed using
|
||||
[Fossil](https://www.fossil-scm.org/), a distributed version control system
|
||||
[Fossil](https://fossil-scm.org/), a distributed version control system
|
||||
that was specifically designed and written to support SQLite development.
|
||||
The [Fossil repository](https://sqlite.org/src/timeline) contains the urtext.
|
||||
|
||||
@@ -68,24 +73,26 @@ archives or [SQLite archives](https://sqlite.org/cli.html#sqlar) as follows:
|
||||
then click on the "Tarball" or "ZIP Archive" links on the information
|
||||
page.
|
||||
|
||||
If you do want to use Fossil to check out the source tree,
|
||||
To access sources directly using [Fossil](https://fossil-scm.org/home),
|
||||
first install Fossil version 2.0 or later.
|
||||
(Source tarballs and precompiled binaries available
|
||||
[here](https://www.fossil-scm.org/fossil/uv/download.html). Fossil is
|
||||
Source tarballs and precompiled binaries available at
|
||||
<https://fossil-scm.org/home/uv/download.html>. Fossil is
|
||||
a stand-alone program. To install, simply download or build the single
|
||||
executable file and put that file someplace on your $PATH.)
|
||||
executable file and put that file someplace on your $PATH.
|
||||
Then run commands like this:
|
||||
|
||||
mkdir -p ~/sqlite ~/Fossils
|
||||
mkdir -p ~/sqlite
|
||||
cd ~/sqlite
|
||||
fossil clone https://www.sqlite.org/src ~/Fossils/sqlite.fossil
|
||||
fossil open ~/Fossils/sqlite.fossil
|
||||
fossil open https://sqlite.org/src
|
||||
|
||||
After setting up a repository using the steps above, you can always
|
||||
update to the latest version using:
|
||||
The "fossil open" command will take two or three minutes. Afterwards,
|
||||
you can do fast, bandwidth-efficient updates to the whatever versions
|
||||
of SQLite you like. Some examples:
|
||||
|
||||
fossil update trunk ;# latest trunk check-in
|
||||
fossil update release ;# latest official release
|
||||
fossil update trunk ;# latest trunk check-in
|
||||
fossil update release ;# latest official release
|
||||
fossil update trunk:2024-01-01 ;# First trunk check-in after 2024-01-01
|
||||
fossil update version-3.39.0 ;# Version 3.39.0
|
||||
|
||||
Or type "fossil ui" to get a web-based user interface.
|
||||
|
||||
@@ -99,15 +106,42 @@ script found at the root of the source tree. Then run "make".
|
||||
|
||||
For example:
|
||||
|
||||
tar xzf sqlite.tar.gz ;# Unpack the source tree into "sqlite"
|
||||
mkdir bld ;# Build will occur in a sibling directory
|
||||
cd bld ;# Change to the build directory
|
||||
../sqlite/configure ;# Run the configure script
|
||||
make ;# Builds the "sqlite3" command-line tool
|
||||
make sqlite3.c ;# Build the "amalgamation" source file
|
||||
make devtest ;# Run some tests (requires Tcl)
|
||||
apt install gcc make tcl-dev ;# Make sure you have all the necessary build tools
|
||||
tar xzf sqlite.tar.gz ;# Unpack the source tree into "sqlite"
|
||||
mkdir bld ;# Build will occur in a sibling directory
|
||||
cd bld ;# Change to the build directory
|
||||
../sqlite/configure ;# Run the configure script
|
||||
make sqlite3 ;# Builds the "sqlite3" command-line tool
|
||||
make sqlite3.c ;# Build the "amalgamation" source file
|
||||
make sqldiff ;# Builds the "sqldiff" command-line tool
|
||||
# Makefile targets below this point require tcl-dev
|
||||
make tclextension-install ;# Build and install the SQLite TCL extension
|
||||
make devtest ;# Run development tests
|
||||
make releasetest ;# Run full release tests
|
||||
make sqlite3_analyzer ;# Builds the "sqlite3_analyzer" tool
|
||||
|
||||
See the makefile for additional targets.
|
||||
See the makefile for additional targets. For debugging builds, the
|
||||
core developers typically run "configure" with options like this:
|
||||
|
||||
../sqlite/configure --enable-all --enable-debug CFLAGS='-O0 -g'
|
||||
|
||||
For release builds, the core developers usually do:
|
||||
|
||||
../sqlite/configure --enable-all
|
||||
|
||||
Almost all makefile targets require a "tclsh" TCL interpreter version 8.6 or
|
||||
later. The "tclextension-install" target and the test targets that follow
|
||||
all require TCL development libraries too. ("apt install tcl-dev"). It is
|
||||
helpful, but is not required, to install the SQLite TCL extension (the
|
||||
"tclextension-install" target) prior to running tests. The "releasetest"
|
||||
target has additional requiremenst, such as "valgrind".
|
||||
|
||||
On "make" command-lines, one can add "OPTIONS=..." to specify additional
|
||||
compile-time options over and above those set by ./configure. For example,
|
||||
to compile with the SQLITE_OMIT_DEPRECATED compile-time option, one could say:
|
||||
|
||||
./configure --enable-all
|
||||
make OPTIONS=-DSQLITE_OMIT_DEPRECATED sqlite3
|
||||
|
||||
The configure script uses autoconf 2.61 and libtool. If the configure
|
||||
script does not work out for you, there is a generic makefile named
|
||||
@@ -117,7 +151,7 @@ show what changes are needed.
|
||||
|
||||
## Compiling for Windows Using MSVC
|
||||
|
||||
On Windows, all applicable build products can be compiled with MSVC.
|
||||
On Windows, everything can be compiled with MSVC.
|
||||
You will also need a working installation of TCL.
|
||||
See the [compile-for-windows.md](doc/compile-for-windows.md) document for
|
||||
additional information about how to install MSVC and TCL and configure your
|
||||
@@ -128,48 +162,72 @@ TCL library, using a command like this:
|
||||
|
||||
set TCLDIR=c:\Tcl
|
||||
|
||||
SQLite uses "tclsh.exe" as part of the build process, and so that utility
|
||||
program will need to be somewhere on your %PATH%. The finished SQLite library
|
||||
does not contain any TCL code, but it does use TCL to help with the build process
|
||||
and to run tests.
|
||||
SQLite uses "tclsh.exe" as part of the build process, and so that
|
||||
program will need to be somewhere on your %PATH%. SQLite itself
|
||||
does not contain any TCL code, but it does use TCL to help with the
|
||||
build process and to run tests. You may need to install TCL development
|
||||
libraries in order to successfully complete some makefile targets.
|
||||
It is helpful, but is not required, to install the SQLite TCL extension
|
||||
(the "tclextension-install" target) prior to running tests.
|
||||
|
||||
Build using Makefile.msc. Example:
|
||||
|
||||
nmake /f Makefile.msc
|
||||
nmake /f Makefile.msc sqlite3.exe
|
||||
nmake /f Makefile.msc sqlite3.c
|
||||
nmake /f Makefile.msc sqldiff.exe
|
||||
# Makefile targets below this point require TCL development libraries
|
||||
nmake /f Makefile.msc tclextension-install
|
||||
nmake /f Makefile.msc devtest
|
||||
nmake /f Makefile.msc releasetest
|
||||
nmake /f Makefile.msc sqlite3_analyzer.exe
|
||||
|
||||
There are many other makefile targets. See comments in Makefile.msc for
|
||||
details.
|
||||
|
||||
## Source Code Tour
|
||||
As with the unix Makefile, the OPTIONS=... argument can be passed on the nmake
|
||||
command-line to enable new compile-time options. For example:
|
||||
|
||||
Most of the core source files are in the **src/** subdirectory. The
|
||||
**src/** folder also contains files used to build the "testfixture" test
|
||||
harness. The names of the source files used by "testfixture" all begin
|
||||
with "test".
|
||||
The **src/** also contains the "shell.c" file
|
||||
which is the main program for the "sqlite3.exe"
|
||||
[command-line shell](https://sqlite.org/cli.html) and
|
||||
the "tclsqlite.c" file which implements the
|
||||
[Tcl bindings](https://sqlite.org/tclsqlite.html) for SQLite.
|
||||
(Historical note: SQLite began as a Tcl
|
||||
extension and only later escaped to the wild as an independent library.)
|
||||
nmake /f Makefile.msc OPTIONS=-DSQLITE_OMIT_DEPRECATED sqlite3.exe
|
||||
|
||||
Test scripts and programs are found in the **test/** subdirectory.
|
||||
Additional test code is found in other source repositories.
|
||||
See [How SQLite Is Tested](https://www.sqlite.org/testing.html) for
|
||||
additional information.
|
||||
## Source Tree Map
|
||||
|
||||
The **ext/** subdirectory contains code for extensions. The
|
||||
Full-text search engine is in **ext/fts3**. The R-Tree engine is in
|
||||
**ext/rtree**. The **ext/misc** subdirectory contains a number of
|
||||
smaller, single-file extensions, such as a REGEXP operator.
|
||||
* **src/** - This directory contains the primary source code for the
|
||||
SQLite core. For historical reasons, C-code used for testing is
|
||||
also found here. Source files intended for testing begin with "`test`".
|
||||
The `tclsqlite3.c` and `tclsqlite3.h` files are the TCL interface
|
||||
for SQLite and are also not part of the core.
|
||||
|
||||
The **tool/** subdirectory contains various scripts and programs used
|
||||
for building generated source code files or for testing or for generating
|
||||
accessory programs such as "sqlite3_analyzer(.exe)".
|
||||
* **test/** - This directory and its subdirectories contains code used
|
||||
for testing. Files that end in "`.test`" are TCL scripts that run
|
||||
tests using an augmented TCL interpreter named "testfixture". Use
|
||||
a command like "`make testfixture`" (unix) or
|
||||
"`nmake /f Makefile.msc testfixture.exe`" (windows) to build that
|
||||
augmented TCL interpreter, then run individual tests using commands like
|
||||
"`testfixture test/main.test`". This test/ subdirectory also contains
|
||||
additional C code modules and scripts for other kinds of testing.
|
||||
|
||||
* **tool/** - This directory contains programs and scripts used to
|
||||
build some of the machine-generated code that goes into the SQLite
|
||||
core, as well as to build and run tests and perform diagnostics.
|
||||
The source code to [the Lemon parser generator](./doc/lemon.html) is
|
||||
found here. There are also TCL scripts used to build and/or transform
|
||||
source code files. For example, the tool/mksqlite3h.tcl script reads
|
||||
the src/sqlite.h.in file and uses it as a template to construct
|
||||
the deliverable "sqlite3.h" file that defines the SQLite interface.
|
||||
|
||||
* **ext/** - Various extensions to SQLite are found under this
|
||||
directory. For example, the FTS5 subsystem is in "ext/fts5/".
|
||||
Some of these extensions (ex: FTS3/4, FTS5, RTREE) might get built
|
||||
into the SQLite amalgamation, but not all of them. The
|
||||
"ext/misc/" subdirectory contains an assortment of one-file extensions,
|
||||
many of which are omitted from the SQLite core, but which are included
|
||||
in the [SQLite CLI](https://sqlite.org/cli.html).
|
||||
|
||||
* **doc/** - Some documentation files about SQLite internals are found
|
||||
here. Note, however, that the primary documentation designed for
|
||||
application developers and users of SQLite is in a completely separate
|
||||
repository. Note also that the primary API documentation is derived
|
||||
from specially constructed comments in the src/sqlite.h.in file.
|
||||
|
||||
### Generated Source Code Files
|
||||
|
||||
@@ -252,31 +310,37 @@ individual source file exceeds 32K lines in length.
|
||||
SQLite is modular in design.
|
||||
See the [architectural description](https://www.sqlite.org/arch.html)
|
||||
for details. Other documents that are useful in
|
||||
(helping to understand how SQLite works include the
|
||||
helping to understand how SQLite works include the
|
||||
[file format](https://www.sqlite.org/fileformat2.html) description,
|
||||
the [virtual machine](https://www.sqlite.org/opcode.html) that runs
|
||||
prepared statements, the description of
|
||||
[how transactions work](https://www.sqlite.org/atomiccommit.html), and
|
||||
the [overview of the query planner](https://www.sqlite.org/optoverview.html).
|
||||
|
||||
Years of effort have gone into optimizing SQLite, both
|
||||
Decades of effort have gone into optimizing SQLite, both
|
||||
for small size and high performance. And optimizations tend to result in
|
||||
complex code. So there is a lot of complexity in the current SQLite
|
||||
implementation. It will not be the easiest library in the world to hack.
|
||||
|
||||
Key files:
|
||||
### Key source code files
|
||||
|
||||
* **sqlite.h.in** - This file defines the public interface to the SQLite
|
||||
library. Readers will need to be familiar with this interface before
|
||||
trying to understand how the library works internally.
|
||||
trying to understand how the library works internally. This file is
|
||||
really a template that is transformed into the "sqlite3.h" deliverable
|
||||
using a script invoked by the makefile.
|
||||
|
||||
* **sqliteInt.h** - this header file defines many of the data objects
|
||||
used internally by SQLite. In addition to "sqliteInt.h", some
|
||||
subsystems have their own header files.
|
||||
subsystems inside of sQLite have their own header files. These internal
|
||||
interfaces are not for use by applications. They can and do change
|
||||
from one release of SQLite to the next.
|
||||
|
||||
* **parse.y** - This file describes the LALR(1) grammar that SQLite uses
|
||||
to parse SQL statements, and the actions that are taken at each step
|
||||
in the parsing process.
|
||||
in the parsing process. The file is processed by the
|
||||
[Lemon Parser Generator](./doc/lemon.html) to produce the actual C code
|
||||
used for parsing.
|
||||
|
||||
* **vdbe.c** - This file implements the virtual machine that runs
|
||||
prepared statements. There are various helper files whose names
|
||||
@@ -319,6 +383,11 @@ Key files:
|
||||
(and some other test programs too) is built and run when you type
|
||||
"make test".
|
||||
|
||||
* **VERSION**, **manifest**, and **manifest.uuid** - These files define
|
||||
the current SQLite version number. The "VERSION" file is human generated,
|
||||
but the "manifest" and "manifest.uuid" files are automatically generated
|
||||
by the [Fossil version control system](https://fossil-scm.org/).
|
||||
|
||||
There are many other source files. Each has a succinct header comment that
|
||||
describes its purpose and role within the larger system.
|
||||
|
||||
@@ -336,7 +405,7 @@ The `manifest.uuid` file should contain the SHA3-256 hash of the
|
||||
`manifest` file. If all of the above hash comparisons are correct, then
|
||||
you can be confident that your source tree is authentic and unadulterated.
|
||||
Details on the format for the `manifest` files are available
|
||||
[on the Fossil website](https://fossil-scm.org/fossil/doc/trunk/www/fileformat.wiki#manifest).
|
||||
[on the Fossil website](https://fossil-scm.org/home/doc/trunk/www/fileformat.wiki#manifest).
|
||||
|
||||
The process of checking source code authenticity is automated by the
|
||||
makefile:
|
||||
@@ -357,3 +426,7 @@ The main SQLite website is [https://sqlite.org/](https://sqlite.org/)
|
||||
with geographically distributed backups at
|
||||
[https://www2.sqlite.org/](https://www2.sqlite.org) and
|
||||
[https://www3.sqlite.org/](https://www3.sqlite.org).
|
||||
|
||||
Contact the SQLite developers through the
|
||||
[SQLite Forum](https://sqlite.org/forum/). In an emergency, you
|
||||
can send private email to the lead developer at drh at sqlite dot org.
|
||||
|
||||
@@ -301,6 +301,7 @@ SQLITE3EXEPDB = /pdb:sqlite3sh.pdb
|
||||
# the Windows platform.
|
||||
#
|
||||
!IFNDEF OPT_FEATURE_FLAGS
|
||||
OPT_FEATURE_FLAGS = $(OPT_XTRA)
|
||||
!IF $(MINIMAL_AMALGAMATION)==0
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_FTS3=1
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_FTS5=1
|
||||
@@ -314,6 +315,14 @@ OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_BYTECODE_VTAB=1
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_COLUMN_METADATA=1
|
||||
!ENDIF
|
||||
|
||||
# Additional feature-options above and beyond what are normally used can be
|
||||
# be added using OPTIONS=.... on the command-line. These values are
|
||||
# appended to the OPT_FEATURE_FLAGS variable.
|
||||
#
|
||||
!IFDEF OPTIONS
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) $(OPTIONS)
|
||||
!ENDIF
|
||||
|
||||
# Should the session extension be enabled? If so, add compilation options
|
||||
# to enable it.
|
||||
#
|
||||
|
||||
@@ -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.46.0])
|
||||
AC_INIT([sqlite],[3.47.0])
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# Call TEA_INIT as the first TEA_ macro to set up initial vars.
|
||||
|
||||
@@ -4064,4 +4064,4 @@ AC_DEFUN([TEA_ZIPFS_SUPPORT], [
|
||||
|
||||
# Local Variables:
|
||||
# mode: autoconf
|
||||
# End:
|
||||
# End:
|
||||
|
||||
@@ -708,4 +708,3 @@ TK_INCLUDES = -I"$(_TKDIR)\generic" -I"$(_TKDIR)\win" -I"$(_TKDIR)\xlib"
|
||||
!message *** Link options '$(LINKERFLAGS)'
|
||||
|
||||
!endif
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#! /bin/sh
|
||||
# Guess values for system-dependent variables and create Makefiles.
|
||||
# Generated by GNU Autoconf 2.69 for sqlite 3.46.0.
|
||||
# Generated by GNU Autoconf 2.69 for sqlite 3.47.0.
|
||||
#
|
||||
#
|
||||
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
|
||||
@@ -726,8 +726,8 @@ MAKEFLAGS=
|
||||
# Identity of this package.
|
||||
PACKAGE_NAME='sqlite'
|
||||
PACKAGE_TARNAME='sqlite'
|
||||
PACKAGE_VERSION='3.46.0'
|
||||
PACKAGE_STRING='sqlite 3.46.0'
|
||||
PACKAGE_VERSION='3.47.0'
|
||||
PACKAGE_STRING='sqlite 3.47.0'
|
||||
PACKAGE_BUGREPORT=''
|
||||
PACKAGE_URL=''
|
||||
|
||||
@@ -781,18 +781,6 @@ TARGET_HAVE_EDITLINE
|
||||
TARGET_HAVE_READLINE
|
||||
TARGET_READLINE_INC
|
||||
TARGET_READLINE_LIBS
|
||||
HAVE_TCL
|
||||
TCL_SHLIB_SUFFIX
|
||||
TCL_STUB_LIB_SPEC
|
||||
TCL_STUB_LIB_FLAG
|
||||
TCL_STUB_LIB_FILE
|
||||
TCL_LIB_SPEC
|
||||
TCL_LIB_FLAG
|
||||
TCL_LIB_FILE
|
||||
TCL_INCLUDE_SPEC
|
||||
TCL_SRC_DIR
|
||||
TCL_BIN_DIR
|
||||
TCL_VERSION
|
||||
TARGET_EXEEXT
|
||||
SQLITE_OS_WIN
|
||||
SQLITE_OS_UNIX
|
||||
@@ -805,7 +793,12 @@ HAVE_WASI_SDK
|
||||
RELEASE
|
||||
VERSION
|
||||
program_prefix
|
||||
TSTRNNR_OPTS
|
||||
TCLLIBDIR
|
||||
HAVE_TCL
|
||||
TCL_STUB_LIB_SPEC
|
||||
TCL_LIB_SPEC
|
||||
TCL_INCLUDE_SPEC
|
||||
TCLSH_CMD
|
||||
INSTALL_DATA
|
||||
INSTALL_SCRIPT
|
||||
@@ -894,12 +887,14 @@ enable_fast_install
|
||||
with_gnu_ld
|
||||
enable_libtool_lock
|
||||
enable_largefile
|
||||
with_tclsh
|
||||
with_tcl
|
||||
enable_tcl
|
||||
enable_test_status
|
||||
with_wasi_sdk
|
||||
enable_threadsafe
|
||||
enable_releasemode
|
||||
enable_tempstore
|
||||
enable_tcl
|
||||
with_tcl
|
||||
enable_editline
|
||||
enable_readline
|
||||
with_readline_lib
|
||||
@@ -1472,7 +1467,7 @@ if test "$ac_init_help" = "long"; then
|
||||
# Omit some internal or obsolete options to make the list less imposing.
|
||||
# This message is too long to be a string in the A/UX 3.1 sh.
|
||||
cat <<_ACEOF
|
||||
\`configure' configures sqlite 3.46.0 to adapt to many kinds of systems.
|
||||
\`configure' configures sqlite 3.47.0 to adapt to many kinds of systems.
|
||||
|
||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||
|
||||
@@ -1537,7 +1532,7 @@ fi
|
||||
|
||||
if test -n "$ac_init_help"; then
|
||||
case $ac_init_help in
|
||||
short | recursive ) echo "Configuration of sqlite 3.46.0:";;
|
||||
short | recursive ) echo "Configuration of sqlite 3.47.0:";;
|
||||
esac
|
||||
cat <<\_ACEOF
|
||||
|
||||
@@ -1551,11 +1546,13 @@ Optional Features:
|
||||
optimize for fast installation [default=yes]
|
||||
--disable-libtool-lock avoid locking (might break parallel builds)
|
||||
--disable-largefile omit support for large files
|
||||
--disable-tcl omit building accessory programs that require
|
||||
TCL-dev
|
||||
--enable-test-status Full-screen status of tests
|
||||
--disable-threadsafe Disable mutexing
|
||||
--enable-releasemode Support libtool link to release mode
|
||||
--enable-tempstore Use an in-ram database for temporary tables
|
||||
(never,no,yes,always)
|
||||
--disable-tcl do not build TCL extension
|
||||
--enable-editline enable BSD editline support
|
||||
--disable-readline disable readline support
|
||||
--enable-debug enable debugging & verbose explain
|
||||
@@ -1583,10 +1580,10 @@ Optional Packages:
|
||||
--with-pic try to use only PIC/non-PIC objects [default=use
|
||||
both]
|
||||
--with-gnu-ld assume the C compiler uses GNU ld [default=no]
|
||||
--with-tclsh=PATHNAME full pathname of a tclsh to use
|
||||
--with-tcl=DIR directory containing (tclConfig.sh)
|
||||
--with-wasi-sdk=DIR directory containing the WASI SDK. Triggers
|
||||
cross-compile to WASM.
|
||||
--with-tcl=DIR directory containing tcl configuration
|
||||
(tclConfig.sh)
|
||||
--with-readline-lib specify readline library
|
||||
--with-readline-inc specify readline include paths
|
||||
--with-linenoise=DIR source directory for linenoise library
|
||||
@@ -1668,7 +1665,7 @@ fi
|
||||
test -n "$ac_init_help" && exit $ac_status
|
||||
if $ac_init_version; then
|
||||
cat <<\_ACEOF
|
||||
sqlite configure 3.46.0
|
||||
sqlite configure 3.47.0
|
||||
generated by GNU Autoconf 2.69
|
||||
|
||||
Copyright (C) 2012 Free Software Foundation, Inc.
|
||||
@@ -2087,7 +2084,7 @@ cat >config.log <<_ACEOF
|
||||
This file contains any messages produced by compilers while
|
||||
running configure, to aid debugging if configure makes a mistake.
|
||||
|
||||
It was created by sqlite $as_me 3.46.0, which was
|
||||
It was created by sqlite $as_me 3.47.0, which was
|
||||
generated by GNU Autoconf 2.69. Invocation command line was
|
||||
|
||||
$ $0 $@
|
||||
@@ -3945,13 +3942,13 @@ if ${lt_cv_nm_interface+:} false; then :
|
||||
else
|
||||
lt_cv_nm_interface="BSD nm"
|
||||
echo "int some_variable = 0;" > conftest.$ac_ext
|
||||
(eval echo "\"\$as_me:3948: $ac_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:3945: $ac_compile\"" >&5)
|
||||
(eval "$ac_compile" 2>conftest.err)
|
||||
cat conftest.err >&5
|
||||
(eval echo "\"\$as_me:3951: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
|
||||
(eval echo "\"\$as_me:3948: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
|
||||
(eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
|
||||
cat conftest.err >&5
|
||||
(eval echo "\"\$as_me:3954: output\"" >&5)
|
||||
(eval echo "\"\$as_me:3951: output\"" >&5)
|
||||
cat conftest.out >&5
|
||||
if $GREP 'External.*some_variable' conftest.out > /dev/null; then
|
||||
lt_cv_nm_interface="MS dumpbin"
|
||||
@@ -5157,7 +5154,7 @@ ia64-*-hpux*)
|
||||
;;
|
||||
*-*-irix6*)
|
||||
# Find out which ABI we are using.
|
||||
echo '#line 5160 "configure"' > conftest.$ac_ext
|
||||
echo '#line 5157 "configure"' > conftest.$ac_ext
|
||||
if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
|
||||
(eval $ac_compile) 2>&5
|
||||
ac_status=$?
|
||||
@@ -6682,11 +6679,11 @@ else
|
||||
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
|
||||
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
|
||||
-e 's:$: $lt_compiler_flag:'`
|
||||
(eval echo "\"\$as_me:6685: $lt_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:6682: $lt_compile\"" >&5)
|
||||
(eval "$lt_compile" 2>conftest.err)
|
||||
ac_status=$?
|
||||
cat conftest.err >&5
|
||||
echo "$as_me:6689: \$? = $ac_status" >&5
|
||||
echo "$as_me:6686: \$? = $ac_status" >&5
|
||||
if (exit $ac_status) && test -s "$ac_outfile"; then
|
||||
# The compiler can only warn and ignore the option if not recognized
|
||||
# So say no if there are warnings other than the usual output.
|
||||
@@ -7021,11 +7018,11 @@ else
|
||||
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
|
||||
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
|
||||
-e 's:$: $lt_compiler_flag:'`
|
||||
(eval echo "\"\$as_me:7024: $lt_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:7021: $lt_compile\"" >&5)
|
||||
(eval "$lt_compile" 2>conftest.err)
|
||||
ac_status=$?
|
||||
cat conftest.err >&5
|
||||
echo "$as_me:7028: \$? = $ac_status" >&5
|
||||
echo "$as_me:7025: \$? = $ac_status" >&5
|
||||
if (exit $ac_status) && test -s "$ac_outfile"; then
|
||||
# The compiler can only warn and ignore the option if not recognized
|
||||
# So say no if there are warnings other than the usual output.
|
||||
@@ -7126,11 +7123,11 @@ else
|
||||
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
|
||||
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
|
||||
-e 's:$: $lt_compiler_flag:'`
|
||||
(eval echo "\"\$as_me:7129: $lt_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:7126: $lt_compile\"" >&5)
|
||||
(eval "$lt_compile" 2>out/conftest.err)
|
||||
ac_status=$?
|
||||
cat out/conftest.err >&5
|
||||
echo "$as_me:7133: \$? = $ac_status" >&5
|
||||
echo "$as_me:7130: \$? = $ac_status" >&5
|
||||
if (exit $ac_status) && test -s out/conftest2.$ac_objext
|
||||
then
|
||||
# The compiler can only warn and ignore the option if not recognized
|
||||
@@ -7181,11 +7178,11 @@ else
|
||||
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
|
||||
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
|
||||
-e 's:$: $lt_compiler_flag:'`
|
||||
(eval echo "\"\$as_me:7184: $lt_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:7181: $lt_compile\"" >&5)
|
||||
(eval "$lt_compile" 2>out/conftest.err)
|
||||
ac_status=$?
|
||||
cat out/conftest.err >&5
|
||||
echo "$as_me:7188: \$? = $ac_status" >&5
|
||||
echo "$as_me:7185: \$? = $ac_status" >&5
|
||||
if (exit $ac_status) && test -s out/conftest2.$ac_objext
|
||||
then
|
||||
# The compiler can only warn and ignore the option if not recognized
|
||||
@@ -9561,7 +9558,7 @@ else
|
||||
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
|
||||
lt_status=$lt_dlunknown
|
||||
cat > conftest.$ac_ext <<_LT_EOF
|
||||
#line 9564 "configure"
|
||||
#line 9561 "configure"
|
||||
#include "confdefs.h"
|
||||
|
||||
#if HAVE_DLFCN_H
|
||||
@@ -9657,7 +9654,7 @@ else
|
||||
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
|
||||
lt_status=$lt_dlunknown
|
||||
cat > conftest.$ac_ext <<_LT_EOF
|
||||
#line 9660 "configure"
|
||||
#line 9657 "configure"
|
||||
#include "confdefs.h"
|
||||
|
||||
#if HAVE_DLFCN_H
|
||||
@@ -10314,11 +10311,31 @@ done
|
||||
USE_AMALGAMATION=1
|
||||
|
||||
#########
|
||||
# See whether we can run specific tclsh versions known to work well;
|
||||
# if not, then we fall back to plain tclsh.
|
||||
# TODO: try other versions before falling back?
|
||||
# Figure out all the name of a working tclsh and parameters needed to compile against Tcl.
|
||||
# The --with-tcl= and/or --with-tclsh= configuration arguments might be useful for this.
|
||||
#
|
||||
for ac_prog in tclsh8.7 tclsh8.6 tclsh8.5 tclsh
|
||||
|
||||
# Check whether --with-tclsh was given.
|
||||
if test "${with_tclsh+set}" = set; then :
|
||||
withval=$with_tclsh;
|
||||
fi
|
||||
|
||||
|
||||
# Check whether --with-tcl was given.
|
||||
if test "${with_tcl+set}" = set; then :
|
||||
withval=$with_tcl;
|
||||
fi
|
||||
|
||||
# Check whether --enable-tcl was given.
|
||||
if test "${enable_tcl+set}" = set; then :
|
||||
enableval=$enable_tcl; use_tcl=$enableval
|
||||
else
|
||||
use_tcl=yes
|
||||
fi
|
||||
|
||||
original_use_tcl=${use_tcl}
|
||||
if test x"${with_tclsh}" == x -a x"${with_tcl}" == x; then
|
||||
for ac_prog in tclsh8.6 tclsh tclsh9.0
|
||||
do
|
||||
# Extract the first word of "$ac_prog", so it can be a program name with args.
|
||||
set dummy $ac_prog; ac_word=$2
|
||||
@@ -10361,10 +10378,99 @@ fi
|
||||
done
|
||||
test -n "$TCLSH_CMD" || TCLSH_CMD="none"
|
||||
|
||||
with_tclsh=${TCLSH_CMD}
|
||||
fi
|
||||
if test x"${with_tclsh}" != x -a x"${with_tclsh}" != xnone; then
|
||||
TCLSH_CMD=${with_tclsh}
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: using tclsh at \"$TCLSH_CMD\"" >&5
|
||||
$as_echo "using tclsh at \"$TCLSH_CMD\"" >&6; }
|
||||
if test x"${use_tcl}" = "xyes"; then
|
||||
with_tcl=`${with_tclsh} <${srcdir}/tool/find_tclconfig.tcl`
|
||||
if test x"${with_tcl}" != x; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $TCLSH_CMD recommends the tclConfig.sh at ${with_tcl}" >&5
|
||||
$as_echo "$TCLSH_CMD recommends the tclConfig.sh at ${with_tcl}" >&6; }
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $TCLSH_CMD is unable to recommend a tclConfig.sh" >&5
|
||||
$as_echo "$as_me: WARNING: $TCLSH_CMD is unable to recommend a tclConfig.sh" >&2;}
|
||||
use_tcl=no
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
if test x"${use_tcl}" = "xyes"; then
|
||||
if test x"${with_tcl}" != x; then
|
||||
if test -r ${with_tcl}/tclConfig.sh; then
|
||||
tclconfig="${with_tcl}/tclConfig.sh"
|
||||
else
|
||||
for i in tcl8.6 tcl9.0 lib; do
|
||||
if test -r ${with_tcl}/$i/tclConfig.sh; then
|
||||
tclconfig=${with_tcl}/$i/tclConfig.sh
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
if test ! -r "${tclconfig}"; then
|
||||
as_fn_error $? "no tclConfig.sh file found under ${with_tcl}" "$LINENO" 5
|
||||
fi
|
||||
else
|
||||
# If we have not yet found a tclConfig.sh file, look in $libdir whic is
|
||||
# set automatically by autoconf or by the --prefix command-line option.
|
||||
# See https://sqlite.org/forum/forumpost/e04e693439a22457
|
||||
libdir=${prefix}/lib
|
||||
if test -r ${libdir}/tclConfig.sh; then
|
||||
tclconfig=${libdir}/tclConfig.sh
|
||||
else
|
||||
for i in tcl8.6 tcl9.0 lib; do
|
||||
if test -r ${libdir}/$i/tclConfig.sh; then
|
||||
tclconfig=${libdir}/$i/tclConfig.sh
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
if test ! -r "${tclconfig}"; then
|
||||
as_fn_error $? "cannot find a usable tclConfig.sh file.
|
||||
Use --with-tcl=DIR to specify a directory where tclConfig.sh can be found.
|
||||
SQLite does not use TCL internally, but TCL is required to build SQLite
|
||||
from canonical sources and TCL is required for testing." "$LINENO" 5
|
||||
fi
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: loading TCL configuration from ${tclconfig}" >&5
|
||||
$as_echo "loading TCL configuration from ${tclconfig}" >&6; }
|
||||
. ${tclconfig}
|
||||
|
||||
|
||||
|
||||
# There are lots of other configuration variables that are provided by the
|
||||
# tclConfig.sh file and that could be included here. But as of right now,
|
||||
# TCL_LIB_SPEC is the only what that the Makefile uses.
|
||||
HAVE_TCL=1
|
||||
elif test x"${original_use_tcl}" = "xno"; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: unable to run tests because of --disable-tcl" >&5
|
||||
$as_echo "unable to run tests because of --disable-tcl" >&6; }
|
||||
HAVE_TCL=0
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: unable to run tests because no tclConfig.sh file could be located" >&5
|
||||
$as_echo "unable to run tests because no tclConfig.sh file could be located" >&6; }
|
||||
HAVE_TCL=0
|
||||
fi
|
||||
|
||||
if test x"$TCLSH_CMD" == x; then
|
||||
TCLSH_CMD=${TCL_EXEC_PREFIX}/bin/tclsh${TCL_VERSION}
|
||||
if test ! -x ${TCLSH_CMD}; then
|
||||
TCLSH_CMD_2=${TCL_EXEC_PREFIX}/bin/tclsh
|
||||
if test ! -x ${TCLSH_CMD_2}; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cannot find a usable tclsh at either ${TCLSH_CMD} or ${TCLSH_CMD_2}" >&5
|
||||
$as_echo "$as_me: WARNING: cannot find a usable tclsh at either ${TCLSH_CMD} or ${TCLSH_CMD_2}" >&2;}
|
||||
TCLSH_CMD=none
|
||||
else
|
||||
TCLSH_CMD=${TCLSH_CMD_2}
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
if test "$TCLSH_CMD" = "none"; then
|
||||
# If we can't find a local tclsh, then building the amalgamation will fail.
|
||||
# We act as though --disable-amalgamation has been used.
|
||||
echo "Warning: can't find tclsh - defaulting to non-amalgamation build."
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Warning: can't find tclsh - defaulting to non-amalgamation build." >&5
|
||||
$as_echo "$as_me: WARNING: Warning: can't find tclsh - defaulting to non-amalgamation build." >&2;}
|
||||
USE_AMALGAMATION=0
|
||||
TCLSH_CMD="tclsh"
|
||||
fi
|
||||
@@ -10372,7 +10478,6 @@ fi
|
||||
|
||||
|
||||
if test "x${TCLLIBDIR+set}" != "xset" ; then
|
||||
TCLLIBDIR='$(libdir)'
|
||||
for i in `echo 'puts stdout $auto_path' | ${TCLSH_CMD}` ; do
|
||||
if test -d $i ; then
|
||||
TCLLIBDIR=$i
|
||||
@@ -10382,6 +10487,23 @@ if test "x${TCLLIBDIR+set}" != "xset" ; then
|
||||
TCLLIBDIR="${TCLLIBDIR}/sqlite3"
|
||||
fi
|
||||
|
||||
#########
|
||||
# Set up options for running tests.
|
||||
#
|
||||
# Check whether --enable-test-status was given.
|
||||
if test "${enable_test_status+set}" = set; then :
|
||||
enableval=$enable_test_status; use_vt100=$enableval
|
||||
else
|
||||
use_vt100=no
|
||||
fi
|
||||
|
||||
if test $use_vt100 != no; then
|
||||
TSTRNNR_OPTS=--status
|
||||
else
|
||||
TSTRNNR_OPTS=
|
||||
fi
|
||||
|
||||
|
||||
|
||||
#########
|
||||
# Set up an appropriate program prefix
|
||||
@@ -10769,213 +10891,6 @@ fi
|
||||
|
||||
|
||||
|
||||
##########
|
||||
# Figure out all the parameters needed to compile against Tcl.
|
||||
#
|
||||
# This code is derived from the SC_PATH_TCLCONFIG and SC_LOAD_TCLCONFIG
|
||||
# macros in the in the tcl.m4 file of the standard TCL distribution.
|
||||
# Those macros could not be used directly since we have to make some
|
||||
# minor changes to accomodate systems that do not have TCL installed.
|
||||
#
|
||||
# Check whether --enable-tcl was given.
|
||||
if test "${enable_tcl+set}" = set; then :
|
||||
enableval=$enable_tcl; use_tcl=$enableval
|
||||
else
|
||||
use_tcl=yes
|
||||
fi
|
||||
|
||||
if test "${use_tcl}" = "yes" ; then
|
||||
|
||||
# Check whether --with-tcl was given.
|
||||
if test "${with_tcl+set}" = set; then :
|
||||
withval=$with_tcl; with_tclconfig=${withval}
|
||||
fi
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for Tcl configuration" >&5
|
||||
$as_echo_n "checking for Tcl configuration... " >&6; }
|
||||
if ${ac_cv_c_tclconfig+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
|
||||
# First check to see if --with-tcl was specified.
|
||||
if test x"${with_tclconfig}" != x ; then
|
||||
if test -f "${with_tclconfig}/tclConfig.sh" ; then
|
||||
ac_cv_c_tclconfig=`(cd ${with_tclconfig}; pwd)`
|
||||
else
|
||||
as_fn_error $? "${with_tclconfig} directory doesn't contain tclConfig.sh" "$LINENO" 5
|
||||
fi
|
||||
fi
|
||||
|
||||
# Start autosearch by asking tclsh
|
||||
if test x"${ac_cv_c_tclconfig}" = x ; then
|
||||
if test x"$cross_compiling" = xno; then
|
||||
for i in `echo 'puts stdout $auto_path' | ${TCLSH_CMD}`
|
||||
do
|
||||
if test -f "$i/tclConfig.sh" ; then
|
||||
ac_cv_c_tclconfig="$i"
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
fi
|
||||
|
||||
# On ubuntu 14.10, $auto_path on tclsh is not quite correct.
|
||||
# So try again after applying corrections.
|
||||
if test x"${ac_cv_c_tclconfig}" = x ; then
|
||||
if test x"$cross_compiling" = xno; then
|
||||
for i in `echo 'puts stdout $auto_path' | ${TCLSH_CMD} | sed 's,/tcltk/tcl,/tcl,g'`
|
||||
do
|
||||
if test -f "$i/tclConfig.sh" ; then
|
||||
ac_cv_c_tclconfig="$i"
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
fi
|
||||
|
||||
# Recent versions of Xcode on Macs hid the tclConfig.sh file
|
||||
# in a strange place.
|
||||
if test x"${ac_cv_c_tclconfig}" = x ; then
|
||||
if test x"$cross_compiling" = xno; then
|
||||
for i in /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX*.sdk/usr/lib
|
||||
do
|
||||
if test -f "$i/tclConfig.sh" ; then
|
||||
ac_cv_c_tclconfig="$i"
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
fi
|
||||
|
||||
# then check for a private Tcl installation
|
||||
if test x"${ac_cv_c_tclconfig}" = x ; then
|
||||
for i in \
|
||||
../tcl \
|
||||
`ls -dr ../tcl[8-9].[0-9].[0-9]* 2>/dev/null` \
|
||||
`ls -dr ../tcl[8-9].[0-9] 2>/dev/null` \
|
||||
`ls -dr ../tcl[8-9].[0-9]* 2>/dev/null` \
|
||||
../../tcl \
|
||||
`ls -dr ../../tcl[8-9].[0-9].[0-9]* 2>/dev/null` \
|
||||
`ls -dr ../../tcl[8-9].[0-9] 2>/dev/null` \
|
||||
`ls -dr ../../tcl[8-9].[0-9]* 2>/dev/null` \
|
||||
../../../tcl \
|
||||
`ls -dr ../../../tcl[8-9].[0-9].[0-9]* 2>/dev/null` \
|
||||
`ls -dr ../../../tcl[8-9].[0-9] 2>/dev/null` \
|
||||
`ls -dr ../../../tcl[8-9].[0-9]* 2>/dev/null`
|
||||
do
|
||||
if test -f "$i/unix/tclConfig.sh" ; then
|
||||
ac_cv_c_tclconfig=`(cd $i/unix; pwd)`
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
# check in a few common install locations
|
||||
if test x"${ac_cv_c_tclconfig}" = x ; then
|
||||
for i in \
|
||||
`ls -d ${libdir} 2>/dev/null` \
|
||||
`ls -d /usr/local/lib 2>/dev/null` \
|
||||
`ls -d /usr/contrib/lib 2>/dev/null` \
|
||||
`ls -d /usr/lib 2>/dev/null`
|
||||
do
|
||||
if test -f "$i/tclConfig.sh" ; then
|
||||
ac_cv_c_tclconfig=`(cd $i; pwd)`
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
# check in a few other private locations
|
||||
if test x"${ac_cv_c_tclconfig}" = x ; then
|
||||
for i in \
|
||||
${srcdir}/../tcl \
|
||||
`ls -dr ${srcdir}/../tcl[8-9].[0-9].[0-9]* 2>/dev/null` \
|
||||
`ls -dr ${srcdir}/../tcl[8-9].[0-9] 2>/dev/null` \
|
||||
`ls -dr ${srcdir}/../tcl[8-9].[0-9]* 2>/dev/null`
|
||||
do
|
||||
if test -f "$i/unix/tclConfig.sh" ; then
|
||||
ac_cv_c_tclconfig=`(cd $i/unix; pwd)`
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
|
||||
if test x"${ac_cv_c_tclconfig}" = x ; then
|
||||
use_tcl=no
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Can't find Tcl configuration definitions" >&5
|
||||
$as_echo "$as_me: WARNING: Can't find Tcl configuration definitions" >&2;}
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** Without Tcl the regression tests cannot be executed ***" >&5
|
||||
$as_echo "$as_me: WARNING: *** Without Tcl the regression tests cannot be executed ***" >&2;}
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** Consider using --with-tcl=... to define location of Tcl ***" >&5
|
||||
$as_echo "$as_me: WARNING: *** Consider using --with-tcl=... to define location of Tcl ***" >&2;}
|
||||
else
|
||||
TCL_BIN_DIR=${ac_cv_c_tclconfig}
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: found $TCL_BIN_DIR/tclConfig.sh" >&5
|
||||
$as_echo "found $TCL_BIN_DIR/tclConfig.sh" >&6; }
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for existence of $TCL_BIN_DIR/tclConfig.sh" >&5
|
||||
$as_echo_n "checking for existence of $TCL_BIN_DIR/tclConfig.sh... " >&6; }
|
||||
if test -f "$TCL_BIN_DIR/tclConfig.sh" ; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: loading" >&5
|
||||
$as_echo "loading" >&6; }
|
||||
. $TCL_BIN_DIR/tclConfig.sh
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: file not found" >&5
|
||||
$as_echo "file not found" >&6; }
|
||||
fi
|
||||
|
||||
#
|
||||
# If the TCL_BIN_DIR is the build directory (not the install directory),
|
||||
# then set the common variable name to the value of the build variables.
|
||||
# For example, the variable TCL_LIB_SPEC will be set to the value
|
||||
# of TCL_BUILD_LIB_SPEC. An extension should make use of TCL_LIB_SPEC
|
||||
# instead of TCL_BUILD_LIB_SPEC since it will work with both an
|
||||
# installed and uninstalled version of Tcl.
|
||||
#
|
||||
|
||||
if test -f $TCL_BIN_DIR/Makefile ; then
|
||||
TCL_LIB_SPEC=${TCL_BUILD_LIB_SPEC}
|
||||
TCL_STUB_LIB_SPEC=${TCL_BUILD_STUB_LIB_SPEC}
|
||||
TCL_STUB_LIB_PATH=${TCL_BUILD_STUB_LIB_PATH}
|
||||
fi
|
||||
|
||||
#
|
||||
# eval is required to do the TCL_DBGX substitution
|
||||
#
|
||||
|
||||
eval "TCL_LIB_FILE=\"${TCL_LIB_FILE}\""
|
||||
eval "TCL_LIB_FLAG=\"${TCL_LIB_FLAG}\""
|
||||
eval "TCL_LIB_SPEC=\"${TCL_LIB_SPEC}\""
|
||||
|
||||
eval "TCL_STUB_LIB_FILE=\"${TCL_STUB_LIB_FILE}\""
|
||||
eval "TCL_STUB_LIB_FLAG=\"${TCL_STUB_LIB_FLAG}\""
|
||||
eval "TCL_STUB_LIB_SPEC=\"${TCL_STUB_LIB_SPEC}\""
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
fi
|
||||
fi
|
||||
if test "${use_tcl}" = "no" ; then
|
||||
HAVE_TCL=""
|
||||
else
|
||||
HAVE_TCL=1
|
||||
fi
|
||||
|
||||
|
||||
##########
|
||||
# Figure out what C libraries are required to compile programs
|
||||
# that use "readline()" library.
|
||||
@@ -12481,7 +12396,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
|
||||
# report actual input values of CONFIG_FILES etc. instead of their
|
||||
# values after options handling.
|
||||
ac_log="
|
||||
This file was extended by sqlite $as_me 3.46.0, which was
|
||||
This file was extended by sqlite $as_me 3.47.0, which was
|
||||
generated by GNU Autoconf 2.69. Invocation command line was
|
||||
|
||||
CONFIG_FILES = $CONFIG_FILES
|
||||
@@ -12547,7 +12462,7 @@ _ACEOF
|
||||
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
||||
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
|
||||
ac_cs_version="\\
|
||||
sqlite config.status 3.46.0
|
||||
sqlite config.status 3.47.0
|
||||
configured by $0, generated by GNU Autoconf 2.69,
|
||||
with options \\"\$ac_cs_config\\"
|
||||
|
||||
|
||||
+104
-191
@@ -116,15 +116,101 @@ AC_CHECK_FUNCS([fdatasync gmtime_r isnan localtime_r localtime_s malloc_usable_s
|
||||
USE_AMALGAMATION=1
|
||||
|
||||
#########
|
||||
# See whether we can run specific tclsh versions known to work well;
|
||||
# if not, then we fall back to plain tclsh.
|
||||
# TODO: try other versions before falling back?
|
||||
#
|
||||
AC_CHECK_PROGS(TCLSH_CMD, [tclsh8.7 tclsh8.6 tclsh8.5 tclsh], none)
|
||||
# Figure out all the name of a working tclsh and parameters needed to compile against Tcl.
|
||||
# The --with-tcl= and/or --with-tclsh= configuration arguments might be useful for this.
|
||||
#
|
||||
AC_ARG_WITH(tclsh, AS_HELP_STRING([--with-tclsh=PATHNAME],[full pathname of a tclsh to use]))
|
||||
AC_ARG_WITH(tcl, AS_HELP_STRING([--with-tcl=DIR],[directory containing (tclConfig.sh)]))
|
||||
AC_ARG_ENABLE(tcl, AS_HELP_STRING([--disable-tcl],[omit building accessory programs that require TCL-dev]),
|
||||
[use_tcl=$enableval],[use_tcl=yes])
|
||||
original_use_tcl=${use_tcl}
|
||||
if test x"${with_tclsh}" == x -a x"${with_tcl}" == x; then
|
||||
AC_CHECK_PROGS(TCLSH_CMD, [tclsh8.6 tclsh tclsh9.0],none)
|
||||
with_tclsh=${TCLSH_CMD}
|
||||
fi
|
||||
if test x"${with_tclsh}" != x -a x"${with_tclsh}" != xnone; then
|
||||
TCLSH_CMD=${with_tclsh}
|
||||
AC_MSG_RESULT([using tclsh at "$TCLSH_CMD"])
|
||||
if test x"${use_tcl}" = "xyes"; then
|
||||
with_tcl=`${with_tclsh} <${srcdir}/tool/find_tclconfig.tcl`
|
||||
if test x"${with_tcl}" != x; then
|
||||
AC_MSG_RESULT([$TCLSH_CMD recommends the tclConfig.sh at ${with_tcl}])
|
||||
else
|
||||
AC_MSG_WARN([$TCLSH_CMD is unable to recommend a tclConfig.sh])
|
||||
use_tcl=no
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
if test x"${use_tcl}" = "xyes"; then
|
||||
if test x"${with_tcl}" != x; then
|
||||
if test -r ${with_tcl}/tclConfig.sh; then
|
||||
tclconfig="${with_tcl}/tclConfig.sh"
|
||||
else
|
||||
for i in tcl8.6 tcl9.0 lib; do
|
||||
if test -r ${with_tcl}/$i/tclConfig.sh; then
|
||||
tclconfig=${with_tcl}/$i/tclConfig.sh
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
if test ! -r "${tclconfig}"; then
|
||||
AC_MSG_ERROR([no tclConfig.sh file found under ${with_tcl}])
|
||||
fi
|
||||
else
|
||||
# If we have not yet found a tclConfig.sh file, look in $libdir whic is
|
||||
# set automatically by autoconf or by the --prefix command-line option.
|
||||
# See https://sqlite.org/forum/forumpost/e04e693439a22457
|
||||
libdir=${prefix}/lib
|
||||
if test -r ${libdir}/tclConfig.sh; then
|
||||
tclconfig=${libdir}/tclConfig.sh
|
||||
else
|
||||
for i in tcl8.6 tcl9.0 lib; do
|
||||
if test -r ${libdir}/$i/tclConfig.sh; then
|
||||
tclconfig=${libdir}/$i/tclConfig.sh
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
if test ! -r "${tclconfig}"; then
|
||||
AC_MSG_ERROR([cannot find a usable tclConfig.sh file.
|
||||
Use --with-tcl=DIR to specify a directory where tclConfig.sh can be found.
|
||||
SQLite does not use TCL internally, but TCL is required to build SQLite
|
||||
from canonical sources and TCL is required for testing.])
|
||||
fi
|
||||
fi
|
||||
AC_MSG_RESULT([loading TCL configuration from ${tclconfig}])
|
||||
. ${tclconfig}
|
||||
AC_SUBST(TCL_INCLUDE_SPEC)
|
||||
AC_SUBST(TCL_LIB_SPEC)
|
||||
AC_SUBST(TCL_STUB_LIB_SPEC)
|
||||
# There are lots of other configuration variables that are provided by the
|
||||
# tclConfig.sh file and that could be included here. But as of right now,
|
||||
# TCL_LIB_SPEC is the only what that the Makefile uses.
|
||||
HAVE_TCL=1
|
||||
elif test x"${original_use_tcl}" = "xno"; then
|
||||
AC_MSG_RESULT([unable to run tests because of --disable-tcl])
|
||||
HAVE_TCL=0
|
||||
else
|
||||
AC_MSG_RESULT([unable to run tests because no tclConfig.sh file could be located])
|
||||
HAVE_TCL=0
|
||||
fi
|
||||
AC_SUBST(HAVE_TCL)
|
||||
if test x"$TCLSH_CMD" == x; then
|
||||
TCLSH_CMD=${TCL_EXEC_PREFIX}/bin/tclsh${TCL_VERSION}
|
||||
if test ! -x ${TCLSH_CMD}; then
|
||||
TCLSH_CMD_2=${TCL_EXEC_PREFIX}/bin/tclsh
|
||||
if test ! -x ${TCLSH_CMD_2}; then
|
||||
AC_MSG_WARN([cannot find a usable tclsh at either ${TCLSH_CMD} or ${TCLSH_CMD_2}])
|
||||
TCLSH_CMD=none
|
||||
else
|
||||
TCLSH_CMD=${TCLSH_CMD_2}
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
if test "$TCLSH_CMD" = "none"; then
|
||||
# If we can't find a local tclsh, then building the amalgamation will fail.
|
||||
# We act as though --disable-amalgamation has been used.
|
||||
echo "Warning: can't find tclsh - defaulting to non-amalgamation build."
|
||||
AC_MSG_WARN([Warning: can't find tclsh - defaulting to non-amalgamation build.])
|
||||
USE_AMALGAMATION=0
|
||||
TCLSH_CMD="tclsh"
|
||||
fi
|
||||
@@ -132,7 +218,6 @@ AC_SUBST(TCLSH_CMD)
|
||||
|
||||
AC_ARG_VAR([TCLLIBDIR], [Where to install tcl plugin])
|
||||
if test "x${TCLLIBDIR+set}" != "xset" ; then
|
||||
TCLLIBDIR='$(libdir)'
|
||||
for i in `echo 'puts stdout $auto_path' | ${TCLSH_CMD}` ; do
|
||||
if test -d $i ; then
|
||||
TCLLIBDIR=$i
|
||||
@@ -142,6 +227,18 @@ if test "x${TCLLIBDIR+set}" != "xset" ; then
|
||||
TCLLIBDIR="${TCLLIBDIR}/sqlite3"
|
||||
fi
|
||||
|
||||
#########
|
||||
# Set up options for running tests.
|
||||
#
|
||||
AC_ARG_ENABLE(test-status, AS_HELP_STRING([--enable-test-status],[Full-screen status of tests]),
|
||||
[use_vt100=$enableval],[use_vt100=no])
|
||||
if test $use_vt100 != no; then
|
||||
TSTRNNR_OPTS=--status
|
||||
else
|
||||
TSTRNNR_OPTS=
|
||||
fi
|
||||
AC_SUBST(TSTRNNR_OPTS)
|
||||
|
||||
|
||||
#########
|
||||
# Set up an appropriate program prefix
|
||||
@@ -339,190 +436,6 @@ AC_SUBST(SQLITE_OS_UNIX)
|
||||
AC_SUBST(SQLITE_OS_WIN)
|
||||
AC_SUBST(TARGET_EXEEXT)
|
||||
|
||||
##########
|
||||
# Figure out all the parameters needed to compile against Tcl.
|
||||
#
|
||||
# This code is derived from the SC_PATH_TCLCONFIG and SC_LOAD_TCLCONFIG
|
||||
# macros in the in the tcl.m4 file of the standard TCL distribution.
|
||||
# Those macros could not be used directly since we have to make some
|
||||
# minor changes to accomodate systems that do not have TCL installed.
|
||||
#
|
||||
AC_ARG_ENABLE(tcl, AS_HELP_STRING([--disable-tcl],[do not build TCL extension]),
|
||||
[use_tcl=$enableval],[use_tcl=yes])
|
||||
if test "${use_tcl}" = "yes" ; then
|
||||
AC_ARG_WITH(tcl, AS_HELP_STRING([--with-tcl=DIR],[directory containing tcl configuration (tclConfig.sh)]), with_tclconfig=${withval})
|
||||
AC_MSG_CHECKING([for Tcl configuration])
|
||||
AC_CACHE_VAL(ac_cv_c_tclconfig,[
|
||||
# First check to see if --with-tcl was specified.
|
||||
if test x"${with_tclconfig}" != x ; then
|
||||
if test -f "${with_tclconfig}/tclConfig.sh" ; then
|
||||
ac_cv_c_tclconfig=`(cd ${with_tclconfig}; pwd)`
|
||||
else
|
||||
AC_MSG_ERROR([${with_tclconfig} directory doesn't contain tclConfig.sh])
|
||||
fi
|
||||
fi
|
||||
|
||||
# Start autosearch by asking tclsh
|
||||
if test x"${ac_cv_c_tclconfig}" = x ; then
|
||||
if test x"$cross_compiling" = xno; then
|
||||
for i in `echo 'puts stdout $auto_path' | ${TCLSH_CMD}`
|
||||
do
|
||||
if test -f "$i/tclConfig.sh" ; then
|
||||
ac_cv_c_tclconfig="$i"
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
fi
|
||||
|
||||
# On ubuntu 14.10, $auto_path on tclsh is not quite correct.
|
||||
# So try again after applying corrections.
|
||||
if test x"${ac_cv_c_tclconfig}" = x ; then
|
||||
if test x"$cross_compiling" = xno; then
|
||||
for i in `echo 'puts stdout $auto_path' | ${TCLSH_CMD} | sed 's,/tcltk/tcl,/tcl,g'`
|
||||
do
|
||||
if test -f "$i/tclConfig.sh" ; then
|
||||
ac_cv_c_tclconfig="$i"
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
fi
|
||||
|
||||
# Recent versions of Xcode on Macs hid the tclConfig.sh file
|
||||
# in a strange place.
|
||||
if test x"${ac_cv_c_tclconfig}" = x ; then
|
||||
if test x"$cross_compiling" = xno; then
|
||||
for i in /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX*.sdk/usr/lib
|
||||
do
|
||||
if test -f "$i/tclConfig.sh" ; then
|
||||
ac_cv_c_tclconfig="$i"
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
fi
|
||||
|
||||
# then check for a private Tcl installation
|
||||
if test x"${ac_cv_c_tclconfig}" = x ; then
|
||||
for i in \
|
||||
../tcl \
|
||||
`ls -dr ../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \
|
||||
`ls -dr ../tcl[[8-9]].[[0-9]] 2>/dev/null` \
|
||||
`ls -dr ../tcl[[8-9]].[[0-9]]* 2>/dev/null` \
|
||||
../../tcl \
|
||||
`ls -dr ../../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \
|
||||
`ls -dr ../../tcl[[8-9]].[[0-9]] 2>/dev/null` \
|
||||
`ls -dr ../../tcl[[8-9]].[[0-9]]* 2>/dev/null` \
|
||||
../../../tcl \
|
||||
`ls -dr ../../../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \
|
||||
`ls -dr ../../../tcl[[8-9]].[[0-9]] 2>/dev/null` \
|
||||
`ls -dr ../../../tcl[[8-9]].[[0-9]]* 2>/dev/null`
|
||||
do
|
||||
if test -f "$i/unix/tclConfig.sh" ; then
|
||||
ac_cv_c_tclconfig=`(cd $i/unix; pwd)`
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
# check in a few common install locations
|
||||
if test x"${ac_cv_c_tclconfig}" = x ; then
|
||||
for i in \
|
||||
`ls -d ${libdir} 2>/dev/null` \
|
||||
`ls -d /usr/local/lib 2>/dev/null` \
|
||||
`ls -d /usr/contrib/lib 2>/dev/null` \
|
||||
`ls -d /usr/lib 2>/dev/null`
|
||||
do
|
||||
if test -f "$i/tclConfig.sh" ; then
|
||||
ac_cv_c_tclconfig=`(cd $i; pwd)`
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
# check in a few other private locations
|
||||
if test x"${ac_cv_c_tclconfig}" = x ; then
|
||||
for i in \
|
||||
${srcdir}/../tcl \
|
||||
`ls -dr ${srcdir}/../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \
|
||||
`ls -dr ${srcdir}/../tcl[[8-9]].[[0-9]] 2>/dev/null` \
|
||||
`ls -dr ${srcdir}/../tcl[[8-9]].[[0-9]]* 2>/dev/null`
|
||||
do
|
||||
if test -f "$i/unix/tclConfig.sh" ; then
|
||||
ac_cv_c_tclconfig=`(cd $i/unix; pwd)`
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
])
|
||||
|
||||
if test x"${ac_cv_c_tclconfig}" = x ; then
|
||||
use_tcl=no
|
||||
AC_MSG_WARN(Can't find Tcl configuration definitions)
|
||||
AC_MSG_WARN(*** Without Tcl the regression tests cannot be executed ***)
|
||||
AC_MSG_WARN(*** Consider using --with-tcl=... to define location of Tcl ***)
|
||||
else
|
||||
TCL_BIN_DIR=${ac_cv_c_tclconfig}
|
||||
AC_MSG_RESULT(found $TCL_BIN_DIR/tclConfig.sh)
|
||||
|
||||
AC_MSG_CHECKING([for existence of $TCL_BIN_DIR/tclConfig.sh])
|
||||
if test -f "$TCL_BIN_DIR/tclConfig.sh" ; then
|
||||
AC_MSG_RESULT([loading])
|
||||
. $TCL_BIN_DIR/tclConfig.sh
|
||||
else
|
||||
AC_MSG_RESULT([file not found])
|
||||
fi
|
||||
|
||||
#
|
||||
# If the TCL_BIN_DIR is the build directory (not the install directory),
|
||||
# then set the common variable name to the value of the build variables.
|
||||
# For example, the variable TCL_LIB_SPEC will be set to the value
|
||||
# of TCL_BUILD_LIB_SPEC. An extension should make use of TCL_LIB_SPEC
|
||||
# instead of TCL_BUILD_LIB_SPEC since it will work with both an
|
||||
# installed and uninstalled version of Tcl.
|
||||
#
|
||||
|
||||
if test -f $TCL_BIN_DIR/Makefile ; then
|
||||
TCL_LIB_SPEC=${TCL_BUILD_LIB_SPEC}
|
||||
TCL_STUB_LIB_SPEC=${TCL_BUILD_STUB_LIB_SPEC}
|
||||
TCL_STUB_LIB_PATH=${TCL_BUILD_STUB_LIB_PATH}
|
||||
fi
|
||||
|
||||
#
|
||||
# eval is required to do the TCL_DBGX substitution
|
||||
#
|
||||
|
||||
eval "TCL_LIB_FILE=\"${TCL_LIB_FILE}\""
|
||||
eval "TCL_LIB_FLAG=\"${TCL_LIB_FLAG}\""
|
||||
eval "TCL_LIB_SPEC=\"${TCL_LIB_SPEC}\""
|
||||
|
||||
eval "TCL_STUB_LIB_FILE=\"${TCL_STUB_LIB_FILE}\""
|
||||
eval "TCL_STUB_LIB_FLAG=\"${TCL_STUB_LIB_FLAG}\""
|
||||
eval "TCL_STUB_LIB_SPEC=\"${TCL_STUB_LIB_SPEC}\""
|
||||
|
||||
AC_SUBST(TCL_VERSION)
|
||||
AC_SUBST(TCL_BIN_DIR)
|
||||
AC_SUBST(TCL_SRC_DIR)
|
||||
AC_SUBST(TCL_INCLUDE_SPEC)
|
||||
|
||||
AC_SUBST(TCL_LIB_FILE)
|
||||
AC_SUBST(TCL_LIB_FLAG)
|
||||
AC_SUBST(TCL_LIB_SPEC)
|
||||
|
||||
AC_SUBST(TCL_STUB_LIB_FILE)
|
||||
AC_SUBST(TCL_STUB_LIB_FLAG)
|
||||
AC_SUBST(TCL_STUB_LIB_SPEC)
|
||||
AC_SUBST(TCL_SHLIB_SUFFIX)
|
||||
fi
|
||||
fi
|
||||
if test "${use_tcl}" = "no" ; then
|
||||
HAVE_TCL=""
|
||||
else
|
||||
HAVE_TCL=1
|
||||
fi
|
||||
AC_SUBST(HAVE_TCL)
|
||||
|
||||
##########
|
||||
# Figure out what C libraries are required to compile programs
|
||||
# that use "readline()" library.
|
||||
|
||||
@@ -57,10 +57,29 @@ canonical source on a new Windows 11 PC, as of 2023-11-01:
|
||||
<ul>
|
||||
<li> `nmake /f makefile.msc`
|
||||
<li> `nmake /f makefile.msc sqlite3.c`
|
||||
<li> `nmake /f makefile.msc sqlite3.exe`
|
||||
<li> `nmake /f makefile.msc sqldiff.exe`
|
||||
<li> `nmake /f makefile.msc tclextension-install`
|
||||
<li> `nmake /f makefile.msc devtest`
|
||||
<li> `nmake /f makefile.msc releasetest`
|
||||
<li> `nmake /f makefile.msc sqlite3_analyzer.exe`
|
||||
</ul>
|
||||
|
||||
It is not required that you run the "tclextension-install" target prior to
|
||||
running tests. However, the tests will run more smoothly if you do.
|
||||
The version of SQLite used for the TCL extension does *not* need to
|
||||
correspond to the version of SQLite under test. So you can install the
|
||||
SQLite TCL extension once, and then use it to test many different versions
|
||||
of SQLite.
|
||||
|
||||
|
||||
7. For a debugging build of the CLI, where the ".treetrace" and ".wheretrace"
|
||||
commands work, add the DEBUG=3 argument to nmake. Like this:
|
||||
<ul>
|
||||
<li> `nmake /f makefile.msc DEBUG=3 clean sqlite3.exe`
|
||||
</ul>
|
||||
|
||||
|
||||
## 32-bit Builds
|
||||
|
||||
Doing a 32-bit build is just like doing a 64-bit build with the
|
||||
|
||||
+89
-7
@@ -53,11 +53,6 @@
|
||||
# define CIO_WIN_WC_XLATE 0 /* Not exposing translation routines at all */
|
||||
#endif
|
||||
|
||||
#if CIO_WIN_WC_XLATE
|
||||
/* Character used to represent a known-incomplete UTF-8 char group (�) */
|
||||
static WCHAR cBadGroup = 0xfffd;
|
||||
#endif
|
||||
|
||||
#if CIO_WIN_WC_XLATE
|
||||
static HANDLE handleOfFile(FILE *pf){
|
||||
int fileDesc = _fileno(pf);
|
||||
@@ -600,6 +595,93 @@ oPutbUtf8(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){
|
||||
# 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){
|
||||
@@ -611,7 +693,7 @@ ePutbUtf8(const char *cBuf, int nAccept){
|
||||
return conZstrEmit(ppst, cBuf, nAccept);
|
||||
}else {
|
||||
# endif
|
||||
return (int)fwrite(cBuf, 1, nAccept, pfErr);
|
||||
return (int)cfWrite(cBuf, 1, nAccept, pfErr);
|
||||
# if CIO_WIN_WC_XLATE
|
||||
}
|
||||
# endif
|
||||
@@ -677,7 +759,7 @@ SQLITE_INTERNAL_LINKAGE char* fGetsUtf8(char *cBuf, int ncMax, FILE *pfIn){
|
||||
# endif
|
||||
}else{
|
||||
# endif
|
||||
return fgets(cBuf, ncMax, pfIn);
|
||||
return cfGets(cBuf, ncMax, pfIn);
|
||||
# if CIO_WIN_WC_XLATE
|
||||
}
|
||||
# endif
|
||||
|
||||
+11
-4
@@ -176,12 +176,19 @@ 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 platforms that require same. Defers to the
|
||||
** C library fgets() when input is not from the console. Newline
|
||||
** translation may be done as set by set{Binary,Text}Mode(). As a
|
||||
** convenience, pfIn==NULL is treated as stdin.
|
||||
** 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. */
|
||||
|
||||
@@ -428,6 +428,8 @@ do_execsql_test 5.0 {
|
||||
|
||||
WITH s(i) AS ( VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<100)
|
||||
INSERT INTO t2 SELECT (i-1)/20, (i-1)/5 FROM s;
|
||||
|
||||
CREATE INDEX i1 ON t1( lower(a) );
|
||||
}
|
||||
do_candidates_test 5.1 {
|
||||
SELECT * FROM t1,t2 WHERE (b=? OR a=?) AND (c=? OR d=?)
|
||||
@@ -457,6 +459,7 @@ do_execsql_test 5.3 {
|
||||
ANALYZE;
|
||||
SELECT * FROM sqlite_stat1 ORDER BY 1, 2;
|
||||
} {
|
||||
t1 i1 {100 50}
|
||||
t1 t1_idx_00000061 {100 50}
|
||||
t1 t1_idx_00000062 {100 20}
|
||||
t1 t1_idx_000123a7 {100 50 17}
|
||||
@@ -465,6 +468,13 @@ do_execsql_test 5.3 {
|
||||
t2 t2_idx_0001295b {100 20 5}
|
||||
}
|
||||
|
||||
do_catchsql_test 5.4 {
|
||||
SELECT sqlite_expert_rem(123, 123);
|
||||
} {1 {no such function: sqlite_expert_rem}}
|
||||
do_catchsql_test 5.5 {
|
||||
SELECT sqlite_expert_sample();
|
||||
} {1 {no such function: sqlite_expert_sample}}
|
||||
|
||||
if 0 {
|
||||
do_test expert1-6.0 {
|
||||
catchcmd :memory: {
|
||||
@@ -484,4 +494,17 @@ USE TEMP B-TREE FOR ORDER BY
|
||||
}}
|
||||
}
|
||||
|
||||
do_execsql_test 6.0 {
|
||||
CREATE TABLE x1(a, b, c, d);
|
||||
CREATE INDEX x1ab ON x1(a, lower(b));
|
||||
CREATE INDEX x1dcba ON x1(d, b+c, a);
|
||||
}
|
||||
|
||||
do_candidates_test 6.1 {
|
||||
SELECT * FROM x1 WHERE b=? ORDER BY a;
|
||||
} {
|
||||
CREATE INDEX x1_idx_0001267f ON x1(b, a);
|
||||
CREATE INDEX x1_idx_00000062 ON x1(b);
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -626,7 +626,7 @@ static int expertFilter(
|
||||
pCsr->pData = 0;
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = idxPrintfPrepareStmt(pExpert->db, &pCsr->pData, &pVtab->base.zErrMsg,
|
||||
"SELECT * FROM main.%Q WHERE sample()", pVtab->pTab->zName
|
||||
"SELECT * FROM main.%Q WHERE sqlite_expert_sample()", pVtab->pTab->zName
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1500,7 +1500,7 @@ struct IdxRemCtx {
|
||||
};
|
||||
|
||||
/*
|
||||
** Implementation of scalar function rem().
|
||||
** Implementation of scalar function sqlite_expert_rem().
|
||||
*/
|
||||
static void idxRemFunc(
|
||||
sqlite3_context *pCtx,
|
||||
@@ -1513,7 +1513,7 @@ static void idxRemFunc(
|
||||
assert( argc==2 );
|
||||
|
||||
iSlot = sqlite3_value_int(argv[0]);
|
||||
assert( iSlot<=p->nSlot );
|
||||
assert( iSlot<p->nSlot );
|
||||
pSlot = &p->aSlot[iSlot];
|
||||
|
||||
switch( pSlot->eType ){
|
||||
@@ -1623,8 +1623,15 @@ static int idxPopulateOneStat1(
|
||||
const char *zComma = zCols==0 ? "" : ", ";
|
||||
const char *zName = (const char*)sqlite3_column_text(pIndexXInfo, 0);
|
||||
const char *zColl = (const char*)sqlite3_column_text(pIndexXInfo, 1);
|
||||
if( zName==0 ){
|
||||
/* This index contains an expression. Ignore it. */
|
||||
sqlite3_free(zCols);
|
||||
sqlite3_free(zOrder);
|
||||
return sqlite3_reset(pIndexXInfo);
|
||||
}
|
||||
zCols = idxAppendText(&rc, zCols,
|
||||
"%sx.%Q IS rem(%d, x.%Q) COLLATE %s", zComma, zName, nCol, zName, zColl
|
||||
"%sx.%Q IS sqlite_expert_rem(%d, x.%Q) COLLATE %s",
|
||||
zComma, zName, nCol, zName, zColl
|
||||
);
|
||||
zOrder = idxAppendText(&rc, zOrder, "%s%d", zComma, ++nCol);
|
||||
}
|
||||
@@ -1757,13 +1764,13 @@ static int idxPopulateStat1(sqlite3expert *p, char **pzErr){
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
sqlite3 *dbrem = (p->iSample==100 ? p->db : p->dbv);
|
||||
rc = sqlite3_create_function(
|
||||
dbrem, "rem", 2, SQLITE_UTF8, (void*)pCtx, idxRemFunc, 0, 0
|
||||
rc = sqlite3_create_function(dbrem, "sqlite_expert_rem",
|
||||
2, SQLITE_UTF8, (void*)pCtx, idxRemFunc, 0, 0
|
||||
);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3_create_function(
|
||||
p->db, "sample", 0, SQLITE_UTF8, (void*)&samplectx, idxSampleFunc, 0, 0
|
||||
rc = sqlite3_create_function(p->db, "sqlite_expert_sample",
|
||||
0, SQLITE_UTF8, (void*)&samplectx, idxSampleFunc, 0, 0
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1815,6 +1822,9 @@ static int idxPopulateStat1(sqlite3expert *p, char **pzErr){
|
||||
rc = sqlite3_exec(p->dbm, "ANALYZE sqlite_schema", 0, 0, 0);
|
||||
}
|
||||
|
||||
sqlite3_create_function(p->db, "sqlite_expert_rem", 2, SQLITE_UTF8, 0,0,0,0);
|
||||
sqlite3_create_function(p->db, "sqlite_expert_sample", 0,SQLITE_UTF8,0,0,0,0);
|
||||
|
||||
sqlite3_exec(p->db, "DROP TABLE IF EXISTS temp."UNIQUE_TABLE_NAME,0,0,0);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -16,15 +16,7 @@
|
||||
#include "sqlite3expert.h"
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#if defined(INCLUDE_SQLITE_TCL_H)
|
||||
# include "sqlite_tcl.h"
|
||||
#else
|
||||
# include "tcl.h"
|
||||
# ifndef SQLITE_TCLAPI
|
||||
# define SQLITE_TCLAPI
|
||||
# endif
|
||||
#endif
|
||||
#include "tclsqlite.h"
|
||||
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
|
||||
|
||||
@@ -398,6 +398,7 @@ static int fts3SnippetNextCandidate(SnippetIter *pIter){
|
||||
return 1;
|
||||
}
|
||||
|
||||
assert( pIter->nSnippet>=0 );
|
||||
pIter->iCurrent = iStart = iEnd - pIter->nSnippet + 1;
|
||||
for(i=0; i<pIter->nPhrase; i++){
|
||||
SnippetPhrase *pPhrase = &pIter->aPhrase[i];
|
||||
@@ -446,7 +447,7 @@ static void fts3SnippetDetails(
|
||||
}
|
||||
mCover |= mPhrase;
|
||||
|
||||
for(j=0; j<pPhrase->nToken; j++){
|
||||
for(j=0; j<pPhrase->nToken && j<pIter->nSnippet; j++){
|
||||
mHighlight |= (mPos>>j);
|
||||
}
|
||||
|
||||
|
||||
+12
-4
@@ -78,6 +78,8 @@ static int fts3termConnectMethod(
|
||||
iIndex = atoi(argv[4]);
|
||||
argc--;
|
||||
}
|
||||
|
||||
*ppVtab = 0;
|
||||
|
||||
/* The user should specify a single argument - the name of an fts3 table. */
|
||||
if( argc!=4 ){
|
||||
@@ -95,12 +97,17 @@ static int fts3termConnectMethod(
|
||||
rc = sqlite3_declare_vtab(db, FTS3_TERMS_SCHEMA);
|
||||
if( rc!=SQLITE_OK ) return rc;
|
||||
|
||||
nByte = sizeof(Fts3termTable) + sizeof(Fts3Table) + nDb + nFts3 + 2;
|
||||
p = (Fts3termTable *)sqlite3_malloc64(nByte);
|
||||
nByte = sizeof(Fts3termTable);
|
||||
p = (Fts3termTable *)sqlite3Fts3MallocZero(nByte);
|
||||
if( !p ) return SQLITE_NOMEM;
|
||||
memset(p, 0, (size_t)nByte);
|
||||
|
||||
p->pFts3Tab = (Fts3Table *)&p[1];
|
||||
p->pFts3Tab = (Fts3Table*)sqlite3Fts3MallocZero(
|
||||
sizeof(Fts3Table) + nDb + nFts3 + 2
|
||||
);
|
||||
if( p->pFts3Tab==0 ){
|
||||
sqlite3_free(p);
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
p->pFts3Tab->zDb = (char *)&p->pFts3Tab[1];
|
||||
p->pFts3Tab->zName = &p->pFts3Tab->zDb[nDb+1];
|
||||
p->pFts3Tab->db = db;
|
||||
@@ -130,6 +137,7 @@ static int fts3termDisconnectMethod(sqlite3_vtab *pVtab){
|
||||
sqlite3_finalize(pFts3->aStmt[i]);
|
||||
}
|
||||
sqlite3_free(pFts3->zSegmentsTbl);
|
||||
sqlite3_free(pFts3);
|
||||
sqlite3_free(p);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
+13
-16
@@ -18,14 +18,7 @@
|
||||
** that the sqlite3_tokenizer_module.xLanguage() method is invoked correctly.
|
||||
*/
|
||||
|
||||
#if defined(INCLUDE_SQLITE_TCL_H)
|
||||
# include "sqlite_tcl.h"
|
||||
#else
|
||||
# include "tcl.h"
|
||||
# ifndef SQLITE_TCLAPI
|
||||
# define SQLITE_TCLAPI
|
||||
# endif
|
||||
#endif
|
||||
#include "tclsqlite.h"
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
@@ -167,7 +160,8 @@ static int SQLITE_TCLAPI fts3_near_match_cmd(
|
||||
Tcl_Obj *pPhrasecount = 0;
|
||||
|
||||
Tcl_Obj **apExprToken;
|
||||
int nExprToken;
|
||||
Tcl_Size nExprToken;
|
||||
Tcl_Size nn;
|
||||
|
||||
UNUSED_PARAMETER(clientData);
|
||||
|
||||
@@ -201,23 +195,25 @@ static int SQLITE_TCLAPI fts3_near_match_cmd(
|
||||
}
|
||||
}
|
||||
|
||||
rc = Tcl_ListObjGetElements(interp, objv[1], &doc.nToken, &apDocToken);
|
||||
rc = Tcl_ListObjGetElements(interp, objv[1], &nn, &apDocToken);
|
||||
doc.nToken = (int)nn;
|
||||
if( rc!=TCL_OK ) goto near_match_out;
|
||||
doc.aToken = (NearToken *)ckalloc(doc.nToken*sizeof(NearToken));
|
||||
for(ii=0; ii<doc.nToken; ii++){
|
||||
doc.aToken[ii].z = Tcl_GetStringFromObj(apDocToken[ii], &doc.aToken[ii].n);
|
||||
doc.aToken[ii].z = Tcl_GetStringFromObj(apDocToken[ii], &nn);
|
||||
doc.aToken[ii].n = (int)nn;
|
||||
}
|
||||
|
||||
rc = Tcl_ListObjGetElements(interp, objv[2], &nExprToken, &apExprToken);
|
||||
if( rc!=TCL_OK ) goto near_match_out;
|
||||
|
||||
nPhrase = (nExprToken + 1) / 2;
|
||||
nPhrase = (int)(nExprToken + 1) / 2;
|
||||
aPhrase = (NearPhrase *)ckalloc(nPhrase * sizeof(NearPhrase));
|
||||
memset(aPhrase, 0, nPhrase * sizeof(NearPhrase));
|
||||
for(ii=0; ii<nPhrase; ii++){
|
||||
Tcl_Obj *pPhrase = apExprToken[ii*2];
|
||||
Tcl_Obj **apToken;
|
||||
int nToken;
|
||||
Tcl_Size nToken;
|
||||
int jj;
|
||||
|
||||
rc = Tcl_ListObjGetElements(interp, pPhrase, &nToken, &apToken);
|
||||
@@ -227,11 +223,12 @@ static int SQLITE_TCLAPI fts3_near_match_cmd(
|
||||
rc = TCL_ERROR;
|
||||
goto near_match_out;
|
||||
}
|
||||
for(jj=0; jj<nToken; jj++){
|
||||
for(jj=0; jj<(int)nToken; jj++){
|
||||
NearToken *pT = &aPhrase[ii].aToken[jj];
|
||||
pT->z = Tcl_GetStringFromObj(apToken[jj], &pT->n);
|
||||
pT->z = Tcl_GetStringFromObj(apToken[jj], &nn);
|
||||
pT->n = (int)nn;
|
||||
}
|
||||
aPhrase[ii].nToken = nToken;
|
||||
aPhrase[ii].nToken = (int)nToken;
|
||||
}
|
||||
for(ii=1; ii<nPhrase; ii++){
|
||||
Tcl_Obj *pNear = apExprToken[2*ii-1];
|
||||
|
||||
@@ -226,11 +226,7 @@ int sqlite3Fts3InitTokenizer(
|
||||
|
||||
#ifdef SQLITE_TEST
|
||||
|
||||
#if defined(INCLUDE_SQLITE_TCL_H)
|
||||
# include "sqlite_tcl.h"
|
||||
#else
|
||||
# include "tcl.h"
|
||||
#endif
|
||||
#include "tclsqlite.h"
|
||||
#include <string.h>
|
||||
|
||||
/*
|
||||
|
||||
@@ -628,6 +628,9 @@ proc print_categories {lMap} {
|
||||
$caseP
|
||||
$caseS
|
||||
$caseZ
|
||||
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ proc get_struct_docs {data names} {
|
||||
set current_doc ""
|
||||
}
|
||||
set subject n/a
|
||||
regexp {^ *([[:alpha:]]*)} $line -> subject
|
||||
regexp {^ *([[:alnum:]_]*)} $line -> subject
|
||||
if {[lsearch $names $subject]>=0} {
|
||||
set current_header $subject
|
||||
} else {
|
||||
@@ -108,8 +108,11 @@ proc get_tokenizer_docs {data} {
|
||||
append res "<dt><b>$line</b></dt><dd><p style=margin-top:0>\n"
|
||||
continue
|
||||
}
|
||||
if {[regexp {FTS5_TOKENIZER} $line]} {
|
||||
set line </dl><p>
|
||||
}
|
||||
if {[regexp {SYNONYM SUPPORT} $line]} {
|
||||
set line "</dl><h3>Synonym Support</h3>"
|
||||
set line "<h3>Synonym Support</h3>"
|
||||
}
|
||||
if {[string trim $line] == ""} {
|
||||
append res "<p>\n"
|
||||
|
||||
+119
-4
@@ -238,6 +238,10 @@ struct Fts5PhraseIter {
|
||||
** (i.e. if it is a contentless table), then this API always iterates
|
||||
** through an empty set (all calls to xPhraseFirst() set iCol to -1).
|
||||
**
|
||||
** In all cases, matches are visited in (column ASC, offset ASC) order.
|
||||
** i.e. all those in column 0, sorted by offset, followed by those in
|
||||
** column 1, etc.
|
||||
**
|
||||
** xPhraseNext()
|
||||
** See xPhraseFirst above.
|
||||
**
|
||||
@@ -304,9 +308,32 @@ struct Fts5PhraseIter {
|
||||
**
|
||||
** This API can be quite slow if used with an FTS5 table created with the
|
||||
** "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
|
||||
** number of columns in the table, SQLITE_RANGE is returned.
|
||||
**
|
||||
** Otherwise, this function attempts to retrieve the locale associated
|
||||
** with column iCol of the current row. Usually, there is no associated
|
||||
** locale, and output parameters (*pzLocale) and (*pnLocale) are set
|
||||
** to NULL and 0, respectively. However, if the fts5_locale() function
|
||||
** was used to associate a locale with the value when it was inserted
|
||||
** into the fts5 table, then (*pzLocale) is set to point to a nul-terminated
|
||||
** buffer containing the name of the locale in utf-8 encoding. (*pnLocale)
|
||||
** is set to the size in bytes of the buffer, not including the
|
||||
** nul-terminator.
|
||||
**
|
||||
** If successful, SQLITE_OK is returned. Or, if an error occurs, an
|
||||
** SQLite error code is returned. The final value of the output parameters
|
||||
** is undefined in this case.
|
||||
**
|
||||
** xTokenize_v2:
|
||||
** Tokenize text using the tokenizer belonging to the FTS5 table. This
|
||||
** API is the same as the xTokenize() API, except that it allows a tokenizer
|
||||
** locale to be specified.
|
||||
*/
|
||||
struct Fts5ExtensionApi {
|
||||
int iVersion; /* Currently always set to 3 */
|
||||
int iVersion; /* Currently always set to 4 */
|
||||
|
||||
void *(*xUserData)(Fts5Context*);
|
||||
|
||||
@@ -348,6 +375,15 @@ struct Fts5ExtensionApi {
|
||||
const char **ppToken, int *pnToken
|
||||
);
|
||||
int (*xInstToken)(Fts5Context*, int iIdx, int iToken, const char**, int*);
|
||||
|
||||
/* Below this point are iVersion>=4 only */
|
||||
int (*xColumnLocale)(Fts5Context*, int iCol, const char **pz, int *pn);
|
||||
int (*xTokenize_v2)(Fts5Context*,
|
||||
const char *pText, int nText, /* Text to tokenize */
|
||||
const char *pLocale, int nLocale, /* Locale to pass to tokenizer */
|
||||
void *pCtx, /* Context passed to xToken() */
|
||||
int (*xToken)(void*, int, const char*, int, int, int) /* Callback */
|
||||
);
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -360,6 +396,7 @@ struct Fts5ExtensionApi {
|
||||
** Applications may also register custom tokenizer types. A tokenizer
|
||||
** is registered by providing fts5 with a populated instance of the
|
||||
** following structure. All structure methods must be defined, setting
|
||||
**
|
||||
** any member of the fts5_tokenizer struct to NULL leads to undefined
|
||||
** behaviour. The structure methods are expected to function as follows:
|
||||
**
|
||||
@@ -368,7 +405,7 @@ struct Fts5ExtensionApi {
|
||||
** A tokenizer instance is required to actually tokenize text.
|
||||
**
|
||||
** The first argument passed to this function is a copy of the (void*)
|
||||
** pointer provided by the application when the fts5_tokenizer object
|
||||
** pointer provided by the application when the fts5_tokenizer_v2 object
|
||||
** was registered with FTS5 (the third argument to xCreateTokenizer()).
|
||||
** The second and third arguments are an array of nul-terminated strings
|
||||
** containing the tokenizer arguments, if any, specified following the
|
||||
@@ -392,7 +429,7 @@ struct Fts5ExtensionApi {
|
||||
** argument passed to this function is a pointer to an Fts5Tokenizer object
|
||||
** returned by an earlier call to xCreate().
|
||||
**
|
||||
** The second argument indicates the reason that FTS5 is requesting
|
||||
** The third argument indicates the reason that FTS5 is requesting
|
||||
** tokenization of the supplied text. This is always one of the following
|
||||
** four values:
|
||||
**
|
||||
@@ -416,6 +453,13 @@ struct Fts5ExtensionApi {
|
||||
** on a columnsize=0 database.
|
||||
** </ul>
|
||||
**
|
||||
** The sixth and seventh arguments passed to xTokenize() - pLocale and
|
||||
** nLocale - are a pointer to a buffer containing the locale to use for
|
||||
** tokenization (e.g. "en_US") and its size in bytes, respectively. The
|
||||
** pLocale buffer is not nul-terminated. pLocale may be passed NULL (in
|
||||
** which case nLocale is always 0) to indicate that the tokenizer should
|
||||
** use its default locale.
|
||||
**
|
||||
** For each token in the input string, the supplied callback xToken() must
|
||||
** be invoked. The first argument to it should be a copy of the pointer
|
||||
** passed as the second argument to xTokenize(). The third and fourth
|
||||
@@ -439,6 +483,30 @@ struct Fts5ExtensionApi {
|
||||
** may abandon the tokenization and return any error code other than
|
||||
** SQLITE_OK or SQLITE_DONE.
|
||||
**
|
||||
** If the tokenizer is registered using an fts5_tokenizer_v2 object,
|
||||
** then the xTokenize() method has two additional arguments - pLocale
|
||||
** and nLocale. These specify the locale that the tokenizer should use
|
||||
** for the current request. If pLocale and nLocale are both 0, then the
|
||||
** tokenizer should use its default locale. Otherwise, pLocale points to
|
||||
** an nLocale byte buffer containing the name of the locale to use as utf-8
|
||||
** text. pLocale is not nul-terminated.
|
||||
**
|
||||
** FTS5_TOKENIZER
|
||||
**
|
||||
** There is also an fts5_tokenizer object. This is an older, deprecated,
|
||||
** version of fts5_tokenizer_v2. It is similar except that:
|
||||
**
|
||||
** <ul>
|
||||
** <li> There is no "iVersion" field, and
|
||||
** <li> The xTokenize() method does not take a locale argument.
|
||||
** </ul>
|
||||
**
|
||||
** Legacy fts5_tokenizer tokenizers must be registered using the
|
||||
** legacy xCreateTokenizer() function, instead of xCreateTokenizer_v2().
|
||||
**
|
||||
** Tokenizer implementations registered using either API may be retrieved
|
||||
** using both xFindTokenizer() and xFindTokenizer_v2().
|
||||
**
|
||||
** SYNONYM SUPPORT
|
||||
**
|
||||
** Custom tokenizers may also support synonyms. Consider a case in which a
|
||||
@@ -547,6 +615,33 @@ struct Fts5ExtensionApi {
|
||||
** inefficient.
|
||||
*/
|
||||
typedef struct Fts5Tokenizer Fts5Tokenizer;
|
||||
typedef struct fts5_tokenizer_v2 fts5_tokenizer_v2;
|
||||
struct fts5_tokenizer_v2 {
|
||||
int iVersion; /* Currently always 2 */
|
||||
|
||||
int (*xCreate)(void*, const char **azArg, int nArg, Fts5Tokenizer **ppOut);
|
||||
void (*xDelete)(Fts5Tokenizer*);
|
||||
int (*xTokenize)(Fts5Tokenizer*,
|
||||
void *pCtx,
|
||||
int flags, /* Mask of FTS5_TOKENIZE_* flags */
|
||||
const char *pText, int nText,
|
||||
const char *pLocale, int nLocale,
|
||||
int (*xToken)(
|
||||
void *pCtx, /* Copy of 2nd argument to xTokenize() */
|
||||
int tflags, /* Mask of FTS5_TOKEN_* flags */
|
||||
const char *pToken, /* Pointer to buffer containing token */
|
||||
int nToken, /* Size of token in bytes */
|
||||
int iStart, /* Byte offset of token within input text */
|
||||
int iEnd /* Byte offset of end of token within input text */
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
/*
|
||||
** New code should use the fts5_tokenizer_v2 type to define tokenizer
|
||||
** implementations. The following type is included for legacy applications
|
||||
** that still use it.
|
||||
*/
|
||||
typedef struct fts5_tokenizer fts5_tokenizer;
|
||||
struct fts5_tokenizer {
|
||||
int (*xCreate)(void*, const char **azArg, int nArg, Fts5Tokenizer **ppOut);
|
||||
@@ -566,6 +661,7 @@ struct fts5_tokenizer {
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
/* Flags that may be passed as the third argument to xTokenize() */
|
||||
#define FTS5_TOKENIZE_QUERY 0x0001
|
||||
#define FTS5_TOKENIZE_PREFIX 0x0002
|
||||
@@ -585,7 +681,7 @@ struct fts5_tokenizer {
|
||||
*/
|
||||
typedef struct fts5_api fts5_api;
|
||||
struct fts5_api {
|
||||
int iVersion; /* Currently always set to 2 */
|
||||
int iVersion; /* Currently always set to 3 */
|
||||
|
||||
/* Create a new tokenizer */
|
||||
int (*xCreateTokenizer)(
|
||||
@@ -612,6 +708,25 @@ struct fts5_api {
|
||||
fts5_extension_function xFunction,
|
||||
void (*xDestroy)(void*)
|
||||
);
|
||||
|
||||
/* APIs below this point are only available if iVersion>=3 */
|
||||
|
||||
/* Create a new tokenizer */
|
||||
int (*xCreateTokenizer_v2)(
|
||||
fts5_api *pApi,
|
||||
const char *zName,
|
||||
void *pUserData,
|
||||
fts5_tokenizer_v2 *pTokenizer,
|
||||
void (*xDestroy)(void*)
|
||||
);
|
||||
|
||||
/* Find an existing tokenizer */
|
||||
int (*xFindTokenizer_v2)(
|
||||
fts5_api *pApi,
|
||||
const char *zName,
|
||||
void **ppUserData,
|
||||
fts5_tokenizer_v2 **ppTokenizer
|
||||
);
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
+51
-12
@@ -59,6 +59,22 @@ typedef sqlite3_uint64 u64;
|
||||
# define LARGEST_INT64 (0xffffffff|(((i64)0x7fffffff)<<32))
|
||||
# define SMALLEST_INT64 (((i64)-1) - LARGEST_INT64)
|
||||
|
||||
/* The uptr type is an unsigned integer large enough to hold a pointer
|
||||
*/
|
||||
#if defined(HAVE_STDINT_H)
|
||||
typedef uintptr_t uptr;
|
||||
#elif SQLITE_PTRSIZE==4
|
||||
typedef u32 uptr;
|
||||
#else
|
||||
typedef u64 uptr;
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_4_BYTE_ALIGNED_MALLOC
|
||||
# define EIGHT_BYTE_ALIGNMENT(X) ((((uptr)(X) - (uptr)0)&3)==0)
|
||||
#else
|
||||
# define EIGHT_BYTE_ALIGNMENT(X) ((((uptr)(X) - (uptr)0)&7)==0)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/* Truncate very long tokens to this many bytes. Hard limit is
|
||||
@@ -142,6 +158,18 @@ struct Fts5Colset {
|
||||
*/
|
||||
|
||||
typedef struct Fts5Config Fts5Config;
|
||||
typedef struct Fts5TokenizerConfig Fts5TokenizerConfig;
|
||||
|
||||
struct Fts5TokenizerConfig {
|
||||
Fts5Tokenizer *pTok;
|
||||
fts5_tokenizer_v2 *pApi2;
|
||||
fts5_tokenizer *pApi1;
|
||||
const char **azArg;
|
||||
int nArg;
|
||||
int ePattern; /* FTS_PATTERN_XXX constant */
|
||||
const char *pLocale; /* Current locale to use */
|
||||
int nLocale; /* Size of pLocale in bytes */
|
||||
};
|
||||
|
||||
/*
|
||||
** An instance of the following structure encodes all information that can
|
||||
@@ -181,9 +209,12 @@ typedef struct Fts5Config Fts5Config;
|
||||
**
|
||||
** INSERT INTO tbl(tbl, rank) VALUES('prefix-index', $bPrefixIndex);
|
||||
**
|
||||
** bLocale:
|
||||
** Set to true if locale=1 was specified when the table was created.
|
||||
*/
|
||||
struct Fts5Config {
|
||||
sqlite3 *db; /* Database handle */
|
||||
Fts5Global *pGlobal; /* Global fts5 object for handle db */
|
||||
char *zDb; /* Database holding FTS index (e.g. "main") */
|
||||
char *zName; /* Name of FTS index */
|
||||
int nCol; /* Number of columns */
|
||||
@@ -197,12 +228,12 @@ struct Fts5Config {
|
||||
char *zContentRowid; /* "content_rowid=" option value */
|
||||
int bColumnsize; /* "columnsize=" option value (dflt==1) */
|
||||
int bTokendata; /* "tokendata=" option value (dflt==0) */
|
||||
int bLocale; /* "locale=" option value (dflt==0) */
|
||||
int eDetail; /* FTS5_DETAIL_XXX value */
|
||||
char *zContentExprlist;
|
||||
Fts5Tokenizer *pTok;
|
||||
fts5_tokenizer *pTokApi;
|
||||
Fts5TokenizerConfig t;
|
||||
int bLock; /* True when table is preparing statement */
|
||||
int ePattern; /* FTS_PATTERN_XXX constant */
|
||||
|
||||
|
||||
/* Values loaded from the %_config table */
|
||||
int iVersion; /* fts5 file format 'version' */
|
||||
@@ -268,6 +299,8 @@ int sqlite3Fts5ConfigSetValue(Fts5Config*, const char*, sqlite3_value*, int*);
|
||||
|
||||
int sqlite3Fts5ConfigParseRank(const char*, char**, char**);
|
||||
|
||||
void sqlite3Fts5ConfigErrmsg(Fts5Config *pConfig, const char *zFmt, ...);
|
||||
|
||||
/*
|
||||
** End of interface to code in fts5_config.c.
|
||||
**************************************************************************/
|
||||
@@ -312,7 +345,7 @@ char *sqlite3Fts5Mprintf(int *pRc, const char *zFmt, ...);
|
||||
void sqlite3Fts5Put32(u8*, int);
|
||||
int sqlite3Fts5Get32(const u8*);
|
||||
|
||||
#define FTS5_POS2COLUMN(iPos) (int)(iPos >> 32)
|
||||
#define FTS5_POS2COLUMN(iPos) (int)((iPos >> 32) & 0x7FFFFFFF)
|
||||
#define FTS5_POS2OFFSET(iPos) (int)(iPos & 0x7FFFFFFF)
|
||||
|
||||
typedef struct Fts5PoslistReader Fts5PoslistReader;
|
||||
@@ -597,18 +630,20 @@ struct Fts5Table {
|
||||
Fts5Index *pIndex; /* Full-text index */
|
||||
};
|
||||
|
||||
int sqlite3Fts5GetTokenizer(
|
||||
Fts5Global*,
|
||||
const char **azArg,
|
||||
int nArg,
|
||||
Fts5Config*,
|
||||
char **pzErr
|
||||
);
|
||||
int sqlite3Fts5LoadTokenizer(Fts5Config *pConfig);
|
||||
|
||||
Fts5Table *sqlite3Fts5TableFromCsrid(Fts5Global*, i64);
|
||||
|
||||
int sqlite3Fts5FlushToDisk(Fts5Table*);
|
||||
|
||||
void sqlite3Fts5ClearLocale(Fts5Config *pConfig);
|
||||
void sqlite3Fts5SetLocale(Fts5Config *pConfig, const char *pLoc, int nLoc);
|
||||
|
||||
int sqlite3Fts5IsLocaleValue(Fts5Config *pConfig, sqlite3_value *pVal);
|
||||
int sqlite3Fts5DecodeLocaleValue(sqlite3_value *pVal,
|
||||
const char **ppText, int *pnText, const char **ppLoc, int *pnLoc
|
||||
);
|
||||
|
||||
/*
|
||||
** End of interface to code in fts5.c.
|
||||
**************************************************************************/
|
||||
@@ -688,7 +723,7 @@ int sqlite3Fts5StorageRename(Fts5Storage*, const char *zName);
|
||||
int sqlite3Fts5DropAll(Fts5Config*);
|
||||
int sqlite3Fts5CreateTable(Fts5Config*, const char*, const char*, int, char **);
|
||||
|
||||
int sqlite3Fts5StorageDelete(Fts5Storage *p, i64, sqlite3_value**);
|
||||
int sqlite3Fts5StorageDelete(Fts5Storage *p, i64, sqlite3_value**, int);
|
||||
int sqlite3Fts5StorageContentInsert(Fts5Storage *p, sqlite3_value**, i64*);
|
||||
int sqlite3Fts5StorageIndexInsert(Fts5Storage *p, sqlite3_value**, i64);
|
||||
|
||||
@@ -714,6 +749,9 @@ int sqlite3Fts5StorageOptimize(Fts5Storage *p);
|
||||
int sqlite3Fts5StorageMerge(Fts5Storage *p, int nMerge);
|
||||
int sqlite3Fts5StorageReset(Fts5Storage *p);
|
||||
|
||||
void sqlite3Fts5StorageReleaseDeleteRow(Fts5Storage*);
|
||||
int sqlite3Fts5StorageFindDeleteRow(Fts5Storage *p, i64 iDel);
|
||||
|
||||
/*
|
||||
** End of interface to code in fts5_storage.c.
|
||||
**************************************************************************/
|
||||
@@ -866,6 +904,7 @@ int sqlite3Fts5TokenizerPattern(
|
||||
int (*xCreate)(void*, const char**, int, Fts5Tokenizer**),
|
||||
Fts5Tokenizer *pTok
|
||||
);
|
||||
int sqlite3Fts5TokenizerPreload(Fts5TokenizerConfig*);
|
||||
/*
|
||||
** End of interface to code in fts5_tokenizer.c.
|
||||
**************************************************************************/
|
||||
|
||||
+75
-7
@@ -226,6 +226,7 @@ static int fts5HighlightCb(
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Implementation of highlight() function.
|
||||
*/
|
||||
@@ -256,12 +257,19 @@ static void fts5HighlightFunction(
|
||||
sqlite3_result_text(pCtx, "", -1, SQLITE_STATIC);
|
||||
rc = SQLITE_OK;
|
||||
}else if( ctx.zIn ){
|
||||
const char *pLoc = 0; /* Locale of column iCol */
|
||||
int nLoc = 0; /* Size of pLoc in bytes */
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = fts5CInstIterInit(pApi, pFts, iCol, &ctx.iter);
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = pApi->xTokenize(pFts, ctx.zIn, ctx.nIn, (void*)&ctx,fts5HighlightCb);
|
||||
rc = pApi->xColumnLocale(pFts, iCol, &pLoc, &nLoc);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = pApi->xTokenize_v2(
|
||||
pFts, ctx.zIn, ctx.nIn, pLoc, nLoc, (void*)&ctx, fts5HighlightCb
|
||||
);
|
||||
}
|
||||
if( ctx.bOpen ){
|
||||
fts5HighlightAppend(&rc, &ctx, ctx.zClose, -1);
|
||||
@@ -458,6 +466,8 @@ static void fts5SnippetFunction(
|
||||
memset(&sFinder, 0, sizeof(Fts5SFinder));
|
||||
for(i=0; i<nCol; i++){
|
||||
if( iCol<0 || iCol==i ){
|
||||
const char *pLoc = 0; /* Locale of column iCol */
|
||||
int nLoc = 0; /* Size of pLoc in bytes */
|
||||
int nDoc;
|
||||
int nDocsize;
|
||||
int ii;
|
||||
@@ -465,8 +475,10 @@ static void fts5SnippetFunction(
|
||||
sFinder.nFirst = 0;
|
||||
rc = pApi->xColumnText(pFts, i, &sFinder.zDoc, &nDoc);
|
||||
if( rc!=SQLITE_OK ) break;
|
||||
rc = pApi->xTokenize(pFts,
|
||||
sFinder.zDoc, nDoc, (void*)&sFinder,fts5SentenceFinderCb
|
||||
rc = pApi->xColumnLocale(pFts, i, &pLoc, &nLoc);
|
||||
if( rc!=SQLITE_OK ) break;
|
||||
rc = pApi->xTokenize_v2(pFts,
|
||||
sFinder.zDoc, nDoc, pLoc, nLoc, (void*)&sFinder, fts5SentenceFinderCb
|
||||
);
|
||||
if( rc!=SQLITE_OK ) break;
|
||||
rc = pApi->xColumnSize(pFts, i, &nDocsize);
|
||||
@@ -524,6 +536,9 @@ static void fts5SnippetFunction(
|
||||
rc = pApi->xColumnSize(pFts, iBestCol, &nColSize);
|
||||
}
|
||||
if( ctx.zIn ){
|
||||
const char *pLoc = 0; /* Locale of column iBestCol */
|
||||
int nLoc = 0; /* Bytes in pLoc */
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = fts5CInstIterInit(pApi, pFts, iBestCol, &ctx.iter);
|
||||
}
|
||||
@@ -542,7 +557,12 @@ static void fts5SnippetFunction(
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = pApi->xTokenize(pFts, ctx.zIn, ctx.nIn, (void*)&ctx,fts5HighlightCb);
|
||||
rc = pApi->xColumnLocale(pFts, iBestCol, &pLoc, &nLoc);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = pApi->xTokenize_v2(
|
||||
pFts, ctx.zIn, ctx.nIn, pLoc, nLoc, (void*)&ctx,fts5HighlightCb
|
||||
);
|
||||
}
|
||||
if( ctx.bOpen ){
|
||||
fts5HighlightAppend(&rc, &ctx, ctx.zClose, -1);
|
||||
@@ -726,6 +746,53 @@ static void fts5Bm25Function(
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Implementation of fts5_get_locale() function.
|
||||
*/
|
||||
static void fts5GetLocaleFunction(
|
||||
const Fts5ExtensionApi *pApi, /* API offered by current FTS version */
|
||||
Fts5Context *pFts, /* First arg to pass to pApi functions */
|
||||
sqlite3_context *pCtx, /* Context for returning result/error */
|
||||
int nVal, /* Number of values in apVal[] array */
|
||||
sqlite3_value **apVal /* Array of trailing arguments */
|
||||
){
|
||||
int iCol = 0;
|
||||
int eType = 0;
|
||||
int rc = SQLITE_OK;
|
||||
const char *zLocale = 0;
|
||||
int nLocale = 0;
|
||||
|
||||
/* xColumnLocale() must be available */
|
||||
assert( pApi->iVersion>=4 );
|
||||
|
||||
if( nVal!=1 ){
|
||||
const char *z = "wrong number of arguments to function fts5_get_locale()";
|
||||
sqlite3_result_error(pCtx, z, -1);
|
||||
return;
|
||||
}
|
||||
|
||||
eType = sqlite3_value_numeric_type(apVal[0]);
|
||||
if( eType!=SQLITE_INTEGER ){
|
||||
const char *z = "non-integer argument passed to function fts5_get_locale()";
|
||||
sqlite3_result_error(pCtx, z, -1);
|
||||
return;
|
||||
}
|
||||
|
||||
iCol = sqlite3_value_int(apVal[0]);
|
||||
if( iCol<0 || iCol>=pApi->xColumnCount(pFts) ){
|
||||
sqlite3_result_error_code(pCtx, SQLITE_RANGE);
|
||||
return;
|
||||
}
|
||||
|
||||
rc = pApi->xColumnLocale(pFts, iCol, &zLocale, &nLocale);
|
||||
if( rc!=SQLITE_OK ){
|
||||
sqlite3_result_error_code(pCtx, rc);
|
||||
return;
|
||||
}
|
||||
|
||||
sqlite3_result_text(pCtx, zLocale, nLocale, SQLITE_TRANSIENT);
|
||||
}
|
||||
|
||||
int sqlite3Fts5AuxInit(fts5_api *pApi){
|
||||
struct Builtin {
|
||||
const char *zFunc; /* Function name (nul-terminated) */
|
||||
@@ -733,9 +800,10 @@ int sqlite3Fts5AuxInit(fts5_api *pApi){
|
||||
fts5_extension_function xFunc;/* Callback function */
|
||||
void (*xDestroy)(void*); /* Destructor function */
|
||||
} aBuiltin [] = {
|
||||
{ "snippet", 0, fts5SnippetFunction, 0 },
|
||||
{ "highlight", 0, fts5HighlightFunction, 0 },
|
||||
{ "bm25", 0, fts5Bm25Function, 0 },
|
||||
{ "snippet", 0, fts5SnippetFunction, 0 },
|
||||
{ "highlight", 0, fts5HighlightFunction, 0 },
|
||||
{ "bm25", 0, fts5Bm25Function, 0 },
|
||||
{ "fts5_get_locale", 0, fts5GetLocaleFunction, 0 },
|
||||
};
|
||||
int rc = SQLITE_OK; /* Return code */
|
||||
int i; /* To iterate through builtin functions */
|
||||
|
||||
+81
-43
@@ -234,7 +234,6 @@ static int fts5ConfigSetEnum(
|
||||
** eventually free any such error message using sqlite3_free().
|
||||
*/
|
||||
static int fts5ConfigParseSpecial(
|
||||
Fts5Global *pGlobal,
|
||||
Fts5Config *pConfig, /* Configuration object to update */
|
||||
const char *zCmd, /* Special command to parse */
|
||||
const char *zArg, /* Argument to parse */
|
||||
@@ -298,12 +297,11 @@ static int fts5ConfigParseSpecial(
|
||||
if( sqlite3_strnicmp("tokenize", zCmd, nCmd)==0 ){
|
||||
const char *p = (const char*)zArg;
|
||||
sqlite3_int64 nArg = strlen(zArg) + 1;
|
||||
char **azArg = sqlite3Fts5MallocZero(&rc, sizeof(char*) * nArg);
|
||||
char *pDel = sqlite3Fts5MallocZero(&rc, nArg * 2);
|
||||
char *pSpace = pDel;
|
||||
char **azArg = sqlite3Fts5MallocZero(&rc, (sizeof(char*) + 2) * nArg);
|
||||
|
||||
if( azArg && pSpace ){
|
||||
if( pConfig->pTok ){
|
||||
if( azArg ){
|
||||
char *pSpace = (char*)&azArg[nArg];
|
||||
if( pConfig->t.azArg ){
|
||||
*pzErr = sqlite3_mprintf("multiple tokenize=... directives");
|
||||
rc = SQLITE_ERROR;
|
||||
}else{
|
||||
@@ -326,16 +324,14 @@ static int fts5ConfigParseSpecial(
|
||||
*pzErr = sqlite3_mprintf("parse error in tokenize directive");
|
||||
rc = SQLITE_ERROR;
|
||||
}else{
|
||||
rc = sqlite3Fts5GetTokenizer(pGlobal,
|
||||
(const char**)azArg, (int)nArg, pConfig,
|
||||
pzErr
|
||||
);
|
||||
pConfig->t.azArg = (const char**)azArg;
|
||||
pConfig->t.nArg = nArg;
|
||||
azArg = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sqlite3_free(azArg);
|
||||
sqlite3_free(pDel);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -384,6 +380,16 @@ static int fts5ConfigParseSpecial(
|
||||
return rc;
|
||||
}
|
||||
|
||||
if( sqlite3_strnicmp("locale", zCmd, nCmd)==0 ){
|
||||
if( (zArg[0]!='0' && zArg[0]!='1') || zArg[1]!='\0' ){
|
||||
*pzErr = sqlite3_mprintf("malformed locale=... directive");
|
||||
rc = SQLITE_ERROR;
|
||||
}else{
|
||||
pConfig->bLocale = (zArg[0]=='1');
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
if( sqlite3_strnicmp("detail", zCmd, nCmd)==0 ){
|
||||
const Fts5Enum aDetail[] = {
|
||||
{ "none", FTS5_DETAIL_NONE },
|
||||
@@ -412,16 +418,6 @@ static int fts5ConfigParseSpecial(
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
** Allocate an instance of the default tokenizer ("simple") at
|
||||
** Fts5Config.pTokenizer. Return SQLITE_OK if successful, or an SQLite error
|
||||
** code if an error occurs.
|
||||
*/
|
||||
static int fts5ConfigDefaultTokenizer(Fts5Global *pGlobal, Fts5Config *pConfig){
|
||||
assert( pConfig->pTok==0 && pConfig->pTokApi==0 );
|
||||
return sqlite3Fts5GetTokenizer(pGlobal, 0, 0, pConfig, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
** Gobble up the first bareword or quoted word from the input buffer zIn.
|
||||
** Return a pointer to the character immediately following the last in
|
||||
@@ -520,6 +516,15 @@ static int fts5ConfigMakeExprlist(Fts5Config *p){
|
||||
}
|
||||
}
|
||||
}
|
||||
if( p->eContent==FTS5_CONTENT_NORMAL && p->bLocale ){
|
||||
for(i=0; i<p->nCol; i++){
|
||||
if( p->abUnindexed[i]==0 ){
|
||||
sqlite3Fts5BufferAppendPrintf(&rc, &buf, ", T.l%d", i);
|
||||
}else{
|
||||
sqlite3Fts5BufferAppendPrintf(&rc, &buf, ", NULL");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert( p->zContentExprlist==0 );
|
||||
p->zContentExprlist = (char*)buf.p;
|
||||
@@ -554,6 +559,7 @@ int sqlite3Fts5ConfigParse(
|
||||
*ppOut = pRet = (Fts5Config*)sqlite3_malloc(sizeof(Fts5Config));
|
||||
if( pRet==0 ) return SQLITE_NOMEM;
|
||||
memset(pRet, 0, sizeof(Fts5Config));
|
||||
pRet->pGlobal = pGlobal;
|
||||
pRet->db = db;
|
||||
pRet->iCookie = -1;
|
||||
|
||||
@@ -602,7 +608,7 @@ int sqlite3Fts5ConfigParse(
|
||||
rc = SQLITE_ERROR;
|
||||
}else{
|
||||
if( bOption ){
|
||||
rc = fts5ConfigParseSpecial(pGlobal, pRet,
|
||||
rc = fts5ConfigParseSpecial(pRet,
|
||||
ALWAYS(zOne)?zOne:"",
|
||||
zTwo?zTwo:"",
|
||||
pzErr
|
||||
@@ -640,13 +646,6 @@ int sqlite3Fts5ConfigParse(
|
||||
rc = SQLITE_ERROR;
|
||||
}
|
||||
|
||||
/* If a tokenizer= option was successfully parsed, the tokenizer has
|
||||
** already been allocated. Otherwise, allocate an instance of the default
|
||||
** tokenizer (unicode61) now. */
|
||||
if( rc==SQLITE_OK && pRet->pTok==0 ){
|
||||
rc = fts5ConfigDefaultTokenizer(pGlobal, pRet);
|
||||
}
|
||||
|
||||
/* If no zContent option was specified, fill in the default values. */
|
||||
if( rc==SQLITE_OK && pRet->zContent==0 ){
|
||||
const char *zTail = 0;
|
||||
@@ -688,9 +687,14 @@ int sqlite3Fts5ConfigParse(
|
||||
void sqlite3Fts5ConfigFree(Fts5Config *pConfig){
|
||||
if( pConfig ){
|
||||
int i;
|
||||
if( pConfig->pTok ){
|
||||
pConfig->pTokApi->xDelete(pConfig->pTok);
|
||||
if( pConfig->t.pTok ){
|
||||
if( pConfig->t.pApi1 ){
|
||||
pConfig->t.pApi1->xDelete(pConfig->t.pTok);
|
||||
}else{
|
||||
pConfig->t.pApi2->xDelete(pConfig->t.pTok);
|
||||
}
|
||||
}
|
||||
sqlite3_free((char*)pConfig->t.azArg);
|
||||
sqlite3_free(pConfig->zDb);
|
||||
sqlite3_free(pConfig->zName);
|
||||
for(i=0; i<pConfig->nCol; i++){
|
||||
@@ -765,10 +769,24 @@ int sqlite3Fts5Tokenize(
|
||||
void *pCtx, /* Context passed to xToken() */
|
||||
int (*xToken)(void*, int, const char*, int, int, int) /* Callback */
|
||||
){
|
||||
if( pText==0 ) return SQLITE_OK;
|
||||
return pConfig->pTokApi->xTokenize(
|
||||
pConfig->pTok, pCtx, flags, pText, nText, xToken
|
||||
);
|
||||
int rc = SQLITE_OK;
|
||||
if( pText ){
|
||||
if( pConfig->t.pTok==0 ){
|
||||
rc = sqlite3Fts5LoadTokenizer(pConfig);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
if( pConfig->t.pApi1 ){
|
||||
rc = pConfig->t.pApi1->xTokenize(
|
||||
pConfig->t.pTok, pCtx, flags, pText, nText, xToken
|
||||
);
|
||||
}else{
|
||||
rc = pConfig->t.pApi2->xTokenize(pConfig->t.pTok, pCtx, flags,
|
||||
pText, nText, pConfig->t.pLocale, pConfig->t.nLocale, xToken
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1022,13 +1040,10 @@ int sqlite3Fts5ConfigLoad(Fts5Config *pConfig, int iCookie){
|
||||
&& iVersion!=FTS5_CURRENT_VERSION_SECUREDELETE
|
||||
){
|
||||
rc = SQLITE_ERROR;
|
||||
if( pConfig->pzErrmsg ){
|
||||
assert( 0==*pConfig->pzErrmsg );
|
||||
*pConfig->pzErrmsg = sqlite3_mprintf("invalid fts5 file format "
|
||||
"(found %d, expected %d or %d) - run 'rebuild'",
|
||||
iVersion, FTS5_CURRENT_VERSION, FTS5_CURRENT_VERSION_SECUREDELETE
|
||||
);
|
||||
}
|
||||
sqlite3Fts5ConfigErrmsg(pConfig, "invalid fts5 file format "
|
||||
"(found %d, expected %d or %d) - run 'rebuild'",
|
||||
iVersion, FTS5_CURRENT_VERSION, FTS5_CURRENT_VERSION_SECUREDELETE
|
||||
);
|
||||
}else{
|
||||
pConfig->iVersion = iVersion;
|
||||
}
|
||||
@@ -1038,3 +1053,26 @@ int sqlite3Fts5ConfigLoad(Fts5Config *pConfig, int iCookie){
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Set (*pConfig->pzErrmsg) to point to an sqlite3_malloc()ed buffer
|
||||
** containing the error message created using printf() style formatting
|
||||
** string zFmt and its trailing arguments.
|
||||
*/
|
||||
void sqlite3Fts5ConfigErrmsg(Fts5Config *pConfig, const char *zFmt, ...){
|
||||
va_list ap; /* ... printf arguments */
|
||||
char *zMsg = 0;
|
||||
|
||||
va_start(ap, zFmt);
|
||||
zMsg = sqlite3_vmprintf(zFmt, ap);
|
||||
if( pConfig->pzErrmsg ){
|
||||
assert( *pConfig->pzErrmsg==0 );
|
||||
*pConfig->pzErrmsg = zMsg;
|
||||
}else{
|
||||
sqlite3_free(zMsg);
|
||||
}
|
||||
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
|
||||
|
||||
+29
-19
@@ -54,7 +54,7 @@ struct Fts5Expr {
|
||||
|
||||
/*
|
||||
** eType:
|
||||
** Expression node type. Always one of:
|
||||
** Expression node type. Usually one of:
|
||||
**
|
||||
** FTS5_AND (nChild, apChild valid)
|
||||
** FTS5_OR (nChild, apChild valid)
|
||||
@@ -62,6 +62,10 @@ struct Fts5Expr {
|
||||
** FTS5_STRING (pNear valid)
|
||||
** FTS5_TERM (pNear valid)
|
||||
**
|
||||
** An expression node with eType==0 may also exist. It always matches zero
|
||||
** rows. This is created when a phrase containing no tokens is parsed.
|
||||
** e.g. "".
|
||||
**
|
||||
** iHeight:
|
||||
** Distance from this node to furthest leaf. This is always 0 for nodes
|
||||
** of type FTS5_STRING and FTS5_TERM. For all other nodes it is one
|
||||
@@ -282,11 +286,12 @@ int sqlite3Fts5ExprNew(
|
||||
}while( sParse.rc==SQLITE_OK && t!=FTS5_EOF );
|
||||
sqlite3Fts5ParserFree(pEngine, fts5ParseFree);
|
||||
|
||||
assert( sParse.pExpr || sParse.rc!=SQLITE_OK );
|
||||
assert_expr_depth_ok(sParse.rc, sParse.pExpr);
|
||||
|
||||
/* If the LHS of the MATCH expression was a user column, apply the
|
||||
** implicit column-filter. */
|
||||
if( iCol<pConfig->nCol && sParse.pExpr && sParse.rc==SQLITE_OK ){
|
||||
if( sParse.rc==SQLITE_OK && iCol<pConfig->nCol ){
|
||||
int n = sizeof(Fts5Colset);
|
||||
Fts5Colset *pColset = (Fts5Colset*)sqlite3Fts5MallocZero(&sParse.rc, n);
|
||||
if( pColset ){
|
||||
@@ -303,15 +308,7 @@ int sqlite3Fts5ExprNew(
|
||||
sParse.rc = SQLITE_NOMEM;
|
||||
sqlite3Fts5ParseNodeFree(sParse.pExpr);
|
||||
}else{
|
||||
if( !sParse.pExpr ){
|
||||
const int nByte = sizeof(Fts5ExprNode);
|
||||
pNew->pRoot = (Fts5ExprNode*)sqlite3Fts5MallocZero(&sParse.rc, nByte);
|
||||
if( pNew->pRoot ){
|
||||
pNew->pRoot->bEof = 1;
|
||||
}
|
||||
}else{
|
||||
pNew->pRoot = sParse.pExpr;
|
||||
}
|
||||
pNew->pRoot = sParse.pExpr;
|
||||
pNew->pIndex = 0;
|
||||
pNew->pConfig = pConfig;
|
||||
pNew->apExprPhrase = sParse.apPhrase;
|
||||
@@ -324,7 +321,11 @@ int sqlite3Fts5ExprNew(
|
||||
}
|
||||
|
||||
sqlite3_free(sParse.apPhrase);
|
||||
*pzErr = sParse.zErr;
|
||||
if( 0==*pzErr ){
|
||||
*pzErr = sParse.zErr;
|
||||
}else{
|
||||
sqlite3_free(sParse.zErr);
|
||||
}
|
||||
return sParse.rc;
|
||||
}
|
||||
|
||||
@@ -1125,7 +1126,7 @@ static int fts5ExprNodeTest_STRING(
|
||||
}
|
||||
}else{
|
||||
Fts5IndexIter *pIter = pPhrase->aTerm[j].pIter;
|
||||
if( pIter->iRowid==iLast || pIter->bEof ) continue;
|
||||
if( pIter->iRowid==iLast ) continue;
|
||||
bMatch = 0;
|
||||
if( fts5ExprAdvanceto(pIter, bDesc, &iLast, &rc, &pNode->bEof) ){
|
||||
return rc;
|
||||
@@ -1647,9 +1648,6 @@ Fts5ExprNearset *sqlite3Fts5ParseNearset(
|
||||
Fts5ExprNearset *pRet = 0;
|
||||
|
||||
if( pParse->rc==SQLITE_OK ){
|
||||
if( pPhrase==0 ){
|
||||
return pNear;
|
||||
}
|
||||
if( pNear==0 ){
|
||||
sqlite3_int64 nByte;
|
||||
nByte = sizeof(Fts5ExprNearset) + SZALLOC * sizeof(Fts5ExprPhrase*);
|
||||
@@ -1871,6 +1869,7 @@ Fts5ExprPhrase *sqlite3Fts5ParseTerm(
|
||||
}else if( sCtx.pPhrase->nTerm ){
|
||||
sCtx.pPhrase->aTerm[sCtx.pPhrase->nTerm-1].bPrefix = (u8)bPrefix;
|
||||
}
|
||||
assert( pParse->apPhrase!=0 );
|
||||
pParse->apPhrase[pParse->nPhrase-1] = sCtx.pPhrase;
|
||||
}
|
||||
|
||||
@@ -1890,7 +1889,7 @@ int sqlite3Fts5ExprClonePhrase(
|
||||
Fts5ExprPhrase *pOrig = 0; /* The phrase extracted from pExpr */
|
||||
Fts5Expr *pNew = 0; /* Expression to return via *ppNew */
|
||||
TokenCtx sCtx = {0,0,0}; /* Context object for fts5ParseTokenize */
|
||||
if( iPhrase<0 || iPhrase>=pExpr->nPhrase ){
|
||||
if( !pExpr || iPhrase<0 || iPhrase>=pExpr->nPhrase ){
|
||||
rc = SQLITE_RANGE;
|
||||
}else{
|
||||
pOrig = pExpr->apExprPhrase[iPhrase];
|
||||
@@ -2258,6 +2257,9 @@ static void fts5ExprAssignXNext(Fts5ExprNode *pNode){
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Add pSub as a child of p.
|
||||
*/
|
||||
static void fts5ExprAddChildren(Fts5ExprNode *p, Fts5ExprNode *pSub){
|
||||
int ii = p->nChild;
|
||||
if( p->eType!=FTS5_NOT && pSub->eType==p->eType ){
|
||||
@@ -2402,19 +2404,23 @@ Fts5ExprNode *sqlite3Fts5ParseNode(
|
||||
"fts5: %s queries are not supported (detail!=full)",
|
||||
pNear->nPhrase==1 ? "phrase": "NEAR"
|
||||
);
|
||||
sqlite3_free(pRet);
|
||||
sqlite3Fts5ParseNodeFree(pRet);
|
||||
pRet = 0;
|
||||
pNear = 0;
|
||||
assert( pLeft==0 && pRight==0 );
|
||||
}
|
||||
}
|
||||
}else{
|
||||
assert( pNear==0 );
|
||||
fts5ExprAddChildren(pRet, pLeft);
|
||||
fts5ExprAddChildren(pRet, pRight);
|
||||
pLeft = pRight = 0;
|
||||
if( pRet->iHeight>SQLITE_FTS5_MAX_EXPR_DEPTH ){
|
||||
sqlite3Fts5ParseError(pParse,
|
||||
"fts5 expression tree is too large (maximum depth %d)",
|
||||
SQLITE_FTS5_MAX_EXPR_DEPTH
|
||||
);
|
||||
sqlite3_free(pRet);
|
||||
sqlite3Fts5ParseNodeFree(pRet);
|
||||
pRet = 0;
|
||||
}
|
||||
}
|
||||
@@ -2452,6 +2458,7 @@ Fts5ExprNode *sqlite3Fts5ParseImplicitAnd(
|
||||
assert( pRight->eType==FTS5_STRING
|
||||
|| pRight->eType==FTS5_TERM
|
||||
|| pRight->eType==FTS5_EOF
|
||||
|| (pRight->eType==FTS5_AND && pParse->bPhraseToAnd)
|
||||
);
|
||||
|
||||
if( pLeft->eType==FTS5_AND ){
|
||||
@@ -2465,6 +2472,8 @@ Fts5ExprNode *sqlite3Fts5ParseImplicitAnd(
|
||||
);
|
||||
|
||||
if( pRight->eType==FTS5_EOF ){
|
||||
assert( pParse->apPhrase!=0 );
|
||||
assert( pParse->nPhrase>0 );
|
||||
assert( pParse->apPhrase[pParse->nPhrase-1]==pRight->pNear->apPhrase[0] );
|
||||
sqlite3Fts5ParseNodeFree(pRight);
|
||||
pRet = pLeft;
|
||||
@@ -3097,6 +3106,7 @@ static int fts5ExprCheckPoslists(Fts5ExprNode *pNode, i64 iRowid){
|
||||
pNode->iRowid = iRowid;
|
||||
pNode->bEof = 0;
|
||||
switch( pNode->eType ){
|
||||
case 0:
|
||||
case FTS5_TERM:
|
||||
case FTS5_STRING:
|
||||
return (pNode->pNear->apPhrase[0]->poslist.n>0);
|
||||
|
||||
@@ -831,11 +831,12 @@ static Fts5Data *fts5DataRead(Fts5Index *p, i64 iRowid){
|
||||
if( rc==SQLITE_OK ){
|
||||
u8 *aOut = 0; /* Read blob data into this buffer */
|
||||
int nByte = sqlite3_blob_bytes(p->pReader);
|
||||
sqlite3_int64 nAlloc = sizeof(Fts5Data) + nByte + FTS5_DATA_PADDING;
|
||||
int szData = (sizeof(Fts5Data) + 7) & ~7;
|
||||
sqlite3_int64 nAlloc = szData + nByte + FTS5_DATA_PADDING;
|
||||
pRet = (Fts5Data*)sqlite3_malloc64(nAlloc);
|
||||
if( pRet ){
|
||||
pRet->nn = nByte;
|
||||
aOut = pRet->p = (u8*)&pRet[1];
|
||||
aOut = pRet->p = (u8*)pRet + szData;
|
||||
}else{
|
||||
rc = SQLITE_NOMEM;
|
||||
}
|
||||
@@ -858,6 +859,7 @@ static Fts5Data *fts5DataRead(Fts5Index *p, i64 iRowid){
|
||||
}
|
||||
|
||||
assert( (pRet==0)==(p->rc!=SQLITE_OK) );
|
||||
assert( pRet==0 || EIGHT_BYTE_ALIGNMENT( pRet->p ) );
|
||||
return pRet;
|
||||
}
|
||||
|
||||
@@ -2183,7 +2185,7 @@ static void fts5SegIterNext_None(
|
||||
|
||||
if( iOff<pIter->iEndofDoclist ){
|
||||
/* Next entry is on the current page */
|
||||
i64 iDelta;
|
||||
u64 iDelta;
|
||||
iOff += sqlite3Fts5GetVarint(&pIter->pLeaf->p[iOff], (u64*)&iDelta);
|
||||
pIter->iLeafOffset = iOff;
|
||||
pIter->iRowid += iDelta;
|
||||
|
||||
+840
-180
File diff suppressed because it is too large
Load Diff
+357
-92
@@ -16,13 +16,40 @@
|
||||
|
||||
#include "fts5Int.h"
|
||||
|
||||
/*
|
||||
** pSavedRow:
|
||||
** SQL statement FTS5_STMT_LOOKUP2 is a copy of FTS5_STMT_LOOKUP, it
|
||||
** does a by-rowid lookup to retrieve a single row from the %_content
|
||||
** table or equivalent external-content table/view.
|
||||
**
|
||||
** However, FTS5_STMT_LOOKUP2 is only used when retrieving the original
|
||||
** values for a row being UPDATEd. In that case, the SQL statement is
|
||||
** not reset and pSavedRow is set to point at it. This is so that the
|
||||
** insert operation that follows the delete may access the original
|
||||
** row values for any new values for which sqlite3_value_nochange() returns
|
||||
** true. i.e. if the user executes:
|
||||
**
|
||||
** CREATE VIRTUAL TABLE ft USING fts5(a, b, c, locale=1);
|
||||
** ...
|
||||
** UPDATE fts SET a=?, b=? WHERE rowid=?;
|
||||
**
|
||||
** then the value passed to the xUpdate() method of this table as the
|
||||
** new.c value is an sqlite3_value_nochange() value. So in this case it
|
||||
** must be read from the saved row stored in Fts5Storage.pSavedRow.
|
||||
**
|
||||
** This is necessary - using sqlite3_value_nochange() instead of just having
|
||||
** SQLite pass the original value back via xUpdate() - so as not to discard
|
||||
** any locale information associated with such values.
|
||||
**
|
||||
*/
|
||||
struct Fts5Storage {
|
||||
Fts5Config *pConfig;
|
||||
Fts5Index *pIndex;
|
||||
int bTotalsValid; /* True if nTotalRow/aTotalSize[] are valid */
|
||||
i64 nTotalRow; /* Total number of rows in FTS table */
|
||||
i64 *aTotalSize; /* Total sizes of each column */
|
||||
sqlite3_stmt *aStmt[11];
|
||||
sqlite3_stmt *pSavedRow;
|
||||
sqlite3_stmt *aStmt[12];
|
||||
};
|
||||
|
||||
|
||||
@@ -36,14 +63,39 @@ struct Fts5Storage {
|
||||
# error "FTS5_STMT_LOOKUP mismatch"
|
||||
#endif
|
||||
|
||||
#define FTS5_STMT_INSERT_CONTENT 3
|
||||
#define FTS5_STMT_REPLACE_CONTENT 4
|
||||
#define FTS5_STMT_DELETE_CONTENT 5
|
||||
#define FTS5_STMT_REPLACE_DOCSIZE 6
|
||||
#define FTS5_STMT_DELETE_DOCSIZE 7
|
||||
#define FTS5_STMT_LOOKUP_DOCSIZE 8
|
||||
#define FTS5_STMT_REPLACE_CONFIG 9
|
||||
#define FTS5_STMT_SCAN 10
|
||||
#define FTS5_STMT_LOOKUP2 3
|
||||
#define FTS5_STMT_INSERT_CONTENT 4
|
||||
#define FTS5_STMT_REPLACE_CONTENT 5
|
||||
#define FTS5_STMT_DELETE_CONTENT 6
|
||||
#define FTS5_STMT_REPLACE_DOCSIZE 7
|
||||
#define FTS5_STMT_DELETE_DOCSIZE 8
|
||||
#define FTS5_STMT_LOOKUP_DOCSIZE 9
|
||||
#define FTS5_STMT_REPLACE_CONFIG 10
|
||||
#define FTS5_STMT_SCAN 11
|
||||
|
||||
/*
|
||||
** Return a pointer to a buffer obtained from sqlite3_malloc() that contains
|
||||
** nBind comma-separated question marks. e.g. if nBind is passed 5, this
|
||||
** function returns "?,?,?,?,?".
|
||||
**
|
||||
** If *pRc is not SQLITE_OK when this function is called, it is a no-op and
|
||||
** NULL is returned immediately. Or, if the attempt to malloc a buffer
|
||||
** fails, then *pRc is set to SQLITE_NOMEM and NULL is returned. Otherwise,
|
||||
** if it is SQLITE_OK when this function is called and the malloc() succeeds,
|
||||
** *pRc is left unchanged.
|
||||
*/
|
||||
static char *fts5BindingsList(int *pRc, int nBind){
|
||||
char *zBind = sqlite3Fts5MallocZero(pRc, 1 + nBind*2);
|
||||
if( zBind ){
|
||||
int ii;
|
||||
for(ii=0; ii<nBind; ii++){
|
||||
zBind[ii*2] = '?';
|
||||
zBind[ii*2 + 1] = ',';
|
||||
}
|
||||
zBind[ii*2-1] = '\0';
|
||||
}
|
||||
return zBind;
|
||||
}
|
||||
|
||||
/*
|
||||
** Prepare the two insert statements - Fts5Storage.pInsertContent and
|
||||
@@ -73,6 +125,7 @@ static int fts5StorageGetStmt(
|
||||
"SELECT %s FROM %s T WHERE T.%Q >= ? AND T.%Q <= ? ORDER BY T.%Q ASC",
|
||||
"SELECT %s FROM %s T WHERE T.%Q <= ? AND T.%Q >= ? ORDER BY T.%Q DESC",
|
||||
"SELECT %s FROM %s T WHERE T.%Q=?", /* LOOKUP */
|
||||
"SELECT %s FROM %s T WHERE T.%Q=?", /* LOOKUP2 */
|
||||
|
||||
"INSERT INTO %Q.'%q_content' VALUES(%s)", /* INSERT_CONTENT */
|
||||
"REPLACE INTO %Q.'%q_content' VALUES(%s)", /* REPLACE_CONTENT */
|
||||
@@ -88,6 +141,8 @@ static int fts5StorageGetStmt(
|
||||
Fts5Config *pC = p->pConfig;
|
||||
char *zSql = 0;
|
||||
|
||||
assert( ArraySize(azStmt)==ArraySize(p->aStmt) );
|
||||
|
||||
switch( eStmt ){
|
||||
case FTS5_STMT_SCAN:
|
||||
zSql = sqlite3_mprintf(azStmt[eStmt],
|
||||
@@ -104,24 +159,26 @@ static int fts5StorageGetStmt(
|
||||
break;
|
||||
|
||||
case FTS5_STMT_LOOKUP:
|
||||
case FTS5_STMT_LOOKUP2:
|
||||
zSql = sqlite3_mprintf(azStmt[eStmt],
|
||||
pC->zContentExprlist, pC->zContent, pC->zContentRowid
|
||||
);
|
||||
break;
|
||||
|
||||
case FTS5_STMT_INSERT_CONTENT:
|
||||
case FTS5_STMT_REPLACE_CONTENT: {
|
||||
int nCol = pC->nCol + 1;
|
||||
case FTS5_STMT_INSERT_CONTENT: {
|
||||
int nCol = 0;
|
||||
char *zBind;
|
||||
int i;
|
||||
|
||||
zBind = sqlite3_malloc64(1 + nCol*2);
|
||||
if( zBind ){
|
||||
for(i=0; i<nCol; i++){
|
||||
zBind[i*2] = '?';
|
||||
zBind[i*2 + 1] = ',';
|
||||
nCol = 1 + pC->nCol;
|
||||
if( pC->bLocale ){
|
||||
for(i=0; i<pC->nCol; i++){
|
||||
if( pC->abUnindexed[i]==0 ) nCol++;
|
||||
}
|
||||
zBind[i*2-1] = '\0';
|
||||
}
|
||||
|
||||
zBind = fts5BindingsList(&rc, nCol);
|
||||
if( zBind ){
|
||||
zSql = sqlite3_mprintf(azStmt[eStmt], pC->zDb, pC->zName, zBind);
|
||||
sqlite3_free(zBind);
|
||||
}
|
||||
@@ -150,7 +207,7 @@ static int fts5StorageGetStmt(
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
int f = SQLITE_PREPARE_PERSISTENT;
|
||||
if( eStmt>FTS5_STMT_LOOKUP ) f |= SQLITE_PREPARE_NO_VTAB;
|
||||
if( eStmt>FTS5_STMT_LOOKUP2 ) f |= SQLITE_PREPARE_NO_VTAB;
|
||||
p->pConfig->bLock++;
|
||||
rc = sqlite3_prepare_v3(pC->db, zSql, -1, f, &p->aStmt[eStmt], 0);
|
||||
p->pConfig->bLock--;
|
||||
@@ -312,7 +369,7 @@ int sqlite3Fts5StorageOpen(
|
||||
if( bCreate ){
|
||||
if( pConfig->eContent==FTS5_CONTENT_NORMAL ){
|
||||
int nDefn = 32 + pConfig->nCol*10;
|
||||
char *zDefn = sqlite3_malloc64(32 + (sqlite3_int64)pConfig->nCol * 10);
|
||||
char *zDefn = sqlite3_malloc64(32 + (sqlite3_int64)pConfig->nCol * 20);
|
||||
if( zDefn==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
@@ -324,6 +381,14 @@ int sqlite3Fts5StorageOpen(
|
||||
sqlite3_snprintf(nDefn-iOff, &zDefn[iOff], ", c%d", i);
|
||||
iOff += (int)strlen(&zDefn[iOff]);
|
||||
}
|
||||
if( pConfig->bLocale ){
|
||||
for(i=0; i<pConfig->nCol; i++){
|
||||
if( pConfig->abUnindexed[i]==0 ){
|
||||
sqlite3_snprintf(nDefn-iOff, &zDefn[iOff], ", l%d", i);
|
||||
iOff += (int)strlen(&zDefn[iOff]);
|
||||
}
|
||||
}
|
||||
}
|
||||
rc = sqlite3Fts5CreateTable(pConfig, "content", zDefn, 0, pzErr);
|
||||
}
|
||||
sqlite3_free(zDefn);
|
||||
@@ -399,15 +464,49 @@ static int fts5StorageInsertCallback(
|
||||
return sqlite3Fts5IndexWrite(pIdx, pCtx->iCol, pCtx->szCol-1, pToken, nToken);
|
||||
}
|
||||
|
||||
/*
|
||||
** This function is used as part of an UPDATE statement that modifies the
|
||||
** rowid of a row. In that case, this function is called first to set
|
||||
** Fts5Storage.pSavedRow to point to a statement that may be used to
|
||||
** access the original values of the row being deleted - iDel.
|
||||
**
|
||||
** SQLITE_OK is returned if successful, or an SQLite error code otherwise.
|
||||
** It is not considered an error if row iDel does not exist. In this case
|
||||
** pSavedRow is not set and SQLITE_OK returned.
|
||||
*/
|
||||
int sqlite3Fts5StorageFindDeleteRow(Fts5Storage *p, i64 iDel){
|
||||
int rc = SQLITE_OK;
|
||||
sqlite3_stmt *pSeek = 0;
|
||||
|
||||
assert( p->pSavedRow==0 );
|
||||
rc = fts5StorageGetStmt(p, FTS5_STMT_LOOKUP+1, &pSeek, 0);
|
||||
if( rc==SQLITE_OK ){
|
||||
sqlite3_bind_int64(pSeek, 1, iDel);
|
||||
if( sqlite3_step(pSeek)!=SQLITE_ROW ){
|
||||
rc = sqlite3_reset(pSeek);
|
||||
}else{
|
||||
p->pSavedRow = pSeek;
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** If a row with rowid iDel is present in the %_content table, add the
|
||||
** delete-markers to the FTS index necessary to delete it. Do not actually
|
||||
** remove the %_content row at this time though.
|
||||
**
|
||||
** If parameter bSaveRow is true, then Fts5Storage.pSavedRow is left
|
||||
** pointing to a statement (FTS5_STMT_LOOKUP2) that may be used to access
|
||||
** the original values of the row being deleted. This is used by UPDATE
|
||||
** statements.
|
||||
*/
|
||||
static int fts5StorageDeleteFromIndex(
|
||||
Fts5Storage *p,
|
||||
i64 iDel,
|
||||
sqlite3_value **apVal
|
||||
sqlite3_value **apVal,
|
||||
int bSaveRow /* True to set pSavedRow */
|
||||
){
|
||||
Fts5Config *pConfig = p->pConfig;
|
||||
sqlite3_stmt *pSeek = 0; /* SELECT to read row iDel from %_data */
|
||||
@@ -416,12 +515,21 @@ static int fts5StorageDeleteFromIndex(
|
||||
int iCol;
|
||||
Fts5InsertCtx ctx;
|
||||
|
||||
assert( bSaveRow==0 || apVal==0 );
|
||||
assert( bSaveRow==0 || bSaveRow==1 );
|
||||
assert( FTS5_STMT_LOOKUP2==FTS5_STMT_LOOKUP+1 );
|
||||
|
||||
if( apVal==0 ){
|
||||
rc = fts5StorageGetStmt(p, FTS5_STMT_LOOKUP, &pSeek, 0);
|
||||
if( rc!=SQLITE_OK ) return rc;
|
||||
sqlite3_bind_int64(pSeek, 1, iDel);
|
||||
if( sqlite3_step(pSeek)!=SQLITE_ROW ){
|
||||
return sqlite3_reset(pSeek);
|
||||
if( p->pSavedRow && bSaveRow ){
|
||||
pSeek = p->pSavedRow;
|
||||
p->pSavedRow = 0;
|
||||
}else{
|
||||
rc = fts5StorageGetStmt(p, FTS5_STMT_LOOKUP+bSaveRow, &pSeek, 0);
|
||||
if( rc!=SQLITE_OK ) return rc;
|
||||
sqlite3_bind_int64(pSeek, 1, iDel);
|
||||
if( sqlite3_step(pSeek)!=SQLITE_ROW ){
|
||||
return sqlite3_reset(pSeek);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -429,26 +537,42 @@ static int fts5StorageDeleteFromIndex(
|
||||
ctx.iCol = -1;
|
||||
for(iCol=1; rc==SQLITE_OK && iCol<=pConfig->nCol; iCol++){
|
||||
if( pConfig->abUnindexed[iCol-1]==0 ){
|
||||
const char *zText;
|
||||
int nText;
|
||||
sqlite3_value *pVal = 0;
|
||||
const char *pText = 0;
|
||||
int nText = 0;
|
||||
const char *pLoc = 0;
|
||||
int nLoc = 0;
|
||||
|
||||
assert( pSeek==0 || apVal==0 );
|
||||
assert( pSeek!=0 || apVal!=0 );
|
||||
if( pSeek ){
|
||||
zText = (const char*)sqlite3_column_text(pSeek, iCol);
|
||||
nText = sqlite3_column_bytes(pSeek, iCol);
|
||||
}else if( ALWAYS(apVal) ){
|
||||
zText = (const char*)sqlite3_value_text(apVal[iCol-1]);
|
||||
nText = sqlite3_value_bytes(apVal[iCol-1]);
|
||||
pVal = sqlite3_column_value(pSeek, iCol);
|
||||
}else{
|
||||
continue;
|
||||
pVal = apVal[iCol-1];
|
||||
}
|
||||
ctx.szCol = 0;
|
||||
rc = sqlite3Fts5Tokenize(pConfig, FTS5_TOKENIZE_DOCUMENT,
|
||||
zText, nText, (void*)&ctx, fts5StorageInsertCallback
|
||||
);
|
||||
p->aTotalSize[iCol-1] -= (i64)ctx.szCol;
|
||||
if( p->aTotalSize[iCol-1]<0 ){
|
||||
rc = FTS5_CORRUPT;
|
||||
|
||||
if( pConfig->bLocale && sqlite3Fts5IsLocaleValue(pConfig, pVal) ){
|
||||
rc = sqlite3Fts5DecodeLocaleValue(pVal, &pText, &nText, &pLoc, &nLoc);
|
||||
}else{
|
||||
pText = (const char*)sqlite3_value_text(pVal);
|
||||
nText = sqlite3_value_bytes(pVal);
|
||||
if( pConfig->bLocale && pSeek ){
|
||||
pLoc = (const char*)sqlite3_column_text(pSeek, iCol + pConfig->nCol);
|
||||
nLoc = sqlite3_column_bytes(pSeek, iCol + pConfig->nCol);
|
||||
}
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
sqlite3Fts5SetLocale(pConfig, pLoc, nLoc);
|
||||
ctx.szCol = 0;
|
||||
rc = sqlite3Fts5Tokenize(pConfig, FTS5_TOKENIZE_DOCUMENT,
|
||||
pText, nText, (void*)&ctx, fts5StorageInsertCallback
|
||||
);
|
||||
p->aTotalSize[iCol-1] -= (i64)ctx.szCol;
|
||||
if( rc==SQLITE_OK && p->aTotalSize[iCol-1]<0 ){
|
||||
rc = FTS5_CORRUPT;
|
||||
}
|
||||
sqlite3Fts5ClearLocale(pConfig);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -458,11 +582,29 @@ static int fts5StorageDeleteFromIndex(
|
||||
p->nTotalRow--;
|
||||
}
|
||||
|
||||
rc2 = sqlite3_reset(pSeek);
|
||||
if( rc==SQLITE_OK ) rc = rc2;
|
||||
if( rc==SQLITE_OK && bSaveRow ){
|
||||
assert( p->pSavedRow==0 );
|
||||
p->pSavedRow = pSeek;
|
||||
}else{
|
||||
rc2 = sqlite3_reset(pSeek);
|
||||
if( rc==SQLITE_OK ) rc = rc2;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Reset any saved statement pSavedRow. Zero pSavedRow as well. This
|
||||
** should be called by the xUpdate() method of the fts5 table before
|
||||
** returning from any operation that may have set Fts5Storage.pSavedRow.
|
||||
*/
|
||||
void sqlite3Fts5StorageReleaseDeleteRow(Fts5Storage *pStorage){
|
||||
assert( pStorage->pSavedRow==0
|
||||
|| pStorage->pSavedRow==pStorage->aStmt[FTS5_STMT_LOOKUP2]
|
||||
);
|
||||
sqlite3_reset(pStorage->pSavedRow);
|
||||
pStorage->pSavedRow = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** This function is called to process a DELETE on a contentless_delete=1
|
||||
** table. It adds the tombstone required to delete the entry with rowid
|
||||
@@ -519,12 +661,12 @@ static int fts5StorageInsertDocsize(
|
||||
rc = sqlite3Fts5IndexGetOrigin(p->pIndex, &iOrigin);
|
||||
sqlite3_bind_int64(pReplace, 3, iOrigin);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
sqlite3_bind_blob(pReplace, 2, pBuf->p, pBuf->n, SQLITE_STATIC);
|
||||
sqlite3_step(pReplace);
|
||||
rc = sqlite3_reset(pReplace);
|
||||
sqlite3_bind_null(pReplace, 2);
|
||||
}
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
sqlite3_bind_blob(pReplace, 2, pBuf->p, pBuf->n, SQLITE_STATIC);
|
||||
sqlite3_step(pReplace);
|
||||
rc = sqlite3_reset(pReplace);
|
||||
sqlite3_bind_null(pReplace, 2);
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
@@ -578,7 +720,12 @@ static int fts5StorageSaveTotals(Fts5Storage *p){
|
||||
/*
|
||||
** Remove a row from the FTS table.
|
||||
*/
|
||||
int sqlite3Fts5StorageDelete(Fts5Storage *p, i64 iDel, sqlite3_value **apVal){
|
||||
int sqlite3Fts5StorageDelete(
|
||||
Fts5Storage *p, /* Storage object */
|
||||
i64 iDel, /* Rowid to delete from table */
|
||||
sqlite3_value **apVal, /* Optional - values to remove from index */
|
||||
int bSaveRow /* If true, set pSavedRow for deleted row */
|
||||
){
|
||||
Fts5Config *pConfig = p->pConfig;
|
||||
int rc;
|
||||
sqlite3_stmt *pDel = 0;
|
||||
@@ -595,7 +742,7 @@ int sqlite3Fts5StorageDelete(Fts5Storage *p, i64 iDel, sqlite3_value **apVal){
|
||||
if( p->pConfig->bContentlessDelete ){
|
||||
rc = fts5StorageContentlessDelete(p, iDel);
|
||||
}else{
|
||||
rc = fts5StorageDeleteFromIndex(p, iDel, apVal);
|
||||
rc = fts5StorageDeleteFromIndex(p, iDel, apVal, bSaveRow);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -684,14 +831,36 @@ int sqlite3Fts5StorageRebuild(Fts5Storage *p){
|
||||
for(ctx.iCol=0; rc==SQLITE_OK && ctx.iCol<pConfig->nCol; ctx.iCol++){
|
||||
ctx.szCol = 0;
|
||||
if( pConfig->abUnindexed[ctx.iCol]==0 ){
|
||||
const char *zText = (const char*)sqlite3_column_text(pScan, ctx.iCol+1);
|
||||
int nText = sqlite3_column_bytes(pScan, ctx.iCol+1);
|
||||
rc = sqlite3Fts5Tokenize(pConfig,
|
||||
FTS5_TOKENIZE_DOCUMENT,
|
||||
zText, nText,
|
||||
(void*)&ctx,
|
||||
fts5StorageInsertCallback
|
||||
);
|
||||
int nText = 0; /* Size of pText in bytes */
|
||||
const char *pText = 0; /* Pointer to buffer containing text value */
|
||||
int nLoc = 0; /* Size of pLoc in bytes */
|
||||
const char *pLoc = 0; /* Pointer to buffer containing text value */
|
||||
|
||||
sqlite3_value *pVal = sqlite3_column_value(pScan, ctx.iCol+1);
|
||||
if( pConfig->eContent==FTS5_CONTENT_EXTERNAL
|
||||
&& sqlite3Fts5IsLocaleValue(pConfig, pVal)
|
||||
){
|
||||
rc = sqlite3Fts5DecodeLocaleValue(pVal, &pText, &nText, &pLoc, &nLoc);
|
||||
}else{
|
||||
pText = (const char*)sqlite3_value_text(pVal);
|
||||
nText = sqlite3_value_bytes(pVal);
|
||||
if( pConfig->bLocale ){
|
||||
int iCol = ctx.iCol + 1 + pConfig->nCol;
|
||||
pLoc = (const char*)sqlite3_column_text(pScan, iCol);
|
||||
nLoc = sqlite3_column_bytes(pScan, iCol);
|
||||
}
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
sqlite3Fts5SetLocale(pConfig, pLoc, nLoc);
|
||||
rc = sqlite3Fts5Tokenize(pConfig,
|
||||
FTS5_TOKENIZE_DOCUMENT,
|
||||
pText, nText,
|
||||
(void*)&ctx,
|
||||
fts5StorageInsertCallback
|
||||
);
|
||||
sqlite3Fts5ClearLocale(pConfig);
|
||||
}
|
||||
}
|
||||
sqlite3Fts5BufferAppendVarint(&rc, &buf, ctx.szCol);
|
||||
p->aTotalSize[ctx.iCol] += (i64)ctx.szCol;
|
||||
@@ -773,9 +942,49 @@ int sqlite3Fts5StorageContentInsert(
|
||||
}else{
|
||||
sqlite3_stmt *pInsert = 0; /* Statement to write %_content table */
|
||||
int i; /* Counter variable */
|
||||
int nIndexed = 0; /* Number indexed columns seen */
|
||||
rc = fts5StorageGetStmt(p, FTS5_STMT_INSERT_CONTENT, &pInsert, 0);
|
||||
for(i=1; rc==SQLITE_OK && i<=pConfig->nCol+1; i++){
|
||||
rc = sqlite3_bind_value(pInsert, i, apVal[i]);
|
||||
if( pInsert ) sqlite3_clear_bindings(pInsert);
|
||||
|
||||
/* Bind the rowid value */
|
||||
sqlite3_bind_value(pInsert, 1, apVal[1]);
|
||||
|
||||
/* Loop through values for user-defined columns. i=2 is the leftmost
|
||||
** user-defined column. As is column 1 of pSavedRow. */
|
||||
for(i=2; rc==SQLITE_OK && i<=pConfig->nCol+1; i++){
|
||||
int bUnindexed = pConfig->abUnindexed[i-2];
|
||||
sqlite3_value *pVal = apVal[i];
|
||||
|
||||
nIndexed += !bUnindexed;
|
||||
if( sqlite3_value_nochange(pVal) && p->pSavedRow ){
|
||||
/* This is an UPDATE statement, and column (i-2) was not modified.
|
||||
** Retrieve the value from Fts5Storage.pSavedRow instead. */
|
||||
pVal = sqlite3_column_value(p->pSavedRow, i-1);
|
||||
if( pConfig->bLocale && bUnindexed==0 ){
|
||||
sqlite3_bind_value(pInsert, pConfig->nCol + 1 + nIndexed,
|
||||
sqlite3_column_value(p->pSavedRow, pConfig->nCol + i - 1)
|
||||
);
|
||||
}
|
||||
}else if( sqlite3Fts5IsLocaleValue(pConfig, pVal) ){
|
||||
const char *pText = 0;
|
||||
const char *pLoc = 0;
|
||||
int nText = 0;
|
||||
int nLoc = 0;
|
||||
assert( pConfig->bLocale );
|
||||
|
||||
rc = sqlite3Fts5DecodeLocaleValue(pVal, &pText, &nText, &pLoc, &nLoc);
|
||||
if( rc==SQLITE_OK ){
|
||||
sqlite3_bind_text(pInsert, i, pText, nText, SQLITE_TRANSIENT);
|
||||
if( bUnindexed==0 ){
|
||||
int iLoc = pConfig->nCol + 1 + nIndexed;
|
||||
sqlite3_bind_text(pInsert, iLoc, pLoc, nLoc, SQLITE_TRANSIENT);
|
||||
}
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
rc = sqlite3_bind_value(pInsert, i, pVal);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
sqlite3_step(pInsert);
|
||||
@@ -810,14 +1019,38 @@ int sqlite3Fts5StorageIndexInsert(
|
||||
for(ctx.iCol=0; rc==SQLITE_OK && ctx.iCol<pConfig->nCol; ctx.iCol++){
|
||||
ctx.szCol = 0;
|
||||
if( pConfig->abUnindexed[ctx.iCol]==0 ){
|
||||
const char *zText = (const char*)sqlite3_value_text(apVal[ctx.iCol+2]);
|
||||
int nText = sqlite3_value_bytes(apVal[ctx.iCol+2]);
|
||||
rc = sqlite3Fts5Tokenize(pConfig,
|
||||
FTS5_TOKENIZE_DOCUMENT,
|
||||
zText, nText,
|
||||
(void*)&ctx,
|
||||
fts5StorageInsertCallback
|
||||
);
|
||||
int nText = 0; /* Size of pText in bytes */
|
||||
const char *pText = 0; /* Pointer to buffer containing text value */
|
||||
int nLoc = 0; /* Size of pText in bytes */
|
||||
const char *pLoc = 0; /* Pointer to buffer containing text value */
|
||||
|
||||
sqlite3_value *pVal = apVal[ctx.iCol+2];
|
||||
if( p->pSavedRow && sqlite3_value_nochange(pVal) ){
|
||||
pVal = sqlite3_column_value(p->pSavedRow, ctx.iCol+1);
|
||||
if( pConfig->eContent==FTS5_CONTENT_NORMAL && pConfig->bLocale ){
|
||||
int iCol = ctx.iCol + 1 + pConfig->nCol;
|
||||
pLoc = (const char*)sqlite3_column_text(p->pSavedRow, iCol);
|
||||
nLoc = sqlite3_column_bytes(p->pSavedRow, iCol);
|
||||
}
|
||||
}else{
|
||||
pVal = apVal[ctx.iCol+2];
|
||||
}
|
||||
|
||||
if( pConfig->bLocale && sqlite3Fts5IsLocaleValue(pConfig, pVal) ){
|
||||
rc = sqlite3Fts5DecodeLocaleValue(pVal, &pText, &nText, &pLoc, &nLoc);
|
||||
}else{
|
||||
pText = (const char*)sqlite3_value_text(pVal);
|
||||
nText = sqlite3_value_bytes(pVal);
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
sqlite3Fts5SetLocale(pConfig, pLoc, nLoc);
|
||||
rc = sqlite3Fts5Tokenize(pConfig,
|
||||
FTS5_TOKENIZE_DOCUMENT, pText, nText, (void*)&ctx,
|
||||
fts5StorageInsertCallback
|
||||
);
|
||||
sqlite3Fts5ClearLocale(pConfig);
|
||||
}
|
||||
}
|
||||
sqlite3Fts5BufferAppendVarint(&rc, &buf, ctx.szCol);
|
||||
p->aTotalSize[ctx.iCol] += (i64)ctx.szCol;
|
||||
@@ -981,29 +1214,61 @@ int sqlite3Fts5StorageIntegrity(Fts5Storage *p, int iArg){
|
||||
rc = sqlite3Fts5TermsetNew(&ctx.pTermset);
|
||||
}
|
||||
for(i=0; rc==SQLITE_OK && i<pConfig->nCol; i++){
|
||||
if( pConfig->abUnindexed[i] ) continue;
|
||||
ctx.iCol = i;
|
||||
ctx.szCol = 0;
|
||||
if( pConfig->eDetail==FTS5_DETAIL_COLUMNS ){
|
||||
rc = sqlite3Fts5TermsetNew(&ctx.pTermset);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
const char *zText = (const char*)sqlite3_column_text(pScan, i+1);
|
||||
int nText = sqlite3_column_bytes(pScan, i+1);
|
||||
rc = sqlite3Fts5Tokenize(pConfig,
|
||||
FTS5_TOKENIZE_DOCUMENT,
|
||||
zText, nText,
|
||||
(void*)&ctx,
|
||||
fts5StorageIntegrityCallback
|
||||
);
|
||||
}
|
||||
if( rc==SQLITE_OK && pConfig->bColumnsize && ctx.szCol!=aColSize[i] ){
|
||||
rc = FTS5_CORRUPT;
|
||||
}
|
||||
aTotalSize[i] += ctx.szCol;
|
||||
if( pConfig->eDetail==FTS5_DETAIL_COLUMNS ){
|
||||
sqlite3Fts5TermsetFree(ctx.pTermset);
|
||||
ctx.pTermset = 0;
|
||||
if( pConfig->abUnindexed[i]==0 ){
|
||||
const char *pText = 0;
|
||||
int nText = 0;
|
||||
const char *pLoc = 0;
|
||||
int nLoc = 0;
|
||||
sqlite3_value *pVal = sqlite3_column_value(pScan, i+1);
|
||||
|
||||
if( pConfig->eContent==FTS5_CONTENT_EXTERNAL
|
||||
&& sqlite3Fts5IsLocaleValue(pConfig, pVal)
|
||||
){
|
||||
rc = sqlite3Fts5DecodeLocaleValue(
|
||||
pVal, &pText, &nText, &pLoc, &nLoc
|
||||
);
|
||||
}else{
|
||||
if( pConfig->eContent==FTS5_CONTENT_NORMAL && pConfig->bLocale ){
|
||||
int iCol = i + 1 + pConfig->nCol;
|
||||
pLoc = (const char*)sqlite3_column_text(pScan, iCol);
|
||||
nLoc = sqlite3_column_bytes(pScan, iCol);
|
||||
}
|
||||
pText = (const char*)sqlite3_value_text(pVal);
|
||||
nText = sqlite3_value_bytes(pVal);
|
||||
}
|
||||
|
||||
ctx.iCol = i;
|
||||
ctx.szCol = 0;
|
||||
|
||||
if( rc==SQLITE_OK && pConfig->eDetail==FTS5_DETAIL_COLUMNS ){
|
||||
rc = sqlite3Fts5TermsetNew(&ctx.pTermset);
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
sqlite3Fts5SetLocale(pConfig, pLoc, nLoc);
|
||||
rc = sqlite3Fts5Tokenize(pConfig,
|
||||
FTS5_TOKENIZE_DOCUMENT,
|
||||
pText, nText,
|
||||
(void*)&ctx,
|
||||
fts5StorageIntegrityCallback
|
||||
);
|
||||
sqlite3Fts5ClearLocale(pConfig);
|
||||
}
|
||||
|
||||
/* If this is not a columnsize=0 database, check that the number
|
||||
** of tokens in the value matches the aColSize[] value read from
|
||||
** the %_docsize table. */
|
||||
if( rc==SQLITE_OK
|
||||
&& pConfig->bColumnsize
|
||||
&& ctx.szCol!=aColSize[i]
|
||||
){
|
||||
rc = FTS5_CORRUPT;
|
||||
}
|
||||
aTotalSize[i] += ctx.szCol;
|
||||
if( pConfig->eDetail==FTS5_DETAIL_COLUMNS ){
|
||||
sqlite3Fts5TermsetFree(ctx.pTermset);
|
||||
ctx.pTermset = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
sqlite3Fts5TermsetFree(ctx.pTermset);
|
||||
|
||||
+360
-54
@@ -14,14 +14,7 @@
|
||||
|
||||
|
||||
#ifdef SQLITE_TEST
|
||||
#if defined(INCLUDE_SQLITE_TCL_H)
|
||||
# include "sqlite_tcl.h"
|
||||
#else
|
||||
# include "tcl.h"
|
||||
# ifndef SQLITE_TCLAPI
|
||||
# define SQLITE_TCLAPI
|
||||
# endif
|
||||
#endif
|
||||
#include "tclsqlite.h"
|
||||
|
||||
#ifdef SQLITE_ENABLE_FTS5
|
||||
|
||||
@@ -103,14 +96,14 @@ static int SQLITE_TCLAPI f5tDbAndApi(
|
||||
|
||||
rc = sqlite3_prepare_v2(db, "SELECT fts5(?1)", -1, &pStmt, 0);
|
||||
if( rc!=SQLITE_OK ){
|
||||
Tcl_AppendResult(interp, "error: ", sqlite3_errmsg(db), 0);
|
||||
Tcl_AppendResult(interp, "error: ", sqlite3_errmsg(db), (char*)0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
sqlite3_bind_pointer(pStmt, 1, (void*)&pApi, "fts5_api_ptr", 0);
|
||||
sqlite3_step(pStmt);
|
||||
|
||||
if( sqlite3_finalize(pStmt)!=SQLITE_OK ){
|
||||
Tcl_AppendResult(interp, "error: ", sqlite3_errmsg(db), 0);
|
||||
Tcl_AppendResult(interp, "error: ", sqlite3_errmsg(db), (char*)0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
@@ -247,6 +240,7 @@ static int SQLITE_TCLAPI xF5tApi(
|
||||
|
||||
{ "xQueryToken", 2, "IPHRASE ITERM" }, /* 18 */
|
||||
{ "xInstToken", 2, "IDX ITERM" }, /* 19 */
|
||||
{ "xColumnLocale", 1, "COL" }, /* 20 */
|
||||
{ 0, 0, 0}
|
||||
};
|
||||
|
||||
@@ -297,12 +291,12 @@ static int SQLITE_TCLAPI xF5tApi(
|
||||
break;
|
||||
}
|
||||
CASE(3, "xTokenize") {
|
||||
int nText;
|
||||
Tcl_Size nText;
|
||||
char *zText = Tcl_GetStringFromObj(objv[2], &nText);
|
||||
F5tFunction ctx;
|
||||
ctx.interp = interp;
|
||||
ctx.pScript = objv[3];
|
||||
rc = p->pApi->xTokenize(p->pFts, zText, nText, &ctx, xTokenizeCb);
|
||||
rc = p->pApi->xTokenize(p->pFts, zText, (int)nText, &ctx, xTokenizeCb);
|
||||
if( rc==SQLITE_OK ){
|
||||
Tcl_ResetResult(interp);
|
||||
}
|
||||
@@ -398,7 +392,7 @@ static int SQLITE_TCLAPI xF5tApi(
|
||||
CASE(12, "xSetAuxdata") {
|
||||
F5tAuxData *pData = (F5tAuxData*)sqlite3_malloc(sizeof(F5tAuxData));
|
||||
if( pData==0 ){
|
||||
Tcl_AppendResult(interp, "out of memory", 0);
|
||||
Tcl_AppendResult(interp, "out of memory", (char*)0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
pData->pObj = objv[2];
|
||||
@@ -458,7 +452,7 @@ static int SQLITE_TCLAPI xF5tApi(
|
||||
|
||||
rc = p->pApi->xPhraseFirst(p->pFts, iPhrase, &iter, &iCol, &iOff);
|
||||
if( rc!=SQLITE_OK ){
|
||||
Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
|
||||
Tcl_AppendResult(interp, sqlite3ErrName(rc), (char*)0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
for( ;iCol>=0; p->pApi->xPhraseNext(p->pFts, &iter, &iCol, &iOff) ){
|
||||
@@ -535,6 +529,20 @@ static int SQLITE_TCLAPI xF5tApi(
|
||||
break;
|
||||
}
|
||||
|
||||
CASE(20, "xColumnLocale") {
|
||||
const char *z = 0;
|
||||
int n = 0;
|
||||
int iCol;
|
||||
if( Tcl_GetIntFromObj(interp, objv[2], &iCol) ){
|
||||
return TCL_ERROR;
|
||||
}
|
||||
rc = p->pApi->xColumnLocale(p->pFts, iCol, &z, &n);
|
||||
if( rc==SQLITE_OK && z ){
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(z, n));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
assert( 0 );
|
||||
break;
|
||||
@@ -605,15 +613,16 @@ static void xF5tFunction(
|
||||
sqlite3_result_error(pCtx, Tcl_GetStringResult(p->interp), -1);
|
||||
}else{
|
||||
Tcl_Obj *pVar = Tcl_GetObjResult(p->interp);
|
||||
int n;
|
||||
const char *zType = (pVar->typePtr ? pVar->typePtr->name : "");
|
||||
char c = zType[0];
|
||||
if( c=='b' && strcmp(zType,"bytearray")==0 && pVar->bytes==0 ){
|
||||
/* Only return a BLOB type if the Tcl variable is a bytearray and
|
||||
** has no string representation. */
|
||||
unsigned char *data = Tcl_GetByteArrayFromObj(pVar, &n);
|
||||
sqlite3_result_blob(pCtx, data, n, SQLITE_TRANSIENT);
|
||||
Tcl_Size nn;
|
||||
unsigned char *data = Tcl_GetByteArrayFromObj(pVar, &nn);
|
||||
sqlite3_result_blob(pCtx, data, (int)nn, SQLITE_TRANSIENT);
|
||||
}else if( c=='b' && strcmp(zType,"boolean")==0 ){
|
||||
int n;
|
||||
Tcl_GetIntFromObj(0, pVar, &n);
|
||||
sqlite3_result_int(pCtx, n);
|
||||
}else if( c=='d' && strcmp(zType,"double")==0 ){
|
||||
@@ -626,8 +635,9 @@ static void xF5tFunction(
|
||||
Tcl_GetWideIntFromObj(0, pVar, &v);
|
||||
sqlite3_result_int64(pCtx, v);
|
||||
}else{
|
||||
unsigned char *data = (unsigned char *)Tcl_GetStringFromObj(pVar, &n);
|
||||
sqlite3_result_text(pCtx, (char *)data, n, SQLITE_TRANSIENT);
|
||||
Tcl_Size nn;
|
||||
unsigned char *data = (unsigned char *)Tcl_GetStringFromObj(pVar, &nn);
|
||||
sqlite3_result_text(pCtx, (char*)data, (int)nn, SQLITE_TRANSIENT);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -673,7 +683,7 @@ static int SQLITE_TCLAPI f5tCreateFunction(
|
||||
pApi, zName, (void*)pCtx, xF5tFunction, xF5tDestroy
|
||||
);
|
||||
if( rc!=SQLITE_OK ){
|
||||
Tcl_AppendResult(interp, "error: ", sqlite3_errmsg(db), 0);
|
||||
Tcl_AppendResult(interp, "error: ", sqlite3_errmsg(db), (char*)0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
@@ -720,7 +730,7 @@ static int SQLITE_TCLAPI f5tTokenize(
|
||||
Tcl_Obj *CONST objv[]
|
||||
){
|
||||
char *zText;
|
||||
int nText;
|
||||
Tcl_Size nText;
|
||||
sqlite3 *db = 0;
|
||||
fts5_api *pApi = 0;
|
||||
Fts5Tokenizer *pTok = 0;
|
||||
@@ -729,7 +739,7 @@ static int SQLITE_TCLAPI f5tTokenize(
|
||||
void *pUserdata;
|
||||
int rc;
|
||||
|
||||
int nArg;
|
||||
Tcl_Size nArg;
|
||||
const char **azArg;
|
||||
F5tTokenizeCtx ctx;
|
||||
|
||||
@@ -740,7 +750,7 @@ static int SQLITE_TCLAPI f5tTokenize(
|
||||
if( objc==5 ){
|
||||
char *zOpt = Tcl_GetString(objv[1]);
|
||||
if( strcmp("-subst", zOpt) ){
|
||||
Tcl_AppendResult(interp, "unrecognized option: ", zOpt, 0);
|
||||
Tcl_AppendResult(interp, "unrecognized option: ", zOpt, (char*)0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
}
|
||||
@@ -749,7 +759,7 @@ static int SQLITE_TCLAPI f5tTokenize(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if( nArg==0 ){
|
||||
Tcl_AppendResult(interp, "no such tokenizer: ", 0);
|
||||
Tcl_AppendResult(interp, "no such tokenizer: ", (char*)0);
|
||||
Tcl_Free((void*)azArg);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
@@ -757,13 +767,13 @@ static int SQLITE_TCLAPI f5tTokenize(
|
||||
|
||||
rc = pApi->xFindTokenizer(pApi, azArg[0], &pUserdata, &tokenizer);
|
||||
if( rc!=SQLITE_OK ){
|
||||
Tcl_AppendResult(interp, "no such tokenizer: ", azArg[0], 0);
|
||||
Tcl_AppendResult(interp, "no such tokenizer: ", azArg[0], (char*)0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
rc = tokenizer.xCreate(pUserdata, &azArg[1], nArg-1, &pTok);
|
||||
rc = tokenizer.xCreate(pUserdata, &azArg[1], (int)(nArg-1), &pTok);
|
||||
if( rc!=SQLITE_OK ){
|
||||
Tcl_AppendResult(interp, "error in tokenizer.xCreate()", 0);
|
||||
Tcl_AppendResult(interp, "error in tokenizer.xCreate()", (char*)0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
@@ -773,11 +783,11 @@ static int SQLITE_TCLAPI f5tTokenize(
|
||||
ctx.pRet = pRet;
|
||||
ctx.zInput = zText;
|
||||
rc = tokenizer.xTokenize(
|
||||
pTok, (void*)&ctx, FTS5_TOKENIZE_DOCUMENT, zText, nText, xTokenizeCb2
|
||||
pTok, (void*)&ctx, FTS5_TOKENIZE_DOCUMENT, zText,(int)nText, xTokenizeCb2
|
||||
);
|
||||
tokenizer.xDelete(pTok);
|
||||
if( rc!=SQLITE_OK ){
|
||||
Tcl_AppendResult(interp, "error in tokenizer.xTokenize()", 0);
|
||||
Tcl_AppendResult(interp, "error in tokenizer.xTokenize()", (char*)0);
|
||||
Tcl_DecrRefCount(pRet);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
@@ -801,18 +811,32 @@ typedef struct F5tTokenizerInstance F5tTokenizerInstance;
|
||||
struct F5tTokenizerContext {
|
||||
void *pCtx;
|
||||
int (*xToken)(void*, int, const char*, int, int, int);
|
||||
F5tTokenizerInstance *pInst;
|
||||
};
|
||||
|
||||
struct F5tTokenizerModule {
|
||||
Tcl_Interp *interp;
|
||||
Tcl_Obj *pScript;
|
||||
void *pParentCtx;
|
||||
fts5_tokenizer_v2 parent_v2;
|
||||
fts5_tokenizer parent;
|
||||
F5tTokenizerContext *pContext;
|
||||
};
|
||||
|
||||
/*
|
||||
** zLocale:
|
||||
** Within a call to xTokenize_v2(), pLocale/nLocale store the locale
|
||||
** passed to the call by fts5. This can be retrieved by a Tcl tokenize
|
||||
** script using [sqlite3_fts5_locale].
|
||||
*/
|
||||
struct F5tTokenizerInstance {
|
||||
Tcl_Interp *interp;
|
||||
Tcl_Obj *pScript;
|
||||
F5tTokenizerModule *pModule;
|
||||
Fts5Tokenizer *pParent;
|
||||
F5tTokenizerContext *pContext;
|
||||
const char *pLocale;
|
||||
int nLocale;
|
||||
};
|
||||
|
||||
static int f5tTokenizerCreate(
|
||||
@@ -821,11 +845,20 @@ static int f5tTokenizerCreate(
|
||||
int nArg,
|
||||
Fts5Tokenizer **ppOut
|
||||
){
|
||||
Fts5Tokenizer *pParent = 0;
|
||||
F5tTokenizerModule *pMod = (F5tTokenizerModule*)pCtx;
|
||||
Tcl_Obj *pEval;
|
||||
int rc = TCL_OK;
|
||||
int i;
|
||||
|
||||
assert( pMod->parent_v2.xCreate==0 || pMod->parent.xCreate==0 );
|
||||
if( pMod->parent_v2.xCreate ){
|
||||
rc = pMod->parent_v2.xCreate(pMod->pParentCtx, 0, 0, &pParent);
|
||||
}
|
||||
if( pMod->parent.xCreate ){
|
||||
rc = pMod->parent.xCreate(pMod->pParentCtx, 0, 0, &pParent);
|
||||
}
|
||||
|
||||
pEval = Tcl_DuplicateObj(pMod->pScript);
|
||||
Tcl_IncrRefCount(pEval);
|
||||
for(i=0; rc==TCL_OK && i<nArg; i++){
|
||||
@@ -845,6 +878,8 @@ static int f5tTokenizerCreate(
|
||||
pInst->interp = pMod->interp;
|
||||
pInst->pScript = Tcl_GetObjResult(pMod->interp);
|
||||
pInst->pContext = pMod->pContext;
|
||||
pInst->pParent = pParent;
|
||||
pInst->pModule = pMod;
|
||||
Tcl_IncrRefCount(pInst->pScript);
|
||||
*ppOut = (Fts5Tokenizer*)pInst;
|
||||
}
|
||||
@@ -855,11 +890,21 @@ static int f5tTokenizerCreate(
|
||||
|
||||
static void f5tTokenizerDelete(Fts5Tokenizer *p){
|
||||
F5tTokenizerInstance *pInst = (F5tTokenizerInstance*)p;
|
||||
Tcl_DecrRefCount(pInst->pScript);
|
||||
ckfree((char *)pInst);
|
||||
if( pInst ){
|
||||
if( pInst->pParent ){
|
||||
if( pInst->pModule->parent_v2.xDelete ){
|
||||
pInst->pModule->parent_v2.xDelete(pInst->pParent);
|
||||
}else{
|
||||
pInst->pModule->parent.xDelete(pInst->pParent);
|
||||
}
|
||||
}
|
||||
Tcl_DecrRefCount(pInst->pScript);
|
||||
ckfree((char *)pInst);
|
||||
}
|
||||
}
|
||||
|
||||
static int f5tTokenizerTokenize(
|
||||
|
||||
static int f5tTokenizerReallyTokenize(
|
||||
Fts5Tokenizer *p,
|
||||
void *pCtx,
|
||||
int flags,
|
||||
@@ -867,6 +912,7 @@ static int f5tTokenizerTokenize(
|
||||
int (*xToken)(void*, int, const char*, int, int, int)
|
||||
){
|
||||
F5tTokenizerInstance *pInst = (F5tTokenizerInstance*)p;
|
||||
F5tTokenizerInstance *pOldInst = 0;
|
||||
void *pOldCtx;
|
||||
int (*xOldToken)(void*, int, const char*, int, int, int);
|
||||
Tcl_Obj *pEval;
|
||||
@@ -875,9 +921,11 @@ static int f5tTokenizerTokenize(
|
||||
|
||||
pOldCtx = pInst->pContext->pCtx;
|
||||
xOldToken = pInst->pContext->xToken;
|
||||
pOldInst = pInst->pContext->pInst;
|
||||
|
||||
pInst->pContext->pCtx = pCtx;
|
||||
pInst->pContext->xToken = xToken;
|
||||
pInst->pContext->pInst = pInst;
|
||||
|
||||
assert(
|
||||
flags==FTS5_TOKENIZE_DOCUMENT
|
||||
@@ -913,9 +961,105 @@ static int f5tTokenizerTokenize(
|
||||
|
||||
pInst->pContext->pCtx = pOldCtx;
|
||||
pInst->pContext->xToken = xOldToken;
|
||||
pInst->pContext->pInst = pOldInst;
|
||||
return rc;
|
||||
}
|
||||
|
||||
typedef struct CallbackCtx CallbackCtx;
|
||||
struct CallbackCtx {
|
||||
Fts5Tokenizer *p;
|
||||
void *pCtx;
|
||||
int flags;
|
||||
int (*xToken)(void*, int, const char*, int, int, int);
|
||||
};
|
||||
|
||||
static int f5tTokenizeCallback(
|
||||
void *pCtx,
|
||||
int tflags,
|
||||
const char *z, int n,
|
||||
int iStart, int iEnd
|
||||
){
|
||||
CallbackCtx *p = (CallbackCtx*)pCtx;
|
||||
return f5tTokenizerReallyTokenize(p->p, p->pCtx, p->flags, z, n, p->xToken);
|
||||
}
|
||||
|
||||
static int f5tTokenizerTokenize_v2(
|
||||
Fts5Tokenizer *p,
|
||||
void *pCtx,
|
||||
int flags,
|
||||
const char *pText, int nText,
|
||||
const char *pLoc, int nLoc,
|
||||
int (*xToken)(void*, int, const char*, int, int, int)
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
F5tTokenizerInstance *pInst = (F5tTokenizerInstance*)p;
|
||||
|
||||
pInst->pLocale = pLoc;
|
||||
pInst->nLocale = nLoc;
|
||||
|
||||
if( pInst->pParent ){
|
||||
CallbackCtx ctx;
|
||||
ctx.p = p;
|
||||
ctx.pCtx = pCtx;
|
||||
ctx.flags = flags;
|
||||
ctx.xToken = xToken;
|
||||
if( pInst->pModule->parent_v2.xTokenize ){
|
||||
rc = pInst->pModule->parent_v2.xTokenize(
|
||||
pInst->pParent, (void*)&ctx, flags, pText, nText,
|
||||
pLoc, nLoc, f5tTokenizeCallback
|
||||
);
|
||||
}else{
|
||||
rc = pInst->pModule->parent.xTokenize(
|
||||
pInst->pParent, (void*)&ctx, flags, pText, nText, f5tTokenizeCallback
|
||||
);
|
||||
}
|
||||
}else{
|
||||
rc = f5tTokenizerReallyTokenize(p, pCtx, flags, pText, nText, xToken);
|
||||
}
|
||||
|
||||
pInst->pLocale = 0;
|
||||
pInst->nLocale = 0;
|
||||
return rc;
|
||||
}
|
||||
static int f5tTokenizerTokenize(
|
||||
Fts5Tokenizer *p,
|
||||
void *pCtx,
|
||||
int flags,
|
||||
const char *pText, int nText,
|
||||
int (*xToken)(void*, int, const char*, int, int, int)
|
||||
){
|
||||
return f5tTokenizerTokenize_v2(p, pCtx, flags, pText, nText, 0, 0, xToken);
|
||||
}
|
||||
|
||||
/*
|
||||
** sqlite3_fts5_locale
|
||||
*/
|
||||
static int SQLITE_TCLAPI f5tTokenizerLocale(
|
||||
void * clientData,
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
Tcl_Obj *CONST objv[]
|
||||
){
|
||||
F5tTokenizerContext *p = (F5tTokenizerContext*)clientData;
|
||||
|
||||
if( objc!=1 ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
if( p->xToken==0 ){
|
||||
Tcl_AppendResult(interp,
|
||||
"sqlite3_fts5_locale may only be used by tokenizer callback", (char*)0
|
||||
);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
Tcl_SetObjResult(interp,
|
||||
Tcl_NewStringObj(p->pInst->pLocale, p->pInst->nLocale)
|
||||
);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** sqlite3_fts5_token ?-colocated? TEXT START END
|
||||
*/
|
||||
@@ -928,13 +1072,13 @@ static int SQLITE_TCLAPI f5tTokenizerReturn(
|
||||
F5tTokenizerContext *p = (F5tTokenizerContext*)clientData;
|
||||
int iStart;
|
||||
int iEnd;
|
||||
int nToken;
|
||||
Tcl_Size nToken;
|
||||
int tflags = 0;
|
||||
char *zToken;
|
||||
int rc;
|
||||
|
||||
if( objc==5 ){
|
||||
int nArg;
|
||||
Tcl_Size nArg;
|
||||
char *zArg = Tcl_GetStringFromObj(objv[1], &nArg);
|
||||
if( nArg<=10 && nArg>=2 && memcmp("-colocated", zArg, nArg)==0 ){
|
||||
tflags |= FTS5_TOKEN_COLOCATED;
|
||||
@@ -954,12 +1098,12 @@ static int SQLITE_TCLAPI f5tTokenizerReturn(
|
||||
|
||||
if( p->xToken==0 ){
|
||||
Tcl_AppendResult(interp,
|
||||
"sqlite3_fts5_token may only be used by tokenizer callback", 0
|
||||
"sqlite3_fts5_token may only be used by tokenizer callback", (char*)0
|
||||
);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
rc = p->xToken(p->pCtx, tflags, zToken, nToken, iStart, iEnd);
|
||||
rc = p->xToken(p->pCtx, tflags, zToken, (int)nToken, iStart, iEnd);
|
||||
Tcl_SetResult(interp, (char*)sqlite3ErrName(rc), TCL_VOLATILE);
|
||||
return rc==SQLITE_OK ? TCL_OK : TCL_ERROR;
|
||||
|
||||
@@ -1001,32 +1145,112 @@ static int SQLITE_TCLAPI f5tCreateTokenizer(
|
||||
fts5_api *pApi;
|
||||
char *zName;
|
||||
Tcl_Obj *pScript;
|
||||
fts5_tokenizer t;
|
||||
F5tTokenizerModule *pMod;
|
||||
int rc;
|
||||
int rc = SQLITE_OK;
|
||||
int bV2 = 0; /* True to use _v2 API */
|
||||
int iVersion = 2; /* Value for _v2.iVersion */
|
||||
const char *zParent = 0; /* Name of parent tokenizer, if any */
|
||||
int ii = 0;
|
||||
|
||||
if( objc!=4 ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "DB NAME SCRIPT");
|
||||
if( objc<4 ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "?OPTIONS? DB NAME SCRIPT");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if( f5tDbAndApi(interp, objv[1], &db, &pApi) ){
|
||||
|
||||
/* Parse any options. Set stack variables bV2 and zParent. */
|
||||
for(ii=1; ii<objc-3; ii++){
|
||||
int iOpt = 0;
|
||||
const char *azOpt[] = { "-v2", "-parent", "-version", 0 };
|
||||
if( Tcl_GetIndexFromObj(interp, objv[ii], azOpt, "OPTION", 0, &iOpt) ){
|
||||
return TCL_ERROR;
|
||||
}
|
||||
switch( iOpt ){
|
||||
case 0: /* -v2 */ {
|
||||
bV2 = 1;
|
||||
break;
|
||||
}
|
||||
case 1: /* -parent */ {
|
||||
ii++;
|
||||
if( ii==objc-3 ){
|
||||
Tcl_AppendResult(
|
||||
interp, "option requires an argument: -parent", (char*)0
|
||||
);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
zParent = Tcl_GetString(objv[ii]);
|
||||
break;
|
||||
}
|
||||
case 2: /* -version */ {
|
||||
ii++;
|
||||
if( ii==objc-3 ){
|
||||
Tcl_AppendResult(
|
||||
interp, "option requires an argument: -version", (char*)0
|
||||
);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if( Tcl_GetIntFromObj(interp, objv[ii], &iVersion) ){
|
||||
return TCL_ERROR;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
assert( 0 );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( f5tDbAndApi(interp, objv[objc-3], &db, &pApi) ){
|
||||
return TCL_ERROR;
|
||||
}
|
||||
zName = Tcl_GetString(objv[2]);
|
||||
pScript = objv[3];
|
||||
|
||||
t.xCreate = f5tTokenizerCreate;
|
||||
t.xTokenize = f5tTokenizerTokenize;
|
||||
t.xDelete = f5tTokenizerDelete;
|
||||
zName = Tcl_GetString(objv[objc-2]);
|
||||
pScript = objv[objc-1];
|
||||
|
||||
pMod = (F5tTokenizerModule*)ckalloc(sizeof(F5tTokenizerModule));
|
||||
memset(pMod, 0, sizeof(F5tTokenizerModule));
|
||||
pMod->interp = interp;
|
||||
pMod->pScript = pScript;
|
||||
pMod->pContext = pContext;
|
||||
Tcl_IncrRefCount(pScript);
|
||||
rc = pApi->xCreateTokenizer(pApi, zName, (void*)pMod, &t, f5tDelTokenizer);
|
||||
pMod->pContext = pContext;
|
||||
if( zParent ){
|
||||
if( bV2 ){
|
||||
fts5_tokenizer_v2 *pParent = 0;
|
||||
rc = pApi->xFindTokenizer_v2(pApi, zParent, &pMod->pParentCtx, &pParent);
|
||||
if( rc==SQLITE_OK ){
|
||||
memcpy(&pMod->parent_v2, pParent, sizeof(fts5_tokenizer_v2));
|
||||
pMod->parent_v2.xDelete(0);
|
||||
}
|
||||
}else{
|
||||
rc = pApi->xFindTokenizer(pApi, zParent, &pMod->pParentCtx,&pMod->parent);
|
||||
if( rc==SQLITE_OK ){
|
||||
pMod->parent.xDelete(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
void *pModCtx = (void*)pMod;
|
||||
if( bV2==0 ){
|
||||
fts5_tokenizer t;
|
||||
t.xCreate = f5tTokenizerCreate;
|
||||
t.xTokenize = f5tTokenizerTokenize;
|
||||
t.xDelete = f5tTokenizerDelete;
|
||||
rc = pApi->xCreateTokenizer(pApi, zName, pModCtx, &t, f5tDelTokenizer);
|
||||
}else{
|
||||
fts5_tokenizer_v2 t2;
|
||||
memset(&t2, 0, sizeof(t2));
|
||||
t2.iVersion = iVersion;
|
||||
t2.xCreate = f5tTokenizerCreate;
|
||||
t2.xTokenize = f5tTokenizerTokenize_v2;
|
||||
t2.xDelete = f5tTokenizerDelete;
|
||||
rc = pApi->xCreateTokenizer_v2(pApi, zName, pModCtx, &t2,f5tDelTokenizer);
|
||||
}
|
||||
}
|
||||
|
||||
if( rc!=SQLITE_OK ){
|
||||
Tcl_AppendResult(interp, "error in fts5_api.xCreateTokenizer()", 0);
|
||||
Tcl_AppendResult(interp, (
|
||||
bV2 ? "error in fts5_api.xCreateTokenizer_v2()"
|
||||
: "error in fts5_api.xCreateTokenizer()"
|
||||
), (char*)0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
@@ -1083,7 +1307,7 @@ static int SQLITE_TCLAPI f5tTokenHash(
|
||||
Tcl_Obj *CONST objv[]
|
||||
){
|
||||
char *z;
|
||||
int n;
|
||||
Tcl_Size n;
|
||||
unsigned int iVal;
|
||||
int nSlot;
|
||||
|
||||
@@ -1096,7 +1320,7 @@ static int SQLITE_TCLAPI f5tTokenHash(
|
||||
}
|
||||
z = Tcl_GetStringFromObj(objv[2], &n);
|
||||
|
||||
iVal = f5t_fts5HashKey(nSlot, z, n);
|
||||
iVal = f5t_fts5HashKey(nSlot, z, (int)n);
|
||||
Tcl_SetObjResult(interp, Tcl_NewIntObj(iVal));
|
||||
return TCL_OK;
|
||||
}
|
||||
@@ -1316,12 +1540,92 @@ static int SQLITE_TCLAPI f5tRegisterOriginText(
|
||||
|
||||
Tcl_ResetResult(interp);
|
||||
if( rc!=SQLITE_OK ){
|
||||
Tcl_AppendResult(interp, "error: ", sqlite3_errmsg(db), 0);
|
||||
Tcl_AppendResult(interp, "error: ", sqlite3_errmsg(db), (void*)0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** This function is used to DROP an fts5 table. It works even if the data
|
||||
** structures fts5 stores within the database are corrupt, which sometimes
|
||||
** prevents a straight "DROP TABLE" command from succeeding.
|
||||
**
|
||||
** The first parameter is the database handle to use for the DROP TABLE
|
||||
** operation. The second is the name of the database to drop the fts5 table
|
||||
** from (i.e. "main", "temp" or the name of an attached database). The
|
||||
** third parameter is the name of the fts5 table to drop.
|
||||
**
|
||||
** SQLITE_OK is returned if the table is successfully dropped. Or, if an
|
||||
** error occurs, an SQLite error code.
|
||||
*/
|
||||
static int sqlite3_fts5_drop_corrupt_table(
|
||||
sqlite3 *db, /* Database handle */
|
||||
const char *zDb, /* Database name ("main", "temp" etc.) */
|
||||
const char *zTab /* Name of fts5 table to drop */
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
int bDef = 0;
|
||||
|
||||
rc = sqlite3_db_config(db, SQLITE_DBCONFIG_DEFENSIVE, -1, &bDef);
|
||||
if( rc==SQLITE_OK ){
|
||||
char *zScript = sqlite3_mprintf(
|
||||
"DELETE FROM %Q.'%q_data';"
|
||||
"DELETE FROM %Q.'%q_config';"
|
||||
"INSERT INTO %Q.'%q_data' VALUES(10, X'0000000000');"
|
||||
"INSERT INTO %Q.'%q_config' VALUES('version', 4);"
|
||||
"DROP TABLE %Q.'%q';",
|
||||
zDb, zTab, zDb, zTab, zDb, zTab, zDb, zTab, zDb, zTab
|
||||
);
|
||||
|
||||
if( zScript==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
if( bDef ) sqlite3_db_config(db, SQLITE_DBCONFIG_DEFENSIVE, 0, 0);
|
||||
rc = sqlite3_exec(db, zScript, 0, 0, 0);
|
||||
if( bDef ) sqlite3_db_config(db, SQLITE_DBCONFIG_DEFENSIVE, 1, 0);
|
||||
sqlite3_free(zScript);
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** sqlite3_fts5_drop_corrupt_table DB DATABASE TABLE
|
||||
**
|
||||
** Description...
|
||||
*/
|
||||
static int SQLITE_TCLAPI f5tDropCorruptTable(
|
||||
void * clientData,
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
Tcl_Obj *CONST objv[]
|
||||
){
|
||||
sqlite3 *db = 0;
|
||||
const char *zDb = 0;
|
||||
const char *zTab = 0;
|
||||
int rc = SQLITE_OK;
|
||||
|
||||
if( objc!=4 ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "DB DATABASE TABLE");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if( f5tDbPointer(interp, objv[1], &db) ){
|
||||
return TCL_ERROR;
|
||||
}
|
||||
zDb = Tcl_GetString(objv[2]);
|
||||
zTab = Tcl_GetString(objv[3]);
|
||||
|
||||
rc = sqlite3_fts5_drop_corrupt_table(db, zDb, zTab);
|
||||
if( rc!=SQLITE_OK ){
|
||||
Tcl_AppendResult(interp, "error: ", sqlite3_errmsg(db), (void*)0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Entry point.
|
||||
*/
|
||||
@@ -1333,13 +1637,15 @@ int Fts5tcl_Init(Tcl_Interp *interp){
|
||||
} aCmd[] = {
|
||||
{ "sqlite3_fts5_create_tokenizer", f5tCreateTokenizer, 1 },
|
||||
{ "sqlite3_fts5_token", f5tTokenizerReturn, 1 },
|
||||
{ "sqlite3_fts5_locale", f5tTokenizerLocale, 1 },
|
||||
{ "sqlite3_fts5_tokenize", f5tTokenize, 0 },
|
||||
{ "sqlite3_fts5_create_function", f5tCreateFunction, 0 },
|
||||
{ "sqlite3_fts5_may_be_corrupt", f5tMayBeCorrupt, 0 },
|
||||
{ "sqlite3_fts5_token_hash", f5tTokenHash, 0 },
|
||||
{ "sqlite3_fts5_register_matchinfo", f5tRegisterMatchinfo, 0 },
|
||||
{ "sqlite3_fts5_register_fts5tokenize", f5tRegisterTok, 0 },
|
||||
{ "sqlite3_fts5_register_origintext",f5tRegisterOriginText, 0 }
|
||||
{ "sqlite3_fts5_register_origintext",f5tRegisterOriginText, 0 },
|
||||
{ "sqlite3_fts5_drop_corrupt_table", f5tDropCorruptTable, 0 }
|
||||
};
|
||||
int i;
|
||||
F5tTokenizerContext *pContext;
|
||||
|
||||
+66
-37
@@ -386,7 +386,6 @@ static int fts5UnicodeCreate(
|
||||
zCat = azArg[i+1];
|
||||
}
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = unicodeSetCategories(p, zCat);
|
||||
}
|
||||
@@ -416,7 +415,6 @@ static int fts5UnicodeCreate(
|
||||
rc = SQLITE_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
}else{
|
||||
rc = SQLITE_NOMEM;
|
||||
}
|
||||
@@ -555,7 +553,7 @@ static int fts5UnicodeTokenize(
|
||||
|
||||
typedef struct PorterTokenizer PorterTokenizer;
|
||||
struct PorterTokenizer {
|
||||
fts5_tokenizer tokenizer; /* Parent tokenizer module */
|
||||
fts5_tokenizer_v2 tokenizer_v2; /* Parent tokenizer module */
|
||||
Fts5Tokenizer *pTokenizer; /* Parent tokenizer instance */
|
||||
char aBuf[FTS5_PORTER_MAX_TOKEN + 64];
|
||||
};
|
||||
@@ -567,7 +565,7 @@ static void fts5PorterDelete(Fts5Tokenizer *pTok){
|
||||
if( pTok ){
|
||||
PorterTokenizer *p = (PorterTokenizer*)pTok;
|
||||
if( p->pTokenizer ){
|
||||
p->tokenizer.xDelete(p->pTokenizer);
|
||||
p->tokenizer_v2.xDelete(p->pTokenizer);
|
||||
}
|
||||
sqlite3_free(p);
|
||||
}
|
||||
@@ -586,6 +584,7 @@ static int fts5PorterCreate(
|
||||
PorterTokenizer *pRet;
|
||||
void *pUserdata = 0;
|
||||
const char *zBase = "unicode61";
|
||||
fts5_tokenizer_v2 *pV2 = 0;
|
||||
|
||||
if( nArg>0 ){
|
||||
zBase = azArg[0];
|
||||
@@ -594,14 +593,15 @@ static int fts5PorterCreate(
|
||||
pRet = (PorterTokenizer*)sqlite3_malloc(sizeof(PorterTokenizer));
|
||||
if( pRet ){
|
||||
memset(pRet, 0, sizeof(PorterTokenizer));
|
||||
rc = pApi->xFindTokenizer(pApi, zBase, &pUserdata, &pRet->tokenizer);
|
||||
rc = pApi->xFindTokenizer_v2(pApi, zBase, &pUserdata, &pV2);
|
||||
}else{
|
||||
rc = SQLITE_NOMEM;
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
int nArg2 = (nArg>0 ? nArg-1 : 0);
|
||||
const char **azArg2 = (nArg2 ? &azArg[1] : 0);
|
||||
rc = pRet->tokenizer.xCreate(pUserdata, azArg2, nArg2, &pRet->pTokenizer);
|
||||
const char **az2 = (nArg2 ? &azArg[1] : 0);
|
||||
memcpy(&pRet->tokenizer_v2, pV2, sizeof(fts5_tokenizer_v2));
|
||||
rc = pRet->tokenizer_v2.xCreate(pUserdata, az2, nArg2, &pRet->pTokenizer);
|
||||
}
|
||||
|
||||
if( rc!=SQLITE_OK ){
|
||||
@@ -1252,6 +1252,7 @@ static int fts5PorterTokenize(
|
||||
void *pCtx,
|
||||
int flags,
|
||||
const char *pText, int nText,
|
||||
const char *pLoc, int nLoc,
|
||||
int (*xToken)(void*, int, const char*, int nToken, int iStart, int iEnd)
|
||||
){
|
||||
PorterTokenizer *p = (PorterTokenizer*)pTokenizer;
|
||||
@@ -1259,8 +1260,8 @@ static int fts5PorterTokenize(
|
||||
sCtx.xToken = xToken;
|
||||
sCtx.pCtx = pCtx;
|
||||
sCtx.aBuf = p->aBuf;
|
||||
return p->tokenizer.xTokenize(
|
||||
p->pTokenizer, (void*)&sCtx, flags, pText, nText, fts5PorterCb
|
||||
return p->tokenizer_v2.xTokenize(
|
||||
p->pTokenizer, (void*)&sCtx, flags, pText, nText, pLoc, nLoc, fts5PorterCb
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1290,40 +1291,46 @@ static int fts5TriCreate(
|
||||
Fts5Tokenizer **ppOut
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
TrigramTokenizer *pNew = (TrigramTokenizer*)sqlite3_malloc(sizeof(*pNew));
|
||||
TrigramTokenizer *pNew = 0;
|
||||
UNUSED_PARAM(pUnused);
|
||||
if( pNew==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
if( nArg%2 ){
|
||||
rc = SQLITE_ERROR;
|
||||
}else{
|
||||
int i;
|
||||
pNew->bFold = 1;
|
||||
pNew->iFoldParam = 0;
|
||||
for(i=0; rc==SQLITE_OK && i<nArg; i+=2){
|
||||
const char *zArg = azArg[i+1];
|
||||
if( 0==sqlite3_stricmp(azArg[i], "case_sensitive") ){
|
||||
if( (zArg[0]!='0' && zArg[0]!='1') || zArg[1] ){
|
||||
rc = SQLITE_ERROR;
|
||||
pNew = (TrigramTokenizer*)sqlite3_malloc(sizeof(*pNew));
|
||||
if( pNew==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
pNew->bFold = 1;
|
||||
pNew->iFoldParam = 0;
|
||||
|
||||
for(i=0; rc==SQLITE_OK && i<nArg; i+=2){
|
||||
const char *zArg = azArg[i+1];
|
||||
if( 0==sqlite3_stricmp(azArg[i], "case_sensitive") ){
|
||||
if( (zArg[0]!='0' && zArg[0]!='1') || zArg[1] ){
|
||||
rc = SQLITE_ERROR;
|
||||
}else{
|
||||
pNew->bFold = (zArg[0]=='0');
|
||||
}
|
||||
}else if( 0==sqlite3_stricmp(azArg[i], "remove_diacritics") ){
|
||||
if( (zArg[0]!='0' && zArg[0]!='1' && zArg[0]!='2') || zArg[1] ){
|
||||
rc = SQLITE_ERROR;
|
||||
}else{
|
||||
pNew->iFoldParam = (zArg[0]!='0') ? 2 : 0;
|
||||
}
|
||||
}else{
|
||||
pNew->bFold = (zArg[0]=='0');
|
||||
}
|
||||
}else if( 0==sqlite3_stricmp(azArg[i], "remove_diacritics") ){
|
||||
if( (zArg[0]!='0' && zArg[0]!='1' && zArg[0]!='2') || zArg[1] ){
|
||||
rc = SQLITE_ERROR;
|
||||
}else{
|
||||
pNew->iFoldParam = (zArg[0]!='0') ? 2 : 0;
|
||||
}
|
||||
}else{
|
||||
}
|
||||
|
||||
if( pNew->iFoldParam!=0 && pNew->bFold==0 ){
|
||||
rc = SQLITE_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if( pNew->iFoldParam!=0 && pNew->bFold==0 ){
|
||||
rc = SQLITE_ERROR;
|
||||
}
|
||||
|
||||
if( rc!=SQLITE_OK ){
|
||||
fts5TriDelete((Fts5Tokenizer*)pNew);
|
||||
pNew = 0;
|
||||
|
||||
if( rc!=SQLITE_OK ){
|
||||
fts5TriDelete((Fts5Tokenizer*)pNew);
|
||||
pNew = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
*ppOut = (Fts5Tokenizer*)pNew;
|
||||
@@ -1428,6 +1435,16 @@ int sqlite3Fts5TokenizerPattern(
|
||||
return FTS5_PATTERN_NONE;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return true if the tokenizer described by p->azArg[] is the trigram
|
||||
** tokenizer. This tokenizer needs to be loaded before xBestIndex is
|
||||
** called for the first time in order to correctly handle LIKE/GLOB.
|
||||
*/
|
||||
int sqlite3Fts5TokenizerPreload(Fts5TokenizerConfig *p){
|
||||
return (p->nArg>=1 && 0==sqlite3_stricmp(p->azArg[0], "trigram"));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Register all built-in tokenizers with FTS5.
|
||||
*/
|
||||
@@ -1438,7 +1455,6 @@ int sqlite3Fts5TokenizerInit(fts5_api *pApi){
|
||||
} aBuiltin[] = {
|
||||
{ "unicode61", {fts5UnicodeCreate, fts5UnicodeDelete, fts5UnicodeTokenize}},
|
||||
{ "ascii", {fts5AsciiCreate, fts5AsciiDelete, fts5AsciiTokenize }},
|
||||
{ "porter", {fts5PorterCreate, fts5PorterDelete, fts5PorterTokenize }},
|
||||
{ "trigram", {fts5TriCreate, fts5TriDelete, fts5TriTokenize}},
|
||||
};
|
||||
|
||||
@@ -1453,6 +1469,19 @@ int sqlite3Fts5TokenizerInit(fts5_api *pApi){
|
||||
0
|
||||
);
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
fts5_tokenizer_v2 sPorter = {
|
||||
2,
|
||||
fts5PorterCreate,
|
||||
fts5PorterDelete,
|
||||
fts5PorterTokenize
|
||||
};
|
||||
rc = pApi->xCreateTokenizer_v2(pApi,
|
||||
"porter",
|
||||
(void*)pApi,
|
||||
&sPorter,
|
||||
0
|
||||
);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -364,6 +364,9 @@ int sqlite3Fts5UnicodeCatParse(const char *zCat, u8 *aArray){
|
||||
default: return 1; }
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
+24
-8
@@ -64,6 +64,7 @@ struct Fts5VocabCursor {
|
||||
|
||||
int nLeTerm; /* Size of zLeTerm in bytes */
|
||||
char *zLeTerm; /* (term <= $zLeTerm) paramater, or NULL */
|
||||
int colUsed; /* Copy of sqlite3_index_info.colUsed */
|
||||
|
||||
/* These are used by 'col' tables only */
|
||||
int iCol;
|
||||
@@ -90,9 +91,11 @@ struct Fts5VocabCursor {
|
||||
/*
|
||||
** Bits for the mask used as the idxNum value by xBestIndex/xFilter.
|
||||
*/
|
||||
#define FTS5_VOCAB_TERM_EQ 0x01
|
||||
#define FTS5_VOCAB_TERM_GE 0x02
|
||||
#define FTS5_VOCAB_TERM_LE 0x04
|
||||
#define FTS5_VOCAB_TERM_EQ 0x0100
|
||||
#define FTS5_VOCAB_TERM_GE 0x0200
|
||||
#define FTS5_VOCAB_TERM_LE 0x0400
|
||||
|
||||
#define FTS5_VOCAB_COLUSED_MASK 0xFF
|
||||
|
||||
|
||||
/*
|
||||
@@ -269,11 +272,13 @@ static int fts5VocabBestIndexMethod(
|
||||
int iTermEq = -1;
|
||||
int iTermGe = -1;
|
||||
int iTermLe = -1;
|
||||
int idxNum = 0;
|
||||
int idxNum = (int)pInfo->colUsed;
|
||||
int nArg = 0;
|
||||
|
||||
UNUSED_PARAM(pUnused);
|
||||
|
||||
assert( (pInfo->colUsed & FTS5_VOCAB_COLUSED_MASK)==pInfo->colUsed );
|
||||
|
||||
for(i=0; i<pInfo->nConstraint; i++){
|
||||
struct sqlite3_index_constraint *p = &pInfo->aConstraint[i];
|
||||
if( p->usable==0 ) continue;
|
||||
@@ -365,7 +370,7 @@ static int fts5VocabOpenMethod(
|
||||
if( rc==SQLITE_OK ){
|
||||
pVTab->zErrMsg = sqlite3_mprintf(
|
||||
"no such fts5 table: %s.%s", pTab->zFts5Db, pTab->zFts5Tbl
|
||||
);
|
||||
);
|
||||
rc = SQLITE_ERROR;
|
||||
}
|
||||
}else{
|
||||
@@ -525,9 +530,19 @@ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){
|
||||
|
||||
switch( pTab->eType ){
|
||||
case FTS5_VOCAB_ROW:
|
||||
if( eDetail==FTS5_DETAIL_FULL ){
|
||||
while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff, &iPos) ){
|
||||
pCsr->aCnt[0]++;
|
||||
/* Do not bother counting the number of instances if the "cnt"
|
||||
** column is not being read (according to colUsed). */
|
||||
if( eDetail==FTS5_DETAIL_FULL && (pCsr->colUsed & 0x04) ){
|
||||
while( iPos<nPos ){
|
||||
u32 ii;
|
||||
fts5FastGetVarint32(pPos, iPos, ii);
|
||||
if( ii==1 ){
|
||||
/* New column in the position list */
|
||||
fts5FastGetVarint32(pPos, iPos, ii);
|
||||
}else{
|
||||
/* An instance - increment pCsr->aCnt[] */
|
||||
pCsr->aCnt[0]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
pCsr->aDoc[0]++;
|
||||
@@ -625,6 +640,7 @@ static int fts5VocabFilterMethod(
|
||||
if( idxNum & FTS5_VOCAB_TERM_EQ ) pEq = apVal[iVal++];
|
||||
if( idxNum & FTS5_VOCAB_TERM_GE ) pGe = apVal[iVal++];
|
||||
if( idxNum & FTS5_VOCAB_TERM_LE ) pLe = apVal[iVal++];
|
||||
pCsr->colUsed = (idxNum & FTS5_VOCAB_COLUSED_MASK);
|
||||
|
||||
if( pEq ){
|
||||
zTerm = (const char *)sqlite3_value_text(pEq);
|
||||
|
||||
@@ -51,6 +51,10 @@ proc fts5_test_poslist2 {cmd} {
|
||||
sort_poslist $res
|
||||
}
|
||||
|
||||
proc fts5_test_insttoken {cmd iInst iToken} {
|
||||
$cmd xInstToken $iInst $iToken
|
||||
}
|
||||
|
||||
proc fts5_test_collist {cmd} {
|
||||
set res [list]
|
||||
|
||||
@@ -78,6 +82,9 @@ proc fts5_test_columnsize {cmd} {
|
||||
proc fts5_columntext {cmd iCol} {
|
||||
$cmd xColumnText $iCol
|
||||
}
|
||||
proc fts5_columnlocale {cmd iCol} {
|
||||
$cmd xColumnLocale $iCol
|
||||
}
|
||||
|
||||
proc fts5_test_columntext {cmd} {
|
||||
set res [list]
|
||||
@@ -87,6 +94,14 @@ proc fts5_test_columntext {cmd} {
|
||||
set res
|
||||
}
|
||||
|
||||
proc fts5_test_columnlocale {cmd} {
|
||||
set res [list]
|
||||
for {set i 0} {$i < [$cmd xColumnCount]} {incr i} {
|
||||
lappend res [$cmd xColumnLocale $i]
|
||||
}
|
||||
set res
|
||||
}
|
||||
|
||||
proc fts5_test_columntotalsize {cmd} {
|
||||
set res [list]
|
||||
for {set i 0} {$i < [$cmd xColumnCount]} {incr i} {
|
||||
@@ -114,6 +129,10 @@ proc fts5_test_rowcount {cmd} {
|
||||
$cmd xRowCount
|
||||
}
|
||||
|
||||
proc fts5_test_rowid {cmd} {
|
||||
$cmd xRowid
|
||||
}
|
||||
|
||||
proc test_queryphrase_cb {cnt cmd} {
|
||||
upvar $cnt L
|
||||
for {set i 0} {$i < [$cmd xInstCount]} {incr i} {
|
||||
@@ -161,17 +180,21 @@ proc fts5_aux_test_functions {db} {
|
||||
foreach f {
|
||||
fts5_test_columnsize
|
||||
fts5_test_columntext
|
||||
fts5_test_columnlocale
|
||||
fts5_test_columntotalsize
|
||||
fts5_test_poslist
|
||||
fts5_test_poslist2
|
||||
fts5_test_collist
|
||||
fts5_test_insttoken
|
||||
fts5_test_tokenize
|
||||
fts5_test_rowcount
|
||||
fts5_test_rowid
|
||||
fts5_test_all
|
||||
|
||||
fts5_test_queryphrase
|
||||
fts5_test_phrasecount
|
||||
fts5_columntext
|
||||
fts5_columnlocale
|
||||
fts5_queryphrase
|
||||
fts5_collist
|
||||
} {
|
||||
|
||||
@@ -440,7 +440,7 @@ do_execsql_test 16.1 {
|
||||
proc funk {} {
|
||||
db eval { UPDATE n1_config SET v=50 WHERE k='version' }
|
||||
set fd [db incrblob main n1_data block 10]
|
||||
fconfigure $fd -encoding binary -translation binary
|
||||
fconfigure $fd -translation binary
|
||||
# puts -nonewline $fd "\x44\x45"
|
||||
close $fd
|
||||
}
|
||||
@@ -453,7 +453,7 @@ db func funk funk
|
||||
# statement no longer fails.
|
||||
#
|
||||
do_catchsql_test 16.2 {
|
||||
SELECT funk(), bm25(n1), funk() FROM n1 WHERE n1 MATCH 'a+b+c+d'
|
||||
SELECT funk(), format('%g',bm25(n1)), funk() FROM n1 WHERE n1 MATCH 'a+b+c+d'
|
||||
} {0 {{} -1e-06 {}}}
|
||||
# {1 {SQL logic error}}
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5ab
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5ac
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5ad
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5ae
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5af
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5ag
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5ah
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
@@ -163,6 +163,17 @@ do_execsql_test 1.8.2 {
|
||||
SELECT count(*) FROM t1 WHERE t1 MATCH 'x' AND rowid < 'text';
|
||||
} {10000}
|
||||
|
||||
do_execsql_test 1.8.3 {
|
||||
SELECT count(*) FROM t1 WHERE t1 MATCH 'x' AND rowid<5000 AND rowid < 'text';
|
||||
} {4999}
|
||||
do_execsql_test 1.8.4 {
|
||||
SELECT count(*) FROM t1 WHERE t1 MATCH 'x' AND rowid>5000 AND rowid > 'text';
|
||||
} {0}
|
||||
|
||||
do_catchsql_test 1.9 {
|
||||
SELECT * FROM t1('*xy');
|
||||
} {1 {unknown special query: xy}}
|
||||
|
||||
} ;# foreach_detail_mode
|
||||
|
||||
#db eval {SELECT rowid, fts5_decode(rowid, block) aS r FROM t1_data} {puts $r}
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5ai
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5aj
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5ak
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5al
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
@@ -293,6 +293,16 @@ do_catchsql_test 4.4.4 {
|
||||
SELECT *, rank FROM t3 WHERE t3 MATCH 'a' AND rank MATCH NULL
|
||||
} {1 {parse error in rank function: }}
|
||||
|
||||
# Check that the second and subsequent rank= constraints are ignored.
|
||||
#
|
||||
do_catchsql_test 4.3.3 {
|
||||
SELECT *, rank FROM t3
|
||||
WHERE t3 MATCH 'a' AND
|
||||
rank MATCH 'nosuch()' AND
|
||||
rank MATCH 'rowidmod(3)'
|
||||
ORDER BY rank ASC
|
||||
} {1 {unable to use function MATCH in the requested context}}
|
||||
|
||||
} ;# foreach_detail_mode
|
||||
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5alter
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5auto
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5aux
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
@@ -377,4 +377,28 @@ do_catchsql_test 12.3.3 {
|
||||
SELECT fts5_collist(t1, 1) FROM t1('one AND two');
|
||||
} {0 1}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test 13.1 {
|
||||
CREATE VIRTUAL TABLE t1 USING fts5(a, tokenize=ascii);
|
||||
INSERT INTO t1 VALUES('a b c'), ('d e f');
|
||||
PRAGMA integrity_check;
|
||||
} {ok}
|
||||
|
||||
do_catchsql_test 13.2 {
|
||||
SELECT highlight(t1, 0, '[', ']') FROM t1
|
||||
} {0 {{a b c} {d e f}}}
|
||||
|
||||
do_execsql_test 13.3 {
|
||||
PRAGMA writable_schema = 1;
|
||||
UPDATE sqlite_schema SET sql = 'CREATE VIRTUAL TABLE t1 USING fts5(a, tokenize=blah)'
|
||||
WHERE name = 't1';
|
||||
}
|
||||
|
||||
db close
|
||||
sqlite3 db test.db
|
||||
do_catchsql_test 13.4 {
|
||||
SELECT highlight(t1, 0, '[', ']') FROM t1
|
||||
} {1 {SQL logic error}}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
# 2024 June 24
|
||||
#
|
||||
# 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 focusing on the auxiliary function APIs.
|
||||
#
|
||||
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5aux
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE VIRTUAL TABLE x1 USING fts5(a, b);
|
||||
INSERT INTO x1 VALUES('a b', 'c d');
|
||||
INSERT INTO x1 VALUES('d e', 'a b');
|
||||
INSERT INTO x1 VALUES('a b', 'e f');
|
||||
INSERT INTO x1 VALUES('d e', 'c d');
|
||||
}
|
||||
|
||||
fts5_aux_test_functions db
|
||||
do_execsql_test 1.1 {
|
||||
SELECT fts5_test_all(x1) FROM x1 WHERE rowid=2
|
||||
} [list [list {*}{
|
||||
columnsize {2 2}
|
||||
columntext {{d e} {a b}}
|
||||
columntotalsize {8 8}
|
||||
poslist {}
|
||||
tokenize {{d e} {a b}}
|
||||
rowcount 4
|
||||
}]]
|
||||
|
||||
do_execsql_test 1.2 {
|
||||
SELECT fts5_test_columntext(x1) FROM x1
|
||||
} {
|
||||
{{a b} {c d}}
|
||||
{{d e} {a b}}
|
||||
{{a b} {e f}}
|
||||
{{d e} {c d}}
|
||||
}
|
||||
|
||||
do_execsql_test 1.3 {
|
||||
SELECT fts5_test_rowid(x1) FROM x1
|
||||
} {
|
||||
1 2 3 4
|
||||
}
|
||||
do_execsql_test 1.4 {
|
||||
SELECT fts5_test_phrasecount(x1) FROM x1
|
||||
} {
|
||||
0 0 0 0
|
||||
}
|
||||
do_catchsql_test 1.5 {
|
||||
SELECT fts5_queryphrase(x1, 0) FROM x1
|
||||
} {1 SQLITE_RANGE}
|
||||
do_execsql_test 1.6 {
|
||||
SELECT fts5_test_rowcount(x1) FROM x1
|
||||
} {4 4 4 4}
|
||||
|
||||
|
||||
finish_test
|
||||
@@ -15,7 +15,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5auxdata
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5bigpl
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
||||
@@ -0,0 +1,166 @@
|
||||
# 2024 July 30
|
||||
#
|
||||
# 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 verifies that:
|
||||
#
|
||||
# * blob values may be written to locale=0 tables.
|
||||
#
|
||||
# * blob values - other than fts5_locale() values - may not be written
|
||||
# to locale=0 tables. This is an SQLITE_MISMATCH error
|
||||
#
|
||||
# * blob values may be returned by queries on the external-content table
|
||||
# of a locale=0 table.
|
||||
#
|
||||
# * blob values not may be returned by queries on the external-content
|
||||
# table of a locale=1 table, apart from fts5_locale() blobs. This is an
|
||||
# SQLITE_MISMATCH error.
|
||||
#
|
||||
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5blob
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
# Test that blobs may be stored in normal locale=0 tables.
|
||||
#
|
||||
foreach {tn enc} {
|
||||
1 utf8
|
||||
2 utf16
|
||||
} {
|
||||
reset_db
|
||||
fts5_aux_test_functions db
|
||||
|
||||
execsql "PRAGMA encoding = $enc"
|
||||
|
||||
execsql "
|
||||
CREATE VIRTUAL TABLE t1 USING fts5(x, y);
|
||||
"
|
||||
do_execsql_test 1.$tn.0 {
|
||||
CREATE VIRTUAL TABLE tt USING fts5vocab('t1', 'instance');
|
||||
INSERT INTO t1(rowid, x, y) VALUES(1, 555, X'0000000041424320444546');
|
||||
INSERT INTO t1(rowid, x, y) VALUES(2, 666, X'41424300444546');
|
||||
INSERT INTO t1(rowid, x, y) VALUES(3, 777, 'xyz');
|
||||
}
|
||||
|
||||
do_execsql_test 1.$tn.1 {
|
||||
SELECT rowid, quote(x), quote(y) FROM t1
|
||||
} {
|
||||
1 555 X'0000000041424320444546'
|
||||
2 666 X'41424300444546'
|
||||
3 777 'xyz'
|
||||
}
|
||||
|
||||
do_execsql_test 1.$tn.2 {
|
||||
DELETE FROM t1 WHERE rowid=2;
|
||||
DELETE FROM t1 WHERE rowid=1;
|
||||
}
|
||||
|
||||
do_execsql_test 1.$tn.3 {
|
||||
PRAGMA integrity_check;
|
||||
} {ok}
|
||||
}
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
# Test that a blob may be stored and retrieved in an unindexed column of
|
||||
# a regular table with locale=1.
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 2.0 {
|
||||
CREATE VIRTUAL TABLE t1 USING fts5(x, y UNINDEXED, locale=1);
|
||||
INSERT INTO t1(rowid, x, y) VALUES(12, 'twelve', X'0000000041424320444546');
|
||||
}
|
||||
|
||||
do_execsql_test 2.1 {
|
||||
select rowid, x, quote(y) FROM t1
|
||||
} {
|
||||
12 twelve X'0000000041424320444546'
|
||||
}
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
# Test that blobs may not be written to any type of table with locale=1
|
||||
# set. Except, they may be written to UNINDEXED columns.
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 3.0 {
|
||||
CREATE TABLE t1(a, b);
|
||||
|
||||
CREATE VIRTUAL TABLE x1 USING fts5(a, b, locale=1);
|
||||
CREATE VIRTUAL TABLE x2 USING fts5(a, b, locale=1, content=t2);
|
||||
CREATE VIRTUAL TABLE x3 USING fts5(a, b, locale=1, content=);
|
||||
}
|
||||
|
||||
do_catchsql_test 3.1 {
|
||||
INSERT INTO x1(rowid, a, b) VALUES(113, 'hello world', X'123456');
|
||||
} {0 {}}
|
||||
do_catchsql_test 3.2 {
|
||||
INSERT INTO x2(rowid, a, b) VALUES(113, 'hello world', X'123456');
|
||||
} {0 {}}
|
||||
do_catchsql_test 3.3 {
|
||||
INSERT INTO x3(rowid, a, b) VALUES(113, 'hello world', X'123456');
|
||||
} {0 {}}
|
||||
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
# Test that fts5_locale() values may not be written to any type of table
|
||||
# without locale=1 set. Even to an UNINDEXED column.
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 3.0 {
|
||||
CREATE TABLE t1(a, b);
|
||||
|
||||
CREATE VIRTUAL TABLE x1 USING fts5(a, b);
|
||||
CREATE VIRTUAL TABLE x2 USING fts5(a, b, content=t2);
|
||||
CREATE VIRTUAL TABLE x3 USING fts5(a, b, content=);
|
||||
|
||||
CREATE VIRTUAL TABLE x4 USING fts5(a, b, c UNINDEXED);
|
||||
}
|
||||
|
||||
do_catchsql_test 3.1 {
|
||||
INSERT INTO x1(rowid, a, b)
|
||||
VALUES(113, 'hello world', fts5_locale('en_AU', 'abc'));
|
||||
} {1 {fts5_locale() requires locale=1}}
|
||||
do_catchsql_test 3.2 {
|
||||
INSERT INTO x2(rowid, a, b)
|
||||
VALUES(113, 'hello world', fts5_locale('en_AU', 'abc'));
|
||||
} {1 {fts5_locale() requires locale=1}}
|
||||
do_catchsql_test 3.3 {
|
||||
INSERT INTO x3(rowid, a, b)
|
||||
VALUES(113, 'hello world', fts5_locale('en_AU', 'abc'));
|
||||
} {1 {fts5_locale() requires locale=1}}
|
||||
do_catchsql_test 3.4 {
|
||||
INSERT INTO x4(rowid, a, b, c)
|
||||
VALUES(113, 'hello world', 'yesno', fts5_locale('en_AU', 'abc'));
|
||||
} {1 {fts5_locale() requires locale=1}}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 4.0 {
|
||||
CREATE VIRTUAL TABLE x1 USING fts5(x);
|
||||
}
|
||||
|
||||
foreach {tn sql} {
|
||||
1 { INSERT INTO x1(rowid, x) VALUES(4.5, 'abcd') }
|
||||
2 { INSERT INTO x1(rowid, x) VALUES('xyz', 'abcd') }
|
||||
3 { INSERT INTO x1(rowid, x) VALUES(X'001122', 'abcd') }
|
||||
} {
|
||||
do_catchsql_test 4.1.$tn $sql {1 {datatype mismatch}}
|
||||
}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -55,5 +55,22 @@ do_execsql_test 1.5 {
|
||||
SELECT * FROM t4t
|
||||
} {สนามกีฬา 1 1}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test 2.0 "
|
||||
CREATE VIRTUAL TABLE x1 USING fts5(c,
|
||||
tokenize=\"unicode61 categories ' \t'\");
|
||||
"
|
||||
|
||||
do_catchsql_test 2.1 "
|
||||
CREATE VIRTUAL TABLE x2 USING fts5(c,
|
||||
tokenize=\"unicode61 categories 'N*\t\tMYZ'\");
|
||||
" {1 {error in tokenizer constructor}}
|
||||
|
||||
do_catchsql_test 2.2 "
|
||||
CREATE VIRTUAL TABLE x2 USING fts5(c,
|
||||
tokenize=\"unicode61 categories 'N*\t\tXYZ'\");
|
||||
" {1 {error in tokenizer constructor}}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -79,7 +79,7 @@ foreach_detail_mode $::testprefix {
|
||||
|
||||
do_catchsql_test 4.1 {
|
||||
SELECT * FROM t1 WHERE rowid MATCH 'a'
|
||||
} {1 {unable to use function MATCH in the requested context}}
|
||||
} {1 {no query solution}}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5columnsize
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5config
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5content
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
@@ -328,4 +328,41 @@ do_execsql_test 8.3.2 { INSERT INTO t1(t1) VALUES('rebuild') }
|
||||
do_execsql_test 8.3.3 { SELECT * FROM t1 WHERE rowid=1 } {one}
|
||||
do_execsql_test 8.3.4 { SELECT rowid FROM t1('two') } {2}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test 9.1 {
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
|
||||
INSERT INTO t1 VALUES(1, 'one two three');
|
||||
INSERT INTO t1 VALUES(2, 'one two three');
|
||||
|
||||
CREATE VIRTUAL TABLE ft USING fts5(b, content=t1, content_rowid=a);
|
||||
INSERT INTO ft(ft) VALUES('rebuild');
|
||||
}
|
||||
|
||||
do_execsql_test 9.2 {
|
||||
SELECT rowid, b FROM ft('two');
|
||||
} {
|
||||
1 {one two three}
|
||||
2 {one two three}
|
||||
}
|
||||
|
||||
do_execsql_test 9.3 {
|
||||
DELETE FROM t1 WHERE a=2;
|
||||
}
|
||||
|
||||
do_catchsql_test 9.4 {
|
||||
SELECT rowid FROM ft('two');
|
||||
} {0 {1 2}}
|
||||
|
||||
do_catchsql_test 9.5 {
|
||||
SELECT * FROM ft('two');
|
||||
} {1 {fts5: missing row 2 from content table 'main'.'t1'}}
|
||||
|
||||
fts5_aux_test_functions db
|
||||
|
||||
do_catchsql_test 9.6 {
|
||||
SELECT rowid, fts5_columntext(ft, 0) FROM ft('two');
|
||||
} {1 SQLITE_CORRUPT_VTAB}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5contentless
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
@@ -267,4 +267,24 @@ do_execsql_test 8.2 {
|
||||
SELECT rowid FROM ft('four');
|
||||
} {}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test 9.0 {
|
||||
CREATE VIRTUAL TABLE ft USING fts5(x, content='', contentless_delete=0);
|
||||
INSERT INTO ft VALUES('hello world');
|
||||
INSERT INTO ft VALUES('one two three');
|
||||
}
|
||||
|
||||
do_catchsql_test 9.1 {
|
||||
INSERT INTO ft(ft, rowid, x) VALUES('delete', 1, 'hello world');
|
||||
} {0 {}}
|
||||
|
||||
do_catchsql_test 9.2 {
|
||||
CREATE VIRTUAL TABLE ft2 USING fts5(x, content='', contentless_delete=2);
|
||||
} {1 {malformed contentless_delete=... directive}}
|
||||
|
||||
do_catchsql_test 9.3 {
|
||||
CREATE VIRTUAL TABLE ft2 USING fts5(x, content='', contentless_delete=11);
|
||||
} {1 {malformed contentless_delete=... directive}}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5contentless2
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5contentless3
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5contentless4
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
||||
@@ -15,11 +15,12 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5contentless5
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
unset -nocomplain res
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE VIRTUAL TABLE t1 USING fts5(a, b, c, content='', contentless_delete=1);
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5corrupt
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
@@ -99,6 +99,27 @@ sqlite3_db_config db DEFENSIVE 0
|
||||
do_catchsql_test 3.1 {
|
||||
DELETE FROM t3_content WHERE rowid = 3;
|
||||
SELECT * FROM t3 WHERE t3 MATCH 'o';
|
||||
} {1 {fts5: missing row 3 from content table 'main'.'t3_content'}}
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 4.0 {
|
||||
CREATE VIRTUAL TABLE t2 USING fts5(x);
|
||||
INSERT INTO t2 VALUES('one two three');
|
||||
INSERT INTO t2 VALUES('four five six');
|
||||
INSERT INTO t2 VALUES('seven eight nine');
|
||||
INSERT INTO t2 VALUES('ten eleven twelve');
|
||||
}
|
||||
do_execsql_test 4.1 {
|
||||
SELECT hex(block) FROM t2_data WHERE id=1;
|
||||
} {040C}
|
||||
do_execsql_test 4.2 {
|
||||
UPDATE t2_data SET block = X'0402' WHERE id=1
|
||||
}
|
||||
breakpoint
|
||||
do_catchsql_test 4.3 {
|
||||
DELETE FROM t2 WHERE rowid=3
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5corrupt2
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
@@ -100,6 +100,7 @@ set lrowid [db one {SELECT max(rowid) FROM t1_data WHERE (rowid & $mask)=0}]
|
||||
set nbyte [db one {SELECT length(block) FROM t1_data WHERE rowid=$lrowid}]
|
||||
set all [db eval {SELECT rowid FROM t1}]
|
||||
sqlite3_db_config db DEFENSIVE 0
|
||||
unset -nocomplain res
|
||||
for {set i [expr $nbyte-2]} {$i>=0} {incr i -1} {
|
||||
do_execsql_test 2.$i.1 {
|
||||
BEGIN;
|
||||
@@ -152,7 +153,7 @@ foreach {tn hdr} {
|
||||
execsql BEGIN
|
||||
|
||||
set fd [db incrblob main x3_data block $rowid]
|
||||
fconfigure $fd -encoding binary -translation binary
|
||||
fconfigure $fd -translation binary
|
||||
set existing [read $fd [string length $hdr]]
|
||||
seek $fd 0
|
||||
puts -nonewline $fd $hdr
|
||||
@@ -238,7 +239,7 @@ foreach {tn hdr} {
|
||||
execsql BEGIN
|
||||
|
||||
set fd [db incrblob main x5_data block $rowid]
|
||||
fconfigure $fd -encoding binary -translation binary
|
||||
fconfigure $fd -translation binary
|
||||
puts -nonewline $fd $hdr
|
||||
close $fd
|
||||
|
||||
|
||||
+172
-13
@@ -17,7 +17,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5corrupt3
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
@@ -680,11 +680,11 @@ do_test 12.0 {
|
||||
|
||||
do_catchsql_test 11.1 {
|
||||
SELECT * FROM t1 WHERE t1 MATCH 'abandon';
|
||||
} {1 {vtable constructor failed: t1}}
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
do_catchsql_test 11.2 {
|
||||
INSERT INTO t1(t1, rank) VALUES('merge', 500);
|
||||
} {1 {vtable constructor failed: t1}}
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
@@ -1040,7 +1040,7 @@ do_test 16.0 {
|
||||
|
||||
do_catchsql_test 16.1 {
|
||||
INSERT INTO t1(t1) VALUES('integrity-check');
|
||||
} {1 {vtable constructor failed: t1}}
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
reset_db
|
||||
@@ -1126,7 +1126,7 @@ do_test 17.0 {
|
||||
|
||||
do_catchsql_test 17.1 {
|
||||
SELECT * FROM t1 WHERE t1 MATCH 'abandon';
|
||||
} {1 {vtable constructor failed: t1}}
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
reset_db
|
||||
@@ -1630,7 +1630,7 @@ do_test 20.0 {
|
||||
|
||||
do_catchsql_test 20.1 {
|
||||
SELECT * FROM t1 WHERE t1 MATCH 'abandon';
|
||||
} {1 {vtable constructor failed: t1}}
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
@@ -2100,7 +2100,7 @@ do_test 22.0 {
|
||||
|
||||
do_catchsql_test 22.1 {
|
||||
INSERT INTO t1(t1) VALUES('optimize');
|
||||
} {1 {vtable constructor failed: t1}}
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
reset_db
|
||||
@@ -3700,7 +3700,7 @@ do_catchsql_test 32.1 {
|
||||
highlight(t1, 2, '[', ']')
|
||||
FROM t1('g + h')
|
||||
WHERE rank MATCH 'bm25(1.0, 1.0)' ORDER BY rank;
|
||||
} {1 {vtable constructor failed: t1}}
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
do_catchsql_test 32.2 {
|
||||
SELECT * FROM t3;
|
||||
@@ -4267,7 +4267,7 @@ do_test 35.0 {
|
||||
|
||||
do_catchsql_test 35.1 {
|
||||
SELECT * FROM t1 WHERE t1 MATCH 'e*';
|
||||
} {1 {database disk image is malformed}}
|
||||
} {1 {fts5: missing row 14 from content table 'main'.'t1_content'}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
@@ -8958,7 +8958,6 @@ do_catchsql_test 61.2 {
|
||||
SELECT * FROM t3 ORDER BY rowid;
|
||||
} {/*malformed database schema*/}
|
||||
|
||||
breakpoint
|
||||
#-------------------------------------------------------------------------
|
||||
do_test 62.0 {
|
||||
sqlite3 db {}
|
||||
@@ -10768,6 +10767,7 @@ do_catchsql_test 73.1 {
|
||||
reset_db
|
||||
do_test 74.0 {
|
||||
sqlite3 db {}
|
||||
sqlite3_fts5_register_matchinfo db
|
||||
db deserialize [decode_hexdb {
|
||||
| size 106496 pagesize 4096 filename x.db
|
||||
| page 1 offset 0
|
||||
@@ -14587,14 +14587,19 @@ do_test 74.0 {
|
||||
| end x.db
|
||||
}]} {}
|
||||
|
||||
do_catchsql_test 74.1 {
|
||||
SELECT rowid, quote(matchinfo(t1,'p�xyb<s')) FROM t1 WHERE t1 MATCH 'e*';
|
||||
do_catchsql_test 74.0.5 {
|
||||
SELECT matchinfo(1,2);
|
||||
} {1 {unable to use function matchinfo in the requested context}}
|
||||
|
||||
do_catchsql_test 74.1 {
|
||||
SELECT rowid, quote(matchinfo(t1,'pxyb<s')) FROM t1 WHERE t1 MATCH 'e*';
|
||||
} {1 {unrecognized matchinfo flag: <}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_test 75.0 {
|
||||
sqlite3 db {}
|
||||
sqlite3_fts5_register_matchinfo db
|
||||
db deserialize [decode_hexdb {
|
||||
| size 32768 pagesize 4096 filename crash-033d665d5caa8d.db
|
||||
| page 1 offset 0
|
||||
@@ -14791,7 +14796,7 @@ do_test 75.0 {
|
||||
|
||||
do_catchsql_test 75.1 {
|
||||
SELECT rowid, quote(matchinfo(t1,'pcxybs')) FROM t1 WHERE t1 MATCH 'e*';
|
||||
} {1 {unable to use function matchinfo in the requested context}}
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
@@ -15519,6 +15524,160 @@ do_catchsql_test 80.1 {
|
||||
SELECT snippet(rowid, -1, '.', '..', '[', '(]'),snippet(rowid, -1, '.', '.', '', '(]'), highlight(t1, 29, 1 , '') FROM t1('g+ h') WHERE rank MATCH 'bm25(1.0, 10)' ORDER BY NOT (SELECT 1 FROM t1('g+ æ') WHERE rank MATCH 'bm25(1.0, 10)' ORDER BY rank);
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_test 81.0 {
|
||||
sqlite3 db {}
|
||||
db deserialize [decode_hexdb {
|
||||
.open --hexdb
|
||||
| size 40960 pagesize 4096 filename crash-44e8035a976422.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 0a .....@ ........
|
||||
| 32: 00 00 00 00 00 00 00 00 00 00 00 0d 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 0d 0b 6e 00 0f a3 0f 4c ..........n....L
|
||||
| 112: 0e e1 0e 81 0e 24 0d cc 0d 72 0d 1b 0c b0 0c 50 .....$...r.....P
|
||||
| 128: 0b f8 0b b3 0b 6e 00 00 00 00 00 00 00 00 00 00 .....n..........
|
||||
| 2912: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 43 0d ..............C.
|
||||
| 2928: 06 17 11 11 08 75 74 61 62 6c 65 74 34 74 34 43 .....utablet4t4C
|
||||
| 2944: 52 45 41 54 45 20 56 49 52 54 55 41 4c 20 54 41 REATE VIRTUAL TA
|
||||
| 2960: 42 4c 45 20 74 34 20 55 53 49 4e 47 20 66 74 73 BLE t4 USING fts
|
||||
| 2976: 35 76 6f 63 61 62 28 27 74 32 27 2c 20 27 72 6f 5vocab('t2', 'ro
|
||||
| 2992: 77 27 29 43 0c 06 17 11 11 08 75 74 61 62 6c 65 w')C......utable
|
||||
| 3008: 74 33 74 33 43 52 45 41 54 45 20 56 49 52 54 55 t3t3CREATE VIRTU
|
||||
| 3024: 41 4c 20 54 41 42 4c 45 20 74 33 20 55 53 49 4e AL TABLE t3 USIN
|
||||
| 3040: 47 20 66 74 73 35 76 6f 63 61 62 28 27 74 31 27 G fts5vocab('t1'
|
||||
| 3056: 2c 20 27 72 6f 77 27 29 56 0b 06 17 1f 1f 01 7d , 'row')V.......
|
||||
| 3072: 74 61 62 6c 65 74 32 5f 63 6f 6e 66 69 67 74 32 tablet2_configt2
|
||||
| 3088: 5f 63 6f 6e 66 69 67 0a 43 52 45 41 54 45 20 54 _config.CREATE T
|
||||
| 3104: 41 42 4c 45 20 27 74 32 5f 63 6f 6e 66 69 67 27 ABLE 't2_config'
|
||||
| 3120: 28 6b 20 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 (k PRIMARY KEY,
|
||||
| 3136: 76 29 20 57 49 54 48 4f 55 54 20 52 4f 57 49 44 v) WITHOUT ROWID
|
||||
| 3152: 5e 0a 07 17 21 21 01 81 07 74 61 62 6c 65 74 32 ^...!!...tablet2
|
||||
| 3168: 5f 63 6f 6e 74 65 6e 74 74 32 5f 63 6f 6e 74 65 _contentt2_conte
|
||||
| 3184: 6e 74 09 43 52 45 41 54 45 20 54 41 42 4c 45 20 nt.CREATE TABLE
|
||||
| 3200: 27 74 32 5f 63 6f 6e 74 65 6e 74 27 28 69 64 20 't2_content'(id
|
||||
| 3216: 49 4e 54 45 47 45 52 20 50 52 49 4d 41 52 59 20 INTEGER PRIMARY
|
||||
| 3232: 4b 45 59 2c 20 63 30 2c 20 63 31 2c 20 63 32 29 KEY, c0, c1, c2)
|
||||
| 3248: 69 09 07 17 19 19 01 81 2d 74 61 62 6c 65 74 32 i.......-tablet2
|
||||
| 3264: 5f 69 64 78 74 32 5f 69 64 78 08 43 52 45 41 54 _idxt2_idx.CREAT
|
||||
| 3280: 45 20 54 41 42 4c 45 20 27 74 32 5f 69 64 78 27 E TABLE 't2_idx'
|
||||
| 3296: 28 73 65 67 69 64 2c 20 74 65 72 6d 2c 20 70 67 (segid, term, pg
|
||||
| 3312: 6e 6f 2c 20 50 52 49 4d 41 52 59 20 4b 45 59 28 no, PRIMARY KEY(
|
||||
| 3328: 73 65 67 69 64 2c 20 74 65 72 6d 29 29 20 57 49 segid, term)) WI
|
||||
| 3344: 54 48 4f 55 54 20 52 4f 57 49 44 55 08 07 17 1b THOUT ROWIDU....
|
||||
| 3360: 1b 01 81 01 74 61 62 6c 65 74 32 5f 64 61 74 61 ....tablet2_data
|
||||
| 3376: 74 32 5f 64 61 74 61 07 43 52 45 41 54 45 20 54 t2_data.CREATE T
|
||||
| 3392: 41 42 4c 45 20 27 74 32 5f 64 61 74 61 27 28 69 ABLE 't2_data'(i
|
||||
| 3408: 64 20 49 4e 54 45 47 45 52 20 50 52 49 4d 41 52 d INTEGER PRIMAR
|
||||
| 3424: 59 20 4b 45 59 2c 20 62 6c 6f 63 6b 20 42 4c 4f Y KEY, block BLO
|
||||
| 3440: 42 29 58 07 07 17 11 11 08 81 1d 74 61 62 6c 65 B)X........table
|
||||
| 3456: 74 32 74 32 43 52 45 41 54 45 20 56 49 52 54 55 t2t2CREATE VIRTU
|
||||
| 3472: 41 4c 20 54 41 42 4c 45 20 74 32 20 55 53 49 4e AL TABLE t2 USIN
|
||||
| 3488: 47 20 66 74 73 35 28 27 61 27 2c 5b 62 5d 2c 22 G fts5('a',[b],.
|
||||
| 3504: 63 22 2c 64 65 74 61 69 6c 3d 6e 6f 6e 65 2c 63 c.,detail=none,c
|
||||
| 3520: 6f 6c 75 6d 6e 73 69 7a 65 3d 30 29 56 06 06 17 olumnsize=0)V...
|
||||
| 3536: 1f 1f 01 7d 74 61 62 6c 65 74 31 5f 63 6f 6e 66 ....tablet1_conf
|
||||
| 3552: 69 67 74 31 5f 63 6f 6e 66 69 67 06 43 52 45 41 igt1_config.CREA
|
||||
| 3568: 54 45 20 54 41 42 4c 45 20 27 74 31 5f 63 6f 6e TE TABLE 't1_con
|
||||
| 3584: 66 69 67 27 28 6b 20 50 52 49 4d 41 52 59 20 4b fig'(k PRIMARY K
|
||||
| 3600: 45 59 2c 20 76 29 20 57 49 54 48 4f 55 54 20 52 EY, v) WITHOUT R
|
||||
| 3616: 4f 57 49 44 5b 05 07 17 21 21 01 81 01 74 61 62 OWID[...!!...tab
|
||||
| 3632: 6c 65 74 31 5f 64 6f 63 73 69 7a 65 74 31 5f 64 let1_docsizet1_d
|
||||
| 3648: 6f 63 73 69 7a 65 05 43 52 45 41 54 45 20 54 41 ocsize.CREATE TA
|
||||
| 3664: 42 4c 45 20 27 74 31 5f 64 6f 63 73 69 7a 65 27 BLE 't1_docsize'
|
||||
| 3680: 28 69 64 20 49 4e 54 45 47 45 52 20 50 52 49 4d (id INTEGER PRIM
|
||||
| 3696: 41 52 59 20 4b 45 59 2c 20 73 7a 20 42 4c 4f 42 ARY KEY, sz BLOB
|
||||
| 3712: 29 5e 04 07 17 21 21 01 81 07 74 61 62 6c 65 74 )^...!!...tablet
|
||||
| 3728: 31 5f 63 6f 6e 74 65 6e 74 74 31 5f 63 6f 6e 74 1_contentt1_cont
|
||||
| 3744: 65 6e 74 04 43 52 45 41 54 45 20 54 41 42 4c 45 ent.CREATE TABLE
|
||||
| 3760: 20 27 74 31 5f 63 6f 6e 74 65 6e 74 27 28 69 64 't1_content'(id
|
||||
| 3776: 20 49 4e 54 45 47 45 52 20 50 52 49 4d 41 52 59 INTEGER PRIMARY
|
||||
| 3792: 20 4b 45 59 2c 20 63 30 2c 20 63 31 2c 20 63 32 KEY, c0, c1, c2
|
||||
| 3808: 29 69 03 07 17 19 19 01 81 2d 74 61 62 6c 65 74 )i.......-tablet
|
||||
| 3824: 31 5f 69 64 78 74 31 5f 69 64 78 03 43 52 45 41 1_idxt1_idx.CREA
|
||||
| 3840: 54 45 20 54 41 42 4c 45 20 27 74 31 5f 69 64 78 TE TABLE 't1_idx
|
||||
| 3856: 27 28 73 65 67 69 64 2c 20 74 65 72 6d 2c 20 70 '(segid, term, p
|
||||
| 3872: 67 6e 6f 2c 20 50 52 49 4d 41 52 59 20 4b 45 59 gno, PRIMARY KEY
|
||||
| 3888: 28 73 65 67 69 64 2c 20 74 65 72 6d 29 29 20 57 (segid, term)) W
|
||||
| 3904: 49 54 48 4f 55 54 20 52 4f 57 49 44 55 02 07 17 ITHOUT ROWIDU...
|
||||
| 3920: 1b 1b 01 81 01 74 61 62 6c 65 74 31 5f 64 61 74 .....tablet1_dat
|
||||
| 3936: 61 74 31 5f 64 61 74 61 02 43 52 45 41 54 45 20 at1_data.CREATE
|
||||
| 3952: 54 41 42 4c 45 20 27 74 31 5f 64 61 74 61 27 28 TABLE 't1_data'(
|
||||
| 3968: 69 64 20 49 4e 54 45 47 45 52 20 50 52 49 4d 41 id INTEGER PRIMA
|
||||
| 3984: 52 59 20 4b 45 59 2c 20 62 6c 6f 63 6b 20 42 4c RY KEY, block BL
|
||||
| 4000: 4f 42 29 5b 01 07 17 11 11 08 81 23 74 61 62 6c OB)[.......#tabl
|
||||
| 4016: 65 74 31 74 31 43 52 45 41 54 45 20 56 49 52 54 et1t1CREATE VIRT
|
||||
| 4032: 55 41 4c 20 54 41 42 4c 45 20 74 31 20 55 53 49 UAL TABLE t1 USI
|
||||
| 4048: 4e 47 20 66 74 73 35 28 61 2c 62 20 75 6e 69 6e NG fts5(a,b unin
|
||||
| 4064: 64 65 78 65 64 2c 63 2c 74 6f 6b 65 6e 69 7a 65 dexed,c,tokenize
|
||||
| 4080: 3d 22 70 6f 72 74 65 72 20 61 73 63 69 69 22 29 =.porter ascii.)
|
||||
| page 2 offset 4096
|
||||
| 0: 0d 0f 68 00 05 0f 13 00 0f e6 0f 13 0f a8 0f 7c ..h............|
|
||||
| 16: 0f 2a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 .*..............
|
||||
| 3856: 00 00 00 15 0a 03 00 30 00 00 00 00 01 03 03 00 .......0........
|
||||
| 3872: 03 01 01 01 02 01 01 03 01 01 37 8c 80 80 80 80 ..........7.....
|
||||
| 3888: 01 03 00 74 00 00 00 2e 02 30 61 03 02 02 01 01 ...t.....0a.....
|
||||
| 3904: 62 03 02 03 01 01 63 03 02 04 01 01 67 03 06 01 b.....c.....g...
|
||||
| 3920: 02 02 01 01 68 03 06 01 02 03 01 01 69 03 06 01 ....h.......i...
|
||||
| 3936: 02 04 04 06 06 06 08 08 0f ef 00 14 2a 00 00 00 ............*...
|
||||
| 3952: 00 01 02 02 00 02 01 01 01 02 01 01 25 88 80 80 ............%...
|
||||
| 3968: 80 80 01 03 00 50 00 00 00 1f 02 30 67 02 08 02 .....P.....0g...
|
||||
| 3984: 01 02 02 01 01 68 02 08 03 8d 02 03 01 01 6a 42 .....h........jB
|
||||
| 4000: 08 04 01 02 04 04 09 09 37 84 80 80 80 80 01 03 ........7.......
|
||||
| 4016: 00 74 00 00 00 2e 02 30 61 01 12 02 01 01 62 01 .t.....0a.....b.
|
||||
| 4032: 02 03 01 01 63 01 02 04 01 01 67 01 06 01 02 02 ....c.....g.....
|
||||
| 4048: 01 01 68 01 05 01 02 03 01 01 69 01 06 01 02 04 ..h.......i.....
|
||||
| 4064: 04 06 06 06 08 08 07 01 03 00 14 03 09 00 09 00 ................
|
||||
| 4080: 00 00 11 24 00 00 00 00 01 01 01 00 01 01 01 01 ...$............
|
||||
| page 3 offset 8192
|
||||
| 0: 0a 00 00 00 03 0f ec 00 0f fa 0f f3 0f ec 00 00 ................
|
||||
| 4064: 00 00 00 00 00 00 00 00 00 00 00 00 06 04 01 0c ................
|
||||
| 4080: 01 03 02 06 04 01 0c 01 02 02 05 04 09 0c 01 02 ................
|
||||
| page 4 offset 12288
|
||||
| 0: 0d 00 00 00 03 0f be 00 0f ea 00 00 00 00 00 00 ................
|
||||
| 4016: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 14 03 ................
|
||||
| 4032: 05 00 17 17 17 61 20 62 20 63 67 20 68 20 69 67 .....a b cg h ig
|
||||
| 4048: 20 68 20 69 14 02 05 00 17 17 17 67 20 68 20 69 h i.......g h i
|
||||
| 4064: 61 20 62 20 63 67 20 68 20 69 14 01 05 00 17 17 a b cg h i......
|
||||
| 4080: 17 61 20 62 20 63 64 20 65 20 66 67 20 68 20 69 .a b cd e fg h i
|
||||
| page 5 offset 16384
|
||||
| 0: 0d 00 00 00 03 0f e8 00 0f f8 0f f0 0f e8 00 00 ................
|
||||
| 4064: 00 00 00 00 00 00 00 00 06 03 03 00 12 03 00 03 ................
|
||||
| 4080: 06 02 03 00 12 03 00 03 06 01 03 00 12 03 00 03 ................
|
||||
| page 6 offset 20480
|
||||
| 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 7 offset 24576
|
||||
| 0: 0d 00 00 00 03 0f 9e 00 0f e6 0f ef 0f 9e 00 00 ................
|
||||
| 3984: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 41 84 ..............A.
|
||||
| 4000: 80 80 80 80 01 04 00 81 06 00 00 00 34 02 30 61 ............4.0a
|
||||
| 4016: 01 01 01 01 01 62 01 01 01 01 01 63 01 01 01 01 .....b.....c....
|
||||
| 4032: e6 64 01 01 01 65 01 01 01 66 01 01 01 67 01 01 .d...e...f...g..
|
||||
| 4048: 01 01 01 68 01 01 01 01 01 69 01 01 01 04 06 06 ...h.....i......
|
||||
| 4064: 06 04 04 04 06 06 07 01 03 00 14 03 09 09 09 0f ................
|
||||
| 4080: 0a 03 00 24 00 00 00 00 01 01 01 00 01 01 01 01 ...$............
|
||||
| page 8 offset 28672
|
||||
| 0: 0a 00 00 00 01 0f fa 00 0f fa 00 00 00 00 00 00 ................
|
||||
| 4080: 00 00 00 00 00 00 00 00 00 00 05 04 09 0c 01 02 ................
|
||||
| page 9 offset 32768
|
||||
| 0: 0d 00 00 00 03 0f be 00 0f ea 0f d4 0f be 00 00 ................
|
||||
| 4016: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 14 03 ................
|
||||
| 4032: 05 00 17 17 17 61 20 62 20 63 67 20 68 20 69 67 .....a b cg h ig
|
||||
| 4048: 20 68 21 69 14 02 05 00 17 17 17 67 20 68 20 69 h!i.......g h i
|
||||
| 4064: 61 20 62 20 63 67 20 68 20 69 14 01 05 00 17 17 a b cg h i......
|
||||
| 4080: 17 61 20 62 20 63 64 20 65 20 66 67 20 68 20 69 .a b cd e fg h i
|
||||
| page 10 offset 36864
|
||||
| 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.
|
||||
| end crash-44e8035a976422.db
|
||||
}]} {}
|
||||
|
||||
do_catchsql_test 81.2 {
|
||||
UPDATE t1 SET b=zeroblob(299);
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
|
||||
sqlite3_fts5_may_be_corrupt 0
|
||||
finish_test
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5corrupt4
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5corrupt5
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5corrupt6
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5corrupt7
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
# 2024 Aug 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.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5corrupt8
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE VIRTUAL TABLE t1 USING fts5(x);
|
||||
}
|
||||
|
||||
do_execsql_test 1.1 {
|
||||
UPDATE t1_data SET block='hello world' WHERE id=10
|
||||
}
|
||||
|
||||
db close
|
||||
sqlite3 db test.db
|
||||
|
||||
do_catchsql_test 1.2 {
|
||||
SELECT * FROM t1
|
||||
} {1 {database disk image is malformed}}
|
||||
do_catchsql_test 1.3 {
|
||||
DROP TABLE t1
|
||||
} {0 {}}
|
||||
do_execsql_test 1.4 {
|
||||
SELECT * FROM sqlite_schema
|
||||
}
|
||||
|
||||
do_execsql_test 2.0 {
|
||||
CREATE VIRTUAL TABLE t1 USING fts5(x);
|
||||
}
|
||||
do_execsql_test 2.1 {
|
||||
UPDATE t1_config SET v=555 WHERE k='version'
|
||||
}
|
||||
db close
|
||||
sqlite3 db test.db
|
||||
do_catchsql_test 2.2 {
|
||||
SELECT * FROM t1
|
||||
} {1 {invalid fts5 file format (found 555, expected 4 or 5) - run 'rebuild'}}
|
||||
do_catchsql_test 2.3 {
|
||||
DROP TABLE t1
|
||||
} {1 {invalid fts5 file format (found 555, expected 4 or 5) - run 'rebuild'}}
|
||||
do_test 2.4 {
|
||||
sqlite3_fts5_drop_corrupt_table db main t1
|
||||
} {}
|
||||
do_execsql_test 2.5 {
|
||||
SELECT * FROM sqlite_schema
|
||||
}
|
||||
|
||||
do_execsql_test 3.0 {
|
||||
CREATE VIRTUAL TABLE t1 USING fts5(x);
|
||||
}
|
||||
do_execsql_test 3.1 {
|
||||
DELETE FROM t1_config;
|
||||
}
|
||||
db close
|
||||
sqlite3 db test.db
|
||||
do_catchsql_test 3.2 {
|
||||
SELECT * FROM t1
|
||||
} {1 {invalid fts5 file format (found 0, expected 4 or 5) - run 'rebuild'}}
|
||||
do_catchsql_test 3.3 {
|
||||
DROP TABLE t1
|
||||
} {1 {invalid fts5 file format (found 0, expected 4 or 5) - run 'rebuild'}}
|
||||
|
||||
|
||||
do_test 3.4 {
|
||||
sqlite3_db_config db DEFENSIVE 1
|
||||
} {1}
|
||||
do_test 3.5 {
|
||||
sqlite3_fts5_drop_corrupt_table db main t1
|
||||
} {}
|
||||
do_test 3.6 {
|
||||
sqlite3_db_config db DEFENSIVE -1
|
||||
} {1}
|
||||
do_execsql_test 3.7 {
|
||||
SELECT * FROM sqlite_schema
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5dlidx
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5doclist
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5ea
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5eb
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
@@ -86,13 +86,13 @@ do_execsql_test 3.0 {
|
||||
INSERT INTO e1 VALUES ('just a few words with a / inside');
|
||||
}
|
||||
do_execsql_test 3.1 {
|
||||
SELECT rowid, bm25(e1) FROM e1 WHERE e1 MATCH '"just"' ORDER BY rank;
|
||||
SELECT rowid, format('%g',bm25(e1)) FROM e1 WHERE e1 MATCH '"just"' ORDER BY rank;
|
||||
} {1 -1e-06}
|
||||
do_execsql_test 3.2 {
|
||||
SELECT rowid FROM e1 WHERE e1 MATCH '"/" OR "just"'
|
||||
} 1
|
||||
do_execsql_test 3.3 {
|
||||
SELECT rowid, bm25(e1) FROM e1 WHERE e1 MATCH '"/" OR "just"' ORDER BY rank;
|
||||
SELECT rowid, format('%g',bm25(e1)) FROM e1 WHERE e1 MATCH '"/" OR "just"' ORDER BY rank;
|
||||
} {1 -1e-06}
|
||||
|
||||
do_execsql_test 3.4 "
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
# 2024 August 8
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#*************************************************************************
|
||||
# This file implements regression tests for SQLite library. The
|
||||
# focus of this script is testing the FTS5 module.
|
||||
#
|
||||
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5expr
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE VIRTUAL TABLE x1 USING fts5(a);
|
||||
INSERT INTO x1(rowid, a) VALUES (113, 'fts5 expr test');
|
||||
}
|
||||
|
||||
do_execsql_test 1.1 {
|
||||
SELECT rowid FROM x1('expr');
|
||||
} {113}
|
||||
|
||||
for {set ii 0} {$ii < 300} {incr ii} {
|
||||
set expr "expr "
|
||||
append expr [string repeat "NOT abcd " $ii]
|
||||
|
||||
if {$ii<257} {
|
||||
set res {0 113}
|
||||
} else {
|
||||
set res {1 {fts5 expression tree is too large (maximum depth 256)}}
|
||||
}
|
||||
do_catchsql_test 1.1.$ii {
|
||||
SELECT rowid FROM x1($expr)
|
||||
} $res
|
||||
}
|
||||
|
||||
do_execsql_test 1.2 {
|
||||
SELECT rowid FROM x1 WHERE a MATCH '"..."'
|
||||
} {}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -90,7 +90,7 @@ set ::res [db eval {SELECT rowid, x1 FROM x1 WHERE x1 MATCH '*reads'}]
|
||||
do_faultsim_test 4 -faults oom-* -body {
|
||||
db eval {SELECT rowid, x, x1 FROM x1 WHERE x1 MATCH '*reads'}
|
||||
} -test {
|
||||
faultsim_test_result {0 {0 {} 3}}
|
||||
faultsim_test_result {0 {0 {} 2}}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
@@ -16,7 +16,7 @@ source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
source $testdir/malloc_common.tcl
|
||||
set testprefix fts5fault6
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
||||
@@ -14,7 +14,7 @@ source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
source $testdir/malloc_common.tcl
|
||||
set testprefix fts5faultG
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
||||
@@ -14,7 +14,7 @@ source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
source $testdir/malloc_common.tcl
|
||||
set testprefix fts5faultG
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
||||
@@ -0,0 +1,294 @@
|
||||
# 2010 June 15
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
source $testdir/malloc_common.tcl
|
||||
set testprefix fts5faultI
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
set ::testprefix fts5faultI
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
PRAGMA encoding = utf16;
|
||||
CREATE VIRTUAL TABLE t1 USING fts5(x, locale=1);
|
||||
INSERT INTO t1 VALUES('origintext unicode61 ascii porter trigram');
|
||||
}
|
||||
|
||||
faultsim_save_and_close
|
||||
faultsim_restore_and_reopen
|
||||
|
||||
do_faultsim_test 1 -faults oom* -prep {
|
||||
} -body {
|
||||
execsql {
|
||||
SELECT rowid FROM t1(fts5_locale('en_US', 'origintext'));
|
||||
}
|
||||
} -test {
|
||||
faultsim_test_result {0 1}
|
||||
}
|
||||
|
||||
do_faultsim_test 2 -faults oom* -prep {
|
||||
faultsim_restore_and_reopen
|
||||
execsql {
|
||||
SELECT * FROM t1('ascii');
|
||||
}
|
||||
} -body {
|
||||
execsql {
|
||||
UPDATE t1 SET rowid=rowid+1;
|
||||
}
|
||||
} -test {
|
||||
faultsim_test_result {0 {}}
|
||||
}
|
||||
|
||||
fts5_aux_test_functions db
|
||||
do_faultsim_test 3 -faults oom* -prep {
|
||||
} -body {
|
||||
execsql {
|
||||
SELECT fts5_columnlocale(t1, 0) FROM t1('unicode*');
|
||||
}
|
||||
} -test {
|
||||
faultsim_test_result {0 {{}}} {1 SQLITE_NOMEM}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test 4.0 {
|
||||
CREATE VIRTUAL TABLE w1 USING fts5(a);
|
||||
}
|
||||
faultsim_save_and_close
|
||||
|
||||
do_faultsim_test 4 -faults oom* -prep {
|
||||
faultsim_restore_and_reopen
|
||||
execsql {
|
||||
BEGIN;
|
||||
INSERT INTO w1 VALUES('token token token');
|
||||
}
|
||||
} -body {
|
||||
execsql {
|
||||
INSERT INTO w1(w1, rank) VALUES('rank', 'bm25()');
|
||||
}
|
||||
} -test {
|
||||
faultsim_test_result {0 {}}
|
||||
}
|
||||
|
||||
do_faultsim_test 5 -faults oom* -prep {
|
||||
faultsim_restore_and_reopen
|
||||
execsql {
|
||||
BEGIN;
|
||||
INSERT INTO w1 VALUES('one');
|
||||
SAVEPOINT one;
|
||||
INSERT INTO w1 VALUES('two');
|
||||
ROLLBACK TO one;
|
||||
}
|
||||
|
||||
} -body {
|
||||
execsql {
|
||||
INSERT INTO w1 VALUES('string');
|
||||
}
|
||||
} -test {
|
||||
faultsim_test_result {0 {}}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test 5.0 {
|
||||
CREATE VIRTUAL TABLE w1 USING fts5(a);
|
||||
INSERT INTO w1 VALUES('one two three');
|
||||
}
|
||||
fts5_aux_test_functions db
|
||||
|
||||
do_faultsim_test 5 -faults oom* -prep {
|
||||
} -body {
|
||||
execsql {
|
||||
SELECT fts5_test_insttoken(w1, 0, 0) FROM w1('two');
|
||||
}
|
||||
} -test {
|
||||
faultsim_test_result {0 two} {1 SQLITE_NOMEM}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test 6.0 {
|
||||
CREATE VIRTUAL TABLE w1 USING fts5(a);
|
||||
INSERT INTO w1 VALUES('one two three');
|
||||
}
|
||||
fts5_aux_test_functions db
|
||||
faultsim_save_and_close
|
||||
|
||||
do_faultsim_test 6 -faults oom* -prep {
|
||||
faultsim_restore_and_reopen
|
||||
db eval {
|
||||
BEGIN;
|
||||
INSERT INTO w1 VALUES('four five six');
|
||||
SAVEPOINT abc;
|
||||
INSERT INTO w1 VALUES('seven eight nine');
|
||||
SAVEPOINT def;
|
||||
INSERT INTO w1 VALUES('ten eleven twelve');
|
||||
}
|
||||
} -body {
|
||||
execsql {
|
||||
RELEASE abc;
|
||||
}
|
||||
} -test {
|
||||
faultsim_test_result {0 {}}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test 7.0 {
|
||||
CREATE VIRTUAL TABLE w1 USING fts5(a);
|
||||
INSERT INTO w1 VALUES('one two three');
|
||||
INSERT INTO w1 VALUES('three two one');
|
||||
DELETE FROM w1_content WHERE rowid=1;
|
||||
}
|
||||
|
||||
faultsim_save_and_close
|
||||
|
||||
do_faultsim_test 7 -faults oom* -prep {
|
||||
faultsim_restore_and_reopen
|
||||
db eval { SELECT * FROM w1 }
|
||||
} -body {
|
||||
execsql {
|
||||
PRAGMA integrity_check;
|
||||
}
|
||||
} -test {
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
fts5_tclnum_register db
|
||||
fts5_aux_test_functions db
|
||||
|
||||
do_execsql_test 8.0 {
|
||||
CREATE VIRTUAL TABLE ft USING fts5(
|
||||
x, tokenize = "tclnum query", detail=columns
|
||||
);
|
||||
INSERT INTO ft VALUES('one two three i ii iii');
|
||||
INSERT INTO ft VALUES('four five six iv v vi');
|
||||
INSERT INTO ft VALUES('eight nine ten viii ix x');
|
||||
} {}
|
||||
|
||||
do_faultsim_test 8.1 -faults oom* -prep {
|
||||
} -body {
|
||||
execsql {
|
||||
SELECT fts5_test_collist (ft) FROM ft('one two');
|
||||
}
|
||||
} -test {
|
||||
faultsim_test_result {0 {{0.0 1.0}}} {1 {SQL logic error}} {1 SQLITE_NOMEM}
|
||||
}
|
||||
|
||||
do_faultsim_test 8.2 -faults oom* -prep {
|
||||
} -body {
|
||||
execsql {
|
||||
SELECT rowid FROM ft('one two') ORDER BY rank;
|
||||
}
|
||||
} -test {
|
||||
faultsim_test_result {0 1} {1 {SQL logic error}} {1 SQLITE_NOMEM}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
|
||||
do_execsql_test 9.0 {
|
||||
CREATE VIRTUAL TABLE ft USING fts5(x);
|
||||
INSERT INTO ft VALUES('one two three i ii iii');
|
||||
INSERT INTO ft VALUES('four five six iv v vi');
|
||||
INSERT INTO ft VALUES('eight nine ten viii ix x');
|
||||
} {}
|
||||
|
||||
faultsim_save_and_close
|
||||
|
||||
do_faultsim_test 9.1 -faults oom* -prep {
|
||||
faultsim_restore_and_reopen
|
||||
} -body {
|
||||
execsql {
|
||||
UPDATE ft SET rowid=4 WHERE rowid=1
|
||||
}
|
||||
} -test {
|
||||
faultsim_test_result {0 {}}
|
||||
}
|
||||
|
||||
do_faultsim_test 9.2 -faults oom* -prep {
|
||||
faultsim_restore_and_reopen
|
||||
} -body {
|
||||
execsql {
|
||||
SELECT rowid FROM ft WHERE x MATCH 'one AND two AND three'
|
||||
}
|
||||
} -test {
|
||||
faultsim_test_result {0 1}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
|
||||
do_execsql_test 10.0 {
|
||||
CREATE VIRTUAL TABLE ft USING fts5(x, locale=1);
|
||||
INSERT INTO ft VALUES(fts5_locale('hello', 'one two three i ii iii'));
|
||||
INSERT INTO ft VALUES('four five six iv v vi');
|
||||
INSERT INTO ft VALUES('eight nine ten viii ix x');
|
||||
} {}
|
||||
|
||||
do_execsql_test 10.1 {
|
||||
SELECT fts5_get_locale(ft, 0) FROM ft WHERE x MATCH 'one AND two AND three'
|
||||
} {hello}
|
||||
|
||||
faultsim_save_and_close
|
||||
do_faultsim_test 10.1 -faults oom* -prep {
|
||||
faultsim_restore_and_reopen
|
||||
} -body {
|
||||
execsql {
|
||||
SELECT fts5_get_locale(ft, 0) FROM ft WHERE x MATCH 'one AND two AND three'
|
||||
}
|
||||
} -test {
|
||||
faultsim_test_result {0 hello}
|
||||
}
|
||||
|
||||
breakpoint
|
||||
faultsim_save_and_close
|
||||
do_faultsim_test 10.2 -faults oom-t* -prep {
|
||||
faultsim_restore_and_reopen
|
||||
} -body {
|
||||
execsql {
|
||||
INSERT INTO ft VALUES(zeroblob(10000));
|
||||
}
|
||||
} -test {
|
||||
faultsim_test_result {0 {}}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
|
||||
do_execsql_test 11.0 {
|
||||
CREATE VIRTUAL TABLE f1 USING fts5(content);
|
||||
CREATE TABLE g1(id, content);
|
||||
INSERT INTO g1 VALUES(30000, 'a b c');
|
||||
INSERT INTO g1 VALUES(40000, 'd e f');
|
||||
}
|
||||
|
||||
faultsim_save_and_close
|
||||
|
||||
do_faultsim_test 11 -faults oom* -prep {
|
||||
faultsim_restore_and_reopen
|
||||
} -body {
|
||||
execsql {
|
||||
INSERT INTO f1(rowid, content) SELECT id, content FROM g1;
|
||||
}
|
||||
} -test {
|
||||
faultsim_test_result {0 {}}
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -22,6 +22,7 @@ do_execsql_test 1.0 {
|
||||
CREATE VIRTUAL TABLE x1 USING fts5(a, b);
|
||||
}
|
||||
|
||||
unset -nocomplain res
|
||||
foreach {tn expr ok} {
|
||||
1 {^abc} 1
|
||||
2 {^abc + def} 1
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5full
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5hash
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5integrity
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
@@ -153,6 +153,7 @@ do_execsql_test 5.3 {
|
||||
INSERT INTO gg(gg) VALUES('integrity-check');
|
||||
}
|
||||
|
||||
unset -nocomplain res
|
||||
do_test 5.4.1 {
|
||||
set ok 0
|
||||
for {set i 0} {$i < 10000} {incr i} {
|
||||
@@ -380,5 +381,32 @@ do_execsql_test 12.3 {
|
||||
} {ok}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test 13.1 {
|
||||
CREATE VIRTUAL TABLE t1 USING fts5(a, tokenize=ascii);
|
||||
INSERT INTO t1 VALUES('a b c'), ('d e f');
|
||||
PRAGMA integrity_check;
|
||||
} {ok}
|
||||
|
||||
db close
|
||||
sqlite3 db test.db
|
||||
do_catchsql_test 13.2 {
|
||||
PRAGMA integrity_check;
|
||||
} {0 ok}
|
||||
|
||||
do_execsql_test 13.3 {
|
||||
PRAGMA writable_schema = 1;
|
||||
UPDATE sqlite_schema SET sql = 'CREATE VIRTUAL TABLE t1 USING fts5(a, tokenize=blah)'
|
||||
WHERE name = 't1';
|
||||
}
|
||||
|
||||
db close
|
||||
sqlite3 db test.db
|
||||
breakpoint
|
||||
do_catchsql_test 13.4 {
|
||||
PRAGMA integrity_check;
|
||||
} {1 {SQL logic error}}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
# 2024 September 3
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
# This file contains tests focused on the integrity-check procedure.
|
||||
#
|
||||
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5integrity2
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
do_execsql_test 2.0 {
|
||||
CREATE VIRTUAL TABLE t2 USING fts5(a, detail='none');
|
||||
BEGIN;
|
||||
INSERT INTO t2(rowid, a) VALUES(-1, 'hello world');
|
||||
INSERT INTO t2(rowid, a) VALUES(9223372036854775807, 'hello world');
|
||||
COMMIT;
|
||||
}
|
||||
|
||||
do_execsql_test 2.1 {
|
||||
SELECT rowid FROM t2('hello AND world');
|
||||
} {-1 9223372036854775807}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
do_execsql_test 2.0 {
|
||||
CREATE VIRTUAL TABLE t1 USING fts5(a, detail='none');
|
||||
CREATE TABLE r1(r);
|
||||
|
||||
WITH c(x) AS (VALUES(1) UNION SELECT x<<1 FROM c)
|
||||
INSERT INTO r1(r) SELECT -1-x FROM c;
|
||||
|
||||
INSERT INTO t1(rowid, a) SELECT r, 'abc' FROM r1;
|
||||
}
|
||||
|
||||
do_execsql_test 2.1 {
|
||||
PRAGMA integrity_check;
|
||||
} {ok}
|
||||
|
||||
do_execsql_test 2.2 {
|
||||
SELECT rowid FROM t1('abc') ORDER BY +rowid;
|
||||
} [db eval {SELECT r FROM r1 ORDER BY r}]
|
||||
|
||||
|
||||
finish_test
|
||||
@@ -33,6 +33,7 @@ proc progress_handler {args} {
|
||||
return 0
|
||||
}
|
||||
|
||||
unset -nocomplain res
|
||||
foreach {tn sql} {
|
||||
1 { INSERT INTO t1(rowid, a) VALUES(0, 'z z z z') }
|
||||
2 { COMMIT }
|
||||
@@ -64,4 +65,3 @@ foreach {tn sql} {
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5lastrowid
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
||||
@@ -0,0 +1,748 @@
|
||||
# 2014 Dec 20
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
# Tests focusing on the built-in fts5 tokenizers.
|
||||
#
|
||||
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5locale
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
proc transform_token {locale token} {
|
||||
switch -- $locale {
|
||||
reverse {
|
||||
set ret ""
|
||||
foreach c [split $token ""] {
|
||||
set ret "$c$ret"
|
||||
}
|
||||
set token $ret
|
||||
}
|
||||
|
||||
default {
|
||||
# no-op
|
||||
}
|
||||
}
|
||||
|
||||
set token
|
||||
}
|
||||
|
||||
proc tcl_create {args} { return "tcl_tokenize" }
|
||||
proc tcl_tokenize {tflags text} {
|
||||
set iToken 1
|
||||
set bSkip 0
|
||||
if {[sqlite3_fts5_locale]=="second"} { set bSkip 1 }
|
||||
foreach {w iStart iEnd} [fts5_tokenize_split $text] {
|
||||
incr iToken
|
||||
if {(($iToken) % ($bSkip + 1))} continue
|
||||
|
||||
set w [transform_token [sqlite3_fts5_locale] $w]
|
||||
sqlite3_fts5_token $w $iStart $iEnd
|
||||
}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Check that queries can have a locale attached to them.
|
||||
#
|
||||
reset_db
|
||||
sqlite3_fts5_create_tokenizer -v2 db tcl tcl_create
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE VIRTUAL TABLE t1 USING fts5(a, tokenize=tcl);
|
||||
INSERT INTO t1 VALUES('abc');
|
||||
INSERT INTO t1 VALUES('cba');
|
||||
} {}
|
||||
|
||||
do_execsql_test 1.1 {
|
||||
SELECT rowid, a FROM t1( fts5_locale('en_US', 'abc') );
|
||||
} {1 abc}
|
||||
|
||||
do_execsql_test 1.2 {
|
||||
SELECT rowid, a FROM t1( fts5_locale('reverse', 'abc') );
|
||||
} {2 cba}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test that the locale= option exists and seems to accept values. And
|
||||
# that fts5_locale() values may only be inserted into an internal-content
|
||||
# table if the locale=1 option was specified.
|
||||
#
|
||||
reset_db
|
||||
sqlite3_fts5_create_tokenizer -v2 db tcl tcl_create
|
||||
|
||||
do_execsql_test 2.1 {
|
||||
CREATE VIRTUAL TABLE b1 USING fts5(x, y, locale=1, tokenize=tcl);
|
||||
CREATE VIRTUAL TABLE b2 USING fts5(x, y, locale=0, tokenize=tcl);
|
||||
|
||||
CREATE VIRTUAL TABLE ttt USING fts5vocab('b1', instance);
|
||||
}
|
||||
|
||||
do_catchsql_test 2.2.1 {
|
||||
CREATE VIRTUAL TABLE b3 USING fts5(x, y, locale=2);
|
||||
} {1 {malformed locale=... directive}}
|
||||
do_catchsql_test 2.2.2 {
|
||||
CREATE VIRTUAL TABLE b3 USING fts5(x, y, locale=111);
|
||||
} {1 {malformed locale=... directive}}
|
||||
|
||||
do_catchsql_test 2.3 {
|
||||
INSERT INTO b1(b1, rank) VALUES('locale', 0);
|
||||
} {1 {SQL logic error}}
|
||||
|
||||
do_execsql_test 2.4.1 {
|
||||
INSERT INTO b1 VALUES('abc', 'one two three');
|
||||
}
|
||||
|
||||
do_execsql_test 2.4.2 {
|
||||
INSERT INTO b1 VALUES('def', fts5_locale('reverse', 'four five six'));
|
||||
}
|
||||
|
||||
do_execsql_test 2.5 {
|
||||
INSERT INTO b2 VALUES('abc', 'one two three');
|
||||
}
|
||||
|
||||
do_catchsql_test 2.6 {
|
||||
INSERT INTO b2 VALUES('def', fts5_locale('reverse', 'four five six'));
|
||||
} {1 {fts5_locale() requires locale=1}}
|
||||
|
||||
do_execsql_test 2.7 { SELECT rowid FROM b1('one') } {1}
|
||||
do_execsql_test 2.8 { SELECT rowid FROM b1('four') } {}
|
||||
do_execsql_test 2.9 { SELECT rowid FROM b1('ruof') } 2
|
||||
do_execsql_test 2.10 { SELECT rowid FROM b1(fts5_locale('reverse', 'five'))} 2
|
||||
|
||||
do_execsql_test 2.11 {
|
||||
SELECT x, quote(y) FROM b1
|
||||
} {
|
||||
abc {'one two three'}
|
||||
def {'four five six'}
|
||||
}
|
||||
|
||||
do_execsql_test 2.12 { SELECT quote(y) FROM b1('ruof') } {
|
||||
{'four five six'}
|
||||
}
|
||||
|
||||
do_execsql_test 2.13 {
|
||||
INSERT INTO b1(b1) VALUES('integrity-check');
|
||||
}
|
||||
|
||||
do_execsql_test 2.14 {
|
||||
INSERT INTO b1(b1) VALUES('rebuild');
|
||||
}
|
||||
do_execsql_test 2.15 {
|
||||
INSERT INTO b1(b1) VALUES('integrity-check');
|
||||
}
|
||||
|
||||
do_execsql_test 2.16 {
|
||||
DELETE FROM b1 WHERE rowid=2
|
||||
}
|
||||
do_execsql_test 2.17 {
|
||||
INSERT INTO b1(b1) VALUES('integrity-check');
|
||||
}
|
||||
|
||||
do_execsql_test 2.18 {
|
||||
INSERT INTO b1(rowid, x, y) VALUES(
|
||||
test_setsubtype(45, 76), 'abc def', 'def abc'
|
||||
);
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test the 'delete' command with contentless tables.
|
||||
#
|
||||
reset_db
|
||||
sqlite3_fts5_create_tokenizer -v2 db tcl tcl_create
|
||||
|
||||
do_execsql_test 3.1 {
|
||||
CREATE VIRTUAL TABLE c1 USING fts5(x, content=, tokenize=tcl, locale=1);
|
||||
CREATE VIRTUAL TABLE c2 USING fts5vocab('c1', instance);
|
||||
|
||||
INSERT INTO c1 VALUES('hello world');
|
||||
INSERT INTO c1 VALUES( fts5_locale('reverse', 'one two three') );
|
||||
}
|
||||
|
||||
do_execsql_test 3.2 {
|
||||
SELECT DISTINCT term FROM c2 ORDER BY 1
|
||||
} {
|
||||
eerht eno hello owt world
|
||||
}
|
||||
|
||||
do_execsql_test 3.3 {
|
||||
INSERT INTO c1(c1, rowid, x)
|
||||
VALUES('delete', 2, fts5_locale('reverse', 'one two three') );
|
||||
}
|
||||
|
||||
do_execsql_test 3.4 {
|
||||
SELECT DISTINCT term FROM c2 ORDER BY 1
|
||||
} {
|
||||
hello world
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test that an UPDATE that updates a subset of the columns does not
|
||||
# magically discard the locale from those columns not updated.
|
||||
#
|
||||
reset_db
|
||||
sqlite3_fts5_create_tokenizer -v2 db tcl tcl_create
|
||||
|
||||
do_execsql_test 4.1 {
|
||||
CREATE VIRTUAL TABLE d1 USING fts5(x, y, locale=1, tokenize=tcl);
|
||||
CREATE VIRTUAL TABLE d2 USING fts5vocab('d1', instance);
|
||||
|
||||
INSERT INTO d1(rowid, x, y) VALUES(1, 'abc', 'def');
|
||||
INSERT INTO d1(rowid, x, y) VALUES(2, 'ghi', fts5_locale('reverse', 'hello'));
|
||||
}
|
||||
|
||||
do_execsql_test 4.2 {
|
||||
SELECT DISTINCT term FROM d2 ORDER BY 1
|
||||
} {
|
||||
abc def ghi olleh
|
||||
}
|
||||
|
||||
do_execsql_test 4.3 {
|
||||
UPDATE d1 SET x='jkl' WHERE rowid=2;
|
||||
}
|
||||
|
||||
do_execsql_test 4.4 {
|
||||
SELECT DISTINCT term FROM d2 ORDER BY 1
|
||||
} {
|
||||
abc def jkl olleh
|
||||
}
|
||||
|
||||
do_execsql_test 4.5 {
|
||||
SELECT rowid, * FROM d1
|
||||
} {
|
||||
1 abc def
|
||||
2 jkl hello
|
||||
}
|
||||
|
||||
do_execsql_test 4.6 {
|
||||
UPDATE d1 SET rowid=4 WHERE rowid=2
|
||||
}
|
||||
|
||||
do_execsql_test 4.7 {
|
||||
SELECT rowid, * FROM d1
|
||||
} {
|
||||
1 abc def
|
||||
4 jkl hello
|
||||
}
|
||||
|
||||
fts5_aux_test_functions db
|
||||
|
||||
do_execsql_test 4.8.1 {
|
||||
SELECT fts5_test_columntext(d1) FROM d1('jkl')
|
||||
} {{jkl hello}}
|
||||
do_execsql_test 4.8.2 {
|
||||
SELECT fts5_test_columntext(d1) FROM d1(fts5_locale('reverse', 'hello'))
|
||||
} {{jkl hello}}
|
||||
|
||||
do_execsql_test 4.9 {
|
||||
SELECT fts5_test_columnlocale(d1) FROM d1(fts5_locale('reverse', 'hello'))
|
||||
} {{{} reverse}}
|
||||
|
||||
do_execsql_test 4.10 {
|
||||
SELECT fts5_test_columnlocale(d1) FROM d1
|
||||
} {
|
||||
{{} {}}
|
||||
{{} reverse}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test that if an fts5_locale() value is written to an UNINDEXED
|
||||
# column it is stored as text. This is so that blobs and other values
|
||||
# can also be stored as is.
|
||||
#
|
||||
reset_db
|
||||
sqlite3_fts5_create_tokenizer -v2 db tcl tcl_create
|
||||
|
||||
do_execsql_test 5.1 {
|
||||
CREATE VIRTUAL TABLE t1 USING fts5(
|
||||
x, y UNINDEXED, locale=1, tokenize=tcl
|
||||
);
|
||||
|
||||
INSERT INTO t1(rowid, x, y) VALUES(111,
|
||||
fts5_locale('reverse', 'one two three'),
|
||||
fts5_locale('reverse', 'four five six')
|
||||
);
|
||||
}
|
||||
|
||||
do_execsql_test 5.2 {
|
||||
SELECT rowid, x, y FROM t1
|
||||
} {
|
||||
111 {one two three} {four five six}
|
||||
}
|
||||
|
||||
do_execsql_test 5.3 {
|
||||
SELECT typeof(c0), typeof(c1), typeof(l0) FROM t1_content
|
||||
} {
|
||||
text text text
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
foreach {tn opt} {
|
||||
1 {}
|
||||
2 {, columnsize=0}
|
||||
} {
|
||||
reset_db
|
||||
sqlite3_fts5_create_tokenizer -v2 db tcl tcl_create
|
||||
do_execsql_test 6.$tn.1 "
|
||||
CREATE VIRTUAL TABLE y1 USING fts5(t, locale=1, tokenize=tcl $opt);
|
||||
"
|
||||
|
||||
do_execsql_test 6.$tn.2 {
|
||||
INSERT INTO y1(rowid, t) VALUES
|
||||
(1, fts5_locale('second', 'the city of London')),
|
||||
(2, fts5_locale('second', 'shall have all the old')),
|
||||
(3, fts5_locale('second', 'Liberties and Customs')),
|
||||
(4, fts5_locale('second', 'which it hath been used to have'));
|
||||
}
|
||||
|
||||
fts5_aux_test_functions db
|
||||
|
||||
do_execsql_test 6.$tn.3 {
|
||||
SELECT fts5_test_columnsize(y1) FROM y1
|
||||
} {
|
||||
2 3 2 4
|
||||
}
|
||||
|
||||
do_execsql_test 6.$tn.4 {
|
||||
SELECT rowid, fts5_test_columnsize(y1) FROM y1('shall');
|
||||
} {
|
||||
2 3
|
||||
}
|
||||
|
||||
do_execsql_test 6.$tn.5 {
|
||||
SELECT rowid, fts5_test_columnsize(y1) FROM y1('shall');
|
||||
} {
|
||||
2 3
|
||||
}
|
||||
|
||||
do_execsql_test 6.$tn.6 {
|
||||
SELECT rowid, fts5_test_columnsize(y1) FROM y1('have');
|
||||
} {
|
||||
4 4
|
||||
}
|
||||
|
||||
do_execsql_test 6.$tn.7 {
|
||||
SELECT rowid, highlight(y1, 0, '[', ']') FROM y1('have');
|
||||
} {
|
||||
4 {which it hath been used to [have]}
|
||||
}
|
||||
|
||||
do_execsql_test 6.$tn.8 {
|
||||
SELECT rowid,
|
||||
highlight(y1, 0, '[', ']'),
|
||||
snippet(y1, 0, '[', ']', '...', 10)
|
||||
FROM y1('Liberties + Customs');
|
||||
} {
|
||||
3 {[Liberties and Customs]}
|
||||
{[Liberties and Customs]}
|
||||
}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test 6.0 {
|
||||
CREATE VIRTUAL TABLE x1 USING fts5(x);
|
||||
}
|
||||
do_catchsql_test 6.1 {
|
||||
INSERT INTO x1(rowid, x) VALUES(123, fts5_locale('en_AU', 'hello world'));
|
||||
} {1 {fts5_locale() requires locale=1}}
|
||||
|
||||
do_execsql_test 6.2 {
|
||||
SELECT typeof( fts5_locale(NULL, 'xyz') ), typeof( fts5_locale('', 'abc') );
|
||||
} {text text}
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
# Test that fts5_locale() works with external-content tables.
|
||||
#
|
||||
reset_db
|
||||
sqlite3_fts5_create_tokenizer -v2 db tcl tcl_create
|
||||
|
||||
do_execsql_test 7.1 {
|
||||
CREATE TABLE t1(ii INTEGER PRIMARY KEY, bb BLOB, tt TEXT, locale TEXT);
|
||||
CREATE VIEW v1 AS
|
||||
SELECT ii AS rowid, bb, fts5_locale(locale, tt) AS tt FROM t1;
|
||||
|
||||
CREATE VIRTUAL TABLE ft USING fts5(
|
||||
bb, tt, locale=1, tokenize=tcl, content=v1
|
||||
);
|
||||
|
||||
INSERT INTO t1 VALUES(1, NULL, 'one two three', NULL);
|
||||
INSERT INTO t1 VALUES(2, '7800616263', 'four five six', 'reverse');
|
||||
INSERT INTO t1 VALUES(3, '000000007800616263', 'seven eight nine', 'second');
|
||||
}
|
||||
|
||||
do_execsql_test 7.2 {
|
||||
INSERT INTO ft(ft) VALUES('rebuild');
|
||||
INSERT INTO ft(ft) VALUES('integrity-check');
|
||||
}
|
||||
|
||||
do_execsql_test 7.3 {
|
||||
SELECT rowid, quote(bb), quote(tt) FROM ft
|
||||
} {
|
||||
1 NULL {'one two three'}
|
||||
2 '7800616263' {'four five six'}
|
||||
3 '000000007800616263' {'seven eight nine'}
|
||||
}
|
||||
|
||||
do_execsql_test 7.4 { SELECT rowid FROM ft('six'); }
|
||||
do_execsql_test 7.5 { SELECT rowid FROM ft(fts5_locale('reverse','six')); } 2
|
||||
|
||||
fts5_aux_test_functions db
|
||||
|
||||
do_execsql_test 7.6 {
|
||||
SELECT fts5_test_columnlocale(ft) FROM ft;
|
||||
} {
|
||||
{{} {}} {{} reverse} {{} second}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test that the porter tokenizer works with locales.
|
||||
#
|
||||
reset_db
|
||||
sqlite3_fts5_create_tokenizer -v2 db tcl tcl_create
|
||||
|
||||
do_execsql_test 8.1 {
|
||||
CREATE VIRTUAL TABLE ft USING fts5(tt, locale=1, tokenize="porter tcl");
|
||||
CREATE VIRTUAL TABLE vocab USING fts5vocab('ft', instance);
|
||||
|
||||
INSERT INTO ft(rowid, tt) VALUES
|
||||
(111, fts5_locale('second', 'the porter tokenizer is a wrapper tokenizer')),
|
||||
(222, fts5_locale('reverse', 'This value may also be set'));
|
||||
}
|
||||
|
||||
do_execsql_test 8.1 {
|
||||
SELECT DISTINCT term FROM vocab ORDER BY 1
|
||||
} {
|
||||
a eb eulav osla sihT te the token yam
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test that position-lists (used by xInst, xPhraseFirst etc.) work with
|
||||
# locales and modes other than detail=full.
|
||||
#
|
||||
foreach {tn detail} {
|
||||
1 detail=full
|
||||
2 detail=none
|
||||
3 detail=column
|
||||
} {
|
||||
reset_db
|
||||
sqlite3_fts5_create_tokenizer -v2 db tcl tcl_create
|
||||
do_execsql_test 9.$tn.0 "
|
||||
CREATE VIRTUAL TABLE ft USING fts5(tt, locale=1, tokenize=tcl, $detail);
|
||||
"
|
||||
do_execsql_test 9.$tn.1 {
|
||||
CREATE VIRTUAL TABLE vocab USING fts5vocab('ft', instance);
|
||||
INSERT INTO ft(rowid, tt) VALUES
|
||||
(-1, fts5_locale('second', 'it is an ancient mariner'));
|
||||
}
|
||||
|
||||
do_execsql_test 9.$tn.2 {
|
||||
SELECT DISTINCT term FROM vocab
|
||||
} {an it mariner}
|
||||
|
||||
do_execsql_test 9.$tn.3 {
|
||||
SELECT highlight(ft, 0, '[', ']') FROM ft('mariner')
|
||||
} {{it is an ancient [mariner]}}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Check some corrupt fts5_locale() blob formats are detected.
|
||||
#
|
||||
foreach_detail_mode $::testprefix {
|
||||
|
||||
reset_db
|
||||
sqlite3_fts5_create_tokenizer -v2 db tcl tcl_create
|
||||
fts5_aux_test_functions db
|
||||
do_execsql_test 10.1 {
|
||||
CREATE TABLE x1(ii INTEGER PRIMARY KEY, x);
|
||||
CREATE VIRTUAL TABLE ft USING fts5(x,
|
||||
content=x1, content_rowid=ii, locale=1, detail=%DETAIL%, columnsize=0
|
||||
);
|
||||
|
||||
CREATE VIRTUAL TABLE ft2 USING fts5(
|
||||
x, locale=1, detail=%DETAIL%, columnsize=0
|
||||
);
|
||||
}
|
||||
|
||||
foreach {tn v} {
|
||||
1 X'001152'
|
||||
2 X'0011223344'
|
||||
3 X'00E0B2EB68656c6c6f'
|
||||
4 X'00E0B2EB0068656c6c6f'
|
||||
} {
|
||||
do_execsql_test 10.2.$tn.0 { INSERT INTO ft(ft) VALUES('delete-all') }
|
||||
do_execsql_test 10.2.$tn.1 { DELETE FROM x1; }
|
||||
do_execsql_test 10.2.$tn.2 " INSERT INTO x1 VALUES(NULL, $v) "
|
||||
|
||||
do_catchsql_test 10.2.$tn.3 {
|
||||
INSERT INTO ft(ft) VALUES('rebuild');
|
||||
} {0 {}}
|
||||
|
||||
do_catchsql_test 10.2.$tn.4 "
|
||||
SELECT * FROM ft( test_setsubtype($v, 76) );
|
||||
" {1 {fts5: syntax error near ""}}
|
||||
|
||||
do_execsql_test 10.2.$tn.5 {
|
||||
INSERT INTO ft(rowid, x) VALUES(1, 'hello world');
|
||||
}
|
||||
|
||||
if {"%DETAIL%"=="full"} {
|
||||
do_execsql_test 10.2.$tn.6 {
|
||||
SELECT fts5_test_poslist(ft) FROM ft('world');
|
||||
} {0.0.1}
|
||||
|
||||
do_execsql_test 10.2.$tn.7.1 {
|
||||
SELECT fts5_test_columnsize(ft) FROM ft('world');
|
||||
} {1}
|
||||
|
||||
do_execsql_test 10.2.$tn.7.2 {
|
||||
SELECT fts5_test_columnlocale(ft) FROM ft('world');
|
||||
} {{{}}}
|
||||
}
|
||||
|
||||
do_catchsql_test 10.2.$tn.8 {
|
||||
SELECT count(*) FROM ft('hello')
|
||||
} {0 1}
|
||||
|
||||
do_catchsql_test 10.2.$tn.9 {
|
||||
PRAGMA integrity_check;
|
||||
} {0 ok}
|
||||
|
||||
do_execsql_test 10.2.$tn.10 {
|
||||
DELETE FROM x1;
|
||||
INSERT INTO x1(ii, x) VALUES(1, 'hello world');
|
||||
}
|
||||
|
||||
do_catchsql_test 10.2.$tn.11 "
|
||||
INSERT INTO ft(ft, rowid, x) VALUES('delete', 1, test_setsubtype($v,76) )
|
||||
" {0 {}}
|
||||
|
||||
do_catchsql_test 10.2.$tn.12 "
|
||||
INSERT INTO ft(rowid, x) VALUES(2, test_setsubtype($v,76) )
|
||||
" {0 {}}
|
||||
|
||||
do_execsql_test 10.2.$tn.13 {
|
||||
INSERT INTO ft2(rowid, x) VALUES(1, 'hello world');
|
||||
}
|
||||
do_execsql_test 10.2.$tn.14 "UPDATE ft2_content SET c0=$v"
|
||||
|
||||
do_catchsql_test 10.2.$tn.15 {
|
||||
PRAGMA integrity_check;
|
||||
} {0 {{malformed inverted index for FTS5 table main.ft2}}}
|
||||
|
||||
do_execsql_test 10.2.$tn.16 {
|
||||
DELETE FROM ft2_content;
|
||||
INSERT INTO ft2(ft2) VALUES('rebuild');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
reset_db
|
||||
sqlite3_fts5_create_tokenizer -v2 db tcl tcl_create
|
||||
fts5_aux_test_functions db
|
||||
do_execsql_test 11.0 {
|
||||
CREATE VIRTUAL TABLE x1 USING fts5(abc, locale=1);
|
||||
INSERT INTO x1(rowid, abc) VALUES(123, fts5_locale('en_US', 'one two three'));
|
||||
}
|
||||
|
||||
do_catchsql_test 11.1 {
|
||||
SELECT fts5_columnlocale(x1, -1) FROM x1('two');
|
||||
} {1 SQLITE_RANGE}
|
||||
do_catchsql_test 11.2 {
|
||||
SELECT fts5_columnlocale(x1, 1) FROM x1('two');
|
||||
} {1 SQLITE_RANGE}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
reset_db
|
||||
do_test 12.0 {
|
||||
list [catch {
|
||||
sqlite3_fts5_create_tokenizer -v2 -version 3 db tcl tcl_create
|
||||
} msg] $msg
|
||||
} {1 {error in fts5_api.xCreateTokenizer_v2()}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Tests for auxiliary function fts5_get_locale().
|
||||
#
|
||||
reset_db
|
||||
|
||||
# Check that if the table does not support locale=1, fts5_get_locale()
|
||||
# always returns NULL.
|
||||
do_execsql_test 13.1.0 {
|
||||
CREATE VIRTUAL TABLE nolocale USING fts5(a, b);
|
||||
INSERT INTO nolocale VALUES('one two three', 'four five six');
|
||||
INSERT INTO nolocale VALUES('three two one', 'seven eight nine');
|
||||
}
|
||||
do_execsql_test 13.1.1 {
|
||||
SELECT fts5_get_locale(nolocale, 0) IS NULL FROM nolocale;
|
||||
} {1 1}
|
||||
do_execsql_test 13.1.2 {
|
||||
SELECT fts5_get_locale(nolocale, 1) IS NULL FROM nolocale('one + two');
|
||||
} {1}
|
||||
do_execsql_test 13.1.3 {
|
||||
SELECT fts5_get_locale(nolocale, 0) IS NULL FROM nolocale('one AND two');
|
||||
} {1 1}
|
||||
do_execsql_test 13.1.4 {
|
||||
SELECT
|
||||
fts5_get_locale(nolocale, 1) IS NULL
|
||||
FROM nolocale('three AND two') ORDER BY rank
|
||||
} {1 1}
|
||||
do_catchsql_test 13.1.5 {
|
||||
SELECT fts5_get_locale(nolocale, 2) IS NULL FROM nolocale('three AND two');
|
||||
} {1 {column index out of range}}
|
||||
do_catchsql_test 13.1.6 {
|
||||
SELECT fts5_get_locale(nolocale, -1) IS NULL FROM nolocale('three AND two');
|
||||
} {1 {column index out of range}}
|
||||
do_catchsql_test 13.1.7 {
|
||||
SELECT fts5_get_locale(nolocale) IS NULL FROM nolocale('three AND two');
|
||||
} {1 {wrong number of arguments to function fts5_get_locale()}}
|
||||
do_catchsql_test 13.1.8 {
|
||||
SELECT fts5_get_locale(nolocale, 0, 0) IS NULL FROM nolocale('three AND two');
|
||||
} {1 {wrong number of arguments to function fts5_get_locale()}}
|
||||
do_catchsql_test 13.1.9 {
|
||||
SELECT fts5_get_locale(nolocale, 'text') FROM nolocale('three AND two');
|
||||
} {1 {non-integer argument passed to function fts5_get_locale()}}
|
||||
|
||||
|
||||
# Check that if the table does support locale=1, fts5_get_locale()
|
||||
# returns the locale of the identified row/column.
|
||||
do_execsql_test 13.2.0 {
|
||||
CREATE VIRTUAL TABLE ft USING fts5(a, b, locale=1);
|
||||
INSERT INTO ft VALUES(
|
||||
fts5_locale('th_TH', 'one two three'), 'four five six seven'
|
||||
);
|
||||
INSERT INTO ft VALUES(
|
||||
'three two one', fts5_locale('en_AU', 'seven eight nine')
|
||||
);
|
||||
}
|
||||
|
||||
do_execsql_test 13.2.1 {
|
||||
SELECT quote(fts5_get_locale(ft, 0)), quote(fts5_get_locale(ft, 1)) FROM ft
|
||||
} { 'th_TH' NULL NULL 'en_AU' }
|
||||
do_execsql_test 13.2.2 {
|
||||
SELECT
|
||||
quote(fts5_get_locale(ft, 0)), quote(fts5_get_locale(ft, 1))
|
||||
FROM ft('one AND three')
|
||||
} { 'th_TH' NULL NULL 'en_AU' }
|
||||
do_execsql_test 13.2.3 {
|
||||
SELECT
|
||||
quote(fts5_get_locale(ft, 0)), quote(fts5_get_locale(ft, 1))
|
||||
FROM ft('one AND three') ORDER BY rank
|
||||
} { NULL 'en_AU' 'th_TH' NULL }
|
||||
do_execsql_test 13.2.4 {
|
||||
SELECT
|
||||
quote(fts5_get_locale(ft, 0)), quote(fts5_get_locale(ft, 1))
|
||||
FROM ft('one AND three') ORDER BY rowid
|
||||
} { 'th_TH' NULL NULL 'en_AU' }
|
||||
|
||||
do_execsql_test 13.2.5 {
|
||||
SELECT
|
||||
quote(fts5_get_locale(ft, '0')), quote(fts5_get_locale(ft, 1))
|
||||
FROM ft('one AND three') ORDER BY rowid
|
||||
} { 'th_TH' NULL NULL 'en_AU' }
|
||||
|
||||
do_catchsql_test 13.2.6 {
|
||||
SELECT
|
||||
quote(fts5_get_locale(ft, '0.0')), quote(fts5_get_locale(ft, 1))
|
||||
FROM ft('one AND three') ORDER BY rowid
|
||||
} {1 {non-integer argument passed to function fts5_get_locale()}}
|
||||
do_catchsql_test 13.2.7 {
|
||||
SELECT
|
||||
quote(fts5_get_locale(ft, 0.0)), quote(fts5_get_locale(ft, 1))
|
||||
FROM ft('one AND three') ORDER BY rowid
|
||||
} {1 {non-integer argument passed to function fts5_get_locale()}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Check that UPDATE statements that may affect more than one row work.
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 14.1 {
|
||||
CREATE VIRTUAL TABLE ft USING fts5(a, b, locale=1);
|
||||
}
|
||||
|
||||
do_execsql_test 14.2 {
|
||||
INSERT INTO ft VALUES('hello', 'world');
|
||||
}
|
||||
|
||||
do_execsql_test 14.3 {
|
||||
UPDATE ft SET b = fts5_locale('en_AU', 'world');
|
||||
}
|
||||
|
||||
do_execsql_test 14.4 {
|
||||
INSERT INTO ft VALUES(X'abcd', X'1234');
|
||||
} {}
|
||||
|
||||
do_execsql_test 14.5 {
|
||||
SELECT quote(a), quote(b) FROM ft
|
||||
} {'hello' 'world' X'ABCD' X'1234'}
|
||||
|
||||
do_execsql_test 14.6 {
|
||||
DELETE FROM ft;
|
||||
INSERT INTO ft VALUES(NULL, 'null');
|
||||
INSERT INTO ft VALUES(123, 'int');
|
||||
INSERT INTO ft VALUES(345.0, 'real');
|
||||
INSERT INTO ft VALUES('abc', 'text');
|
||||
INSERT INTO ft VALUES(fts5_locale('abc', 'def'), 'text');
|
||||
|
||||
SELECT a, typeof(a), b FROM ft
|
||||
} {
|
||||
{} null null
|
||||
123 integer int
|
||||
345.0 real real
|
||||
abc text text
|
||||
def text text
|
||||
}
|
||||
|
||||
do_execsql_test 14.7 {
|
||||
SELECT quote(c0), typeof(c0) FROM ft_content
|
||||
} {
|
||||
NULL null
|
||||
123 integer
|
||||
345.0 real
|
||||
'abc' text
|
||||
'def' text
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Check that inserting UNINDEXED columns between indexed columns of a
|
||||
# locale=1 table does not cause a problem.
|
||||
#
|
||||
reset_db
|
||||
sqlite3_fts5_create_tokenizer -v2 db tcl tcl_create
|
||||
fts5_aux_test_functions db
|
||||
|
||||
do_execsql_test 15.1 {
|
||||
CREATE VIRTUAL TABLE ft USING fts5(a, b UNINDEXED, c, locale=1, tokenize=tcl);
|
||||
}
|
||||
|
||||
do_execsql_test 15.2 {
|
||||
INSERT INTO ft VALUES('one', 'two', 'three');
|
||||
INSERT INTO ft VALUES('one', 'two', fts5_locale('loc', 'three'));
|
||||
}
|
||||
|
||||
do_execsql_test 15.3 {
|
||||
SELECT c2, l2 FROM ft_content
|
||||
} {three {} three loc}
|
||||
|
||||
do_execsql_test 15.4 {
|
||||
SELECT c, fts5_columnlocale(ft, 2) FROM ft
|
||||
} {three {} three loc}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -517,7 +517,7 @@ fts5_aux_test_functions db
|
||||
do_execsql_test 15.3 {
|
||||
SELECT fts5_test_all(t1) FROM t1 LIMIT 1;
|
||||
} {
|
||||
{columnsize {0 0} columntext {c d} columntotalsize {2 2} poslist {} tokenize {c d} rowcount 2}
|
||||
{columnsize {1 1} columntext {c d} columntotalsize {2 2} poslist {} tokenize {c d} rowcount 2}
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5merge
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
||||
+135
-5
@@ -35,21 +35,21 @@ do_catchsql_test 1.1.2 {
|
||||
|
||||
do_catchsql_test 1.2.1 {
|
||||
SELECT highlight(t1, 4, '<b>', '</b>') FROM t1('*id');
|
||||
} {0 {{}}}
|
||||
} {1 {no such cursor: 4}}
|
||||
|
||||
do_catchsql_test 1.2.2 {
|
||||
SELECT a FROM t1
|
||||
WHERE rank = (SELECT highlight(t1, 4, '<b>', '</b>') FROM t1('*id'));
|
||||
} {0 {}}
|
||||
} {1 {no such cursor: 6}}
|
||||
|
||||
do_catchsql_test 1.3.1 {
|
||||
SELECT highlight(t1, 4, '<b>', '</b>') FROM t1('*reads');
|
||||
} {1 {no such cursor: 2}}
|
||||
} {1 {no such cursor: 0}}
|
||||
|
||||
do_catchsql_test 1.3.2 {
|
||||
SELECT a FROM t1
|
||||
WHERE rank = (SELECT highlight(t1, 4, '<b>', '</b>') FROM t1('*reads'));
|
||||
} {1 {no such cursor: 2}}
|
||||
} {1 {no such cursor: 0}}
|
||||
|
||||
db close
|
||||
sqlite3 db test.db
|
||||
@@ -57,7 +57,12 @@ sqlite3 db test.db
|
||||
do_catchsql_test 1.3.3 {
|
||||
SELECT a FROM t1
|
||||
WHERE rank = (SELECT highlight(t1, 4, '<b>', '</b>') FROM t1('*reads'));
|
||||
} {1 {no such cursor: 1}}
|
||||
} {1 {no such cursor: 0}}
|
||||
|
||||
fts5_aux_test_functions db
|
||||
do_catchsql_test 1.3.4 {
|
||||
SELECT fts5_columntext(t1) FROM t1('*reads');
|
||||
} {1 {no such cursor: 0}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
@@ -535,5 +540,130 @@ do_execsql_test 19.0 {
|
||||
COMMIT;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test 20.0 {
|
||||
CREATE VIRTUAL TABLE x1 USING fts5(a);
|
||||
INSERT INTO x1(rowid, a) VALUES
|
||||
(1, 'a b c d'),
|
||||
(2, 'x b c d'),
|
||||
(3, 'x y z d'),
|
||||
(4, 'a y c x');
|
||||
}
|
||||
|
||||
do_execsql_test 20.1 {
|
||||
SELECT rowid FROM x1 WHERE x1 MATCH 'a' AND x1 MATCH 'b';
|
||||
} {1}
|
||||
|
||||
do_execsql_test 20.2 {
|
||||
SELECT rowid FROM x1 WHERE x1 MATCH 'a' AND x1 MATCH 'y';
|
||||
} {4}
|
||||
|
||||
do_execsql_test 20.3 {
|
||||
SELECT rowid FROM x1 WHERE x1 MATCH 'a' OR x1 MATCH 'y';
|
||||
} {1 4 3}
|
||||
|
||||
do_execsql_test 20.4 {
|
||||
SELECT rowid FROM x1 WHERE x1 MATCH 'a' OR (x1 MATCH 'y' AND x1 MATCH 'd');
|
||||
} {1 4 3}
|
||||
|
||||
do_execsql_test 20.5 {
|
||||
SELECT rowid FROM x1 WHERE x1 MATCH 'z' OR (x1 MATCH 'a' AND x1 MATCH 'd');
|
||||
} {3 1}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test 21.0 {
|
||||
CREATE TABLE t1(ii INTEGER, x TEXT, y TEXT);
|
||||
CREATE VIRTUAL TABLE xyz USING fts5(content_rowid=ii, content=t1, x, y);
|
||||
INSERT INTO t1 VALUES(1, 'one', 'i');
|
||||
INSERT INTO t1 VALUES(2, 'two', 'ii');
|
||||
INSERT INTO t1 VALUES(3, 'tree', 'iii');
|
||||
INSERT INTO xyz(xyz) VALUES('rebuild');
|
||||
}
|
||||
|
||||
do_execsql_test 21.1 {
|
||||
UPDATE xyz SET y='TWO' WHERE rowid=2;
|
||||
UPDATE t1 SET y='TWO' WHERE ii=2;
|
||||
}
|
||||
|
||||
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);
|
||||
DROP TABLE xyz_notashadow;
|
||||
}
|
||||
sqlite3_db_config db DEFENSIVE 0
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test 22.0 {
|
||||
SELECT fts5(NULL);
|
||||
} {{}}
|
||||
do_execsql_test 22.1 {
|
||||
SELECT count(*) FROM (
|
||||
SELECT fts5_source_id()
|
||||
)
|
||||
} {1}
|
||||
execsql_pp {
|
||||
SELECT fts5_source_id()
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test 23.0 {
|
||||
CREATE VIRTUAL TABLE x1 USING fts5(x);
|
||||
INSERT INTO x1 VALUES('one + two + three');
|
||||
INSERT INTO x1 VALUES('one + xyz + three');
|
||||
INSERT INTO x1 VALUES('xyz + two + xyz');
|
||||
}
|
||||
do_execsql_test 23.1 {
|
||||
SELECT rowid FROM x1('one + two + three');
|
||||
} {1}
|
||||
|
||||
do_execsql_test 23.2 {
|
||||
SELECT rowid FROM x1('^".." AND one');
|
||||
} {}
|
||||
|
||||
do_execsql_test 23.3 {
|
||||
SELECT rowid FROM x1('abc NEAR ".." NEAR def');
|
||||
} {}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test 24.0 {
|
||||
CREATE VIRTUAL TABLE t1 USING fts5(a, detail='none');
|
||||
INSERT INTO t1(a) VALUES('a');
|
||||
}
|
||||
|
||||
do_execsql_test 24.2 {
|
||||
SELECT rank FROM ( SELECT rank FROM t1('a NOT "" NOT def') ) ORDER BY 1;
|
||||
} {-1e-06}
|
||||
|
||||
do_execsql_test 24.3 {
|
||||
SELECT rank FROM ( SELECT rank FROM t1('a NOT � NOT def') ) ORDER BY 1;
|
||||
} {-1e-06}
|
||||
|
||||
do_execsql_test 24.4 {
|
||||
SELECT rank FROM ( SELECT rank FROM t1('a NOT "" NOT def') );
|
||||
} {-1e-06}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
fts5_aux_test_functions db
|
||||
|
||||
do_execsql_test 25.0 {
|
||||
CREATE VIRTUAL TABLE t1 USING fts5(a, detail='none', content='');
|
||||
INSERT INTO t1(a) VALUES('a b c');
|
||||
}
|
||||
|
||||
do_execsql_test 25.0 {
|
||||
SELECT fts5_test_poslist(t1) FROM t1('b') ORDER BY rank;
|
||||
} {{}}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5near
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5optimize
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5optimize2
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5optimize2
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5origintext
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
@@ -261,8 +261,8 @@ do_execsql_test 5.3 {
|
||||
reset_db
|
||||
sqlite3_fts5_register_origintext db
|
||||
do_execsql_test 6.0 {
|
||||
CREATE VIRTUAL TABLE ft USING fts5(
|
||||
x, y, tokenize='origintext unicode61', detail=%DETAIL%
|
||||
CREATE VIRTUAL TABLE ft USING fts5(
|
||||
x, y, tokenize='origintext unicode61', detail=%DETAIL%, tokendata=0
|
||||
);
|
||||
|
||||
INSERT INTO ft VALUES('One Two', 'Three two');
|
||||
@@ -291,6 +291,22 @@ do_execsql_test 6.3 {
|
||||
SELECT rowid, tokens(ft) FROM ft('Three*');
|
||||
} {1 {{}} 2 {{}}}
|
||||
|
||||
fts5_aux_test_functions db
|
||||
do_catchsql_test 6.4 {
|
||||
SELECT fts5_test_insttoken(ft, -1, 0) FROM ft('one');
|
||||
} {1 SQLITE_RANGE}
|
||||
|
||||
do_catchsql_test 6.5 {
|
||||
SELECT fts5_test_insttoken(ft, 1, 0) FROM ft('one');
|
||||
} {1 SQLITE_RANGE}
|
||||
|
||||
do_catchsql_test 6.6 {
|
||||
CREATE VIRTUAL TABLE ft2 USING fts5(x, tokendata=2);
|
||||
} {1 {malformed tokendata=... directive}}
|
||||
do_catchsql_test 6.7 {
|
||||
CREATE VIRTUAL TABLE ft2 USING fts5(x, content='', tokendata=11);
|
||||
} {1 {malformed tokendata=... directive}}
|
||||
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5origintext2
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5origintext3
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user