Compare commits
723 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c493177e10 | |||
| 3cd92ce875 | |||
| 963aa5bdbf | |||
| d3e44d4fa0 | |||
| 03e2f9da23 | |||
| 4dd457c3ce | |||
| 63725a467f | |||
| 30c605e8ae | |||
| ba96468b9b | |||
| 8a61fe879d | |||
| 360abdca9c | |||
| f15a16e00a | |||
| 5e3ef1e524 | |||
| b36434d0d6 | |||
| e4f445e587 | |||
| 40c674e54a | |||
| 46701fcccf | |||
| 613929c59f | |||
| 967a5e8b75 | |||
| 26787f3538 | |||
| 15e556f552 | |||
| 75b9706776 | |||
| 2c9a970eb8 | |||
| ecf0462e8f | |||
| f10e7bcd1e | |||
| 9f10d81707 | |||
| 82afe06bb4 | |||
| 3022685857 | |||
| 6d3751ebd4 | |||
| db109887e8 | |||
| 97056a2a21 | |||
| 53d352b5c2 | |||
| aebe9962ab | |||
| 23b10e9ff3 | |||
| 659bafd05d | |||
| 31c3599ed0 | |||
| 6c074e5dc4 | |||
| 97af1346f0 | |||
| b6859b6f2c | |||
| 802b042f6e | |||
| e85b2cac0f | |||
| 51dd67080a | |||
| 31615637f3 | |||
| 0d9f2a15f2 | |||
| 1c68deead7 | |||
| 589796cd89 | |||
| dbe48d3c8d | |||
| c2b446f16a | |||
| 6e5802fc74 | |||
| 9e639d2490 | |||
| c6281e4893 | |||
| 3cd34ab981 | |||
| d98689f4d3 | |||
| cf9f841c5e | |||
| 77586831ed | |||
| d256b56880 | |||
| 3cf467a3ec | |||
| 4170780a82 | |||
| f306ca5286 | |||
| c229f11817 | |||
| 14613b1b1d | |||
| c49bfdbbee | |||
| 4b99ec0b8c | |||
| 454a426e31 | |||
| 5c72a39cfb | |||
| de50617bcb | |||
| fdc17e0bc8 | |||
| 276d213b2a | |||
| 45b2669ad3 | |||
| 82f3052e61 | |||
| 8fbf400bb0 | |||
| f6ca35d88c | |||
| a033790303 | |||
| 32933278fd | |||
| efbf481541 | |||
| 824a5bfcf0 | |||
| 80cf9fa00b | |||
| e16b345243 | |||
| 0911f86abf | |||
| 49906e8e4b | |||
| 8bffd498ea | |||
| 000e39e9a8 | |||
| 8dacf71043 | |||
| 73dcf45a3d | |||
| 1392ff5533 | |||
| 00d6b7abfc | |||
| 4f8f1965f7 | |||
| 36279c256b | |||
| 9dcf3d08c9 | |||
| 0424f255ef | |||
| 8b62a82ae3 | |||
| b0c8b08874 | |||
| 50637ca5c5 | |||
| d8c37bbc54 | |||
| 44980e8169 | |||
| 5dcf5890ae | |||
| 7c727bb61b | |||
| e097db7210 | |||
| 2228567ad3 | |||
| fe54b7a1f4 | |||
| fb9e8e48fd | |||
| 0186ee1cd7 | |||
| dea434ea65 | |||
| bc7e41c03c | |||
| 77731d5ec0 | |||
| 079f840e47 | |||
| d37412b80c | |||
| f1c5830311 | |||
| 7ae051df2a | |||
| 299fe02393 | |||
| 7a16413a84 | |||
| 8bfb186728 | |||
| 4331e6bd1d | |||
| dfb5f32758 | |||
| c70631623c | |||
| 07a2e5d1ed | |||
| 1519675a1a | |||
| 02e81f72a0 | |||
| 726a047a47 | |||
| efafde5eb4 | |||
| 72543206e5 | |||
| c9bf7ed9ad | |||
| 83baa239e7 | |||
| f52ed5fd61 | |||
| c850c2be75 | |||
| 9489aefb83 | |||
| 255548562b | |||
| 8e7a16895c | |||
| a6b62a26d4 | |||
| 2e899ccaff | |||
| 631900291d | |||
| b80d01a182 | |||
| d0db5edf61 | |||
| 985b4bc157 | |||
| ae24e13bc7 | |||
| c69d537b93 | |||
| 467e20ad1d | |||
| e9763e4ed7 | |||
| 87cdd5926d | |||
| 17dca772e0 | |||
| 3640785453 | |||
| 2534bf4011 | |||
| c6a39debf9 | |||
| 815709dd00 | |||
| 6cd83aecb9 | |||
| 8291cd78f2 | |||
| 0f4de9bf9d | |||
| 50c4420030 | |||
| 1a1fe1d1da | |||
| e52cdadea7 | |||
| e432f2a316 | |||
| f462046cd1 | |||
| 0887b70286 | |||
| ada3470075 | |||
| e024421624 | |||
| d0c6c6586e | |||
| 1425bae1ab | |||
| 7edb0c3920 | |||
| c957673bf7 | |||
| bfa7218982 | |||
| 4a25b740f2 | |||
| ec50c5a2a4 | |||
| b6953280e7 | |||
| 3202b11f66 | |||
| c5dd908c89 | |||
| 65d0312c96 | |||
| 3ba9adc5c1 | |||
| c738052394 | |||
| d1047faad6 | |||
| 874b5e9fbb | |||
| 73d9eb1bb3 | |||
| 4ea86ac0e3 | |||
| 0609cf85fd | |||
| 290caec8e3 | |||
| 942c958769 | |||
| f1747f93e0 | |||
| 43afab28a0 | |||
| 14bc98d8e2 | |||
| 4b5e8c926a | |||
| 27661f24cd | |||
| c1f914dbc9 | |||
| 35ac4c8685 | |||
| b1cbae8bd6 | |||
| c1242d60d9 | |||
| ad460db7eb | |||
| af8af121ab | |||
| 45d19952c3 | |||
| 6962f3d814 | |||
| fd11e5c082 | |||
| ece1729958 | |||
| 4a83311370 | |||
| 311990d74e | |||
| 4717d573e4 | |||
| e53393250a | |||
| 4a6896379f | |||
| fbbe262820 | |||
| 885f546f97 | |||
| a5dbae3781 | |||
| cee8b04d33 | |||
| f19d7b4de1 | |||
| 15e388d910 | |||
| 85900c04b0 | |||
| 8b53358f8f | |||
| 1e03bd8a89 | |||
| 1c1b3a0f2d | |||
| 1388a71690 | |||
| 7a3d03b1fd | |||
| 4bf468e69d | |||
| 8272128211 | |||
| 8f1bdc0f73 | |||
| ded37f337b | |||
| 8d6e3f513c | |||
| 04364cb3cc | |||
| db258d8ff7 | |||
| 1426d2a264 | |||
| 52c87ac084 | |||
| 3835cf6ea1 | |||
| a683b055fb | |||
| e0b6ee5185 | |||
| 66985fb8ff | |||
| f7fcf7f910 | |||
| 95f6df5b8d | |||
| 71d6456f59 | |||
| 6b19c72f26 | |||
| 4112a63b8f | |||
| 8b68902128 | |||
| e0190a6984 | |||
| 9591d3fe93 | |||
| 142c5de4dd | |||
| ccfb50d55e | |||
| be2a40d489 | |||
| f2d422c528 | |||
| 166f4eb5cf | |||
| 019de3d553 | |||
| 543ee479eb | |||
| 2dcd4fad6b | |||
| b097ef29d1 | |||
| 47bc07d425 | |||
| 0c34eab477 | |||
| 2fb488d10a | |||
| 32dd04b41e | |||
| bd1a5932d9 | |||
| 276172e4a3 | |||
| bba1953426 | |||
| 9ee02515c4 | |||
| 35d302ccb1 | |||
| 6e53f67c63 | |||
| e57527c14f | |||
| e85e33d39c | |||
| c29bc733be | |||
| 54f96dc50e | |||
| 94ad4abc65 | |||
| 4f5ae3fc4e | |||
| a42db7ff40 | |||
| fd360c3943 | |||
| 29d1d91502 | |||
| 9f53d0c817 | |||
| 8703642803 | |||
| 92d252e06d | |||
| 4597870108 | |||
| 1a4b2117f1 | |||
| ef636cc3cd | |||
| c40329c9bf | |||
| 0448e00aaf | |||
| eed134c4d3 | |||
| 76412af157 | |||
| 33c120f9b7 | |||
| 4b491d8565 | |||
| c9ac238b92 | |||
| bfdeb1f6d5 | |||
| ed7fe45c7c | |||
| 3e1f302dbe | |||
| 224e356081 | |||
| d004268b27 | |||
| fd66549cb6 | |||
| a13a645cdf | |||
| 9bc351b3c7 | |||
| d6d9c54bb2 | |||
| c5b9da34f2 | |||
| 03e306b3a1 | |||
| 5c208f36a4 | |||
| 2aac896611 | |||
| 25e042c0b0 | |||
| 187c115a69 | |||
| fed5234fb3 | |||
| e8233f14bd | |||
| dc7b94e63f | |||
| 3ff6aa6e39 | |||
| bfb7f77a8c | |||
| 60ad526639 | |||
| 0bce1d6c9f | |||
| cf04895832 | |||
| 966a158831 | |||
| f12e5d1a0f | |||
| 3e4ccc3208 | |||
| e2a3c7232b | |||
| 19a6315ccf | |||
| 58cb5644bc | |||
| 04a556acf2 | |||
| 0dd542f79e | |||
| f2d56bc578 | |||
| b56f179e45 | |||
| 8ff67df7ac | |||
| 7398e279a7 | |||
| de7e2b178d | |||
| 5c945264b0 | |||
| dcaf03fccf | |||
| 7a13effa20 | |||
| 0cf7131555 | |||
| ed271dc7ea | |||
| 38fdb2a857 | |||
| f0a9af433a | |||
| 9edb535bdd | |||
| a8c68e551d | |||
| d204a83c9b | |||
| 2f70d5838a | |||
| 9bf5bea607 | |||
| 032bcf72fb | |||
| d02833bf05 | |||
| 914e32f24a | |||
| 2722e2e822 | |||
| d4a65cfc51 | |||
| 9566982328 | |||
| a34fbd1b9b | |||
| 18c9e2638e | |||
| 457d9384a2 | |||
| b81e11b25b | |||
| c73b85c156 | |||
| d3aaf963a9 | |||
| 5608fb36ec | |||
| 3cd93a0b67 | |||
| 5ef61df185 | |||
| fbd9de1830 | |||
| fefc7b1bf7 | |||
| ea206ad17b | |||
| 12599d566b | |||
| 5cad859f61 | |||
| 0df847cc77 | |||
| de8aa17eb5 | |||
| 9c8235b1bd | |||
| bbc6e5c9b7 | |||
| f6fdf32553 | |||
| 70d390134c | |||
| 18689b8fb2 | |||
| 50faa8d17e | |||
| f6c7cc606e | |||
| d8f6222bee | |||
| 4b24cb2a3a | |||
| d676227f2c | |||
| 178ce6287b | |||
| 1adf87592f | |||
| e69b4d757e | |||
| 48c8447574 | |||
| 2eb9605e81 | |||
| ece4bf60ff | |||
| aa85c8c854 | |||
| 75ed9f819f | |||
| f121ffbde3 | |||
| 009601d534 | |||
| 59c80e0533 | |||
| c096d6add6 | |||
| 17e7e16b3b | |||
| 98be43ed73 | |||
| ea13658566 | |||
| 752df4c49b | |||
| c87d7bede0 | |||
| f154cef8f2 | |||
| 3b56698541 | |||
| 104ab7e81f | |||
| 26c080a04b | |||
| 31c160ab8f | |||
| 1b37bc0e66 | |||
| 92e9fa6fe8 | |||
| 7b32f84ebf | |||
| 0cd2ffffb7 | |||
| be46f935dc | |||
| 074cad3026 | |||
| e4d4d73397 | |||
| d29a369fe2 | |||
| 45c2b1804f | |||
| a864ac1c5a | |||
| f1b88ec953 | |||
| e9b04e524b | |||
| 5c792a484d | |||
| 497f84885b | |||
| 4ddeccfc15 | |||
| 23cfa0138e | |||
| 4441897daa | |||
| a700db9387 | |||
| a4093dcc06 | |||
| 62801081f3 | |||
| 3b306aac6e | |||
| 6f95d95015 | |||
| d42855e404 | |||
| ee9950d09b | |||
| 6e6820148a | |||
| c7882b975e | |||
| c00d89d599 | |||
| 88e6a942ad | |||
| b4afb2fb2f | |||
| 4c3139d7ee | |||
| 00e863c48e | |||
| d9345f3312 | |||
| 197fa124d7 | |||
| 968dc2489a | |||
| 347e4833f9 | |||
| 19d87fa848 | |||
| 67a3914e65 | |||
| 8acaa6d039 | |||
| 61cf538d27 | |||
| 9243eb4ab8 | |||
| 7e3e031182 | |||
| 598d0d1498 | |||
| 6da414ef41 | |||
| ebb3e03b6d | |||
| 2e29bcd542 | |||
| 199925a352 | |||
| 4c2f7e57a2 | |||
| e957bd1ce7 | |||
| edf7efc61c | |||
| 19c4fa92dd | |||
| 2ad29f3611 | |||
| d2ac1c5b7c | |||
| 2139c35da0 | |||
| 6d443b0d74 | |||
| e69d98df22 | |||
| 3205eab2f2 | |||
| 63346a4bca | |||
| 2c8d251956 | |||
| 710d00aa6f | |||
| 1934310ebd | |||
| bf19927688 | |||
| c6a6f1507c | |||
| bc60d7bee9 | |||
| 4bf24c8830 | |||
| 88ef6be57d | |||
| 2fd38836dc | |||
| 21d90a1607 | |||
| f3d279595e | |||
| 7860052209 | |||
| 266685c7e7 | |||
| 05e279fa46 | |||
| eb83747441 | |||
| 88349483ef | |||
| a9b00b0fb7 | |||
| 97c709b5be | |||
| c6cdee8303 | |||
| 18d21497b2 | |||
| e595a83856 | |||
| 13f03afd17 | |||
| 090b8649be | |||
| f0e7f4c1f2 | |||
| dea749acc3 | |||
| 32b4979559 | |||
| afb8798580 | |||
| bce0d04c98 | |||
| 03cfce20c9 | |||
| d27f6d7881 | |||
| f5187de2fb | |||
| 583770af28 | |||
| 3764f632b8 | |||
| 6d3f22cdc1 | |||
| 98eb4ad6ee | |||
| ec04c41be6 | |||
| 7be78606ff | |||
| 07cdceed8e | |||
| cf758d23cd | |||
| 343fe033c0 | |||
| 0e07bc36d9 | |||
| c6cfc8e3ea | |||
| fe9baec645 | |||
| 7a55fe3a95 | |||
| 07a1e3eb91 | |||
| 1e563f4817 | |||
| 2d73547cdb | |||
| 26eccee741 | |||
| 4f0529e33e | |||
| 9bcb0a510f | |||
| 7d7e82c9b1 | |||
| 55865c47a7 | |||
| fe5f721de6 | |||
| 067f809402 | |||
| 49e7cfc9a3 | |||
| 5be33f7b3f | |||
| 691e7eceb6 | |||
| e034c18591 | |||
| ca698abb5a | |||
| 47f4bb3f2d | |||
| d3335a7970 | |||
| ffddcb725f | |||
| 02834a9a3d | |||
| 4cbc413a25 | |||
| 13e735a5b5 | |||
| e32a50a025 | |||
| 7097105bea | |||
| a94ca1d37c | |||
| 8b3ba8eb5a | |||
| 173c113c5f | |||
| 4824b9c664 | |||
| 51d5aa0915 | |||
| 54a282830f | |||
| bc4df6079c | |||
| fe5602ffd9 | |||
| e40c2699b7 | |||
| 19afe7ffd1 | |||
| 42516b2ef9 | |||
| 8625bd64c2 | |||
| 4b4b5ff1d8 | |||
| 1a466a386e | |||
| de4fc707b5 | |||
| dfa64c5542 | |||
| 5f05a7c3c7 | |||
| cd9b951e6b | |||
| ee0b5e9bed | |||
| 99438c843c | |||
| 5a6dc86df2 | |||
| 36cb4d03ac | |||
| 1682fedaa0 | |||
| e550d98bbf | |||
| 3a92a5c4b3 | |||
| 2005250d7f | |||
| 5be20f3927 | |||
| f6e86e38ac | |||
| 6bb44daae4 | |||
| 9905e7e22b | |||
| 6d05f9af81 | |||
| 346f1e0ed9 | |||
| b27a30c620 | |||
| 0064c43a88 | |||
| 5598a3f8da | |||
| 954c02b414 | |||
| 6c45a5d60e | |||
| b909f23581 | |||
| e2a4ec3921 | |||
| e34646b5dc | |||
| 68b0e8db05 | |||
| c9f16f6562 | |||
| ac1f151796 | |||
| 66fee051a6 | |||
| bad9725a29 | |||
| 1fa0ef3ae8 | |||
| 26068b7901 | |||
| ae50e509f5 | |||
| 784623d599 | |||
| 59b4f75e0f | |||
| 5ea8d1ed5a | |||
| 1c27c39396 | |||
| ccb1211b54 | |||
| 26d5652b56 | |||
| 8ee82c6202 | |||
| dac467890e | |||
| bf441f7575 | |||
| 56d46d9d38 | |||
| 65d83fa221 | |||
| a2d88f6a03 | |||
| d045b42854 | |||
| cbb182fef2 | |||
| 70188a66e0 | |||
| a2a875e3b8 | |||
| 895ad5f4af | |||
| 5460d5da8e | |||
| 043943c261 | |||
| 35660cb5a6 | |||
| d2cbc22dd5 | |||
| 4ccc5de98f | |||
| 4de88eb13e | |||
| f84060f2f8 | |||
| 14e4d9ad30 | |||
| 957209e7ac | |||
| 7ad582ad5a | |||
| a1bc2ad6ce | |||
| aa7c9050fa | |||
| 7db8d195c3 | |||
| 8ce6d66986 | |||
| 9bcfb2b694 | |||
| a734793b2f | |||
| 7796ee07c4 | |||
| ed959dba7d | |||
| ae5ef1e80f | |||
| 4f237f8def | |||
| ae07b98a3c | |||
| 72ef506925 | |||
| 542d1c923e | |||
| e3565d9424 | |||
| 936fa83402 | |||
| 8cfc6a7aed | |||
| 2ba8b9566f | |||
| b79997a7c0 | |||
| 3db85bf0d3 | |||
| 79d3714f24 | |||
| 4cd85bda4a | |||
| 30b20563e4 | |||
| b3cff449f9 | |||
| caf8c28420 | |||
| ce236e031e | |||
| e74c738e55 | |||
| 8c97ad8834 | |||
| 4dadb531b0 | |||
| e615b73040 | |||
| 6d288e2408 | |||
| 18f6445aea | |||
| 8d69bd2a20 | |||
| a7d3d40e06 | |||
| 519fc4f8c2 | |||
| 264c691863 | |||
| 284e70b3a1 | |||
| deb5ad6297 | |||
| 98772d6e75 | |||
| 2c264ad060 | |||
| 8a6ddc551e | |||
| 5d6c11b766 | |||
| 55fca9585c | |||
| fdcd599992 | |||
| 54e1dff24b | |||
| 591123eea9 | |||
| 198b72cfe8 | |||
| 3dbddc5507 | |||
| f896e2bd5b | |||
| 653eb471c3 | |||
| 96501c89d5 | |||
| c8284c766a | |||
| fa8a7f88ff | |||
| 76e48f4d66 | |||
| 4f72770b34 | |||
| 6ac6bedc80 | |||
| 8f90c66407 | |||
| 49f293ba58 | |||
| 1e38a9cc1a | |||
| 894bd83f52 | |||
| f4ab0ad8ee | |||
| 0d7ede8d1c | |||
| 31465666ff | |||
| e6c2759acb | |||
| 744d986d17 | |||
| 7968c38540 | |||
| ad8e79ce53 | |||
| 5bae363b99 | |||
| b124098e51 | |||
| 59ac8f4c7f | |||
| d54bae947d | |||
| a3d219a794 | |||
| 84f952ba8f | |||
| ec5e611935 | |||
| 857bcb6035 | |||
| 8bdece9034 | |||
| f9c73ef7c5 | |||
| 003d304c9b | |||
| 25557128fe | |||
| abf470d7a3 | |||
| 816f4b9cc1 | |||
| a505d89bbe | |||
| 6d8ec2aed4 | |||
| 7abd86c4b8 | |||
| 49de624e41 | |||
| a1e6fbebdf | |||
| b08f1d5d97 | |||
| 83afc4c2b2 | |||
| 20755cef7d | |||
| d1068f8b73 | |||
| 2a1a3d6af5 | |||
| ead26840b8 | |||
| 883f35db10 | |||
| 14101a3c28 | |||
| a60142fef5 | |||
| fa2770fec5 | |||
| 92860ade7a | |||
| c7b822082e | |||
| 49bb81844c | |||
| 114e0543af | |||
| f400f41fde | |||
| 10d1b0c5db | |||
| 59ded3ff14 | |||
| d5503d383b | |||
| d0be4a781e | |||
| d2a88e961a | |||
| ea63f48ec8 | |||
| 51e8287dde | |||
| 2e7c9ae473 | |||
| aca993423f | |||
| c4c951adbe | |||
| 0831b3a989 | |||
| 7d56669bc4 | |||
| 595a2532f3 | |||
| 5ff68db4f1 | |||
| 0be8482f96 | |||
| 3cb46bd929 | |||
| 05c5e76c94 | |||
| 1865e85e0b | |||
| c139ad34de | |||
| 8d2f6c13e3 | |||
| 3c6db6831d | |||
| 587256a634 | |||
| 474cdc54ef | |||
| 9ce9ee6819 | |||
| 69f2da0eed | |||
| 42aa26a607 | |||
| 02616ccf29 | |||
| 66cb9d0ec7 | |||
| 9a1b212f50 | |||
| c2da952f5d | |||
| 76bfcd13be | |||
| cda0d6fd74 | |||
| b1e1d9f3d4 | |||
| 1bc8f07f20 | |||
| bb12cdc11b | |||
| 220434abdd | |||
| 2eff8f2252 | |||
| ae49b334c2 | |||
| 2615879760 | |||
| 13aea08683 | |||
| aaef970446 | |||
| 2d0b1ae73b | |||
| cf9d95002e | |||
| 4e0208fd8e | |||
| bbd6ba04b9 | |||
| 4b5adfc6ba | |||
| dd5b962a15 | |||
| 63c4d89ae1 | |||
| e6b41c4641 | |||
| f4321fff36 | |||
| 6219872845 | |||
| acfd1e2ba8 | |||
| e25a267e81 |
+85
@@ -1,6 +1,91 @@
|
||||
License Information
|
||||
===================
|
||||
|
||||
SQLite Is Public Domain
|
||||
-----------------------
|
||||
|
||||
The SQLite source code, including all of the files in the directories
|
||||
listed in the bullets below are
|
||||
[Public Domain](https://sqlite.org/copyright.html).
|
||||
The authors have submitted written affidavits releasing their work to
|
||||
the public for any use. Every byte of the public-domain code can be
|
||||
traced back to the original authors. The files of this repository
|
||||
that are public domain include the following:
|
||||
|
||||
* All of the primary SQLite source code files found in the
|
||||
[src/ directory](https://sqlite.org/src/tree/src?type=tree&expand)
|
||||
* All of the test cases and testing code in the
|
||||
[test/ directory](https://sqlite.org/src/tree/test?type=tree&expand)
|
||||
* All of the SQLite extension source code and test cases in the
|
||||
[ext/ directory](https://sqlite.org/src/tree/ext?type=tree&expand)
|
||||
* All code that ends up in the "sqlite3.c" and "sqlite3.h" build products
|
||||
that actually implement the SQLite RDBMS.
|
||||
* All of the code used to compile the
|
||||
[command-line interface](https://sqlite.org/cli.html)
|
||||
* All of the code used to build various utility programs such as
|
||||
"sqldiff", "sqlite3_rsync", and "sqlite3_analyzer".
|
||||
|
||||
|
||||
The public domain source files usually contain a header comment
|
||||
similar to the following to make it clear that the software is
|
||||
public domain.
|
||||
|
||||
> ~~~
|
||||
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.
|
||||
~~~
|
||||
|
||||
Almost every file you find in this source repository will be
|
||||
public domain. But there are a small number of exceptions:
|
||||
|
||||
Non-Public-Domain Code Included With This Source Repository AS A Convenience
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
This repository contains a (relatively) small amount of non-public-domain
|
||||
code used to help implement the configuration and build logic. In other
|
||||
words, there are some non-public-domain files used to implement:
|
||||
|
||||
> ~~~
|
||||
./configure && make
|
||||
~~~
|
||||
|
||||
In all cases, the non-public-domain files included with this
|
||||
repository have generous BSD-style licenses. So anyone is free to
|
||||
use any of the code in this source repository for any purpose, though
|
||||
attribution may be required to reuse or republish the configure and
|
||||
build scripts. None of the non-public-domain code ever actually reaches
|
||||
the build products, such as "sqlite3.c", however, so no attribution is
|
||||
required to use SQLite itself. The non-public-domain code consists of
|
||||
scripts used to help compile SQLite. The non-public-domain code is
|
||||
technically not part of SQLite. The non-public-domain code is
|
||||
included in this repository as a convenience to developers, so that those
|
||||
who want to build SQLite do not need to go download a bunch of
|
||||
third-party build scripts in order to compile SQLite.
|
||||
|
||||
Non-public-domain code included in this respository includes:
|
||||
|
||||
* The ["autosetup"](http://msteveb.github.io/autosetup/) configuration
|
||||
system that is contained (mostly) the autosetup/ directory, but also
|
||||
includes the "./configure" script at the top-level of this archive.
|
||||
Autosetup has a separate BSD-style license. See the
|
||||
[autosetup/LICENSE](http://msteveb.github.io/autosetup/license/)
|
||||
for details.
|
||||
|
||||
* There are BSD-style licenses on some of the configuration
|
||||
software found in the legacy autoconf/ directory and its
|
||||
subdirectories.
|
||||
|
||||
The following unix shell command is can be run from the top-level
|
||||
of this source repository in order to remove all non-public-domain
|
||||
code:
|
||||
|
||||
> ~~~
|
||||
rm -rf configure autosetup autoconf
|
||||
~~~
|
||||
|
||||
If you unpack this source repository and then run the command above, what
|
||||
is left will be 100% public domain.
|
||||
|
||||
+257
-1614
File diff suppressed because it is too large
Load Diff
@@ -1,109 +0,0 @@
|
||||
#!/usr/make
|
||||
#
|
||||
# Makefile for SQLITE
|
||||
#
|
||||
# This is a template makefile for SQLite. Most people prefer to
|
||||
# use the autoconf generated "configure" script to generate the
|
||||
# makefile automatically. But that does not work for everybody
|
||||
# and in every situation. If you are having problems with the
|
||||
# "configure" script, you might want to try this makefile as an
|
||||
# alternative. Create a copy of this file, edit the parameters
|
||||
# below and type "make".
|
||||
#
|
||||
|
||||
#### The toplevel directory of the source tree. This is the directory
|
||||
# that contains this "Makefile.in" and the "configure.in" script.
|
||||
#
|
||||
TOP = ../sqlite
|
||||
|
||||
#### C Compiler and options for use in building executables that
|
||||
# will run on the platform that is doing the build.
|
||||
#
|
||||
BCC = gcc -g -O0
|
||||
#BCC = /opt/ancic/bin/c89 -0
|
||||
|
||||
#### If you want the SQLite library to be safe for use within a
|
||||
# multi-threaded program, then define the following macro
|
||||
# appropriately:
|
||||
#
|
||||
#THREADSAFE = -DTHREADSAFE=1
|
||||
THREADSAFE = -DTHREADSAFE=0
|
||||
|
||||
#### Specify any extra linker options needed to make the library
|
||||
# thread safe
|
||||
#
|
||||
THREADLIB = -lpthread -lm -ldl
|
||||
#THREADLIB =
|
||||
|
||||
#### Specify any extra libraries needed to access required functions.
|
||||
#
|
||||
#TLIBS = -lrt # fdatasync on Solaris 8
|
||||
TLIBS =
|
||||
|
||||
#### Leave SQLITE_DEBUG undefined for maximum speed. Use SQLITE_DEBUG=1
|
||||
# to check for memory leaks. Use SQLITE_DEBUG=2 to print a log of all
|
||||
# malloc()s and free()s in order to track down memory leaks.
|
||||
#
|
||||
# SQLite uses some expensive assert() statements in the inner loop.
|
||||
# You can make the library go almost twice as fast if you compile
|
||||
# with -DNDEBUG=1
|
||||
#
|
||||
OPTS += -DSQLITE_DEBUG=1
|
||||
OPTS += -DSQLITE_ENABLE_WHERETRACE
|
||||
OPTS += -DSQLITE_ENABLE_SELECTTRACE
|
||||
|
||||
#### The suffix to add to executable files. ".exe" for windows.
|
||||
# Nothing for unix.
|
||||
#
|
||||
#EXE = .exe
|
||||
EXE =
|
||||
|
||||
#### C Compile and options for use in building executables that
|
||||
# will run on the target platform. This is usually the same
|
||||
# as BCC, unless you are cross-compiling.
|
||||
#
|
||||
TCC = gcc -O0
|
||||
#TCC = gcc -g -O0 -Wall
|
||||
#TCC = gcc -g -O0 -Wall -fprofile-arcs -ftest-coverage
|
||||
#TCC = /opt/mingw/bin/i386-mingw32-gcc -O6
|
||||
#TCC = /opt/ansic/bin/c89 -O +z -Wl,-a,archive
|
||||
|
||||
#### Tools used to build a static library.
|
||||
#
|
||||
AR = ar cr
|
||||
#AR = /opt/mingw/bin/i386-mingw32-ar cr
|
||||
RANLIB = ranlib
|
||||
#RANLIB = /opt/mingw/bin/i386-mingw32-ranlib
|
||||
|
||||
MKSHLIB = gcc -shared
|
||||
SO = so
|
||||
SHPREFIX = lib
|
||||
# SO = dll
|
||||
# SHPREFIX =
|
||||
|
||||
#### Extra compiler options needed for programs that use the TCL library.
|
||||
#
|
||||
TCL_FLAGS = -I/home/drh/tcl/include/tcl8.6
|
||||
|
||||
#### Linker options needed to link against the TCL library.
|
||||
#
|
||||
#LIBTCL = -ltcl -lm -ldl
|
||||
LIBTCL = /home/drh/tcl/lib/libtcl8.6.a -lm -lpthread -ldl -lz
|
||||
|
||||
#### Additional objects for SQLite library when TCL support is enabled.
|
||||
#TCLOBJ =
|
||||
TCLOBJ = tclsqlite.o
|
||||
|
||||
#### Compiler options needed for programs that use the readline() library.
|
||||
#
|
||||
READLINE_FLAGS =
|
||||
#READLINE_FLAGS = -DHAVE_READLINE=1 -I/usr/include/readline
|
||||
|
||||
#### Linker options needed by programs using readline() must link against.
|
||||
#
|
||||
LIBREADLINE =
|
||||
#LIBREADLINE = -static -lreadline -ltermcap
|
||||
|
||||
# You should not have to change anything below this line
|
||||
###############################################################################
|
||||
include $(TOP)/main.mk
|
||||
@@ -0,0 +1,64 @@
|
||||
#!/usr/make
|
||||
all:
|
||||
#
|
||||
# Makefile for SQLITE
|
||||
#
|
||||
# This is a template makefile for SQLite. Most people prefer to
|
||||
# use the autoconf generated "configure" script to generate the
|
||||
# makefile automatically. But that does not work for everybody
|
||||
# and in every situation. If you are having problems with the
|
||||
# "configure" script, you might want to try this makefile as an
|
||||
# alternative. Create a copy of this file, edit the parameters
|
||||
# below and type "make".
|
||||
#
|
||||
# Maintenance note: because this is the template for Linux systems, it
|
||||
# is assumed that the platform has GNU make and this file takes
|
||||
# advantage of that.
|
||||
#
|
||||
####
|
||||
#
|
||||
# $(TOP) = The toplevel directory of the source tree. This is the
|
||||
# directory that contains "Makefile.in" and "auto.def".
|
||||
#
|
||||
TOP ?= $(realpath $(dir $(lastword $(MAKEFILE_LIST))))
|
||||
|
||||
#
|
||||
# $(CFLAGS) will be used when compiling the library and most
|
||||
# utilities. It must normally contain -fPIC on Linux systems,
|
||||
# but overriding CFLAGS is an easy way for users to inadvertently
|
||||
# remove -fPIC from their builds, so we generally expect to see
|
||||
# -fPIC in $(CFLAGS.core), which main.mk will integrate with
|
||||
# the CFLAGS where needed.
|
||||
#
|
||||
CFLAGS =
|
||||
CFLAGS.core = -fPIC
|
||||
|
||||
#
|
||||
# $(SHELL_OPT) contains CFLAGS for building the sqlite3 CLI shell.
|
||||
# See main.mk for other potentially-relevant vars which may need
|
||||
# tweaking, like $(LDFLAGS_READLINE).
|
||||
#
|
||||
SHELL_OPT += -DHAVE_READLINE=1
|
||||
SHELL_OPT += -DSQLITE_HAVE_ZLIB=1
|
||||
LDFLAGS.readline = -lreadline # may need -lcurses etc, depending on the system
|
||||
CFLAGS.readline = # needs -I... if readline.h is in an unusual place.
|
||||
LDFLAGS.zlib = -lz
|
||||
|
||||
#
|
||||
# Library's version number.
|
||||
#
|
||||
PACKAGE_VERSION ?= $(shell cat $(TOP)/VERSION 2>/dev/null)
|
||||
|
||||
# sqlite_cfg.h is typically created by the configure script. It's
|
||||
# commonly not needed but main.mk does not know that so we have to
|
||||
# create a dummy if we don't already have one.
|
||||
sqlite_cfg.h:
|
||||
touch $@
|
||||
distclean-.:
|
||||
rm -f sqlite_cfg.h
|
||||
|
||||
#
|
||||
# With the above in place, we can now import the rules make use of
|
||||
# it...
|
||||
#
|
||||
include $(TOP)/main.mk
|
||||
+59
-52
@@ -19,7 +19,9 @@ USE_AMALGAMATION = 1
|
||||
# <</mark>>
|
||||
|
||||
# Optionally set EXTRA_SRC to a list of C files to append to
|
||||
# the generated sqlite3.c.
|
||||
# the generated sqlite3.c. Any sqlite3 extensions added this
|
||||
# way may require manual editing, as described in
|
||||
# https://sqlite.org/forum/forumpost/903f721f3e7c0d25
|
||||
#
|
||||
!IFNDEF EXTRA_SRC
|
||||
EXTRA_SRC =
|
||||
@@ -982,10 +984,14 @@ TCLLIBS =
|
||||
!ENDIF
|
||||
|
||||
!IFNDEF LIBTCLSTUB
|
||||
!IF EXISTS("$(TCLLIBDIR)\tclstub$(TCLSUFFIX).lib")
|
||||
LIBTCLSTUB = tclstub$(TCLSUFFIX).lib
|
||||
!ELSE
|
||||
!IF EXISTS("$(TCLLIBDIR)\tclstub$(TCLVERSION)$(TCLSUFFIX).lib")
|
||||
LIBTCLSTUB = tclstub$(TCLVERSION)$(TCLSUFFIX).lib
|
||||
!ELSEIF EXISTS("$(TCLLIBDIR)\tclstub$(TCLSUFFIX).lib")
|
||||
LIBTCLSTUB = tclstub$(TCLSUFFIX).lib
|
||||
!ELSEIF EXISTS("$(TCLLIBDIR)\tclstub$(TCLVERSION).lib")
|
||||
LIBTCLSTUB = tclstub$(TCLVERSION).lib
|
||||
!ELSE
|
||||
LIBTCLSTUB = tclstub.lib
|
||||
!ENDIF
|
||||
!ENDIF
|
||||
|
||||
@@ -1059,6 +1065,18 @@ TCLSH_CMD = $(TCLDIR)\bin\tclsh.exe
|
||||
TCLSH_CMD = tclsh
|
||||
!ENDIF
|
||||
!ENDIF
|
||||
|
||||
# A light-weight TCLSH replacement that can be used for code generation
|
||||
# but which is not adequate for testing. This is "jimsh0" by default,
|
||||
# with source code in the repository. To force the whole build to use
|
||||
# the full, official tclsh, add WITHOUT_JIMSH=1 to the nmake command line.
|
||||
#
|
||||
!IFDEF WITHOUT_JIMSH
|
||||
JIM_TCLSH = $(TCLSH_CMD)
|
||||
!ENDIF
|
||||
!IFNDEF JIM_TCLSH
|
||||
JIM_TCLSH = jimsh0.exe
|
||||
!ENDIF
|
||||
# <</mark>>
|
||||
|
||||
# Compiler options needed for programs that use the readline() library.
|
||||
@@ -1089,15 +1107,6 @@ RCC = $(RCC) -DSQLITE_THREAD_OVERRIDE_LOCK=-1
|
||||
TLIBS =
|
||||
!ENDIF
|
||||
|
||||
# Flags controlling use of the in memory btree implementation
|
||||
#
|
||||
# SQLITE_TEMP_STORE is 0 to force temporary tables to be in a file, 1 to
|
||||
# default to file, 2 to default to memory, and 3 to force temporary
|
||||
# tables to always be in memory.
|
||||
#
|
||||
TCC = $(TCC) -DSQLITE_TEMP_STORE=1
|
||||
RCC = $(RCC) -DSQLITE_TEMP_STORE=1
|
||||
|
||||
# Enable/disable loadable extensions, and other optional features
|
||||
# based on configuration. (-DSQLITE_OMIT*, -DSQLITE_ENABLE*).
|
||||
# The same set of OMIT and ENABLE flags should be passed to the
|
||||
@@ -1573,7 +1582,6 @@ TESTSRC = \
|
||||
$(TOP)\src\test8.c \
|
||||
$(TOP)\src\test9.c \
|
||||
$(TOP)\src\test_autoext.c \
|
||||
$(TOP)\src\test_async.c \
|
||||
$(TOP)\src\test_backup.c \
|
||||
$(TOP)\src\test_bestindex.c \
|
||||
$(TOP)\src\test_blob.c \
|
||||
@@ -1670,7 +1678,6 @@ TESTSRC2 = \
|
||||
$(SRC01) \
|
||||
$(SRC07) \
|
||||
$(SRC10) \
|
||||
$(TOP)\ext\async\sqlite3async.c \
|
||||
fts5.c
|
||||
|
||||
# Header files used by all library source files.
|
||||
@@ -1849,6 +1856,11 @@ dll: $(SQLITE3DLL)
|
||||
#
|
||||
shell: $(SQLITE3EXE)
|
||||
|
||||
# jimsh0 - replacement for tclsh
|
||||
#
|
||||
jimsh0.exe: $(TOP)\autosetup\jimsh0.c
|
||||
cl -DHAVE__FULLPATH=1 $(TOP)\autosetup\jimsh0.c
|
||||
|
||||
# <<mark>>
|
||||
libsqlite3.lib: $(LIBOBJ)
|
||||
$(LTLIB) $(LTLIBOPTS) /OUT:$@ $(LIBOBJ) $(TLIBS)
|
||||
@@ -1880,7 +1892,10 @@ tclextension-uninstall:
|
||||
$(TCLSH_CMD) $(TOP)\tool\buildtclext.tcl --uninstall
|
||||
|
||||
tclextension-list:
|
||||
$(TCLSH_CMD) $(TOP)\tool\buildtclext.tcl --info
|
||||
@ $(TCLSH_CMD) $(TOP)\tool\buildtclext.tcl --info
|
||||
|
||||
tclextension-verify: sqlite3.h
|
||||
@ $(TCLSH_CMD) $(TOP)\tool\buildtclext.tcl --version-check
|
||||
|
||||
|
||||
# <</mark>>
|
||||
@@ -1889,10 +1904,10 @@ $(SQLITE3DLL): $(LIBOBJ) $(LIBRESOBJS) $(CORE_LINK_DEP)
|
||||
$(LD) $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) /DLL $(CORE_LINK_OPTS) /OUT:$@ $(LIBOBJ) $(LIBRESOBJS) $(LTLIBS) $(TLIBS)
|
||||
|
||||
# <<block2>>
|
||||
sqlite3.def: libsqlite3.lib
|
||||
sqlite3.def: libsqlite3.lib $(JIM_TCLSH)
|
||||
echo EXPORTS > sqlite3.def
|
||||
dumpbin /all libsqlite3.lib \
|
||||
| $(TCLSH_CMD) $(TOP)\tool\replace.tcl include "^\s+1 _?(sqlite3(?:session|changeset|changegroup|rebaser|rbu)?_[^@]*)(?:@\d+)?$$" \1 \
|
||||
| $(JIM_TCLSH) $(TOP)\tool\replace.tcl include "^\s+1 _?(sqlite3(?:session|changeset|changegroup|rebaser|rbu)?_[^@]*)(?:@\d+)?$$" \1 \
|
||||
| sort >> sqlite3.def
|
||||
# <</block2>>
|
||||
|
||||
@@ -1980,33 +1995,22 @@ mptest: mptester.exe
|
||||
# files are automatically generated. This target takes care of
|
||||
# all that automatic generation.
|
||||
#
|
||||
.target_source: $(SRC) $(TOP)\tool\vdbe-compress.tcl fts5.c $(SQLITE_TCL_DEP)
|
||||
.target_source: $(SRC) $(TOP)\tool\vdbe-compress.tcl fts5.c $(SQLITE_TCL_DEP) $(JIM_TCLSH)
|
||||
-rmdir /Q/S tsrc 2>NUL
|
||||
-mkdir tsrc
|
||||
for %i in ($(SRC00)) do copy /Y %i tsrc
|
||||
for %i in ($(SRC01)) do copy /Y %i tsrc
|
||||
for %i in ($(SRC03)) do copy /Y %i tsrc
|
||||
for %i in ($(SRC04)) do copy /Y %i tsrc
|
||||
for %i in ($(SRC05)) do copy /Y %i tsrc
|
||||
for %i in ($(SRC07)) do copy /Y %i tsrc
|
||||
for %i in ($(SRC09)) do copy /Y %i tsrc
|
||||
for %i in ($(SRC10)) do copy /Y %i tsrc
|
||||
for %i in ($(SRC11)) do copy /Y %i tsrc
|
||||
for %i in ($(SRC12)) do copy /Y %i tsrc
|
||||
copy /Y fts5.c tsrc
|
||||
$(JIM_TCLSH) $(TOP)\tool\cp.tcl $(SRC00) $(SRC01) $(SRC03) $(SRC04) $(SRC05) $(SRC07) $(SRC09) $(SRC10) $(SRC11) $(SRC12) fts5.c fts5.h tsrc
|
||||
copy /B tsrc\fts5.c +,,
|
||||
copy /Y fts5.h tsrc
|
||||
copy /B tsrc\fts5.h +,,
|
||||
del /Q tsrc\sqlite.h.in tsrc\parse.y 2>NUL
|
||||
$(TCLSH_CMD) $(TOP)\tool\vdbe-compress.tcl $(OPTS) < tsrc\vdbe.c > vdbe.new
|
||||
$(JIM_TCLSH) $(TOP)\tool\vdbe-compress.tcl $(OPTS) < tsrc\vdbe.c > vdbe.new
|
||||
move vdbe.new tsrc\vdbe.c
|
||||
echo > .target_source
|
||||
|
||||
sqlite3.c: .target_source sqlite3ext.h sqlite3session.h $(MKSQLITE3C_TOOL) src-verify.exe
|
||||
$(TCLSH_CMD) $(MKSQLITE3C_TOOL) $(MKSQLITE3C_ARGS) $(EXTRA_SRC)
|
||||
sqlite3.c: .target_source sqlite3ext.h sqlite3session.h $(MKSQLITE3C_TOOL) src-verify.exe $(JIM_TCLSH)
|
||||
$(JIM_TCLSH) $(MKSQLITE3C_TOOL) $(MKSQLITE3C_ARGS) $(EXTRA_SRC)
|
||||
|
||||
sqlite3-all.c: sqlite3.c $(TOP)\tool\split-sqlite3c.tcl
|
||||
$(TCLSH_CMD) $(TOP)\tool\split-sqlite3c.tcl
|
||||
sqlite3-all.c: sqlite3.c $(TOP)\tool\split-sqlite3c.tcl $(JIM_TCLSH)
|
||||
$(JIM_TCLSH) $(TOP)\tool\split-sqlite3c.tcl
|
||||
# <</mark>>
|
||||
|
||||
# Rule to build the amalgamation
|
||||
@@ -2048,11 +2052,11 @@ opcodes.lo: opcodes.c
|
||||
#
|
||||
!IF $(USE_RC)!=0
|
||||
# <<block1>>
|
||||
$(LIBRESOBJS): $(TOP)\src\sqlite3.rc $(SQLITE3H) $(TOP)\VERSION
|
||||
$(LIBRESOBJS): $(TOP)\src\sqlite3.rc $(SQLITE3H) $(TOP)\VERSION $(JIM_TCLSH)
|
||||
echo #ifndef SQLITE_RESOURCE_VERSION > sqlite3rc.h
|
||||
for /F %%V in ('type "$(TOP)\VERSION"') do ( \
|
||||
echo #define SQLITE_RESOURCE_VERSION %%V \
|
||||
| $(TCLSH_CMD) $(TOP)\tool\replace.tcl exact . ^, >> sqlite3rc.h \
|
||||
| $(JIM_TCLSH) $(TOP)\tool\replace.tcl exact . ^, >> sqlite3rc.h \
|
||||
)
|
||||
echo #endif >> sqlite3rc.h
|
||||
$(LTRCOMPILE) -fo $(LIBRESOBJS) $(TOP)\src\sqlite3.rc
|
||||
@@ -2313,11 +2317,11 @@ tclsqlite3.exe: tclsqlite-shell.lo $(SQLITE3C) $(SQLITE3H) $(LIBRESOBJS)
|
||||
|
||||
# Rules to build opcodes.c and opcodes.h
|
||||
#
|
||||
opcodes.c: opcodes.h $(TOP)\tool\mkopcodec.tcl
|
||||
$(TCLSH_CMD) $(TOP)\tool\mkopcodec.tcl opcodes.h > opcodes.c
|
||||
opcodes.c: opcodes.h $(TOP)\tool\mkopcodec.tcl $(JIM_TCLSH)
|
||||
$(JIM_TCLSH) $(TOP)\tool\mkopcodec.tcl opcodes.h > opcodes.c
|
||||
|
||||
opcodes.h: parse.h $(TOP)\src\vdbe.c $(TOP)\tool\mkopcodeh.tcl
|
||||
type parse.h $(TOP)\src\vdbe.c | $(TCLSH_CMD) $(TOP)\tool\mkopcodeh.tcl > opcodes.h
|
||||
opcodes.h: parse.h $(TOP)\src\vdbe.c $(TOP)\tool\mkopcodeh.tcl $(JIM_TCLSH)
|
||||
type parse.h $(TOP)\src\vdbe.c | $(JIM_TCLSH) $(TOP)\tool\mkopcodeh.tcl > opcodes.h
|
||||
|
||||
# Rules to build parse.c and parse.h - the outputs of lemon.
|
||||
#
|
||||
@@ -2329,8 +2333,8 @@ parse.c: $(TOP)\src\parse.y lemon.exe
|
||||
copy /B parse.y +,,
|
||||
.\lemon.exe $(REQ_FEATURE_FLAGS) $(OPT_FEATURE_FLAGS) $(EXT_FEATURE_FLAGS) $(OPTS) -S parse.y
|
||||
|
||||
$(SQLITE3H): $(TOP)\src\sqlite.h.in $(TOP)\manifest mksourceid.exe $(TOP)\VERSION
|
||||
$(TCLSH_CMD) $(TOP)\tool\mksqlite3h.tcl $(TOP:\=/) > $(SQLITE3H) $(MKSQLITE3H_ARGS)
|
||||
$(SQLITE3H): $(TOP)\src\sqlite.h.in $(TOP)\manifest mksourceid.exe $(TOP)\VERSION $(JIM_TCLSH)
|
||||
$(JIM_TCLSH) $(TOP)\tool\mksqlite3h.tcl "$(TOP:\=/)" -o $(SQLITE3H) $(MKSQLITE3H_ARGS)
|
||||
|
||||
sqlite3ext.h: .target_source
|
||||
!IF $(USE_STDCALL)!=0 || $(FOR_WIN10)!=0
|
||||
@@ -2393,8 +2397,8 @@ SHELL_DEP = $(SHELL_DEP) $(TOP)\ext\misc\sqlar.c
|
||||
SHELL_DEP = $(SHELL_DEP) $(TOP)\ext\misc\zipfile.c
|
||||
!ENDIF
|
||||
|
||||
shell.c: $(SHELL_DEP) $(TOP)\tool\mkshellc.tcl
|
||||
$(TCLSH_CMD) $(TOP)\tool\mkshellc.tcl > shell.c
|
||||
shell.c: $(SHELL_DEP) $(TOP)\tool\mkshellc.tcl $(JIM_TCLSH)
|
||||
$(JIM_TCLSH) $(TOP)\tool\mkshellc.tcl shell.c
|
||||
|
||||
zlib:
|
||||
pushd $(ZLIBDIR) && $(MAKE) /f win32\Makefile.msc clean $(ZLIBLIB) && popd
|
||||
@@ -2497,13 +2501,13 @@ fts5parse.c: $(TOP)\ext\fts5\fts5parse.y lemon.exe
|
||||
|
||||
fts5parse.h: fts5parse.c
|
||||
|
||||
fts5.c: $(FTS5_SRC)
|
||||
$(TCLSH_CMD) $(TOP)\ext\fts5\tool\mkfts5c.tcl
|
||||
fts5.c: $(FTS5_SRC) $(JIM_TCLSH)
|
||||
$(JIM_TCLSH) $(TOP)\ext\fts5\tool\mkfts5c.tcl
|
||||
copy /Y $(TOP)\ext\fts5\fts5.h .
|
||||
copy /B fts5.h +,,
|
||||
|
||||
lsm1.c: $(LSM1_SRC)
|
||||
$(TCLSH_CMD) $(TOP)\ext\lsm1\tool\mklsm1c.tcl
|
||||
lsm1.c: $(LSM1_SRC) $(JIM_TCLSH)
|
||||
$(JIM_TCLSH) $(TOP)\ext\lsm1\tool\mklsm1c.tcl
|
||||
copy /Y $(TOP)\ext\lsm1\lsm.h .
|
||||
copy /B lsm.h +,,
|
||||
|
||||
@@ -2665,7 +2669,7 @@ shelltest: $(TESTPROGS)
|
||||
.\testfixture.exe $(TOP)\test\permutations.test shell
|
||||
|
||||
sqlite3_analyzer.c: $(SQLITE3C) $(SQLITE3H) $(TOP)\src\tclsqlite.c $(TOP)\tool\spaceanal.tcl $(TOP)\tool\mkccode.tcl $(TOP)\tool\sqlite3_analyzer.c.in $(TOP)\ext\misc\sqlite3_stdio.h $(TOP)\ext\misc\sqlite3_stdio.c $(SQLITE_TCL_DEP)
|
||||
$(TCLSH_CMD) $(TOP)\tool\mkccode.tcl $(TOP)\tool\sqlite3_analyzer.c.in > $@
|
||||
$(TCLSH_CMD) $(TOP)\tool\mkccode.tcl -DINCLUDE_SQLITE3_C $(TOP)\tool\sqlite3_analyzer.c.in > $@
|
||||
|
||||
sqlite3_analyzer.exe: sqlite3_analyzer.c $(LIBRESOBJS)
|
||||
$(LTLINK) $(NO_WARN) -DBUILD_sqlite -I$(TCLINCDIR) sqlite3_analyzer.c \
|
||||
@@ -2795,6 +2799,8 @@ tcl-env:
|
||||
@echo LIBTCL = $(LIBTCL)
|
||||
@echo LIBTCLSTUB = $(LIBTCLSTUB)
|
||||
@echo TCLSH_CMD = $(TCLSH_CMD)
|
||||
@echo JIM_TCLSH = $(JIM_TCLSH)
|
||||
@echo VISUALSTUDIOVERSION = $(VISUALSTUDIOVERSION)
|
||||
|
||||
LSMDIR=$(TOP)\ext\lsm1
|
||||
!INCLUDE $(LSMDIR)\Makefile.msc
|
||||
@@ -2805,7 +2811,8 @@ moreclean: clean
|
||||
|
||||
clean:
|
||||
del /Q *.exp *.lo *.ilk *.lib *.obj *.ncb *.pdb *.sdf *.suo 2>NUL
|
||||
del /Q *.bsc *.def *.cod *.da *.bb *.bbg *.vc gmon.out 2>NUL
|
||||
del /Q *.bsc *.cod *.da *.bb *.bbg *.vc gmon.out 2>NUL
|
||||
del /Q sqlite3.def tclsqlite3.def 2>NUL
|
||||
del /Q $(SQLITE3EXE) $(SQLITE3DLL) Replace.exe 2>NUL
|
||||
# <<mark>>
|
||||
del /Q $(SQLITE3TCLDLL) pkgIndex.tcl 2>NUL
|
||||
|
||||
Vendored
-7972
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,104 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="103.73447mm"
|
||||
height="46.723713mm"
|
||||
viewBox="0 0 103.73447 46.723713"
|
||||
version="1.1"
|
||||
id="svg470"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs467">
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath41">
|
||||
<path
|
||||
d="m 994.055,997.609 c 6.725,-11.629 35.115,-61.371 40.815,-77.398 6.42,-18.121 7.77,-23.313 7.77,-23.313 0,0 -15.57,80.114 -41.12,126.862 5.6,18.9 12.29,39.79 19.86,62.12 8.85,-15.53 28.96,-51.2 36.23,-68.1 0.27,3.19 0.54,6.38 0.82,9.54 -6.44,24.75 -16.22,57.15 -28.74,82.54 32.14,167.25 135.59,386.25 247.04,504.48 H 509.602 c -37.883,0 -68.711,-30.82 -68.711,-68.71 V 731.789 c 173.738,66.68 383.23,127.633 563.529,125.02 -6.693,25.812 -14.315,49.152 -22.318,62.679 -4.122,6.981 0.449,35.653 11.953,78.121 z"
|
||||
id="path39" />
|
||||
</clipPath>
|
||||
<linearGradient
|
||||
x1="0"
|
||||
y1="0"
|
||||
x2="1"
|
||||
y2="0"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(-4.02e-5,-918.907,-918.907,4.02e-5,858.809,1614.34)"
|
||||
spreadMethod="pad"
|
||||
id="linearGradient51">
|
||||
<stop
|
||||
style="stop-opacity:1;stop-color:#97d9f6"
|
||||
offset="0"
|
||||
id="stop43" />
|
||||
<stop
|
||||
style="stop-opacity:1;stop-color:#0f80cc"
|
||||
offset="0.66199914"
|
||||
id="stop45" />
|
||||
<stop
|
||||
style="stop-opacity:1;stop-color:#0f80cc"
|
||||
offset="0.920245"
|
||||
id="stop47" />
|
||||
<stop
|
||||
style="stop-opacity:1;stop-color:#0f80cc"
|
||||
offset="1"
|
||||
id="stop49" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<g
|
||||
id="g337">
|
||||
<rect
|
||||
style="fill:#ffffff;stroke:#ffffff;stroke-width:0.239562;stroke-linecap:round;stroke-linejoin:round"
|
||||
id="rect366"
|
||||
width="103.4949"
|
||||
height="46.48415"
|
||||
x="0.119781"
|
||||
y="0.119781"
|
||||
ry="0" />
|
||||
<g
|
||||
id="g465"
|
||||
transform="translate(-56.57816,-61.353828)">
|
||||
<path
|
||||
d="m 79.198545,96.729705 c -0.02011,-0.25467 -0.0321,-0.420158 -0.0321,-0.420158 0,0 -0.77223,-5.206224 -1.691499,-6.759822 -0.145415,-0.246275 0.01584,-1.257759 0.421676,-2.755936 0.237243,0.410245 1.238779,2.165033 1.439862,2.73043 0.226484,0.639268 0.274109,0.822431 0.274109,0.822431 0,0 -0.549275,-2.826244 -1.450623,-4.47541 0.197556,-0.66675 0.433564,-1.403703 0.700617,-2.191456 0.341489,0.599017 1.158875,2.049286 1.338792,2.552348 0.03634,0.103364 0.06703,0.191205 0.09454,0.271639 0.0088,-0.04833 0.01764,-0.09666 0.02646,-0.144992 -0.206375,-0.875595 -0.611716,-2.399242 -1.166636,-3.524956 1.231195,-6.408209 5.430309,-14.973654 9.735256,-18.795296 H 60.806192 c -1.88214,0 -3.422086,1.540228 -3.422086,3.422298 v 30.970081 c 0,1.881964 1.539946,3.421944 3.422086,3.421944 h 18.49607 c -0.13335,-1.61438 -0.1778,-3.40046 -0.103717,-5.123145"
|
||||
style="fill:#0f80cc;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.0352778"
|
||||
id="path21" />
|
||||
<path
|
||||
d="m 99.934471,84.584659 h 0.474839 v 3.954957 h -0.503061 c -0.115005,-1.093188 -0.510469,-1.946593 -1.186392,-2.560426 -0.676627,-0.612775 -1.526822,-0.920045 -2.5527,-0.920045 -0.911578,0 -1.64465,0.230364 -2.200628,0.690387 -0.555977,0.459669 -0.833966,1.073467 -0.833966,1.840759 0,0.709401 0.230011,1.356536 0.690386,1.940948 0.459669,0.585258 1.457325,1.337134 2.991556,2.258907 1.782939,1.063978 2.981325,1.992912 3.594805,2.789414 0.61348,0.795549 0.92004,1.706421 0.92004,2.732229 0,1.322916 -0.46813,2.454275 -1.405815,3.393691 -0.939094,0.93983 -2.069042,1.40945 -3.389489,1.40945 -0.766233,0 -1.742369,-0.21096 -2.929467,-0.63334 -0.487891,-0.17237 -0.799394,-0.25781 -0.933097,-0.25781 -0.277989,0 -0.492831,0.21523 -0.646289,0.64699 h -0.503414 v -4.558981 h 0.503414 c 0.0092,1.256206 0.418747,2.262752 1.227314,3.020521 0.808567,0.75667 1.753306,1.13524 2.834217,1.13524 1.024819,0 1.844322,-0.27231 2.462389,-0.81979 0.617008,-0.54723 0.925689,-1.276066 0.925689,-2.188068 0,-0.681143 -0.254,-1.333394 -0.760942,-1.956823 -0.506589,-0.623958 -1.567392,-1.427621 -3.180292,-2.412259 -1.31445,-0.812765 -2.192161,-1.452422 -2.63278,-1.923027 -0.44062,-0.470182 -0.766234,-0.985591 -0.976842,-1.547284 -0.210608,-0.560564 -0.316089,-1.177537 -0.316089,-1.848485 0,-1.294659 0.424744,-2.345302 1.273175,-3.151399 0.848431,-0.805392 1.953331,-1.208264 3.314347,-1.208264 0.747889,0 1.563159,0.148519 2.445103,0.445558 0.411692,0.134409 0.699559,0.201436 0.862189,0.201436 0.135114,0 0.225778,-0.02858 0.27305,-0.08608 0.04868,-0.05786 0.1016,-0.186973 0.15875,-0.388409"
|
||||
style="fill:#003b57;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.0352778"
|
||||
id="path23" />
|
||||
<path
|
||||
d="m 119.14851,93.38576 c 0,-2.579547 -0.59019,-4.611476 -1.76953,-6.097835 -1.17969,-1.48583 -2.70369,-2.22878 -4.57412,-2.22878 -1.98437,0 -3.56799,0.746125 -4.75191,2.235977 -1.18463,1.491438 -1.77553,3.482834 -1.77553,5.975562 0,2.42577 0.58702,4.398857 1.76106,5.918271 1.17511,1.519415 2.70616,2.278595 4.59458,2.278595 1.96568,0 3.5426,-0.73562 4.7311,-2.207334 1.18851,-1.472177 1.78435,-3.430094 1.78435,-5.874456 z m 2.93265,12.9716 0.18662,0.46041 c -0.82409,0.37402 -1.7586,0.56085 -2.80353,0.56085 -0.86289,0 -1.66405,-0.11314 -2.40206,-0.33789 -0.73731,-0.22571 -1.43122,-0.57051 -2.07751,-1.03572 -0.647,-0.46496 -1.43616,-1.23941 -2.36608,-2.32198 -0.82515,-0.95928 -1.45768,-1.55445 -1.8983,-1.78404 -1.92723,-0.39232 -3.58246,-1.40973 -4.96852,-3.048067 -1.38536,-1.639323 -2.07822,-3.509716 -2.07822,-5.609167 0,-1.5627 0.39794,-3.033889 1.19345,-4.414556 0.79587,-1.380772 1.87466,-2.461718 3.23709,-3.242416 1.36031,-0.782108 2.87055,-1.172633 4.52896,-1.172633 2.56011,0 4.71699,0.851253 6.47206,2.55263 1.75366,1.7012 2.63067,3.79416 2.63067,6.276975 0,2.09102 -0.67522,3.951923 -2.02706,5.586695 -1.3522,1.635479 -3.08293,2.658779 -5.19148,3.070539 0.20179,0.16151 0.56233,0.5697 1.0795,1.22234 1.10031,1.36204 2.02071,2.28604 2.75837,2.76998 0.73871,0.48274 1.47214,0.72542 2.20133,0.72542 0.53728,0 1.04634,-0.0868 1.52471,-0.25937"
|
||||
style="fill:#003b57;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.0352778"
|
||||
id="path25" />
|
||||
<path
|
||||
d="m 134.47177,99.116318 -0.28116,2.694482 h -11.00385 l 0.0233,-0.53619 c 0.59654,-0.061 1.01458,-0.21413 1.25835,-0.45861 0.24342,-0.24624 0.36654,-0.81111 0.37571,-1.699682 l 0.0127,-11.904593 c -0.004,-0.621877 -0.0346,-1.050502 -0.0861,-1.284393 -0.13828,-0.653698 -0.75565,-0.980017 -1.85984,-0.980017 l -0.0236,-0.535164 h 5.74393 l 0.0219,0.535164 c -0.61242,0.04163 -1.03152,0.206728 -1.26612,0.496711 -0.23212,0.291042 -0.34713,0.880533 -0.34678,1.767699 l -0.0441,12.029053 c 0.002,0.204646 0.0191,0.391901 0.0572,0.565538 0.1845,0.877674 0.88053,1.315474 2.08774,1.315474 h 1.03681 c 1.34161,0 2.27259,-0.15088 2.79788,-0.45226 0.52388,-0.29919 0.8569,-0.818023 1.00048,-1.553212 h 0.49565"
|
||||
style="fill:#003b57;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.0352778"
|
||||
id="path27" />
|
||||
<path
|
||||
d="m 138.12055,87.618936 c 0.25965,0 0.49883,0.09095 0.71967,0.273685 0.21837,0.182034 0.36054,0.407071 0.41522,0.674829 0.0533,0.25975 0.009,0.48507 -0.133,0.676769 -0.14217,0.191523 -0.34114,0.28702 -0.60078,0.28702 -0.26846,0 -0.51858,-0.0955 -0.75001,-0.28702 -0.23283,-0.191699 -0.37535,-0.417019 -0.42827,-0.676769 -0.0547,-0.267758 -0.0106,-0.492795 0.14605,-0.674829 0.15311,-0.182738 0.36266,-0.273685 0.63112,-0.273685 z m 1.75754,4.127783 -0.0176,7.535404 c 0.003,0.526662 0.03,0.900957 0.0769,1.122117 0.0607,0.30688 0.19685,0.5147 0.40111,0.6248 0.20778,0.11081 0.67133,0.1662 1.39065,0.1662 l 0.0166,0.50299 h -5.17702 l 0.0123,-0.50299 c 0.70979,0 1.14582,-0.0656 1.31198,-0.1947 0.16475,-0.12887 0.24941,-0.56307 0.25859,-1.301433 l 0.0325,-5.335094 c -0.006,-0.291042 -0.0243,-0.518548 -0.0586,-0.683613 -0.1016,-0.493219 -0.42686,-0.740587 -0.97367,-0.740587 l -1.12324,0.143616 -0.005,-0.589527 3.26319,-0.747183 h 0.59161"
|
||||
style="fill:#003b57;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.0352778"
|
||||
id="path29" />
|
||||
<path
|
||||
d="m 148.56207,92.004952 0.0247,0.805074 h -2.70545 l -0.0194,6.728955 c 0,0.183409 0.0109,0.341065 0.0423,0.476109 0.11465,0.55605 0.41945,0.83467 0.90946,0.83467 0.79728,0 1.70709,-0.52239 2.73967,-1.567637 l 0.43427,0.366148 c -1.43016,1.587219 -2.79682,2.380119 -4.10033,2.380119 -0.901,0 -1.43828,-0.41229 -1.6129,-1.23677 -0.072,-0.34438 -0.10795,-1.025556 -0.11077,-2.041838 l 0.037,-5.939756 h -1.76954 l -0.0205,-0.502708 c 1.51836,-0.153105 2.50472,-1.106981 2.96087,-2.861769 h 0.51752 l -0.005,2.559403 h 2.67758"
|
||||
style="fill:#003b57;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.0352778"
|
||||
id="path31" />
|
||||
<path
|
||||
d="m 152.6931,96.836244 c 2.82998,-0.546417 4.09434,-1.527845 3.79906,-2.9464 -0.0603,-0.288819 -0.24483,-0.55245 -0.54716,-0.791527 -0.30656,-0.239925 -0.61418,-0.359975 -0.92921,-0.359975 -0.71932,0 -1.3081,0.424462 -1.76178,1.272505 -0.4572,0.848854 -0.6417,1.791017 -0.56091,2.825397 z m -0.0162,0.533436 c 0.024,0.248708 0.0575,0.48394 0.10442,0.704179 0.36089,1.725437 1.3328,2.588371 2.91395,2.588371 1.15005,0 2.67264,-0.694412 3.42829,-2.08471 l 0.38312,0.395217 c -0.47378,1.071703 -0.9899,1.848523 -1.54658,2.331513 -0.55527,0.48327 -1.87678,0.72414 -2.82434,0.72414 -1.01776,0 -1.86161,-0.28497 -2.53259,-0.85548 -0.67204,-0.57076 -1.11407,-1.378306 -1.33456,-2.423128 -0.37465,-1.783751 -0.0843,-3.405012 0.86854,-4.868334 0.95779,-1.460853 2.19145,-2.19329 3.70593,-2.19329 0.59584,0 1.66511,0.152118 2.07574,0.453637 0.40535,0.30166 0.66393,0.707072 0.77118,1.214614 0.18027,0.85411 -0.78352,1.660948 -1.74484,2.423689 -0.96203,0.762318 -2.38725,1.291767 -4.26826,1.589582"
|
||||
style="fill:#003b57;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.0352778"
|
||||
id="path33" />
|
||||
<g
|
||||
id="g37"
|
||||
clip-path="url(#clipPath41)"
|
||||
transform="matrix(0.03527778,0,0,-0.03527778,42.828565,121.98722)">
|
||||
<path
|
||||
d="m 994.055,997.609 c 6.725,-11.629 35.115,-61.371 40.815,-77.398 6.42,-18.121 7.77,-23.313 7.77,-23.313 0,0 -15.57,80.114 -41.12,126.862 5.6,18.9 12.29,39.79 19.86,62.12 8.85,-15.53 28.96,-51.2 36.23,-68.1 0.27,3.19 0.54,6.38 0.82,9.54 -6.44,24.75 -16.22,57.15 -28.74,82.54 32.14,167.25 135.59,386.25 247.04,504.48 H 509.602 c -37.883,0 -68.711,-30.82 -68.711,-68.71 V 731.789 c 173.738,66.68 383.23,127.633 563.529,125.02 -6.693,25.812 -14.315,49.152 -22.318,62.679 -4.122,6.981 0.449,35.653 11.953,78.121"
|
||||
style="fill:url(#linearGradient51);fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path53" />
|
||||
</g>
|
||||
<path
|
||||
d="m 95.439377,63.024997 c -1.923345,-1.715206 -4.252031,-1.026231 -6.550379,1.01353 -0.341136,0.303037 -0.681566,0.639234 -1.020233,0.998362 -3.931709,4.170892 -7.581195,11.896725 -8.715023,17.796934 0.441678,0.895703 0.786695,2.038703 1.013884,2.911828 0.05821,0.224014 0.110772,0.43427 0.152752,0.613128 0.09984,0.423298 0.153459,0.697794 0.153459,0.697794 0,0 -0.03528,-0.133385 -0.179917,-0.552802 -0.02752,-0.08043 -0.05821,-0.168275 -0.09454,-0.271639 -0.01552,-0.04269 -0.03704,-0.09454 -0.06068,-0.149931 -0.25647,-0.596194 -0.965906,-1.854553 -1.278114,-2.402417 -0.267053,0.787753 -0.503061,1.524706 -0.700617,2.191456 0.901348,1.649166 1.450623,4.47541 1.450623,4.47541 0,0 -0.04762,-0.183163 -0.274109,-0.822431 -0.201083,-0.565397 -1.202619,-2.320185 -1.439862,-2.73043 -0.405836,1.498177 -0.567091,2.509661 -0.421676,2.755936 0.282328,0.477202 0.551216,1.300586 0.78733,2.211176 0.5334,2.051367 0.904169,4.548646 0.904169,4.548646 0,0 0.01199,0.165488 0.0321,0.420158 -0.07408,1.722685 -0.02963,3.508765 0.103717,5.123145 0.176741,2.13706 0.509411,3.97288 0.93345,4.9554 l 0.287866,-0.15695 c -0.622652,-1.93573 -0.875594,-4.47255 -0.764822,-7.39814 0.16757,-4.471846 1.196623,-9.86469 3.098095,-15.485534 3.212395,-8.485012 7.669389,-15.292918 11.748559,-18.544118 -3.717925,3.357739 -8.749948,14.22647 -10.256309,18.251312 -1.686631,4.50709 -2.881842,8.736578 -3.602214,12.788831 1.242836,-3.798959 5.261328,-5.431932 5.261328,-5.431932 0,0 1.97097,-2.430745 4.274256,-5.903454 -1.379714,0.314678 -3.645253,0.853369 -4.404078,1.172281 -1.119364,0.469547 -1.420989,0.629708 -1.420989,0.629708 0,0 3.62585,-2.208036 6.736645,-3.207809 4.278136,-6.738056 8.939042,-16.310328 4.245328,-20.497448"
|
||||
style="fill:#003b57;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.0352778"
|
||||
id="path55" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 12 KiB |
@@ -0,0 +1,73 @@
|
||||
#!/do/not/tclsh
|
||||
# ^^^ help out editors which guess this file's content type.
|
||||
#
|
||||
# This is the main autosetup-compatible configure script for the
|
||||
# SQLite project.
|
||||
#
|
||||
# This script should be kept compatible with JimTCL, a copy of which
|
||||
# is included in this source tree as ./autosetup/jimsh0.c. The number
|
||||
# of incompatibilities between canonical TCL and JimTCL is very low
|
||||
# and alternative formulations of incompatible constructs have, so
|
||||
# far, been easy to find.
|
||||
#
|
||||
# JimTCL: https://jim.tcl.tk
|
||||
#
|
||||
|
||||
use sqlite-config
|
||||
sqlite-config-bootstrap canonical
|
||||
sqlite-setup-default-cflags
|
||||
proj-if-opt-truthy dev {
|
||||
# --enable-dev needs to come early so that the downstream tests
|
||||
# which check for the following flags use their updated state.
|
||||
proj-opt-set all 1
|
||||
proj-opt-set debug 1
|
||||
proj-opt-set amalgamation 0
|
||||
define CFLAGS [get-env CFLAGS {-O0 -g}]
|
||||
# -------------^^^^^^^ intentionally using [get-env] instead of
|
||||
# [proj-get-env] here because [sqlite-setup-default-cflags] uses
|
||||
# [proj-get-env] and we want this to supercede that.
|
||||
}
|
||||
|
||||
sqlite-check-common-bins ;# must come before [sqlite-handle-wasi-sdk]
|
||||
sqlite-handle-wasi-sdk ;# must run relatively early, as it changes the environment
|
||||
sqlite-check-common-system-deps
|
||||
|
||||
#
|
||||
# Enable large file support (if special flags are necessary)
|
||||
#
|
||||
define HAVE_LFS 0
|
||||
if {[opt-bool largefile]} {
|
||||
cc-check-lfs
|
||||
}
|
||||
|
||||
proj-define-for-opt shared ENABLE_SHARED "Build shared library?"
|
||||
|
||||
if {![proj-define-for-opt static ENABLE_STATIC \
|
||||
"Build static library?"]} {
|
||||
proj-warn "Static lib build may be implicitly re-activated by other components, e.g. some test apps."
|
||||
}
|
||||
|
||||
proj-define-for-opt amalgamation USE_AMALGAMATION "Use amalgamation for builds?"
|
||||
|
||||
proj-define-for-opt gcov USE_GCOV "Use gcov?"
|
||||
|
||||
proj-define-for-opt test-status TSTRNNR_OPTS \
|
||||
"test-runner flags:" {--status} {}
|
||||
|
||||
proj-define-for-opt linemacros AMALGAMATION_LINE_MACROS \
|
||||
"Use #line macros in the amalgamation:"
|
||||
|
||||
define LINK_TOOLS_DYNAMICALLY [proj-opt-was-provided dynlink-tools]
|
||||
|
||||
proj-check-rpath
|
||||
sqlite-handle-soname
|
||||
sqlite-handle-debug
|
||||
sqlite-handle-tcl
|
||||
sqlite-handle-threadsafe
|
||||
sqlite-handle-tempstore
|
||||
sqlite-handle-line-editing
|
||||
sqlite-handle-load-extension
|
||||
sqlite-handle-math
|
||||
sqlite-handle-icu
|
||||
sqlite-handle-emsdk
|
||||
sqlite-config-finalize
|
||||
@@ -1,370 +0,0 @@
|
||||
Installation Instructions
|
||||
*************************
|
||||
|
||||
Copyright (C) 1994-1996, 1999-2002, 2004-2011 Free Software Foundation,
|
||||
Inc.
|
||||
|
||||
Copying and distribution of this file, with or without modification,
|
||||
are permitted in any medium without royalty provided the copyright
|
||||
notice and this notice are preserved. This file is offered as-is,
|
||||
without warranty of any kind.
|
||||
|
||||
Basic Installation
|
||||
==================
|
||||
|
||||
Briefly, the shell commands `./configure; make; make install' should
|
||||
configure, build, and install this package. The following
|
||||
more-detailed instructions are generic; see the `README' file for
|
||||
instructions specific to this package. Some packages provide this
|
||||
`INSTALL' file but do not implement all of the features documented
|
||||
below. The lack of an optional feature in a given package is not
|
||||
necessarily a bug. More recommendations for GNU packages can be found
|
||||
in *note Makefile Conventions: (standards)Makefile Conventions.
|
||||
|
||||
The `configure' shell script attempts to guess correct values for
|
||||
various system-dependent variables used during compilation. It uses
|
||||
those values to create a `Makefile' in each directory of the package.
|
||||
It may also create one or more `.h' files containing system-dependent
|
||||
definitions. Finally, it creates a shell script `config.status' that
|
||||
you can run in the future to recreate the current configuration, and a
|
||||
file `config.log' containing compiler output (useful mainly for
|
||||
debugging `configure').
|
||||
|
||||
It can also use an optional file (typically called `config.cache'
|
||||
and enabled with `--cache-file=config.cache' or simply `-C') that saves
|
||||
the results of its tests to speed up reconfiguring. Caching is
|
||||
disabled by default to prevent problems with accidental use of stale
|
||||
cache files.
|
||||
|
||||
If you need to do unusual things to compile the package, please try
|
||||
to figure out how `configure' could check whether to do them, and mail
|
||||
diffs or instructions to the address given in the `README' so they can
|
||||
be considered for the next release. If you are using the cache, and at
|
||||
some point `config.cache' contains results you don't want to keep, you
|
||||
may remove or edit it.
|
||||
|
||||
The file `configure.ac' (or `configure.in') is used to create
|
||||
`configure' by a program called `autoconf'. You need `configure.ac' if
|
||||
you want to change it or regenerate `configure' using a newer version
|
||||
of `autoconf'.
|
||||
|
||||
The simplest way to compile this package is:
|
||||
|
||||
1. `cd' to the directory containing the package's source code and type
|
||||
`./configure' to configure the package for your system.
|
||||
|
||||
Running `configure' might take a while. While running, it prints
|
||||
some messages telling which features it is checking for.
|
||||
|
||||
2. Type `make' to compile the package.
|
||||
|
||||
3. Optionally, type `make check' to run any self-tests that come with
|
||||
the package, generally using the just-built uninstalled binaries.
|
||||
|
||||
4. Type `make install' to install the programs and any data files and
|
||||
documentation. When installing into a prefix owned by root, it is
|
||||
recommended that the package be configured and built as a regular
|
||||
user, and only the `make install' phase executed with root
|
||||
privileges.
|
||||
|
||||
5. Optionally, type `make installcheck' to repeat any self-tests, but
|
||||
this time using the binaries in their final installed location.
|
||||
This target does not install anything. Running this target as a
|
||||
regular user, particularly if the prior `make install' required
|
||||
root privileges, verifies that the installation completed
|
||||
correctly.
|
||||
|
||||
6. You can remove the program binaries and object files from the
|
||||
source code directory by typing `make clean'. To also remove the
|
||||
files that `configure' created (so you can compile the package for
|
||||
a different kind of computer), type `make distclean'. There is
|
||||
also a `make maintainer-clean' target, but that is intended mainly
|
||||
for the package's developers. If you use it, you may have to get
|
||||
all sorts of other programs in order to regenerate files that came
|
||||
with the distribution.
|
||||
|
||||
7. Often, you can also type `make uninstall' to remove the installed
|
||||
files again. In practice, not all packages have tested that
|
||||
uninstallation works correctly, even though it is required by the
|
||||
GNU Coding Standards.
|
||||
|
||||
8. Some packages, particularly those that use Automake, provide `make
|
||||
distcheck', which can by used by developers to test that all other
|
||||
targets like `make install' and `make uninstall' work correctly.
|
||||
This target is generally not run by end users.
|
||||
|
||||
Compilers and Options
|
||||
=====================
|
||||
|
||||
Some systems require unusual options for compilation or linking that
|
||||
the `configure' script does not know about. Run `./configure --help'
|
||||
for details on some of the pertinent environment variables.
|
||||
|
||||
You can give `configure' initial values for configuration parameters
|
||||
by setting variables in the command line or in the environment. Here
|
||||
is an example:
|
||||
|
||||
./configure CC=c99 CFLAGS=-g LIBS=-lposix
|
||||
|
||||
*Note Defining Variables::, for more details.
|
||||
|
||||
Compiling For Multiple Architectures
|
||||
====================================
|
||||
|
||||
You can compile the package for more than one kind of computer at the
|
||||
same time, by placing the object files for each architecture in their
|
||||
own directory. To do this, you can use GNU `make'. `cd' to the
|
||||
directory where you want the object files and executables to go and run
|
||||
the `configure' script. `configure' automatically checks for the
|
||||
source code in the directory that `configure' is in and in `..'. This
|
||||
is known as a "VPATH" build.
|
||||
|
||||
With a non-GNU `make', it is safer to compile the package for one
|
||||
architecture at a time in the source code directory. After you have
|
||||
installed the package for one architecture, use `make distclean' before
|
||||
reconfiguring for another architecture.
|
||||
|
||||
On MacOS X 10.5 and later systems, you can create libraries and
|
||||
executables that work on multiple system types--known as "fat" or
|
||||
"universal" binaries--by specifying multiple `-arch' options to the
|
||||
compiler but only a single `-arch' option to the preprocessor. Like
|
||||
this:
|
||||
|
||||
./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
|
||||
CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
|
||||
CPP="gcc -E" CXXCPP="g++ -E"
|
||||
|
||||
This is not guaranteed to produce working output in all cases, you
|
||||
may have to build one architecture at a time and combine the results
|
||||
using the `lipo' tool if you have problems.
|
||||
|
||||
Installation Names
|
||||
==================
|
||||
|
||||
By default, `make install' installs the package's commands under
|
||||
`/usr/local/bin', include files under `/usr/local/include', etc. You
|
||||
can specify an installation prefix other than `/usr/local' by giving
|
||||
`configure' the option `--prefix=PREFIX', where PREFIX must be an
|
||||
absolute file name.
|
||||
|
||||
You can specify separate installation prefixes for
|
||||
architecture-specific files and architecture-independent files. If you
|
||||
pass the option `--exec-prefix=PREFIX' to `configure', the package uses
|
||||
PREFIX as the prefix for installing programs and libraries.
|
||||
Documentation and other data files still use the regular prefix.
|
||||
|
||||
In addition, if you use an unusual directory layout you can give
|
||||
options like `--bindir=DIR' to specify different values for particular
|
||||
kinds of files. Run `configure --help' for a list of the directories
|
||||
you can set and what kinds of files go in them. In general, the
|
||||
default for these options is expressed in terms of `${prefix}', so that
|
||||
specifying just `--prefix' will affect all of the other directory
|
||||
specifications that were not explicitly provided.
|
||||
|
||||
The most portable way to affect installation locations is to pass the
|
||||
correct locations to `configure'; however, many packages provide one or
|
||||
both of the following shortcuts of passing variable assignments to the
|
||||
`make install' command line to change installation locations without
|
||||
having to reconfigure or recompile.
|
||||
|
||||
The first method involves providing an override variable for each
|
||||
affected directory. For example, `make install
|
||||
prefix=/alternate/directory' will choose an alternate location for all
|
||||
directory configuration variables that were expressed in terms of
|
||||
`${prefix}'. Any directories that were specified during `configure',
|
||||
but not in terms of `${prefix}', must each be overridden at install
|
||||
time for the entire installation to be relocated. The approach of
|
||||
makefile variable overrides for each directory variable is required by
|
||||
the GNU Coding Standards, and ideally causes no recompilation.
|
||||
However, some platforms have known limitations with the semantics of
|
||||
shared libraries that end up requiring recompilation when using this
|
||||
method, particularly noticeable in packages that use GNU Libtool.
|
||||
|
||||
The second method involves providing the `DESTDIR' variable. For
|
||||
example, `make install DESTDIR=/alternate/directory' will prepend
|
||||
`/alternate/directory' before all installation names. The approach of
|
||||
`DESTDIR' overrides is not required by the GNU Coding Standards, and
|
||||
does not work on platforms that have drive letters. On the other hand,
|
||||
it does better at avoiding recompilation issues, and works well even
|
||||
when some directory options were not specified in terms of `${prefix}'
|
||||
at `configure' time.
|
||||
|
||||
Optional Features
|
||||
=================
|
||||
|
||||
If the package supports it, you can cause programs to be installed
|
||||
with an extra prefix or suffix on their names by giving `configure' the
|
||||
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
|
||||
|
||||
Some packages pay attention to `--enable-FEATURE' options to
|
||||
`configure', where FEATURE indicates an optional part of the package.
|
||||
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
|
||||
is something like `gnu-as' or `x' (for the X Window System). The
|
||||
`README' should mention any `--enable-' and `--with-' options that the
|
||||
package recognizes.
|
||||
|
||||
For packages that use the X Window System, `configure' can usually
|
||||
find the X include and library files automatically, but if it doesn't,
|
||||
you can use the `configure' options `--x-includes=DIR' and
|
||||
`--x-libraries=DIR' to specify their locations.
|
||||
|
||||
Some packages offer the ability to configure how verbose the
|
||||
execution of `make' will be. For these packages, running `./configure
|
||||
--enable-silent-rules' sets the default to minimal output, which can be
|
||||
overridden with `make V=1'; while running `./configure
|
||||
--disable-silent-rules' sets the default to verbose, which can be
|
||||
overridden with `make V=0'.
|
||||
|
||||
Particular systems
|
||||
==================
|
||||
|
||||
On HP-UX, the default C compiler is not ANSI C compatible. If GNU
|
||||
CC is not installed, it is recommended to use the following options in
|
||||
order to use an ANSI C compiler:
|
||||
|
||||
./configure CC="cc -Ae -D_XOPEN_SOURCE=500"
|
||||
|
||||
and if that doesn't work, install pre-built binaries of GCC for HP-UX.
|
||||
|
||||
HP-UX `make' updates targets which have the same time stamps as
|
||||
their prerequisites, which makes it generally unusable when shipped
|
||||
generated files such as `configure' are involved. Use GNU `make'
|
||||
instead.
|
||||
|
||||
On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot
|
||||
parse its `<wchar.h>' header file. The option `-nodtk' can be used as
|
||||
a workaround. If GNU CC is not installed, it is therefore recommended
|
||||
to try
|
||||
|
||||
./configure CC="cc"
|
||||
|
||||
and if that doesn't work, try
|
||||
|
||||
./configure CC="cc -nodtk"
|
||||
|
||||
On Solaris, don't put `/usr/ucb' early in your `PATH'. This
|
||||
directory contains several dysfunctional programs; working variants of
|
||||
these programs are available in `/usr/bin'. So, if you need `/usr/ucb'
|
||||
in your `PATH', put it _after_ `/usr/bin'.
|
||||
|
||||
On Haiku, software installed for all users goes in `/boot/common',
|
||||
not `/usr/local'. It is recommended to use the following options:
|
||||
|
||||
./configure --prefix=/boot/common
|
||||
|
||||
Specifying the System Type
|
||||
==========================
|
||||
|
||||
There may be some features `configure' cannot figure out
|
||||
automatically, but needs to determine by the type of machine the package
|
||||
will run on. Usually, assuming the package is built to be run on the
|
||||
_same_ architectures, `configure' can figure that out, but if it prints
|
||||
a message saying it cannot guess the machine type, give it the
|
||||
`--build=TYPE' option. TYPE can either be a short name for the system
|
||||
type, such as `sun4', or a canonical name which has the form:
|
||||
|
||||
CPU-COMPANY-SYSTEM
|
||||
|
||||
where SYSTEM can have one of these forms:
|
||||
|
||||
OS
|
||||
KERNEL-OS
|
||||
|
||||
See the file `config.sub' for the possible values of each field. If
|
||||
`config.sub' isn't included in this package, then this package doesn't
|
||||
need to know the machine type.
|
||||
|
||||
If you are _building_ compiler tools for cross-compiling, you should
|
||||
use the option `--target=TYPE' to select the type of system they will
|
||||
produce code for.
|
||||
|
||||
If you want to _use_ a cross compiler, that generates code for a
|
||||
platform different from the build platform, you should specify the
|
||||
"host" platform (i.e., that on which the generated programs will
|
||||
eventually be run) with `--host=TYPE'.
|
||||
|
||||
Sharing Defaults
|
||||
================
|
||||
|
||||
If you want to set default values for `configure' scripts to share,
|
||||
you can create a site shell script called `config.site' that gives
|
||||
default values for variables like `CC', `cache_file', and `prefix'.
|
||||
`configure' looks for `PREFIX/share/config.site' if it exists, then
|
||||
`PREFIX/etc/config.site' if it exists. Or, you can set the
|
||||
`CONFIG_SITE' environment variable to the location of the site script.
|
||||
A warning: not all `configure' scripts look for a site script.
|
||||
|
||||
Defining Variables
|
||||
==================
|
||||
|
||||
Variables not defined in a site shell script can be set in the
|
||||
environment passed to `configure'. However, some packages may run
|
||||
configure again during the build, and the customized values of these
|
||||
variables may be lost. In order to avoid this problem, you should set
|
||||
them in the `configure' command line, using `VAR=value'. For example:
|
||||
|
||||
./configure CC=/usr/local2/bin/gcc
|
||||
|
||||
causes the specified `gcc' to be used as the C compiler (unless it is
|
||||
overridden in the site shell script).
|
||||
|
||||
Unfortunately, this technique does not work for `CONFIG_SHELL' due to
|
||||
an Autoconf bug. Until the bug is fixed you can use this workaround:
|
||||
|
||||
CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash
|
||||
|
||||
`configure' Invocation
|
||||
======================
|
||||
|
||||
`configure' recognizes the following options to control how it
|
||||
operates.
|
||||
|
||||
`--help'
|
||||
`-h'
|
||||
Print a summary of all of the options to `configure', and exit.
|
||||
|
||||
`--help=short'
|
||||
`--help=recursive'
|
||||
Print a summary of the options unique to this package's
|
||||
`configure', and exit. The `short' variant lists options used
|
||||
only in the top level, while the `recursive' variant lists options
|
||||
also present in any nested packages.
|
||||
|
||||
`--version'
|
||||
`-V'
|
||||
Print the version of Autoconf used to generate the `configure'
|
||||
script, and exit.
|
||||
|
||||
`--cache-file=FILE'
|
||||
Enable the cache: use and save the results of the tests in FILE,
|
||||
traditionally `config.cache'. FILE defaults to `/dev/null' to
|
||||
disable caching.
|
||||
|
||||
`--config-cache'
|
||||
`-C'
|
||||
Alias for `--cache-file=config.cache'.
|
||||
|
||||
`--quiet'
|
||||
`--silent'
|
||||
`-q'
|
||||
Do not print messages saying which checks are being made. To
|
||||
suppress all normal output, redirect it to `/dev/null' (any error
|
||||
messages will still be shown).
|
||||
|
||||
`--srcdir=DIR'
|
||||
Look for the package's source code in directory DIR. Usually
|
||||
`configure' can determine that directory automatically.
|
||||
|
||||
`--prefix=DIR'
|
||||
Use DIR as the installation prefix. *note Installation Names::
|
||||
for more details, including other options available for fine-tuning
|
||||
the installation locations.
|
||||
|
||||
`--no-create'
|
||||
`-n'
|
||||
Run the configure checks, but stop before creating any output
|
||||
files.
|
||||
|
||||
`configure' also accepts some other, not widely useful, options. Run
|
||||
`configure --help' for more details.
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
|
||||
AM_CFLAGS = @BUILD_CFLAGS@
|
||||
lib_LTLIBRARIES = libsqlite3.la
|
||||
libsqlite3_la_SOURCES = sqlite3.c
|
||||
libsqlite3_la_LDFLAGS = -no-undefined -version-info 8:6:8
|
||||
|
||||
bin_PROGRAMS = sqlite3
|
||||
sqlite3_SOURCES = shell.c sqlite3.h
|
||||
EXTRA_sqlite3_SOURCES = sqlite3.c
|
||||
sqlite3_LDADD = @EXTRA_SHELL_OBJ@ @READLINE_LIBS@
|
||||
sqlite3_DEPENDENCIES = @EXTRA_SHELL_OBJ@
|
||||
sqlite3_CFLAGS = $(AM_CFLAGS) -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_DQS=0 -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_ENABLE_STMTVTAB -DSQLITE_ENABLE_DBSTAT_VTAB $(SHELL_CFLAGS)
|
||||
|
||||
include_HEADERS = sqlite3.h sqlite3ext.h
|
||||
|
||||
EXTRA_DIST = sqlite3.1 tea Makefile.msc sqlite3.rc sqlite3rc.h README.txt Replace.cs Makefile.fallback
|
||||
pkgconfigdir = ${libdir}/pkgconfig
|
||||
pkgconfig_DATA = sqlite3.pc
|
||||
|
||||
man_MANS = sqlite3.1
|
||||
@@ -0,0 +1,264 @@
|
||||
########################################################################
|
||||
# This is a main makefile for the "autoconf" bundle of SQLite. This is
|
||||
# a trimmed-down version of the canonical makefile, devoid of most
|
||||
# documentation. For the full docs, see /main.mk in the canonical
|
||||
# source tree.
|
||||
#
|
||||
# Maintenance reminders:
|
||||
#
|
||||
# - To keep this working with an out-of-tree build, be sure to prefix
|
||||
# input file names with $(TOP)/ where appropriate (which is most
|
||||
# places).
|
||||
#
|
||||
# - The original/canonical recipes can be found in /main.mk in the
|
||||
# canonical source tree.
|
||||
all:
|
||||
|
||||
TOP = @abs_top_srcdir@
|
||||
|
||||
PACKAGE_VERSION = @PACKAGE_VERSION@
|
||||
|
||||
#
|
||||
# Filename extensions for binaries and libraries
|
||||
#
|
||||
B.exe = @BUILD_EXEEXT@
|
||||
T.exe = @TARGET_EXEEXT@
|
||||
B.dll = @BUILD_DLLEXT@
|
||||
T.dll = @TARGET_DLLEXT@
|
||||
B.lib = @BUILD_LIBEXT@
|
||||
T.lib = @TARGET_LIBEXT@
|
||||
|
||||
#
|
||||
# Autotools-compatibility dirs
|
||||
#
|
||||
prefix = @prefix@
|
||||
datadir = @datadir@
|
||||
mandir = @mandir@
|
||||
includedir = @includedir@
|
||||
exec_prefix = @exec_prefix@
|
||||
bindir = @bindir@
|
||||
libdir = @libdir@
|
||||
|
||||
#
|
||||
# Required binaries
|
||||
#
|
||||
INSTALL = @BIN_INSTALL@
|
||||
AR = @AR@
|
||||
AR.flags = cr
|
||||
CC = @CC@
|
||||
|
||||
|
||||
ENABLE_LIB_SHARED = @ENABLE_LIB_SHARED@
|
||||
ENABLE_LIB_STATIC = @ENABLE_LIB_STATIC@
|
||||
|
||||
CFLAGS = @CFLAGS@ @CPPFLAGS@
|
||||
#
|
||||
# $(LDFLAGS.configure) represents any LDFLAGS=... the client passes to
|
||||
# configure. See main.mk.
|
||||
#
|
||||
LDFLAGS.configure = @LDFLAGS@
|
||||
|
||||
CFLAGS.core = @SH_CFLAGS@
|
||||
LDFLAGS.shlib = @SH_LDFLAGS@
|
||||
LDFLAGS.zlib = @LDFLAGS_ZLIB@
|
||||
LDFLAGS.math = @LDFLAGS_MATH@
|
||||
LDFLAGS.rpath = @LDFLAGS_RPATH@
|
||||
LDFLAGS.pthread = @LDFLAGS_PTHREAD@
|
||||
LDFLAGS.dlopen = @LDFLAGS_DLOPEN@
|
||||
LDFLAGS.readline = @LDFLAGS_READLINE@
|
||||
CFLAGS.readline = @CFLAGS_READLINE@
|
||||
LDFLAGS.rt = @LDFLAGS_RT@
|
||||
LDFLAGS.icu = @LDFLAGS_ICU@
|
||||
CFLAGS.icu = @CFLAGS_ICU@
|
||||
|
||||
# When cross-compiling, we need to avoid the -s flag because it only
|
||||
# works on the build host's platform.
|
||||
INSTALL.strip.1 = $(INSTALL)
|
||||
INSTALL.strip.0 = $(INSTALL) -s
|
||||
INSTALL.strip = $(INSTALL.strip.@IS_CROSS_COMPILING@)
|
||||
INSTALL.noexec = $(INSTALL) -m 0644
|
||||
|
||||
install-dir.bin = $(DESTDIR)$(bindir)
|
||||
install-dir.lib = $(DESTDIR)$(libdir)
|
||||
install-dir.include = $(DESTDIR)$(includedir)
|
||||
install-dir.pkgconfig = $(DESTDIR)$(libdir)/pkgconfig
|
||||
install-dir.man1 = $(DESTDIR)$(mandir)/man1
|
||||
install-dir.all = $(install-dir.bin) $(install-dir.include) \
|
||||
$(install-dir.lib) $(install-dir.man1) \
|
||||
$(install-dir.pkgconfig)
|
||||
$(install-dir.all):
|
||||
@if [ ! -d "$@" ]; then set -x; $(INSTALL) -d "$@"; fi
|
||||
# ^^^^ on some platforms, install -d fails if the target already exists.
|
||||
|
||||
|
||||
#
|
||||
# Vars with the AS_ prefix are specifically related to AutoSetup.
|
||||
#
|
||||
# AS_AUTO_DEF is the main configure script.
|
||||
#
|
||||
AS_AUTO_DEF = $(TOP)/auto.def
|
||||
|
||||
#
|
||||
# Shell commands to re-run $(TOP)/configure with the same args it was
|
||||
# invoked with to produce this makefile.
|
||||
#
|
||||
AS_AUTORECONFIG = @SQLITE_AUTORECONFIG@
|
||||
Makefile: $(TOP)/Makefile.in $(AS_AUTO_DEF)
|
||||
$(AS_AUTORECONFIG)
|
||||
@touch $@
|
||||
|
||||
sqlite3.pc: $(TOP)/sqlite3.pc.in $(AS_AUTO_DEF)
|
||||
$(AS_AUTORECONFIG)
|
||||
@touch $@
|
||||
|
||||
sqlite_cfg.h: $(AS_AUTO_DEF)
|
||||
$(AS_AUTORECONFIG)
|
||||
@touch $@
|
||||
|
||||
#
|
||||
# CFLAGS for sqlite3$(T.exe)
|
||||
#
|
||||
SHELL_OPT ?= @OPT_SHELL@
|
||||
|
||||
#
|
||||
# Library-level feature flags
|
||||
#
|
||||
OPT_FEATURE_FLAGS = @OPT_FEATURE_FLAGS@
|
||||
|
||||
LDFLAGS.libsqlite3.soname = @LDFLAGS_LIBSQLITE3_SONAME@
|
||||
# soname: see https://sqlite.org/src/forumpost/5a3b44f510df8ded
|
||||
LDFLAGS.libsqlite3.os-specific = @LDFLAGS_MAC_CVERSION@ @LDFLAGS_OUT_IMPLIB@
|
||||
# os-specific: see
|
||||
# - https://sqlite.org/forum/forumpost/9dfd5b8fd525a5d7
|
||||
# - https://sqlite.org/forum/forumpost/0c7fc097b2
|
||||
|
||||
LDFLAGS.libsqlite3 = \
|
||||
$(LDFLAGS.rpath) $(LDFLAGS.pthread) \
|
||||
$(LDFLAGS.math) $(LDFLAGS.dlopen) \
|
||||
$(LDFLAGS.zlib) $(LDFLAGS.icu) \
|
||||
$(LDFLAGS.rt) $(LDFLAGS.configure)
|
||||
CFLAGS.libsqlite3 = -I. $(CFLAGS.core) $(CFLAGS.icu) $(OPT_FEATURE_FLAGS)
|
||||
|
||||
sqlite3.o: $(TOP)/sqlite3.h $(TOP)/sqlite3.c
|
||||
$(CC) -c $(TOP)/sqlite3.c -o $@ $(CFLAGS) $(CFLAGS.libsqlite3)
|
||||
|
||||
libsqlite3.LIB = libsqlite3$(T.lib)
|
||||
libsqlite3.SO = libsqlite3$(T.dll)
|
||||
|
||||
$(libsqlite3.SO): sqlite3.o
|
||||
$(CC) -o $@ sqlite3.o $(LDFLAGS.shlib) \
|
||||
$(LDFLAGS) $(LDFLAGS.libsqlite3) \
|
||||
$(LDFLAGS.libsqlite3.os-specific) $(LDFLAGS.libsqlite3.soname)
|
||||
all: $(libsqlite3.SO)
|
||||
|
||||
$(libsqlite3.LIB): sqlite3.o
|
||||
$(AR) $(AR.flags) $@ sqlite3.o
|
||||
all: $(libsqlite3.LIB)
|
||||
|
||||
install-so-1: $(install-dir.lib) $(libsqlite3.SO)
|
||||
$(INSTALL) $(libsqlite3.SO) "$(install-dir.lib)"
|
||||
@if [ -f $(libsqlite3.SO).a ]; then \
|
||||
$(INSTALL) $(libsqlite3.SO).a "$(install-dir.lib)"; \
|
||||
fi
|
||||
@echo "Setting up $(libsqlite3.SO) version symlinks..."; \
|
||||
if [ x.dll = x$(T.dll) ]; then \
|
||||
echo "No library symlinks needed on this platform"; \
|
||||
elif [ x.dylib = x$(T.dll) ]; then \
|
||||
cd "$(install-dir.lib)" || exit $$?; \
|
||||
rm -f libsqlite3.0$(T.dll) libsqlite3.$(PACKAGE_VERSION)$(T.dll) || exit $$?; \
|
||||
dllname=libsqlite3.$(PACKAGE_VERSION)$(T.dll); \
|
||||
mv $(libsqlite3.SO) $$dllname || exit $$?; \
|
||||
ln -s $$dllname $(libsqlite3.SO) || exit $$?; \
|
||||
ln -s $$dllname libsqlite3.0$(T.dll) || exit $$?; \
|
||||
ls -la $$dllname $(libsqlite3.SO) libsqlite3.0$(T.dll); \
|
||||
else \
|
||||
cd "$(install-dir.lib)" || exit $$?; \
|
||||
rm -f $(libsqlite3.SO).0 $(libsqlite3.SO).$(PACKAGE_VERSION) || exit $$?; \
|
||||
mv $(libsqlite3.SO) $(libsqlite3.SO).$(PACKAGE_VERSION) || exit $$?; \
|
||||
ln -s $(libsqlite3.SO).$(PACKAGE_VERSION) $(libsqlite3.SO) || exit $$?; \
|
||||
ln -s $(libsqlite3.SO).$(PACKAGE_VERSION) $(libsqlite3.SO).0 || exit $$?; \
|
||||
ls -la $(libsqlite3.SO) $(libsqlite3.SO).[a03]*; \
|
||||
if [ -e $(libsqlite3.SO).0.8.6 ]; then \
|
||||
echo "ACHTUNG: legacy libtool-compatible install found. Re-linking it..."; \
|
||||
rm -f libsqlite3.la $(libsqlite3.SO).0.8.6 || exit $$?; \
|
||||
ln -s $(libsqlite3.SO).$(PACKAGE_VERSION) $(libsqlite3.SO).0.8.6 || exit $$?; \
|
||||
ls -la $(libsqlite3.SO).0.8.6; \
|
||||
elif [ x1 = "x$(INSTALL_SO_086_LINK)" ]; then \
|
||||
echo "ACHTUNG: installing legacy libtool-style links because INSTALL_SO_086_LINK=1"; \
|
||||
rm -f libsqlite3.la $(libsqlite3.SO).0.8.6 || exit $$?; \
|
||||
ln -s $(libsqlite3.SO).$(PACKAGE_VERSION) $(libsqlite3.SO).0.8.6 || exit $$?; \
|
||||
ls -la $(libsqlite3.SO).0.8.6; \
|
||||
fi; \
|
||||
fi
|
||||
|
||||
install-so-0 install-so-:
|
||||
install-so: install-so-$(ENABLE_LIB_SHARED)
|
||||
install: install-so
|
||||
|
||||
install-lib-1: $(install-dir.lib) $(libsqlite3.LIB)
|
||||
$(INSTALL.noexec) $(libsqlite3.LIB) "$(install-dir.lib)"
|
||||
install-lib-0 install-lib-:
|
||||
install-lib: install-lib-$(ENABLE_LIB_STATIC)
|
||||
install: install-lib
|
||||
|
||||
|
||||
# Flags to link the shell app either directly against sqlite3.c
|
||||
# (ENABLE_STATIC_SHELL==1) or libsqlite3.so (ENABLE_STATIC_SHELL==0).
|
||||
#
|
||||
ENABLE_STATIC_SHELL = @ENABLE_STATIC_SHELL@
|
||||
sqlite3-shell-link-flags.1 = $(TOP)/sqlite3.c $(LDFLAGS.libsqlite3)
|
||||
sqlite3-shell-link-flags.0 = -L. -lsqlite3 $(LDFLAGS.zlib)
|
||||
sqlite3-shell-deps.1 = $(TOP)/sqlite3.c
|
||||
sqlite3-shell-deps.0 = $(libsqlite3.SO)
|
||||
sqlite3$(T.exe): $(TOP)/shell.c $(sqlite3-shell-deps.$(ENABLE_STATIC_SHELL))
|
||||
$(CC) -o $@ \
|
||||
$(TOP)/shell.c $(sqlite3-shell-link-flags.$(ENABLE_STATIC_SHELL)) \
|
||||
-I. $(OPT_FEATURE_FLAGS) $(SHELL_OPT) \
|
||||
$(CFLAGS) $(CFLAGS.readline) $(CFLAGS.icu) \
|
||||
$(LDFLAGS) $(LDFLAGS.readline)
|
||||
|
||||
all: sqlite3$(T.exe)
|
||||
|
||||
install-shell: sqlite3$(T.exe) $(install-dir.bin)
|
||||
$(INSTALL.strip) sqlite3$(T.exe) "$(install-dir.bin)"
|
||||
install: install-shell
|
||||
|
||||
install-headers: $(TOP)/sqlite3.h $(install-dir.include)
|
||||
$(INSTALL.noexec) $(TOP)/sqlite3.h $(TOP)/sqlite3ext.h "$(install-dir.include)"
|
||||
install: install-headers
|
||||
|
||||
install-pc: sqlite3.pc $(install-dir.pkgconfig)
|
||||
$(INSTALL.noexec) sqlite3.pc "$(install-dir.pkgconfig)"
|
||||
install: install-pc
|
||||
|
||||
install-man1: $(TOP)/sqlite3.1 $(install-dir.man1)
|
||||
$(INSTALL.noexec) $(TOP)/sqlite3.1 "$(install-dir.man1)"
|
||||
install: install-man1
|
||||
|
||||
clean:
|
||||
rm -f *.o sqlite3$(T.exe)
|
||||
rm -f $(libsqlite3.LIB) $(libsqlite3.SO) $(libsqlite3.SO).a
|
||||
|
||||
distclean: clean
|
||||
rm -f jimsh0$(T.exe) config.* sqlite3.pc sqlite_cfg.h Makefile
|
||||
|
||||
DIST_FILES := \
|
||||
README.txt VERSION \
|
||||
auto.def autosetup configure tea \
|
||||
sqlite3.h sqlite3.c shell.c sqlite3ext.h \
|
||||
Makefile.in Makefile.msc Makefile.fallback \
|
||||
sqlite3.rc sqlite3rc.h Replace.cs \
|
||||
sqlite3.pc.in sqlite3.1
|
||||
|
||||
# Maintenance note: dist_name must be sqlite-$(PACKAGE_VERSION) so
|
||||
# that tool/mkautoconfamal.sh knows how to find it.
|
||||
dist_name = sqlite-$(PACKAGE_VERSION)
|
||||
dist_tarball = $(dist_name).tar.gz
|
||||
dist:
|
||||
rm -fr $(dist_name)
|
||||
mkdir -p $(dist_name)
|
||||
cp -rp $(DIST_FILES) $(dist_name)/.
|
||||
rm -f $(dist_name)/tea/configure.ac.in
|
||||
tar czf $(dist_tarball) $(dist_name)
|
||||
rm -fr $(dist_name)
|
||||
ls -l $(dist_tarball)
|
||||
+10
-11
@@ -19,7 +19,9 @@ TOP = .
|
||||
|
||||
|
||||
# Optionally set EXTRA_SRC to a list of C files to append to
|
||||
# the generated sqlite3.c.
|
||||
# the generated sqlite3.c. Any sqlite3 extensions added this
|
||||
# way may require manual editing, as described in
|
||||
# https://sqlite.org/forum/forumpost/903f721f3e7c0d25
|
||||
#
|
||||
!IFNDEF EXTRA_SRC
|
||||
EXTRA_SRC =
|
||||
@@ -799,15 +801,6 @@ RCC = $(RCC) -DSQLITE_THREAD_OVERRIDE_LOCK=-1
|
||||
TLIBS =
|
||||
!ENDIF
|
||||
|
||||
# Flags controlling use of the in memory btree implementation
|
||||
#
|
||||
# SQLITE_TEMP_STORE is 0 to force temporary tables to be in a file, 1 to
|
||||
# default to file, 2 to default to memory, and 3 to force temporary
|
||||
# tables to always be in memory.
|
||||
#
|
||||
TCC = $(TCC) -DSQLITE_TEMP_STORE=1
|
||||
RCC = $(RCC) -DSQLITE_TEMP_STORE=1
|
||||
|
||||
# Enable/disable loadable extensions, and other optional features
|
||||
# based on configuration. (-DSQLITE_OMIT*, -DSQLITE_ENABLE*).
|
||||
# The same set of OMIT and ENABLE flags should be passed to the
|
||||
@@ -1039,6 +1032,11 @@ dll: $(SQLITE3DLL)
|
||||
#
|
||||
shell: $(SQLITE3EXE)
|
||||
|
||||
# jimsh0 - replacement for tclsh
|
||||
#
|
||||
jimsh0.exe: $(TOP)\autosetup\jimsh0.c
|
||||
cl -DHAVE__FULLPATH=1 $(TOP)\autosetup\jimsh0.c
|
||||
|
||||
|
||||
$(SQLITE3DLL): $(LIBOBJ) $(LIBRESOBJS) $(CORE_LINK_DEP)
|
||||
$(LD) $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) /DLL $(CORE_LINK_OPTS) /OUT:$@ $(LIBOBJ) $(LIBRESOBJS) $(LTLIBS) $(TLIBS)
|
||||
@@ -1089,5 +1087,6 @@ $(LIBRESOBJS): $(TOP)\sqlite3.rc rcver.vc $(SQLITE3H)
|
||||
|
||||
clean:
|
||||
del /Q *.exp *.lo *.ilk *.lib *.obj *.ncb *.pdb *.sdf *.suo 2>NUL
|
||||
del /Q *.bsc *.def *.cod *.da *.bb *.bbg *.vc gmon.out 2>NUL
|
||||
del /Q *.bsc *.cod *.da *.bb *.bbg *.vc gmon.out 2>NUL
|
||||
del /Q sqlite3.def tclsqlite3.def 2>NUL
|
||||
del /Q $(SQLITE3EXE) $(SQLITE3DLL) Replace.exe 2>NUL
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
This directory contains components use to build an autoconf-ready package
|
||||
of the SQLite amalgamation: sqlite-autoconf-30XXXXXX.tar.gz
|
||||
This directory contains components used to build an autoconf-like
|
||||
package of the SQLite amalgamation: sqlite-autoconf-30XXXXXX.tar.gz
|
||||
|
||||
To build the autoconf amalgamation, run from the top-level:
|
||||
To build the autoconf amalgamation, run from the top of the canonical
|
||||
source tree:
|
||||
|
||||
./configure
|
||||
make amalgamation-tarball
|
||||
|
||||
The amalgamation-tarball target (also available in "main.mk") runs the
|
||||
script tool/mkautoconfamal.sh which does the work. Refer to that script
|
||||
for details.
|
||||
The amalgamation-tarball target (available in "main.mk") runs the
|
||||
script tool/mkautoconfamal.sh which does the work. Refer to that
|
||||
script for details.
|
||||
|
||||
+13
-12
@@ -4,7 +4,7 @@ This package contains:
|
||||
* the sqlite3.h and sqlite3ext.h header files that define the C-language
|
||||
interface to the sqlite3.c library file
|
||||
* the shell.c file used to build the sqlite3 command-line shell program
|
||||
* autoconf/automake installation infrastucture for building on POSIX
|
||||
* autoconf-like installation infrastucture for building on POSIX
|
||||
compliant systems
|
||||
* a Makefile.msc, sqlite3.rc, and Replace.cs for building with Microsoft
|
||||
Visual C++ on Windows
|
||||
@@ -19,8 +19,10 @@ using only generic tools and without having to install TCL. The purpose
|
||||
of this package is to provide that capability.
|
||||
|
||||
This package contains a pre-build SQLite amalgamation file "sqlite3.c"
|
||||
(and its associated header file "sqlite3.h"). Because the amalgamation
|
||||
has been pre-built, no TCL is required.
|
||||
(and its associated header file "sqlite3.h"). Because the
|
||||
amalgamation has been pre-built, no TCL is required for the code
|
||||
generate (the configure script itself is written in TCL but it can use
|
||||
the embedded copy of JimTCL).
|
||||
|
||||
REASONS TO USE THE CANONICAL BUILD SYSTEM RATHER THAN THIS PACKAGE
|
||||
==================================================================
|
||||
@@ -47,14 +49,12 @@ SUMMARY OF HOW TO BUILD USING THIS PACKAGE
|
||||
BUILDING ON POSIX
|
||||
=================
|
||||
|
||||
The generic installation instructions for autoconf/automake are found
|
||||
in the INSTALL file.
|
||||
The configure script follows common conventions, making it easy
|
||||
to use for anyone who has configured a software tree before.
|
||||
It supports a number of build-time flags, the full list of which
|
||||
can be seen by running:
|
||||
|
||||
The following SQLite specific boolean options are supported:
|
||||
|
||||
--enable-readline use readline in shell tool [default=yes]
|
||||
--enable-threadsafe build a thread-safe library [default=yes]
|
||||
--enable-dynamic-extensions support loadable extensions [default=yes]
|
||||
./configure --help
|
||||
|
||||
The default value for the CFLAGS variable (options passed to the C
|
||||
compiler) includes debugging symbols in the build, resulting in larger
|
||||
@@ -65,10 +65,11 @@ line like this:
|
||||
|
||||
to produce a smaller installation footprint.
|
||||
|
||||
Other SQLite compilation parameters can also be set using CFLAGS. For
|
||||
Many SQLite compilation parameters can be defined by passing flags
|
||||
to the configure script. Others may be passed on in the CFLAGS. For
|
||||
example:
|
||||
|
||||
$ CFLAGS="-Os -DSQLITE_THREADSAFE=0" ./configure
|
||||
$ CFLAGS="-Os -DSQLITE_OMIT_DEPRECATED" ./configure
|
||||
|
||||
|
||||
BUILDING WITH MICROSOFT VISUAL C++
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
#!/do/not/tclsh
|
||||
# ^^^ help out editors which guess this file's content type.
|
||||
#
|
||||
# This is the main autosetup-compatible configure script for the
|
||||
# "autoconf" bundle of the SQLite project.
|
||||
#
|
||||
# This script must be kept compatible with JimTCL, a copy of which is
|
||||
# included in this source tree as ./autosetup/jimsh0.c.
|
||||
#
|
||||
use sqlite-config
|
||||
sqlite-config-bootstrap autoconf
|
||||
sqlite-check-common-bins
|
||||
sqlite-check-common-system-deps
|
||||
proj-check-rpath
|
||||
sqlite-handle-soname
|
||||
sqlite-setup-default-cflags
|
||||
sqlite-handle-debug
|
||||
sqlite-handle-threadsafe
|
||||
sqlite-handle-tempstore
|
||||
sqlite-handle-line-editing
|
||||
sqlite-handle-load-extension
|
||||
sqlite-handle-math
|
||||
sqlite-handle-icu
|
||||
|
||||
define ENABLE_STATIC_SHELL [opt-bool static-shell]
|
||||
define ENABLE_LIB_SHARED [opt-bool shared]
|
||||
define ENABLE_LIB_STATIC [opt-bool static]
|
||||
|
||||
sqlite-config-finalize
|
||||
@@ -1,270 +0,0 @@
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Supports the following non-standard switches.
|
||||
#
|
||||
# --enable-threadsafe
|
||||
# --enable-readline
|
||||
# --enable-editline
|
||||
# --enable-static-shell
|
||||
# --enable-dynamic-extensions
|
||||
#
|
||||
|
||||
AC_PREREQ(2.61)
|
||||
AC_INIT(sqlite, --SQLITE-VERSION--, http://www.sqlite.org)
|
||||
AC_CONFIG_SRCDIR([sqlite3.c])
|
||||
AC_CONFIG_AUX_DIR([.])
|
||||
|
||||
# Use automake.
|
||||
AM_INIT_AUTOMAKE([foreign])
|
||||
|
||||
AC_SYS_LARGEFILE
|
||||
|
||||
# Check for required programs.
|
||||
AC_PROG_CC
|
||||
AC_PROG_LIBTOOL
|
||||
AC_PROG_MKDIR_P
|
||||
|
||||
# Check for library functions that SQLite can optionally use.
|
||||
AC_CHECK_FUNCS([fdatasync usleep fullfsync localtime_r gmtime_r])
|
||||
AC_FUNC_STRERROR_R
|
||||
|
||||
AC_CONFIG_FILES([Makefile sqlite3.pc])
|
||||
BUILD_CFLAGS=
|
||||
AC_SUBST(BUILD_CFLAGS)
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Two options to enable readline compatible libraries:
|
||||
#
|
||||
# --enable-editline
|
||||
# --enable-readline
|
||||
#
|
||||
# Both are enabled by default. If, after command line processing both are
|
||||
# still enabled, the script searches for editline first and automatically
|
||||
# disables readline if it is found. So, to use readline explicitly, the
|
||||
# user must pass "--disable-editline". To disable command line editing
|
||||
# support altogether, "--disable-editline --disable-readline".
|
||||
#
|
||||
# When searching for either library, check for headers before libraries
|
||||
# as some distros supply packages that contain libraries but not header
|
||||
# files, which come as a separate development package.
|
||||
#
|
||||
AC_ARG_ENABLE(editline, [AS_HELP_STRING([--enable-editline],[use BSD libedit])])
|
||||
AC_ARG_ENABLE(readline, [AS_HELP_STRING([--enable-readline],[use readline])])
|
||||
|
||||
AS_IF([ test x"$enable_editline" != xno ],[
|
||||
AC_CHECK_HEADERS([editline/readline.h],[
|
||||
sLIBS=$LIBS
|
||||
LIBS=""
|
||||
AC_SEARCH_LIBS([readline],[edit],[
|
||||
AC_DEFINE([HAVE_EDITLINE],1,Define to use BSD editline)
|
||||
READLINE_LIBS="$LIBS -ltinfo"
|
||||
enable_readline=no
|
||||
],[],[-ltinfo])
|
||||
AS_UNSET(ac_cv_search_readline)
|
||||
LIBS=$sLIBS
|
||||
])
|
||||
])
|
||||
|
||||
AS_IF([ test x"$enable_readline" != xno ],[
|
||||
AC_CHECK_HEADERS([readline/readline.h],[
|
||||
sLIBS=$LIBS
|
||||
LIBS=""
|
||||
AC_SEARCH_LIBS(tgetent, termcap curses ncurses ncursesw, [], [])
|
||||
AC_SEARCH_LIBS(readline,[readline edit], [
|
||||
AC_DEFINE([HAVE_READLINE],1,Define to use readline or wrapper)
|
||||
READLINE_LIBS=$LIBS
|
||||
])
|
||||
LIBS=$sLIBS
|
||||
])
|
||||
])
|
||||
|
||||
AC_SUBST(READLINE_LIBS)
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# --enable-threadsafe
|
||||
#
|
||||
AC_ARG_ENABLE(threadsafe, [AS_HELP_STRING(
|
||||
[--enable-threadsafe], [build a thread-safe library [default=yes]])],
|
||||
[], [enable_threadsafe=yes])
|
||||
if test x"$enable_threadsafe" == "xno"; then
|
||||
BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_THREADSAFE=0"
|
||||
else
|
||||
BUILD_CFLAGS="$BUILD_CFLAGS -D_REENTRANT=1 -DSQLITE_THREADSAFE=1"
|
||||
AC_SEARCH_LIBS(pthread_create, pthread)
|
||||
AC_SEARCH_LIBS(pthread_mutexattr_init, pthread)
|
||||
fi
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# --enable-dynamic-extensions
|
||||
#
|
||||
AC_ARG_ENABLE(dynamic-extensions, [AS_HELP_STRING(
|
||||
[--enable-dynamic-extensions], [support loadable extensions [default=yes]])],
|
||||
[], [enable_dynamic_extensions=yes])
|
||||
if test x"$enable_dynamic_extensions" != "xno"; then
|
||||
AC_SEARCH_LIBS(dlopen, dl)
|
||||
else
|
||||
BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_OMIT_LOAD_EXTENSION=1"
|
||||
fi
|
||||
AC_MSG_CHECKING([for whether to support dynamic extensions])
|
||||
AC_MSG_RESULT($enable_dynamic_extensions)
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# --enable-math
|
||||
#
|
||||
AC_ARG_ENABLE(math, [AS_HELP_STRING(
|
||||
[--enable-math], [SQL math functions [default=yes]])],
|
||||
[], [enable_math=yes])
|
||||
AC_MSG_CHECKING([SQL math functions])
|
||||
if test x"$enable_math" = "xyes"; then
|
||||
BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_ENABLE_MATH_FUNCTIONS"
|
||||
AC_MSG_RESULT([enabled])
|
||||
AC_SEARCH_LIBS(ceil, m)
|
||||
else
|
||||
AC_MSG_RESULT([disabled])
|
||||
fi
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# --enable-fts4
|
||||
#
|
||||
AC_ARG_ENABLE(fts4, [AS_HELP_STRING(
|
||||
[--enable-fts4], [include fts4 support [default=yes]])],
|
||||
[], [enable_fts4=yes])
|
||||
AC_MSG_CHECKING([FTS4 extension])
|
||||
if test x"$enable_fts4" = "xyes"; then
|
||||
BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_ENABLE_FTS4"
|
||||
AC_MSG_RESULT([enabled])
|
||||
else
|
||||
AC_MSG_RESULT([disabled])
|
||||
fi
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# --enable-fts3
|
||||
#
|
||||
AC_ARG_ENABLE(fts3, [AS_HELP_STRING(
|
||||
[--enable-fts3], [include fts3 support [default=no]])],
|
||||
[], [])
|
||||
AC_MSG_CHECKING([FTS3 extension])
|
||||
if test x"$enable_fts3" = "xyes" -a x"$enable_fts4" = "xno"; then
|
||||
BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_ENABLE_FTS3"
|
||||
AC_MSG_RESULT([enabled])
|
||||
else
|
||||
AC_MSG_RESULT([disabled])
|
||||
fi
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# --enable-fts5
|
||||
#
|
||||
AC_ARG_ENABLE(fts5, [AS_HELP_STRING(
|
||||
[--enable-fts5], [include fts5 support [default=yes]])],
|
||||
[], [enable_fts5=yes])
|
||||
AC_MSG_CHECKING([FTS5 extension])
|
||||
if test x"$enable_fts5" = "xyes"; then
|
||||
AC_MSG_RESULT([enabled])
|
||||
AC_SEARCH_LIBS(log, m)
|
||||
BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_ENABLE_FTS5"
|
||||
else
|
||||
AC_MSG_RESULT([disabled])
|
||||
fi
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# --enable-rtree
|
||||
#
|
||||
AC_ARG_ENABLE(rtree, [AS_HELP_STRING(
|
||||
[--enable-rtree], [include rtree support [default=yes]])],
|
||||
[], [enable_rtree=yes])
|
||||
AC_MSG_CHECKING([RTREE extension])
|
||||
if test x"$enable_rtree" = "xyes"; then
|
||||
BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_ENABLE_RTREE -DSQLITE_ENABLE_GEOPOLY"
|
||||
AC_MSG_RESULT([enabled])
|
||||
else
|
||||
AC_MSG_RESULT([disabled])
|
||||
fi
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# --enable-session
|
||||
#
|
||||
AC_ARG_ENABLE(session, [AS_HELP_STRING(
|
||||
[--enable-session], [enable the session extension [default=no]])],
|
||||
[], [])
|
||||
AC_MSG_CHECKING([Session extension])
|
||||
if test x"$enable_session" = "xyes"; then
|
||||
BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_ENABLE_SESSION -DSQLITE_ENABLE_PREUPDATE_HOOK"
|
||||
AC_MSG_RESULT([enabled])
|
||||
else
|
||||
AC_MSG_RESULT([disabled])
|
||||
fi
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# --enable-debug
|
||||
#
|
||||
AC_ARG_ENABLE(debug, [AS_HELP_STRING(
|
||||
[--enable-debug], [build with debugging features enabled [default=no]])],
|
||||
[], [])
|
||||
AC_MSG_CHECKING([Build type])
|
||||
if test x"$enable_debug" = "xyes"; then
|
||||
BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_DEBUG -DSQLITE_ENABLE_SELECTTRACE -DSQLITE_ENABLE_WHERETRACE"
|
||||
CFLAGS="-g -O0"
|
||||
AC_MSG_RESULT([debug])
|
||||
else
|
||||
AC_MSG_RESULT([release])
|
||||
fi
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# --enable-static-shell
|
||||
#
|
||||
AC_ARG_ENABLE(static-shell, [AS_HELP_STRING(
|
||||
[--enable-static-shell],
|
||||
[statically link libsqlite3 into shell tool [default=yes]])],
|
||||
[], [enable_static_shell=yes])
|
||||
if test x"$enable_static_shell" = "xyes"; then
|
||||
EXTRA_SHELL_OBJ=sqlite3-sqlite3.$OBJEXT
|
||||
else
|
||||
EXTRA_SHELL_OBJ=libsqlite3.la
|
||||
fi
|
||||
AC_SUBST(EXTRA_SHELL_OBJ)
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
AC_CHECK_FUNCS(posix_fallocate)
|
||||
AC_CHECK_HEADERS(zlib.h,[
|
||||
AC_SEARCH_LIBS(deflate,z,[BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_HAVE_ZLIB"])
|
||||
])
|
||||
|
||||
AC_SEARCH_LIBS(system,,,[SHELL_CFLAGS="-DSQLITE_NOHAVE_SYSTEM"])
|
||||
AC_SUBST(SHELL_CFLAGS)
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# UPDATE: Maybe it's better if users just set CFLAGS before invoking
|
||||
# configure. This option doesn't really add much...
|
||||
#
|
||||
# --enable-tempstore
|
||||
#
|
||||
# AC_ARG_ENABLE(tempstore, [AS_HELP_STRING(
|
||||
# [--enable-tempstore],
|
||||
# [in-memory temporary tables (never, no, yes, always) [default=no]])],
|
||||
# [], [enable_tempstore=no])
|
||||
# AC_MSG_CHECKING([for whether or not to store temp tables in-memory])
|
||||
# case "$enable_tempstore" in
|
||||
# never ) TEMP_STORE=0 ;;
|
||||
# no ) TEMP_STORE=1 ;;
|
||||
# always ) TEMP_STORE=3 ;;
|
||||
# yes ) TEMP_STORE=3 ;;
|
||||
# * )
|
||||
# TEMP_STORE=1
|
||||
# enable_tempstore=yes
|
||||
# ;;
|
||||
# esac
|
||||
# AC_MSG_RESULT($enable_tempstore)
|
||||
# AC_SUBST(TEMP_STORE)
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
AC_OUTPUT
|
||||
@@ -19,7 +19,7 @@ dnl to configure the system for the local environment.
|
||||
# so that we create the export library with the dll.
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
AC_INIT([sqlite],[3.47.0])
|
||||
AC_INIT([sqlite],[@VERSION@])
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# Call TEA_INIT as the first TEA_ macro to set up initial vars.
|
||||
@@ -0,0 +1,35 @@
|
||||
Unless explicitly stated, all files which form part of autosetup
|
||||
are released under the following license:
|
||||
|
||||
---------------------------------------------------------------------
|
||||
autosetup - A build environment "autoconfigurator"
|
||||
|
||||
Copyright (c) 2010-2011, WorkWare Systems <http://workware.net.au/>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer in the documentation and/or other materials
|
||||
provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE WORKWARE SYSTEMS ``AS IS'' AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WORKWARE
|
||||
SYSTEMS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
The views and conclusions contained in the software and documentation
|
||||
are those of the authors and should not be interpreted as representing
|
||||
official policies, either expressed or implied, of WorkWare Systems.
|
||||
@@ -0,0 +1,11 @@
|
||||
README.autosetup created by autosetup v0.7.2
|
||||
|
||||
This is the autosetup directory for a local install of autosetup.
|
||||
It contains autosetup, support files and loadable modules.
|
||||
|
||||
*.tcl files in this directory are optional modules which
|
||||
can be loaded with the 'use' directive.
|
||||
|
||||
*.auto files in this directory are auto-loaded.
|
||||
|
||||
For more information, see https://msteveb.github.io/autosetup/
|
||||
@@ -0,0 +1,380 @@
|
||||
Maintaining Autosetup in the SQLite Tree
|
||||
========================================================================
|
||||
|
||||
This document provides some tips and reminders for the SQLite
|
||||
developers regarding using and maintaining the [Autosetup][]-based
|
||||
build infrastructure. It is not an [Autosetup][] reference.
|
||||
|
||||
**Table of Contents**:
|
||||
|
||||
- [Autosetup API Reference](#apiref)
|
||||
- [API Tips](#apitips)
|
||||
- [Ensuring TCL Compatibility](#tclcompat)
|
||||
- [Design Conventions](#conventions)
|
||||
- Symbolic Names of Feature Flags
|
||||
- Do Not Update Global Shared State
|
||||
- [Updating Autosetup](#updating)
|
||||
- [Patching Autosetup for Project-local changes](#patching)
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
<a name="apiref"></a>
|
||||
Autosetup API Reference
|
||||
========================================================================
|
||||
|
||||
The Autosetup API is quite extensive and can be read either in
|
||||
the [files in the `autosetup` dir](/dir/autosetup) or using:
|
||||
|
||||
>
|
||||
```
|
||||
$ ./configure --reference | less
|
||||
```
|
||||
|
||||
That will include any docs from any TCL files in the `./autosetup` dir
|
||||
which contain certain (simple) markup defined by autosetup.
|
||||
|
||||
This project's own configuration-related TCL code is spread across the
|
||||
following files:
|
||||
|
||||
- [proj.tcl][]: project-agnostic utility code for autosetup-driven
|
||||
projects. This file is designed to be shared between this project,
|
||||
other projects managed under the SQLite/Hwaci umbrella
|
||||
(e.g. Fossil), and personal projects of SQLite's developers. It is
|
||||
essentially an amalgamation of a decade's worth of autosetup-related
|
||||
utility code.
|
||||
- [auto.def][]: the primary driver for the `./configure` process.
|
||||
When we talk about "the configure script," we're referring to
|
||||
this file.
|
||||
- [sqlite-config.tcl][]: utility code which is too project-specific
|
||||
for `proj.tcl`. We split this out of `auto.def` so that it can be
|
||||
used by both `auto.def` and...
|
||||
- [autoconf/auto.def][]: the main driver script for the "autoconf"
|
||||
bundle's configure script. It is essentially a slightly trimmed-down
|
||||
version of the main `auto.def` file. The `autoconf` dir was ported
|
||||
from the Autotools to Autosetup in the 3.49.0 dev cycle but retains
|
||||
the "autoconf" name to minimize downstream disruption.
|
||||
|
||||
|
||||
<a name="apitips"></a>
|
||||
Autosetup API Tips
|
||||
========================================================================
|
||||
|
||||
This section briefly covers only APIs which are frequently useful in
|
||||
day-to-day maintenance and might not be immediately recognized as such
|
||||
obvious from a casual perusal of the relevant TCL files. The complete
|
||||
docs of those with `proj-` prefix can be found in [proj.tcl][] and
|
||||
those with an `sqlite-` prefix are in [sqlite-config.tcl][]. The
|
||||
others are scattered around [the TCL files in
|
||||
./autosetup](/dir/autosetup).
|
||||
|
||||
In (mostly) alphabetical order:
|
||||
|
||||
- **`file-isexec filename`**\
|
||||
Should be used in place of `[file executable]`, as it will also
|
||||
check for `${filename}.exe` on Windows platforms. However, on such
|
||||
platforms it also assumes that _any_ existing file is executable.
|
||||
|
||||
- **`get-env VAR ?default?`**\
|
||||
Will fetch an "environment variable" from the first of either: (1) a
|
||||
KEY=VALUE passed to the configure script or (2) the system's
|
||||
environment variables. Not to be confused with `getenv`, which only
|
||||
does the latter and is rarely, if ever, useful in this tree.
|
||||
- **`proj-get-env VAR ?default?`**\
|
||||
Works like `get-env` but will, if that function finds no match,
|
||||
look for a file named `./.env-$VAR` and, if found, return its
|
||||
trimmed contents. This can be used, e.g., to set a developer's
|
||||
local preferences for the default `CFLAGS`.
|
||||
|
||||
- **`define-for-opt flag defineName ?checkingMsg? ?yesVal=1? ?noVal=0?`**\
|
||||
`[define $defineName]` to either `$yesVal` or `$noVal`, depending on
|
||||
whether `--$flag` is truthy or not. `$checkingMsg` is a
|
||||
human-readable description of the check being made, e.g. "enable foo?"
|
||||
If no `checkingMsg` is provided, the operation is silent.\
|
||||
Potential TODO: change the final two args to `-yes` and `-no`
|
||||
flags. They're rarely needed, though: search [auto.def][] for
|
||||
`TSTRNNR_OPTS` for an example of where they are used.
|
||||
|
||||
- **`proj-fatal msg`**\
|
||||
Emits `$msg` to stderr and exits with non-zero.
|
||||
|
||||
- **`proj-if-opt-truthy flag thenScript ?elseScript?`**\
|
||||
Evals `thenScript` if the given `--flag` is truthy, else it
|
||||
evals the optional `elseScript`.
|
||||
|
||||
- **`proj-indented-notice ?-error? ?-notice? msg`**\
|
||||
Breaks its `msg` argument into lines, trims them, and emits them
|
||||
with consistent indentation. Exactly how it emits depends on the
|
||||
flags passed to it (or not), as covered in its docs. This will stick
|
||||
out starkly from normal output and is intended to be used only for
|
||||
important notices.
|
||||
|
||||
- **`proj-opt-truthy flag`**\
|
||||
Returns 1 if `--flag`'s value is "truthy," i.e. one of (1, on,
|
||||
enabled, yes, true).
|
||||
|
||||
- **`proj-opt-was-provided FLAG`**\
|
||||
Returns 1 if `--FLAG` was explicitly provided to configure,
|
||||
else 0. This distinction can be used to determine, e.g., whether
|
||||
`--with-readline` was provided or whether we're searching for
|
||||
readline by default. In the former case, failure to find it should
|
||||
be treated as fatal, where in the latter case it's not.
|
||||
|
||||
- **`proj-val-truthy value`**\
|
||||
Returns 1 if `$value` is "truthy," See `proj-opt-truthy` for the definition
|
||||
of "truthy."
|
||||
|
||||
- **`proj-warn msg`**\
|
||||
Emits `$msg` to stderr. Closely-related is autosetup's `user-notice`
|
||||
(described below).
|
||||
|
||||
- **`sqlite-add-feature-flag ?-shell? FLAG...`**\
|
||||
Adds the given feature flag to the CFLAGS which are specific to
|
||||
building libsqlite3. It's intended to be passed one or more
|
||||
`-DSQLITE_ENABLE_...`, or similar, flags. If the `-shell` flag is
|
||||
used then it also passes its arguments to
|
||||
`sqlite-add-shell-opt`. This is a no-op if `FLAG` is not provided or
|
||||
is empty.
|
||||
|
||||
- **`sqlite-add-shell-opt FLAG...`**\
|
||||
The shell-specific counterpart of `sqlite-add-feature-flag` which
|
||||
only adds the given flag(s) to the CLI-shell-specific CFLAGS.
|
||||
|
||||
- **`user-notice msg`**\
|
||||
Queues `$msg` to be sent to stderr, but does not emit it until
|
||||
either `show-notices` is called or the next time autosetup would
|
||||
output something (it internally calls `show-notices`). This can be
|
||||
used to generate warnings between a "checking for..." message and
|
||||
its resulting "yes/no/whatever" message in such a way as to not
|
||||
spoil the layout of such messages.
|
||||
|
||||
|
||||
<a name="tclcompat"></a>
|
||||
Ensuring TCL Compatibility
|
||||
========================================================================
|
||||
|
||||
It is important that any TCL files used by the configure process
|
||||
remain compatible with both [JimTCL][] and the canonical TCL. Though
|
||||
JimTCL has outstanding compatibility with canonical TCL, it does have
|
||||
a few corners with incompatibilities, e.g. regular expressions. If a
|
||||
script runs in JimTCL without using any JimTCL-specific features, then
|
||||
it's a certainty that it will run in canonical TCL as well. The
|
||||
opposite, however, is not _always_ the case.
|
||||
|
||||
When [`./configure`](/file/configure) is run, it goes through a
|
||||
bootstrapping process to find a suitable TCL with which to run the
|
||||
autosetup framework. The first step involves [finding or building a
|
||||
TCL shell](/file/autosetup/autosetup-find-tclsh). That will first
|
||||
search for an available `tclsh` (under several common names,
|
||||
e.g. `tclsh8.6`) before falling back to compiling the copy of
|
||||
`jimsh0.c` included in the source tree. i.e. it will prefer to use a
|
||||
system-installed TCL for running the configure script. Once it finds
|
||||
(or builds) a TCL shell, it then runs [a sanity test to ensure that
|
||||
the shell is suitable](/file/autosetup/autosetup-test-tclsh) before
|
||||
using it to run the main autosetup app.
|
||||
|
||||
There are two simple ways to ensure that running of the configure
|
||||
process uses JimTCL instead of the canonical `tclsh`, and either
|
||||
approach provides equally high assurances about configure script
|
||||
compatibility across TCL implementations:
|
||||
|
||||
1. Build on a system with no `tclsh` installed in the `$PATH`. In that
|
||||
case, the configure process will fall back to building the in-tree
|
||||
copy of JimTCL.
|
||||
|
||||
2. Manually build `./jimsh0` in the top of the checkout with:\
|
||||
`cc -o jimsh0 autosetup/jimsh0.c`\
|
||||
With that in place, the configure script will prefer to use that
|
||||
before looking for a system-level `tclsh`. Be aware, though, that
|
||||
`make distclean` will remove that file.
|
||||
|
||||
**Note that `jimsh0` is distinctly different from the `jimsh`** which
|
||||
gets built for code-generation purposes. The latter requires
|
||||
non-default build flags to enable features which are
|
||||
platform-dependent, most notably to make its `[file normalize]` work.
|
||||
This means, for example, that the configure script and its utility
|
||||
APIs must not use `[file normalize]`, but autosetup provides a
|
||||
TCL-only implementation of `[file-normalize]` (note the dash) for
|
||||
portable use in the configure script.
|
||||
|
||||
Known TCL Incompatibilities
|
||||
------------------------------------------------------------------------
|
||||
|
||||
A summary of known incompatibilities in JimTCL
|
||||
|
||||
- **CRNL line endings**: prior to 2025-02-05 `fconfigure -translation ...`
|
||||
was a no-op in JimTCL, and it emits CRNL line endings by default on
|
||||
Windows. Since then, it supports `-translation binary`, which is
|
||||
close enough to `-translation lf` for our purposes. When working
|
||||
with files using the `open` command, it is important to use mode
|
||||
`"rb"` or `"wb"`, as appropriate, so that the output does not get
|
||||
CRNL-mangled on Windows.
|
||||
|
||||
- **`file copy`** does not support multiple source files. See
|
||||
[](/info/61f18c96183867fe) for a workaround.
|
||||
|
||||
- **Regular expressions**:
|
||||
|
||||
- Patterns treat `\nnn` octal values as back-references (which it
|
||||
does not support). Those can be reformulated as demonstrated in
|
||||
[](/info/aeac23359bb681c0).
|
||||
|
||||
- `regsub` does not support the `\y` flag. A workaround is demonstrated
|
||||
in [](/info/c2e5dd791cce3ec4).
|
||||
|
||||
<a name="conventions"></a>
|
||||
Design Conventions
|
||||
========================================================================
|
||||
|
||||
This section describes the motivations for the most glaring of the
|
||||
build's design decisions, in particular how they deviate from
|
||||
historical, or even widely-conventional, practices.
|
||||
|
||||
Symbolic Names of Feature Flags
|
||||
------------------------------------------------------------------------
|
||||
|
||||
Historically, the project's makefile has exclusively used
|
||||
`UPPER_UNDERSCORE` form for makefile variables. This build, however,
|
||||
primarily uses `X.y` format, where `X` is often a category label,
|
||||
e.g. `CFLAGS`, and `y` is the specific instance of that category,
|
||||
e.g. `CFLAGS.readline`.
|
||||
|
||||
When the configure script exports flags for consumption by filtered
|
||||
files, e.g. [Makefile.in][] and the generated
|
||||
`sqlite_cfg.h`, it does so in the more conventional `X_Y` form because
|
||||
those flags get exported as as C `#define`s to `sqlite_cfg.h`, where
|
||||
dots are not permitted.
|
||||
|
||||
The `X.y` convention is used in the makefiles primarily because the
|
||||
person who did the initial port finds that considerably easier on the
|
||||
eyes and fingers. In practice, the `X_Y` form of such exports is used
|
||||
exactly once in [Makefile.in][], where it's translated into into `X.y`
|
||||
form for consumption by [Makefile.in][] and [main.mk][]. For example:
|
||||
|
||||
>
|
||||
```
|
||||
LDFLAGS.shobj = @SHOBJ_LDFLAGS@
|
||||
LDFLAGS.zlib = @LDFLAGS_ZLIB@
|
||||
LDFLAGS.math = @LDFLAGS_MATH@
|
||||
```
|
||||
|
||||
(That first one is defined by autosetup, and thus applies "LDFLAGS" as
|
||||
the suffix rather than the prefix. Which is more legible is a matter
|
||||
of taste, for which there is no accounting.)
|
||||
|
||||
|
||||
Do Not Update Global Shared State
|
||||
------------------------------------------------------------------------
|
||||
|
||||
In both the legacy Autotools-driven build and in common Autosetup
|
||||
usage, feature tests performed by the configure script may amend
|
||||
global flags such as `LIBS`, `LDFLAGS`, and `CFLAGS`[^as-cflags]. That's
|
||||
appropriate for a makefile which builds a single deliverable, but less
|
||||
so for makefiles which produce multiple deliverables. Drawbacks of
|
||||
that approach include:
|
||||
|
||||
- It's unlikely that every single deliverable will require the same
|
||||
core set of those flags.
|
||||
- It can be difficult to determine the origin of any given change to
|
||||
that global state because those changes are hidden behind voodoo performed
|
||||
outside the immediate visibility of the configure script's
|
||||
maintainer.
|
||||
- It can force the maintainers of the configure script to place tests
|
||||
in a specific order so that the resulting flags get applied at
|
||||
the correct time and/or in the correct order.\
|
||||
(A real-life example: before the approach described below was taken
|
||||
to collecting build-time flags, the test for `-rpath` had to come
|
||||
_after_ the test for zlib because the results of the `-rpath` test
|
||||
implicitly modified global state which broke the zlib feature
|
||||
test. Because the feature tests no longer (intentionally) modify
|
||||
shared global state, that is not an issue.)
|
||||
|
||||
In this build, cases where feature tests modify global state in such a
|
||||
way that it may impact later feature tests are either (A) very
|
||||
intentionally defined to do so (e.g. the `--with-wasi-sdk` flag has
|
||||
invasive side-effects) or (B) are oversights (i.e. bugs).
|
||||
|
||||
This tree's [configure script][auto.def], [utility APIs][proj.tcl],
|
||||
[Makefile.in][], and [main.mk][] therefore strive to separate the
|
||||
results of any given feature test into its own well-defined
|
||||
variables. For example:
|
||||
|
||||
- The linker flags for zlib are exported from the configure script as
|
||||
`LDFLAGS_ZLIB`, which [Makefile.in][] and [main.mk][] then expose as
|
||||
`LDFLAGS.zlib`.
|
||||
- `CFLAGS_READLINE` (a.k.a. `CFLAGS.readline`) contains the `CFLAGS`
|
||||
needed for including `libreadline`, `libedit`, or `linenoise`, and
|
||||
`LDFLAGS_READLINE` (a.k.a. `LDFLAGS.readline`) is its link-time
|
||||
counterpart.
|
||||
|
||||
It is then up to the Makefile to apply and order the flags however is
|
||||
appropriate.
|
||||
|
||||
At the end of the configure script, the global `CFLAGS` _ideally_
|
||||
holds only flags which are either relevant to all targets or, failing
|
||||
that, will have no unintended side-effects on any targets. That said:
|
||||
clients frequently pass custom `CFLAGS` to `./configure` or `make` to
|
||||
set library-level feature toggles, e.g. `-DSQLITE_OMIT_FOO`, in which
|
||||
case there is no practical way to avoid "polluting" the builds of
|
||||
arbitrary makefile targets with those. _C'est la vie._
|
||||
|
||||
|
||||
[^as-cflags]: But see this article for a detailed discussion of how
|
||||
autosetup currently deals specifically with CFLAGS:
|
||||
<https://msteveb.github.io/autosetup/articles/handling-cflags/>
|
||||
|
||||
|
||||
<a name="updating"></a>
|
||||
Updating Autosetup
|
||||
========================================================================
|
||||
|
||||
Updating autosetup is, more often than not, painless. It requires having
|
||||
a checked-out copy of [the autosetup git repository][autosetup-git]:
|
||||
|
||||
>
|
||||
```
|
||||
$ git clone https://github.com/msteveb/autosetup
|
||||
$ cd autosetup
|
||||
# Or, if it's already checked out:
|
||||
$ git pull
|
||||
```
|
||||
|
||||
Then, from the top-most directory of an SQLite checkout:
|
||||
|
||||
>
|
||||
```
|
||||
$ /path/to/autosetup-checkout/autosetup --install .
|
||||
$ fossil status # show the modified files
|
||||
```
|
||||
|
||||
Unless the upgrade made any incompatible changes (which is exceedingly
|
||||
rare), that's all there is to it. After that's done, **apply a patch
|
||||
for the change described in the following section**, test the
|
||||
configure process, and check it in.
|
||||
|
||||
<a name="patching"></a>
|
||||
Patching Autosetup for Project-local Changes
|
||||
------------------------------------------------------------------------
|
||||
|
||||
Autosetup reserves the flag name **`--debug`** for its own purposes,
|
||||
and its own special handling of `--enable-...` flags makes `--debug`
|
||||
an alias for `--enable-debug`. As we have a long history of using
|
||||
`--enable-debug` for this project's own purposes, we patch autosetup
|
||||
to use the name `--autosetup-debug` in place of `--debug`. That
|
||||
requires (as of this writing) four small edits in
|
||||
[](/file/autosetup/autosetup), as demonstrated in [check-in
|
||||
3296c8d3](/info/3296c8d3).
|
||||
|
||||
If autosetup is upgraded and this patch is _not_ applied the invoking
|
||||
`./configure` will fail loudly because of the declaration of the
|
||||
`debug` flag in `auto.def` - duplicated flags are not permitted.
|
||||
|
||||
|
||||
[Autosetup]: https://msteveb.github.io/autosetup/
|
||||
[auto.def]: /file/auto.def
|
||||
[autoconf/auto.def]: /file/autoconf/auto.def
|
||||
[autosetup-git]: https://github.com/msteveb/autosetup
|
||||
[proj.tcl]: /file/autosetup/proj.tcl
|
||||
[sqlite-config.tcl]: /file/autosetup/sqlite-config.tcl
|
||||
[Makefile.in]: /file/Makefile.in
|
||||
[main.mk]: /file/main.mk
|
||||
[JimTCL]: https://jim.tcl.tk
|
||||
Executable
+2536
File diff suppressed because it is too large
Load Diff
Regular → Executable
+715
-559
File diff suppressed because it is too large
Load Diff
Regular → Executable
+996
-440
File diff suppressed because it is too large
Load Diff
Executable
+16
@@ -0,0 +1,16 @@
|
||||
#!/bin/sh
|
||||
# Looks for a suitable tclsh or jimsh in the PATH
|
||||
# If not found, builds a bootstrap jimsh in current dir from source
|
||||
# Prefer $autosetup_tclsh if is set in the environment (unless ./jimsh0 works)
|
||||
# If an argument is given, use that as the test instead of autosetup-test-tclsh
|
||||
d="`dirname "$0"`"
|
||||
for tclsh in ./jimsh0 $autosetup_tclsh jimsh tclsh tclsh8.5 tclsh8.6 tclsh8.7; do
|
||||
{ $tclsh "$d/${1-autosetup-test-tclsh}"; } 2>/dev/null && exit 0
|
||||
done
|
||||
echo 1>&2 "No installed jimsh or tclsh, building local bootstrap jimsh0"
|
||||
for cc in ${CC_FOR_BUILD:-cc} gcc; do
|
||||
{ $cc -o jimsh0 "$d/jimsh0.c"; } >/dev/null 2>&1 || continue
|
||||
./jimsh0 "$d/${1-autosetup-test-tclsh}" && exit 0
|
||||
done
|
||||
echo 1>&2 "No working C compiler found. Tried ${CC_FOR_BUILD:-cc} and gcc."
|
||||
echo false
|
||||
@@ -0,0 +1,20 @@
|
||||
# A small Tcl script to verify that the chosen
|
||||
# interpreter works. Sometimes we might e.g. pick up
|
||||
# an interpreter for a different arch.
|
||||
# Outputs the full path to the interpreter
|
||||
|
||||
if {[catch {info version} version] == 0} {
|
||||
# This is Jim Tcl
|
||||
if {$version >= 0.72} {
|
||||
# Ensure that regexp works
|
||||
regexp (a.*?) a
|
||||
puts [info nameofexecutable]
|
||||
exit 0
|
||||
}
|
||||
} elseif {[catch {info tclversion} version] == 0} {
|
||||
if {$version >= 8.5 && ![string match 8.5a* [info patchlevel]]} {
|
||||
puts [info nameofexecutable]
|
||||
exit 0
|
||||
}
|
||||
}
|
||||
exit 1
|
||||
@@ -0,0 +1,15 @@
|
||||
# Copyright (c) 2011 WorkWare Systems http://www.workware.net.au/
|
||||
# All rights reserved
|
||||
|
||||
# @synopsis:
|
||||
#
|
||||
# The 'cc-db' module provides a knowledge-base of system idiosyncrasies.
|
||||
# In general, this module can always be included.
|
||||
|
||||
use cc
|
||||
|
||||
options {}
|
||||
|
||||
# openbsd needs sys/types.h to detect some system headers
|
||||
cc-include-needs sys/socket.h sys/types.h
|
||||
cc-include-needs netinet/in.h sys/types.h
|
||||
@@ -0,0 +1,187 @@
|
||||
# Copyright (c) 2011 WorkWare Systems http://www.workware.net.au/
|
||||
# All rights reserved
|
||||
|
||||
# @synopsis:
|
||||
#
|
||||
# Provides a library of common tests on top of the 'cc' module.
|
||||
|
||||
use cc
|
||||
|
||||
# @cc-check-lfs
|
||||
#
|
||||
# The equivalent of the 'AC_SYS_LARGEFILE' macro.
|
||||
#
|
||||
# defines 'HAVE_LFS' if LFS is available,
|
||||
# and defines '_FILE_OFFSET_BITS=64' if necessary
|
||||
#
|
||||
# Returns 1 if 'LFS' is available or 0 otherwise
|
||||
#
|
||||
proc cc-check-lfs {} {
|
||||
cc-check-includes sys/types.h
|
||||
msg-checking "Checking if -D_FILE_OFFSET_BITS=64 is needed..."
|
||||
set lfs 1
|
||||
if {[msg-quiet cc-with {-includes sys/types.h} {cc-check-sizeof off_t}] == 8} {
|
||||
msg-result no
|
||||
} elseif {[msg-quiet cc-with {-includes sys/types.h -cflags -D_FILE_OFFSET_BITS=64} {cc-check-sizeof off_t}] == 8} {
|
||||
define _FILE_OFFSET_BITS 64
|
||||
msg-result yes
|
||||
} else {
|
||||
set lfs 0
|
||||
msg-result none
|
||||
}
|
||||
define-feature lfs $lfs
|
||||
return $lfs
|
||||
}
|
||||
|
||||
# @cc-check-endian
|
||||
#
|
||||
# The equivalent of the 'AC_C_BIGENDIAN' macro.
|
||||
#
|
||||
# defines 'HAVE_BIG_ENDIAN' if endian is known to be big,
|
||||
# or 'HAVE_LITTLE_ENDIAN' if endian is known to be little.
|
||||
#
|
||||
# Returns 1 if determined, or 0 if not.
|
||||
#
|
||||
proc cc-check-endian {} {
|
||||
cc-check-includes sys/types.h sys/param.h
|
||||
set rc 0
|
||||
msg-checking "Checking endian..."
|
||||
cc-with {-includes {sys/types.h sys/param.h}} {
|
||||
if {[cctest -code {
|
||||
#if !defined(BIG_ENDIAN) || !defined(BYTE_ORDER)
|
||||
#error unknown
|
||||
#elif BYTE_ORDER != BIG_ENDIAN
|
||||
#error little
|
||||
#endif
|
||||
}]} {
|
||||
define-feature big-endian
|
||||
msg-result "big"
|
||||
set rc 1
|
||||
} elseif {[cctest -code {
|
||||
#if !defined(LITTLE_ENDIAN) || !defined(BYTE_ORDER)
|
||||
#error unknown
|
||||
#elif BYTE_ORDER != LITTLE_ENDIAN
|
||||
#error big
|
||||
#endif
|
||||
}]} {
|
||||
define-feature little-endian
|
||||
msg-result "little"
|
||||
set rc 1
|
||||
} else {
|
||||
msg-result "unknown"
|
||||
}
|
||||
}
|
||||
return $rc
|
||||
}
|
||||
|
||||
# @cc-check-flags flag ?...?
|
||||
#
|
||||
# Checks whether the given C/C++ compiler flags can be used. Defines feature
|
||||
# names prefixed with 'HAVE_CFLAG' and 'HAVE_CXXFLAG' respectively, and
|
||||
# appends working flags to '-cflags' and 'AS_CFLAGS' or 'AS_CXXFLAGS'.
|
||||
proc cc-check-flags {args} {
|
||||
set result 1
|
||||
array set opts [cc-get-settings]
|
||||
switch -exact -- $opts(-lang) {
|
||||
c++ {
|
||||
set lang C++
|
||||
set prefix CXXFLAG
|
||||
}
|
||||
c {
|
||||
set lang C
|
||||
set prefix CFLAG
|
||||
}
|
||||
default {
|
||||
autosetup-error "cc-check-flags failed with unknown language: $opts(-lang)"
|
||||
}
|
||||
}
|
||||
foreach flag $args {
|
||||
msg-checking "Checking whether the $lang compiler accepts $flag..."
|
||||
if {[cctest -cflags $flag]} {
|
||||
msg-result yes
|
||||
define-feature $prefix$flag
|
||||
cc-with [list -cflags [list $flag]]
|
||||
define-append AS_${prefix}S $flag
|
||||
} else {
|
||||
msg-result no
|
||||
set result 0
|
||||
}
|
||||
}
|
||||
return $result
|
||||
}
|
||||
|
||||
# @cc-check-standards ver ?...?
|
||||
#
|
||||
# Checks whether the C/C++ compiler accepts one of the specified '-std=$ver'
|
||||
# options, and appends the first working one to '-cflags' and 'AS_CFLAGS' or
|
||||
# 'AS_CXXFLAGS'.
|
||||
proc cc-check-standards {args} {
|
||||
array set opts [cc-get-settings]
|
||||
foreach std $args {
|
||||
if {[cc-check-flags -std=$std]} {
|
||||
return $std
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
# Checks whether $keyword is usable as alignof
|
||||
proc cctest_alignof {keyword} {
|
||||
msg-checking "Checking for $keyword..."
|
||||
if {[cctest -code "int x = ${keyword}(char), y = ${keyword}('x');"]} then {
|
||||
msg-result ok
|
||||
define-feature $keyword
|
||||
} else {
|
||||
msg-result "not found"
|
||||
}
|
||||
}
|
||||
|
||||
# @cc-check-c11
|
||||
#
|
||||
# Checks for several C11/C++11 extensions and their alternatives. Currently
|
||||
# checks for '_Static_assert', '_Alignof', '__alignof__', '__alignof'.
|
||||
proc cc-check-c11 {} {
|
||||
msg-checking "Checking for _Static_assert..."
|
||||
if {[cctest -code {
|
||||
_Static_assert(1, "static assertions are available");
|
||||
}]} then {
|
||||
msg-result ok
|
||||
define-feature _Static_assert
|
||||
} else {
|
||||
msg-result "not found"
|
||||
}
|
||||
|
||||
cctest_alignof _Alignof
|
||||
cctest_alignof __alignof__
|
||||
cctest_alignof __alignof
|
||||
}
|
||||
|
||||
# @cc-check-alloca
|
||||
#
|
||||
# The equivalent of the 'AC_FUNC_ALLOCA' macro.
|
||||
#
|
||||
# Checks for the existence of 'alloca'
|
||||
# defines 'HAVE_ALLOCA' and returns 1 if it exists.
|
||||
proc cc-check-alloca {} {
|
||||
cc-check-some-feature alloca {
|
||||
cctest -includes alloca.h -code { alloca (2 * sizeof (int)); }
|
||||
}
|
||||
}
|
||||
|
||||
# @cc-signal-return-type
|
||||
#
|
||||
# The equivalent of the 'AC_TYPE_SIGNAL' macro.
|
||||
#
|
||||
# defines 'RETSIGTYPE' to 'int' or 'void'.
|
||||
proc cc-signal-return-type {} {
|
||||
msg-checking "Checking return type of signal handlers..."
|
||||
cc-with {-includes {sys/types.h signal.h}} {
|
||||
if {[cctest -code {return *(signal (0, 0)) (0) == 1;}]} {
|
||||
set type int
|
||||
} else {
|
||||
set type void
|
||||
}
|
||||
define RETSIGTYPE $type
|
||||
msg-result $type
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
# Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/
|
||||
# All rights reserved
|
||||
|
||||
# @synopsis:
|
||||
#
|
||||
# The 'cc-shared' module provides support for shared libraries and shared objects.
|
||||
# It defines the following variables:
|
||||
#
|
||||
## SH_CFLAGS Flags to use compiling sources destined for a shared library
|
||||
## SH_LDFLAGS Flags to use linking (creating) a shared library
|
||||
## SH_SOPREFIX Prefix to use to set the soname when creating a shared library
|
||||
## SH_SOFULLPATH Set to 1 if the shared library soname should include the full install path
|
||||
## SH_SOEXT Extension for shared libs
|
||||
## SH_SOEXTVER Format for versioned shared libs - %s = version
|
||||
## SHOBJ_CFLAGS Flags to use compiling sources destined for a shared object
|
||||
## SHOBJ_LDFLAGS Flags to use linking a shared object, undefined symbols allowed
|
||||
## SHOBJ_LDFLAGS_R - as above, but all symbols must be resolved
|
||||
## SH_LINKRPATH Format for setting the rpath when linking an executable, %s = path
|
||||
## SH_LINKFLAGS Flags to use linking an executable which will load shared objects
|
||||
## LD_LIBRARY_PATH Environment variable which specifies path to shared libraries
|
||||
## STRIPLIBFLAGS Arguments to strip a dynamic library
|
||||
|
||||
options {}
|
||||
|
||||
# Defaults: gcc on unix
|
||||
define SHOBJ_CFLAGS -fPIC
|
||||
define SHOBJ_LDFLAGS -shared
|
||||
define SH_CFLAGS -fPIC
|
||||
define SH_LDFLAGS -shared
|
||||
define SH_LINKFLAGS -rdynamic
|
||||
define SH_LINKRPATH "-Wl,-rpath -Wl,%s"
|
||||
define SH_SOEXT .so
|
||||
define SH_SOEXTVER .so.%s
|
||||
define SH_SOPREFIX -Wl,-soname,
|
||||
define LD_LIBRARY_PATH LD_LIBRARY_PATH
|
||||
define STRIPLIBFLAGS --strip-unneeded
|
||||
|
||||
# Note: This is a helpful reference for identifying the toolchain
|
||||
# http://sourceforge.net/apps/mediawiki/predef/index.php?title=Compilers
|
||||
|
||||
switch -glob -- [get-define host] {
|
||||
*-*-darwin* {
|
||||
define SHOBJ_CFLAGS "-dynamic -fno-common"
|
||||
define SHOBJ_LDFLAGS "-bundle -undefined dynamic_lookup"
|
||||
define SHOBJ_LDFLAGS_R -bundle
|
||||
define SH_CFLAGS -dynamic
|
||||
define SH_LDFLAGS -dynamiclib
|
||||
define SH_LINKFLAGS ""
|
||||
define SH_SOEXT .dylib
|
||||
define SH_SOEXTVER .%s.dylib
|
||||
define SH_SOPREFIX -Wl,-install_name,
|
||||
define SH_SOFULLPATH
|
||||
define LD_LIBRARY_PATH DYLD_LIBRARY_PATH
|
||||
define STRIPLIBFLAGS -x
|
||||
}
|
||||
*-*-ming* - *-*-cygwin - *-*-msys {
|
||||
define SHOBJ_CFLAGS ""
|
||||
define SHOBJ_LDFLAGS -shared
|
||||
define SH_CFLAGS ""
|
||||
define SH_LDFLAGS -shared
|
||||
define SH_LINKRPATH ""
|
||||
define SH_LINKFLAGS ""
|
||||
define SH_SOEXT .dll
|
||||
define SH_SOEXTVER .dll
|
||||
define SH_SOPREFIX ""
|
||||
define LD_LIBRARY_PATH PATH
|
||||
}
|
||||
sparc* {
|
||||
if {[msg-quiet cc-check-decls __SUNPRO_C]} {
|
||||
msg-result "Found sun stdio compiler"
|
||||
# sun stdio compiler
|
||||
# XXX: These haven't been fully tested.
|
||||
define SHOBJ_CFLAGS -KPIC
|
||||
define SHOBJ_LDFLAGS "-G"
|
||||
define SH_CFLAGS -KPIC
|
||||
define SH_LINKFLAGS -Wl,-export-dynamic
|
||||
define SH_SOPREFIX -Wl,-h,
|
||||
}
|
||||
}
|
||||
*-*-solaris* {
|
||||
if {[msg-quiet cc-check-decls __SUNPRO_C]} {
|
||||
msg-result "Found sun stdio compiler"
|
||||
# sun stdio compiler
|
||||
# XXX: These haven't been fully tested.
|
||||
define SHOBJ_CFLAGS -KPIC
|
||||
define SHOBJ_LDFLAGS "-G"
|
||||
define SH_CFLAGS -KPIC
|
||||
define SH_LINKFLAGS -Wl,-export-dynamic
|
||||
define SH_SOPREFIX -Wl,-h,
|
||||
}
|
||||
}
|
||||
*-*-hpux {
|
||||
# XXX: These haven't been tested
|
||||
define SHOBJ_CFLAGS "+O3 +z"
|
||||
define SHOBJ_LDFLAGS -b
|
||||
define SH_CFLAGS +z
|
||||
define SH_LINKFLAGS -Wl,+s
|
||||
define LD_LIBRARY_PATH SHLIB_PATH
|
||||
}
|
||||
*-*-haiku {
|
||||
define SHOBJ_CFLAGS ""
|
||||
define SHOBJ_LDFLAGS -shared
|
||||
define SH_CFLAGS ""
|
||||
define SH_LDFLAGS -shared
|
||||
define SH_LINKFLAGS ""
|
||||
define SH_SOPREFIX ""
|
||||
define LD_LIBRARY_PATH LIBRARY_PATH
|
||||
}
|
||||
}
|
||||
|
||||
if {![is-defined SHOBJ_LDFLAGS_R]} {
|
||||
define SHOBJ_LDFLAGS_R [get-define SHOBJ_LDFLAGS]
|
||||
}
|
||||
@@ -0,0 +1,758 @@
|
||||
# Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/
|
||||
# All rights reserved
|
||||
|
||||
# @synopsis:
|
||||
#
|
||||
# The 'cc' module supports checking various 'features' of the C or C++
|
||||
# compiler/linker environment. Common commands are 'cc-check-includes',
|
||||
# 'cc-check-types', 'cc-check-functions', 'cc-with' and 'make-config-header'
|
||||
#
|
||||
# The following environment variables are used if set:
|
||||
#
|
||||
## CC - C compiler
|
||||
## CXX - C++ compiler
|
||||
## CPP - C preprocessor
|
||||
## CCACHE - Set to "none" to disable automatic use of ccache
|
||||
## CPPFLAGS - Additional C preprocessor compiler flags (C and C++), before CFLAGS, CXXFLAGS
|
||||
## CFLAGS - Additional C compiler flags
|
||||
## CXXFLAGS - Additional C++ compiler flags
|
||||
## LDFLAGS - Additional compiler flags during linking
|
||||
## LINKFLAGS - ?How is this different from LDFLAGS?
|
||||
## LIBS - Additional libraries to use (for all tests)
|
||||
## CROSS - Tool prefix for cross compilation
|
||||
#
|
||||
# The following variables are defined from the corresponding
|
||||
# environment variables if set.
|
||||
#
|
||||
## CC_FOR_BUILD
|
||||
## LD
|
||||
|
||||
use system
|
||||
|
||||
options {}
|
||||
|
||||
# Checks for the existence of the given function by linking
|
||||
#
|
||||
proc cctest_function {function} {
|
||||
cctest -link 1 -declare "extern void $function\(void);" -code "$function\();"
|
||||
}
|
||||
|
||||
# Checks for the existence of the given type by compiling
|
||||
proc cctest_type {type} {
|
||||
cctest -code "$type _x;"
|
||||
}
|
||||
|
||||
# Checks for the existence of the given type/structure member.
|
||||
# e.g. "struct stat.st_mtime"
|
||||
proc cctest_member {struct_member} {
|
||||
# split at the first dot
|
||||
regexp {^([^.]+)[.](.*)$} $struct_member -> struct member
|
||||
cctest -code "static $struct _s; return sizeof(_s.$member);"
|
||||
}
|
||||
|
||||
# Checks for the existence of the given define by compiling
|
||||
#
|
||||
proc cctest_define {name} {
|
||||
cctest -code "#ifndef $name\n#error not defined\n#endif"
|
||||
}
|
||||
|
||||
# Checks for the existence of the given name either as
|
||||
# a macro (#define) or an rvalue (such as an enum)
|
||||
#
|
||||
proc cctest_decl {name} {
|
||||
cctest -code "#ifndef $name\n(void)$name;\n#endif"
|
||||
}
|
||||
|
||||
# @cc-check-sizeof type ...
|
||||
#
|
||||
# Checks the size of the given types (between 1 and 32, inclusive).
|
||||
# Defines a variable with the size determined, or 'unknown' otherwise.
|
||||
# e.g. for type 'long long', defines 'SIZEOF_LONG_LONG'.
|
||||
# Returns the size of the last type.
|
||||
#
|
||||
proc cc-check-sizeof {args} {
|
||||
foreach type $args {
|
||||
msg-checking "Checking for sizeof $type..."
|
||||
set size unknown
|
||||
# Try the most common sizes first
|
||||
foreach i {4 8 1 2 16 32} {
|
||||
if {[cctest -code "static int _x\[sizeof($type) == $i ? 1 : -1\] = { 1 };"]} {
|
||||
set size $i
|
||||
break
|
||||
}
|
||||
}
|
||||
msg-result $size
|
||||
set define [feature-define-name $type SIZEOF_]
|
||||
define $define $size
|
||||
}
|
||||
# Return the last result
|
||||
get-define $define
|
||||
}
|
||||
|
||||
# Checks for each feature in $list by using the given script.
|
||||
#
|
||||
# When the script is evaluated, $each is set to the feature
|
||||
# being checked, and $extra is set to any additional cctest args.
|
||||
#
|
||||
# Returns 1 if all features were found, or 0 otherwise.
|
||||
proc cc-check-some-feature {list script} {
|
||||
set ret 1
|
||||
foreach each $list {
|
||||
if {![check-feature $each $script]} {
|
||||
set ret 0
|
||||
}
|
||||
}
|
||||
return $ret
|
||||
}
|
||||
|
||||
# @cc-check-includes includes ...
|
||||
#
|
||||
# Checks that the given include files can be used.
|
||||
proc cc-check-includes {args} {
|
||||
cc-check-some-feature $args {
|
||||
set with {}
|
||||
if {[dict exists $::autosetup(cc-include-deps) $each]} {
|
||||
set deps [dict keys [dict get $::autosetup(cc-include-deps) $each]]
|
||||
msg-quiet cc-check-includes {*}$deps
|
||||
foreach i $deps {
|
||||
if {[have-feature $i]} {
|
||||
lappend with $i
|
||||
}
|
||||
}
|
||||
}
|
||||
if {[llength $with]} {
|
||||
cc-with [list -includes $with] {
|
||||
cctest -includes $each
|
||||
}
|
||||
} else {
|
||||
cctest -includes $each
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# @cc-include-needs include required ...
|
||||
#
|
||||
# Ensures that when checking for '$include', a check is first
|
||||
# made for each '$required' file, and if found, it is included with '#include'.
|
||||
proc cc-include-needs {file args} {
|
||||
foreach depfile $args {
|
||||
dict set ::autosetup(cc-include-deps) $file $depfile 1
|
||||
}
|
||||
}
|
||||
|
||||
# @cc-check-types type ...
|
||||
#
|
||||
# Checks that the types exist.
|
||||
proc cc-check-types {args} {
|
||||
cc-check-some-feature $args {
|
||||
cctest_type $each
|
||||
}
|
||||
}
|
||||
|
||||
# @cc-check-defines define ...
|
||||
#
|
||||
# Checks that the given preprocessor symbols are defined.
|
||||
proc cc-check-defines {args} {
|
||||
cc-check-some-feature $args {
|
||||
cctest_define $each
|
||||
}
|
||||
}
|
||||
|
||||
# @cc-check-decls name ...
|
||||
#
|
||||
# Checks that each given name is either a preprocessor symbol or rvalue
|
||||
# such as an enum. Note that the define used is 'HAVE_DECL_xxx'
|
||||
# rather than 'HAVE_xxx'.
|
||||
proc cc-check-decls {args} {
|
||||
set ret 1
|
||||
foreach name $args {
|
||||
msg-checking "Checking for $name..."
|
||||
set r [cctest_decl $name]
|
||||
define-feature "decl $name" $r
|
||||
if {$r} {
|
||||
msg-result "ok"
|
||||
} else {
|
||||
msg-result "not found"
|
||||
set ret 0
|
||||
}
|
||||
}
|
||||
return $ret
|
||||
}
|
||||
|
||||
# @cc-check-functions function ...
|
||||
#
|
||||
# Checks that the given functions exist (can be linked).
|
||||
proc cc-check-functions {args} {
|
||||
cc-check-some-feature $args {
|
||||
cctest_function $each
|
||||
}
|
||||
}
|
||||
|
||||
# @cc-check-members type.member ...
|
||||
#
|
||||
# Checks that the given type/structure members exist.
|
||||
# A structure member is of the form 'struct stat.st_mtime'.
|
||||
proc cc-check-members {args} {
|
||||
cc-check-some-feature $args {
|
||||
cctest_member $each
|
||||
}
|
||||
}
|
||||
|
||||
# @cc-check-function-in-lib function libs ?otherlibs?
|
||||
#
|
||||
# Checks that the given function can be found in one of the libs.
|
||||
#
|
||||
# First checks for no library required, then checks each of the libraries
|
||||
# in turn.
|
||||
#
|
||||
# If the function is found, the feature is defined and 'lib_$function' is defined
|
||||
# to '-l$lib' where the function was found, or "" if no library required.
|
||||
# In addition, '-l$lib' is prepended to the 'LIBS' define.
|
||||
#
|
||||
# If additional libraries may be needed for linking, they should be specified
|
||||
# with '$extralibs' as '-lotherlib1 -lotherlib2'.
|
||||
# These libraries are not automatically added to 'LIBS'.
|
||||
#
|
||||
# Returns 1 if found or 0 if not.
|
||||
#
|
||||
proc cc-check-function-in-lib {function libs {otherlibs {}}} {
|
||||
msg-checking "Checking libs for $function..."
|
||||
set found 0
|
||||
cc-with [list -libs $otherlibs] {
|
||||
if {[cctest_function $function]} {
|
||||
msg-result "none needed"
|
||||
define lib_$function ""
|
||||
incr found
|
||||
} else {
|
||||
foreach lib $libs {
|
||||
cc-with [list -libs -l$lib] {
|
||||
if {[cctest_function $function]} {
|
||||
msg-result -l$lib
|
||||
define lib_$function -l$lib
|
||||
# prepend to LIBS
|
||||
define LIBS "-l$lib [get-define LIBS]"
|
||||
incr found
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
define-feature $function $found
|
||||
if {!$found} {
|
||||
msg-result "no"
|
||||
}
|
||||
return $found
|
||||
}
|
||||
|
||||
# @cc-check-tools tool ...
|
||||
#
|
||||
# Checks for existence of the given compiler tools, taking
|
||||
# into account any cross compilation prefix.
|
||||
#
|
||||
# For example, when checking for 'ar', first 'AR' is checked on the command
|
||||
# line and then in the environment. If not found, '${host}-ar' or
|
||||
# simply 'ar' is assumed depending upon whether cross compiling.
|
||||
# The path is searched for this executable, and if found 'AR' is defined
|
||||
# to the executable name.
|
||||
# Note that even when cross compiling, the simple 'ar' is used as a fallback,
|
||||
# but a warning is generated. This is necessary for some toolchains.
|
||||
#
|
||||
# It is an error if the executable is not found.
|
||||
#
|
||||
proc cc-check-tools {args} {
|
||||
foreach tool $args {
|
||||
set TOOL [string toupper $tool]
|
||||
set exe [get-env $TOOL [get-define cross]$tool]
|
||||
if {[find-executable $exe]} {
|
||||
define $TOOL $exe
|
||||
continue
|
||||
}
|
||||
if {[find-executable $tool]} {
|
||||
msg-result "Warning: Failed to find $exe, falling back to $tool which may be incorrect"
|
||||
define $TOOL $tool
|
||||
continue
|
||||
}
|
||||
user-error "Failed to find $exe"
|
||||
}
|
||||
}
|
||||
|
||||
# @cc-check-progs prog ...
|
||||
#
|
||||
# Checks for existence of the given executables on the path.
|
||||
#
|
||||
# For example, when checking for 'grep', the path is searched for
|
||||
# the executable, 'grep', and if found 'GREP' is defined as 'grep'.
|
||||
#
|
||||
# If the executable is not found, the variable is defined as 'false'.
|
||||
# Returns 1 if all programs were found, or 0 otherwise.
|
||||
#
|
||||
proc cc-check-progs {args} {
|
||||
set failed 0
|
||||
foreach prog $args {
|
||||
set PROG [string toupper $prog]
|
||||
msg-checking "Checking for $prog..."
|
||||
if {![find-executable $prog]} {
|
||||
msg-result no
|
||||
define $PROG false
|
||||
incr failed
|
||||
} else {
|
||||
msg-result ok
|
||||
define $PROG $prog
|
||||
}
|
||||
}
|
||||
expr {!$failed}
|
||||
}
|
||||
|
||||
# @cc-path-progs prog ...
|
||||
#
|
||||
# Like cc-check-progs, but sets the define to the full path rather
|
||||
# than just the program name.
|
||||
#
|
||||
proc cc-path-progs {args} {
|
||||
set failed 0
|
||||
foreach prog $args {
|
||||
set PROG [string toupper $prog]
|
||||
msg-checking "Checking for $prog..."
|
||||
set path [find-executable-path $prog]
|
||||
if {$path eq ""} {
|
||||
msg-result no
|
||||
define $PROG false
|
||||
incr failed
|
||||
} else {
|
||||
msg-result $path
|
||||
define $PROG $path
|
||||
}
|
||||
}
|
||||
expr {!$failed}
|
||||
}
|
||||
|
||||
# Adds the given settings to $::autosetup(ccsettings) and
|
||||
# returns the old settings.
|
||||
#
|
||||
proc cc-add-settings {settings} {
|
||||
if {[llength $settings] % 2} {
|
||||
autosetup-error "settings list is missing a value: $settings"
|
||||
}
|
||||
|
||||
set prev [cc-get-settings]
|
||||
# workaround a bug in some versions of jimsh by forcing
|
||||
# conversion of $prev to a list
|
||||
llength $prev
|
||||
|
||||
array set new $prev
|
||||
|
||||
foreach {name value} $settings {
|
||||
switch -exact -- $name {
|
||||
-cflags - -includes {
|
||||
# These are given as lists
|
||||
lappend new($name) {*}[list-non-empty $value]
|
||||
}
|
||||
-declare {
|
||||
lappend new($name) $value
|
||||
}
|
||||
-libs {
|
||||
# Note that new libraries are added before previous libraries
|
||||
set new($name) [list {*}[list-non-empty $value] {*}$new($name)]
|
||||
}
|
||||
-link - -lang - -nooutput {
|
||||
set new($name) $value
|
||||
}
|
||||
-source - -sourcefile - -code {
|
||||
# XXX: These probably are only valid directly from cctest
|
||||
set new($name) $value
|
||||
}
|
||||
default {
|
||||
autosetup-error "unknown cctest setting: $name"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cc-store-settings [array get new]
|
||||
|
||||
return $prev
|
||||
}
|
||||
|
||||
proc cc-store-settings {new} {
|
||||
set ::autosetup(ccsettings) $new
|
||||
}
|
||||
|
||||
proc cc-get-settings {} {
|
||||
return $::autosetup(ccsettings)
|
||||
}
|
||||
|
||||
# Similar to cc-add-settings, but each given setting
|
||||
# simply replaces the existing value.
|
||||
#
|
||||
# Returns the previous settings
|
||||
proc cc-update-settings {args} {
|
||||
set prev [cc-get-settings]
|
||||
cc-store-settings [dict merge $prev $args]
|
||||
return $prev
|
||||
}
|
||||
|
||||
# @cc-with settings ?{ script }?
|
||||
#
|
||||
# Sets the given 'cctest' settings and then runs the tests in '$script'.
|
||||
# Note that settings such as '-lang' replace the current setting, while
|
||||
# those such as '-includes' are appended to the existing setting.
|
||||
#
|
||||
# If no script is given, the settings become the default for the remainder
|
||||
# of the 'auto.def' file.
|
||||
#
|
||||
## cc-with {-lang c++} {
|
||||
## # This will check with the C++ compiler
|
||||
## cc-check-types bool
|
||||
## cc-with {-includes signal.h} {
|
||||
## # This will check with the C++ compiler, signal.h and any existing includes.
|
||||
## ...
|
||||
## }
|
||||
## # back to just the C++ compiler
|
||||
## }
|
||||
#
|
||||
# The '-libs' setting is special in that newer values are added *before* earlier ones.
|
||||
#
|
||||
## cc-with {-libs {-lc -lm}} {
|
||||
## cc-with {-libs -ldl} {
|
||||
## cctest -libs -lsocket ...
|
||||
## # libs will be in this order: -lsocket -ldl -lc -lm
|
||||
## }
|
||||
## }
|
||||
#
|
||||
# If you wish to invoke something like cc-check-flags but not have -cflags updated,
|
||||
# use the following idiom:
|
||||
#
|
||||
## cc-with {} {
|
||||
## cc-check-flags ...
|
||||
## }
|
||||
proc cc-with {settings args} {
|
||||
if {[llength $args] == 0} {
|
||||
cc-add-settings $settings
|
||||
} elseif {[llength $args] > 1} {
|
||||
autosetup-error "usage: cc-with settings ?script?"
|
||||
} else {
|
||||
set save [cc-add-settings $settings]
|
||||
set rc [catch {uplevel 1 [lindex $args 0]} result info]
|
||||
cc-store-settings $save
|
||||
if {$rc != 0} {
|
||||
return -code [dict get $info -code] $result
|
||||
}
|
||||
return $result
|
||||
}
|
||||
}
|
||||
|
||||
# @cctest ?settings?
|
||||
#
|
||||
# Low level C/C++ compiler checker. Compiles and or links a small C program
|
||||
# according to the arguments and returns 1 if OK, or 0 if not.
|
||||
#
|
||||
# Supported settings are:
|
||||
#
|
||||
## -cflags cflags A list of flags to pass to the compiler
|
||||
## -includes list A list of includes, e.g. {stdlib.h stdio.h}
|
||||
## -declare code Code to declare before main()
|
||||
## -link 1 Don't just compile, link too
|
||||
## -lang c|c++ Use the C (default) or C++ compiler
|
||||
## -libs liblist List of libraries to link, e.g. {-ldl -lm}
|
||||
## -code code Code to compile in the body of main()
|
||||
## -source code Compile a complete program. Ignore -includes, -declare and -code
|
||||
## -sourcefile file Shorthand for -source [readfile [get-define srcdir]/$file]
|
||||
## -nooutput 1 Treat any compiler output (e.g. a warning) as an error
|
||||
#
|
||||
# Unless '-source' or '-sourcefile' is specified, the C program looks like:
|
||||
#
|
||||
## #include <firstinclude> /* same for remaining includes in the list */
|
||||
## declare-code /* any code in -declare, verbatim */
|
||||
## int main(void) {
|
||||
## code /* any code in -code, verbatim */
|
||||
## return 0;
|
||||
## }
|
||||
#
|
||||
# And the command line looks like:
|
||||
#
|
||||
## CC -cflags CFLAGS CPPFLAGS conftest.c -o conftest.o
|
||||
## CXX -cflags CXXFLAGS CPPFLAGS conftest.cpp -o conftest.o
|
||||
#
|
||||
# And if linking:
|
||||
#
|
||||
## CC LDFLAGS -cflags CFLAGS conftest.c -o conftest -libs LIBS
|
||||
## CXX LDFLAGS -cflags CXXFLAGS conftest.c -o conftest -libs LIBS
|
||||
#
|
||||
# Any failures are recorded in 'config.log'
|
||||
#
|
||||
proc cctest {args} {
|
||||
set tmp conftest__
|
||||
|
||||
# Easiest way to merge in the settings
|
||||
cc-with $args {
|
||||
array set opts [cc-get-settings]
|
||||
}
|
||||
|
||||
if {[info exists opts(-sourcefile)]} {
|
||||
set opts(-source) [readfile [get-define srcdir]/$opts(-sourcefile) "#error can't find $opts(-sourcefile)"]
|
||||
}
|
||||
if {[info exists opts(-source)]} {
|
||||
set lines $opts(-source)
|
||||
} else {
|
||||
foreach i $opts(-includes) {
|
||||
if {$opts(-code) ne "" && ![feature-checked $i]} {
|
||||
# Compiling real code with an unchecked header file
|
||||
# Quickly (and silently) check for it now
|
||||
|
||||
# Remove all -includes from settings before checking
|
||||
set saveopts [cc-update-settings -includes {}]
|
||||
msg-quiet cc-check-includes $i
|
||||
cc-store-settings $saveopts
|
||||
}
|
||||
if {$opts(-code) eq "" || [have-feature $i]} {
|
||||
lappend source "#include <$i>"
|
||||
}
|
||||
}
|
||||
lappend source {*}$opts(-declare)
|
||||
lappend source "int main(void) {"
|
||||
lappend source $opts(-code)
|
||||
lappend source "return 0;"
|
||||
lappend source "}"
|
||||
|
||||
set lines [join $source \n]
|
||||
}
|
||||
|
||||
# Build the command line
|
||||
set cmdline {}
|
||||
lappend cmdline {*}[get-define CCACHE]
|
||||
switch -exact -- $opts(-lang) {
|
||||
c++ {
|
||||
set src conftest__.cpp
|
||||
lappend cmdline {*}[get-define CXX]
|
||||
set cflags [get-define CXXFLAGS]
|
||||
}
|
||||
c {
|
||||
set src conftest__.c
|
||||
lappend cmdline {*}[get-define CC]
|
||||
set cflags [get-define CFLAGS]
|
||||
}
|
||||
default {
|
||||
autosetup-error "cctest called with unknown language: $opts(-lang)"
|
||||
}
|
||||
}
|
||||
|
||||
if {$opts(-link)} {
|
||||
lappend cmdline {*}[get-define LDFLAGS]
|
||||
} else {
|
||||
lappend cflags {*}[get-define CPPFLAGS]
|
||||
set tmp conftest__.o
|
||||
lappend cmdline -c
|
||||
}
|
||||
lappend cmdline {*}$opts(-cflags) {*}[get-define cc-default-debug ""] {*}$cflags
|
||||
lappend cmdline $src -o $tmp
|
||||
if {$opts(-link)} {
|
||||
lappend cmdline {*}$opts(-libs) {*}[get-define LIBS]
|
||||
}
|
||||
|
||||
# At this point we have the complete command line and the
|
||||
# complete source to be compiled. Get the result from cache if
|
||||
# we can
|
||||
if {[info exists ::cc_cache($cmdline,$lines)]} {
|
||||
msg-checking "(cached) "
|
||||
set ok $::cc_cache($cmdline,$lines)
|
||||
if {$::autosetup(debug)} {
|
||||
configlog "From cache (ok=$ok): [join $cmdline]"
|
||||
configlog "============"
|
||||
configlog $lines
|
||||
configlog "============"
|
||||
}
|
||||
return $ok
|
||||
}
|
||||
|
||||
writefile $src $lines\n
|
||||
|
||||
set ok 1
|
||||
set err [catch {exec-with-stderr {*}$cmdline} result errinfo]
|
||||
if {$err || ($opts(-nooutput) && [string length $result])} {
|
||||
configlog "Failed: [join $cmdline]"
|
||||
configlog $result
|
||||
configlog "============"
|
||||
configlog "The failed code was:"
|
||||
configlog $lines
|
||||
configlog "============"
|
||||
set ok 0
|
||||
} elseif {$::autosetup(debug)} {
|
||||
configlog "Compiled OK: [join $cmdline]"
|
||||
configlog "============"
|
||||
configlog $lines
|
||||
configlog "============"
|
||||
}
|
||||
file delete $src
|
||||
file delete $tmp
|
||||
|
||||
# cache it
|
||||
set ::cc_cache($cmdline,$lines) $ok
|
||||
|
||||
return $ok
|
||||
}
|
||||
|
||||
# @make-autoconf-h outfile ?auto-patterns=HAVE_*? ?bare-patterns=SIZEOF_*?
|
||||
#
|
||||
# Deprecated - see 'make-config-header'
|
||||
proc make-autoconf-h {file {autopatterns {HAVE_*}} {barepatterns {SIZEOF_* HAVE_DECL_*}}} {
|
||||
user-notice "*** make-autoconf-h is deprecated -- use make-config-header instead"
|
||||
make-config-header $file -auto $autopatterns -bare $barepatterns
|
||||
}
|
||||
|
||||
# @make-config-header outfile ?-auto patternlist? ?-bare patternlist? ?-none patternlist? ?-str patternlist? ...
|
||||
#
|
||||
# Examines all defined variables which match the given patterns
|
||||
# and writes an include file, '$file', which defines each of these.
|
||||
# Variables which match '-auto' are output as follows:
|
||||
# - defines which have the value '0' are ignored.
|
||||
# - defines which have integer values are defined as the integer value.
|
||||
# - any other value is defined as a string, e.g. '"value"'
|
||||
# Variables which match '-bare' are defined as-is.
|
||||
# Variables which match '-str' are defined as a string, e.g. '"value"'
|
||||
# Variables which match '-none' are omitted.
|
||||
#
|
||||
# Note that order is important. The first pattern that matches is selected.
|
||||
# Default behaviour is:
|
||||
#
|
||||
## -bare {SIZEOF_* HAVE_DECL_*} -auto HAVE_* -none *
|
||||
#
|
||||
# If the file would be unchanged, it is not written.
|
||||
proc make-config-header {file args} {
|
||||
set guard _[string toupper [regsub -all {[^a-zA-Z0-9]} [file tail $file] _]]
|
||||
file mkdir [file dirname $file]
|
||||
set lines {}
|
||||
lappend lines "#ifndef $guard"
|
||||
lappend lines "#define $guard"
|
||||
|
||||
# Add some defaults
|
||||
lappend args -bare {SIZEOF_* HAVE_DECL_*} -auto HAVE_*
|
||||
|
||||
foreach n [lsort [dict keys [all-defines]]] {
|
||||
set value [get-define $n]
|
||||
set type [calc-define-output-type $n $args]
|
||||
switch -exact -- $type {
|
||||
-bare {
|
||||
# Just output the value unchanged
|
||||
}
|
||||
-none {
|
||||
continue
|
||||
}
|
||||
-str {
|
||||
set value \"[string map [list \\ \\\\ \" \\\"] $value]\"
|
||||
}
|
||||
-auto {
|
||||
# Automatically determine the type
|
||||
if {$value eq "0"} {
|
||||
lappend lines "/* #undef $n */"
|
||||
continue
|
||||
}
|
||||
if {![string is integer -strict $value]} {
|
||||
set value \"[string map [list \\ \\\\ \" \\\"] $value]\"
|
||||
}
|
||||
}
|
||||
"" {
|
||||
continue
|
||||
}
|
||||
default {
|
||||
autosetup-error "Unknown type in make-config-header: $type"
|
||||
}
|
||||
}
|
||||
lappend lines "#define $n $value"
|
||||
}
|
||||
lappend lines "#endif"
|
||||
set buf [join $lines \n]
|
||||
write-if-changed $file $buf {
|
||||
msg-result "Created $file"
|
||||
}
|
||||
}
|
||||
|
||||
proc calc-define-output-type {name spec} {
|
||||
foreach {type patterns} $spec {
|
||||
foreach pattern $patterns {
|
||||
if {[string match $pattern $name]} {
|
||||
return $type
|
||||
}
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
proc cc-init {} {
|
||||
global autosetup
|
||||
|
||||
# Initialise some values from the environment or commandline or default settings
|
||||
foreach i {LDFLAGS LIBS CPPFLAGS LINKFLAGS CFLAGS} {
|
||||
lassign $i var default
|
||||
define $var [get-env $var $default]
|
||||
}
|
||||
|
||||
if {[env-is-set CC]} {
|
||||
# Set by the user, so don't try anything else
|
||||
set try [list [get-env CC ""]]
|
||||
} else {
|
||||
# Try some reasonable options
|
||||
set try [list [get-define cross]cc [get-define cross]gcc]
|
||||
}
|
||||
define CC [find-an-executable {*}$try]
|
||||
if {[get-define CC] eq ""} {
|
||||
user-error "Could not find a C compiler. Tried: [join $try ", "]"
|
||||
}
|
||||
|
||||
define CPP [get-env CPP "[get-define CC] -E"]
|
||||
|
||||
# XXX: Could avoid looking for a C++ compiler until requested
|
||||
# If CXX isn't found, it is set to the empty string.
|
||||
if {[env-is-set CXX]} {
|
||||
define CXX [find-an-executable -required [get-env CXX ""]]
|
||||
} else {
|
||||
define CXX [find-an-executable [get-define cross]c++ [get-define cross]g++]
|
||||
}
|
||||
|
||||
# CXXFLAGS default to CFLAGS if not specified
|
||||
define CXXFLAGS [get-env CXXFLAGS [get-define CFLAGS]]
|
||||
|
||||
# May need a CC_FOR_BUILD, so look for one
|
||||
define CC_FOR_BUILD [find-an-executable [get-env CC_FOR_BUILD ""] cc gcc false]
|
||||
|
||||
# These start empty and never come from the user or environment
|
||||
define AS_CFLAGS ""
|
||||
define AS_CPPFLAGS ""
|
||||
define AS_CXXFLAGS ""
|
||||
|
||||
define CCACHE [find-an-executable [get-env CCACHE ccache]]
|
||||
|
||||
# If any of these are set in the environment, propagate them to the AUTOREMAKE commandline
|
||||
foreach i {CC CXX CCACHE CPP CFLAGS CXXFLAGS CXXFLAGS LDFLAGS LIBS CROSS CPPFLAGS LINKFLAGS CC_FOR_BUILD LD} {
|
||||
if {[env-is-set $i]} {
|
||||
# Note: If the variable is set on the command line, get-env will return that value
|
||||
# so the command line will continue to override the environment
|
||||
define-append-argv AUTOREMAKE $i=[get-env $i ""]
|
||||
}
|
||||
}
|
||||
|
||||
# Initial cctest settings
|
||||
cc-store-settings {-cflags {} -includes {} -declare {} -link 0 -lang c -libs {} -code {} -nooutput 0}
|
||||
set autosetup(cc-include-deps) {}
|
||||
|
||||
msg-result "C compiler...[get-define CCACHE] [get-define CC] [get-define CFLAGS] [get-define CPPFLAGS]"
|
||||
if {[get-define CXX] ne "false"} {
|
||||
msg-result "C++ compiler...[get-define CCACHE] [get-define CXX] [get-define CXXFLAGS] [get-define CPPFLAGS]"
|
||||
}
|
||||
msg-result "Build C compiler...[get-define CC_FOR_BUILD]"
|
||||
|
||||
# On Darwin, we prefer to use -g0 to avoid creating .dSYM directories
|
||||
# but some compilers may not support it, so test here.
|
||||
switch -glob -- [get-define host] {
|
||||
*-*-darwin* {
|
||||
if {[cctest -cflags {-g0}]} {
|
||||
define cc-default-debug -g0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if {![cc-check-includes stdlib.h]} {
|
||||
user-error "Compiler does not work. See config.log"
|
||||
}
|
||||
}
|
||||
|
||||
cc-init
|
||||
+24510
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,168 @@
|
||||
# Copyright (c) 2016 WorkWare Systems http://www.workware.net.au/
|
||||
# All rights reserved
|
||||
|
||||
# @synopsis:
|
||||
#
|
||||
# The 'pkg-config' module allows package information to be found via 'pkg-config'.
|
||||
#
|
||||
# If not cross-compiling, the package path should be determined automatically
|
||||
# by 'pkg-config'.
|
||||
# If cross-compiling, the default package path is the compiler sysroot.
|
||||
# If the C compiler doesn't support '-print-sysroot', the path can be supplied
|
||||
# by the '--sysroot' option or by defining 'SYSROOT'.
|
||||
#
|
||||
# 'PKG_CONFIG' may be set to use an alternative to 'pkg-config'.
|
||||
|
||||
use cc
|
||||
|
||||
options {
|
||||
sysroot:dir => "Override compiler sysroot for pkg-config search path"
|
||||
}
|
||||
|
||||
# @pkg-config-init ?required?
|
||||
#
|
||||
# Initialises the 'pkg-config' system. Unless '$required' is set to 0,
|
||||
# it is a fatal error if a usable 'pkg-config' is not found .
|
||||
#
|
||||
# This command will normally be called automatically as required,
|
||||
# but it may be invoked explicitly if lack of 'pkg-config' is acceptable.
|
||||
#
|
||||
# Returns 1 if ok, or 0 if 'pkg-config' not found/usable (only if '$required' is 0).
|
||||
#
|
||||
proc pkg-config-init {{required 1}} {
|
||||
if {[is-defined HAVE_PKG_CONFIG]} {
|
||||
return [get-define HAVE_PKG_CONFIG]
|
||||
}
|
||||
set found 0
|
||||
|
||||
define PKG_CONFIG [get-env PKG_CONFIG pkg-config]
|
||||
msg-checking "Checking for pkg-config..."
|
||||
|
||||
if {[catch {exec [get-define PKG_CONFIG] --version} version]} {
|
||||
msg-result "[get-define PKG_CONFIG] (not found)"
|
||||
if {$required} {
|
||||
user-error "No usable pkg-config"
|
||||
}
|
||||
} else {
|
||||
msg-result $version
|
||||
define PKG_CONFIG_VERSION $version
|
||||
|
||||
set found 1
|
||||
|
||||
if {[opt-str sysroot o]} {
|
||||
define SYSROOT [file-normalize $o]
|
||||
msg-result "Using specified sysroot [get-define SYSROOT]"
|
||||
} elseif {[get-define build] ne [get-define host]} {
|
||||
if {[catch {exec-with-stderr {*}[get-define CC] -print-sysroot} result errinfo] == 0} {
|
||||
# Use the compiler sysroot, if there is one
|
||||
define SYSROOT $result
|
||||
msg-result "Found compiler sysroot $result"
|
||||
} else {
|
||||
configlog "[get-define CC] -print-sysroot: $result"
|
||||
set msg "pkg-config: Cross compiling, but no compiler sysroot and no --sysroot supplied"
|
||||
if {$required} {
|
||||
user-error $msg
|
||||
} else {
|
||||
msg-result $msg
|
||||
}
|
||||
set found 0
|
||||
}
|
||||
}
|
||||
if {[is-defined SYSROOT]} {
|
||||
set sysroot [get-define SYSROOT]
|
||||
|
||||
# XXX: It's possible that these should be set only when invoking pkg-config
|
||||
global env
|
||||
set env(PKG_CONFIG_DIR) ""
|
||||
# Supposedly setting PKG_CONFIG_LIBDIR means that PKG_CONFIG_PATH is ignored,
|
||||
# but it doesn't seem to work that way in practice
|
||||
set env(PKG_CONFIG_PATH) ""
|
||||
# Do we need to try /usr/local as well or instead?
|
||||
set env(PKG_CONFIG_LIBDIR) $sysroot/usr/lib/pkgconfig:$sysroot/usr/share/pkgconfig
|
||||
set env(PKG_CONFIG_SYSROOT_DIR) $sysroot
|
||||
}
|
||||
}
|
||||
define HAVE_PKG_CONFIG $found
|
||||
return $found
|
||||
}
|
||||
|
||||
# @pkg-config module ?requirements?
|
||||
#
|
||||
# Use 'pkg-config' to find the given module meeting the given requirements.
|
||||
# e.g.
|
||||
#
|
||||
## pkg-config pango >= 1.37.0
|
||||
#
|
||||
# If found, returns 1 and sets 'HAVE_PKG_PANGO' to 1 along with:
|
||||
#
|
||||
## PKG_PANGO_VERSION to the found version
|
||||
## PKG_PANGO_LIBS to the required libs (--libs-only-l)
|
||||
## PKG_PANGO_LDFLAGS to the required linker flags (--libs-only-L)
|
||||
## PKG_PANGO_CFLAGS to the required compiler flags (--cflags)
|
||||
#
|
||||
# If not found, returns 0.
|
||||
#
|
||||
proc pkg-config {module args} {
|
||||
set ok [pkg-config-init]
|
||||
|
||||
msg-checking "Checking for $module $args..."
|
||||
|
||||
if {!$ok} {
|
||||
msg-result "no pkg-config"
|
||||
return 0
|
||||
}
|
||||
|
||||
set pkgconfig [get-define PKG_CONFIG]
|
||||
|
||||
set ret [catch {exec $pkgconfig --modversion "$module $args"} version]
|
||||
configlog "$pkgconfig --modversion $module $args: $version"
|
||||
if {$ret} {
|
||||
msg-result "not found"
|
||||
return 0
|
||||
}
|
||||
# Sometimes --modversion succeeds but because of dependencies it isn't usable
|
||||
# This seems to show up with --cflags
|
||||
set ret [catch {exec $pkgconfig --cflags $module} cflags]
|
||||
if {$ret} {
|
||||
msg-result "unusable ($version - see config.log)"
|
||||
configlog "$pkgconfig --cflags $module"
|
||||
configlog $cflags
|
||||
return 0
|
||||
}
|
||||
msg-result $version
|
||||
set prefix [feature-define-name $module PKG_]
|
||||
define HAVE_${prefix}
|
||||
define ${prefix}_VERSION $version
|
||||
define ${prefix}_CFLAGS $cflags
|
||||
define ${prefix}_LIBS [exec $pkgconfig --libs-only-l $module]
|
||||
define ${prefix}_LDFLAGS [exec $pkgconfig --libs-only-L $module]
|
||||
return 1
|
||||
}
|
||||
|
||||
# @pkg-config-get module setting
|
||||
#
|
||||
# Convenience access to the results of 'pkg-config'.
|
||||
#
|
||||
# For example, '[pkg-config-get pango CFLAGS]' returns
|
||||
# the value of 'PKG_PANGO_CFLAGS', or '""' if not defined.
|
||||
proc pkg-config-get {module name} {
|
||||
set prefix [feature-define-name $module PKG_]
|
||||
get-define ${prefix}_${name} ""
|
||||
}
|
||||
|
||||
# @pkg-config-get-var module variable
|
||||
#
|
||||
# Return the value of the given variable from the given pkg-config module.
|
||||
# The module must already have been successfully detected with pkg-config.
|
||||
# e.g.
|
||||
#
|
||||
## if {[pkg-config harfbuzz >= 2.5]} {
|
||||
## define harfbuzz_libdir [pkg-config-get-var harfbuzz libdir]
|
||||
## }
|
||||
#
|
||||
# Returns the empty string if the variable isn't defined.
|
||||
proc pkg-config-get-var {module variable} {
|
||||
set pkgconfig [get-define PKG_CONFIG]
|
||||
set prefix [feature-define-name $module HAVE_PKG_]
|
||||
exec $pkgconfig $module --variable $variable
|
||||
}
|
||||
+1277
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,420 @@
|
||||
# Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/
|
||||
# All rights reserved
|
||||
|
||||
# @synopsis:
|
||||
#
|
||||
# This module supports common system interrogation and options
|
||||
# such as '--host', '--build', '--prefix', and setting 'srcdir', 'builddir', and 'EXEEXT'.
|
||||
#
|
||||
# It also support the "feature" naming convention, where searching
|
||||
# for a feature such as 'sys/type.h' defines 'HAVE_SYS_TYPES_H'.
|
||||
#
|
||||
# It defines the following variables, based on '--prefix' unless overridden by the user:
|
||||
#
|
||||
## datadir
|
||||
## sysconfdir
|
||||
## sharedstatedir
|
||||
## localstatedir
|
||||
## infodir
|
||||
## mandir
|
||||
## includedir
|
||||
#
|
||||
# If '--prefix' is not supplied, it defaults to '/usr/local' unless 'options-defaults { prefix ... }' is used *before*
|
||||
# including the 'system' module.
|
||||
|
||||
if {[is-defined defaultprefix]} {
|
||||
user-notice "Note: defaultprefix is deprecated. Use options-defaults to set default options"
|
||||
options-defaults [list prefix [get-define defaultprefix]]
|
||||
}
|
||||
|
||||
options {
|
||||
host:host-alias => {a complete or partial cpu-vendor-opsys for the system where
|
||||
the application will run (defaults to the same value as --build)}
|
||||
build:build-alias => {a complete or partial cpu-vendor-opsys for the system
|
||||
where the application will be built (defaults to the
|
||||
result of running config.guess)}
|
||||
prefix:dir=/usr/local => {the target directory for the build (default: '@default@')}
|
||||
|
||||
# These (hidden) options are supported for autoconf/automake compatibility
|
||||
exec-prefix:
|
||||
bindir:
|
||||
sbindir:
|
||||
includedir:
|
||||
mandir:
|
||||
infodir:
|
||||
libexecdir:
|
||||
datadir:
|
||||
libdir:
|
||||
sysconfdir:
|
||||
sharedstatedir:
|
||||
localstatedir:
|
||||
runstatedir:
|
||||
maintainer-mode=0
|
||||
dependency-tracking=0
|
||||
silent-rules=0
|
||||
program-prefix:
|
||||
program-suffix:
|
||||
program-transform-name:
|
||||
x-includes:
|
||||
x-libraries:
|
||||
}
|
||||
|
||||
# @check-feature name { script }
|
||||
#
|
||||
# defines feature '$name' to the return value of '$script',
|
||||
# which should be 1 if found or 0 if not found.
|
||||
#
|
||||
# e.g. the following will define 'HAVE_CONST' to 0 or 1.
|
||||
#
|
||||
## check-feature const {
|
||||
## cctest -code {const int _x = 0;}
|
||||
## }
|
||||
proc check-feature {name code} {
|
||||
msg-checking "Checking for $name..."
|
||||
set r [uplevel 1 $code]
|
||||
define-feature $name $r
|
||||
if {$r} {
|
||||
msg-result "ok"
|
||||
} else {
|
||||
msg-result "not found"
|
||||
}
|
||||
return $r
|
||||
}
|
||||
|
||||
# @have-feature name ?default=0?
|
||||
#
|
||||
# Returns the value of feature '$name' if defined, or '$default' if not.
|
||||
#
|
||||
# See 'feature-define-name' for how the "feature" name
|
||||
# is translated into the "define" name.
|
||||
#
|
||||
proc have-feature {name {default 0}} {
|
||||
get-define [feature-define-name $name] $default
|
||||
}
|
||||
|
||||
# @define-feature name ?value=1?
|
||||
#
|
||||
# Sets the feature 'define' to '$value'.
|
||||
#
|
||||
# See 'feature-define-name' for how the "feature" name
|
||||
# is translated into the "define" name.
|
||||
#
|
||||
proc define-feature {name {value 1}} {
|
||||
define [feature-define-name $name] $value
|
||||
}
|
||||
|
||||
# @feature-checked name
|
||||
#
|
||||
# Returns 1 if feature '$name' has been checked, whether true or not.
|
||||
#
|
||||
proc feature-checked {name} {
|
||||
is-defined [feature-define-name $name]
|
||||
}
|
||||
|
||||
# @feature-define-name name ?prefix=HAVE_?
|
||||
#
|
||||
# Converts a "feature" name to the corresponding "define",
|
||||
# e.g. 'sys/stat.h' becomes 'HAVE_SYS_STAT_H'.
|
||||
#
|
||||
# Converts '*' to 'P' and all non-alphanumeric to underscore.
|
||||
#
|
||||
proc feature-define-name {name {prefix HAVE_}} {
|
||||
string toupper $prefix[regsub -all {[^a-zA-Z0-9]} [regsub -all {[*]} $name p] _]
|
||||
}
|
||||
|
||||
# @write-if-changed filename contents ?script?
|
||||
#
|
||||
# If '$filename' doesn't exist, or it's contents are different to '$contents',
|
||||
# the file is written and '$script' is evaluated.
|
||||
#
|
||||
# Otherwise a "file is unchanged" message is displayed.
|
||||
proc write-if-changed {file buf {script {}}} {
|
||||
set old [readfile $file ""]
|
||||
if {$old eq $buf && [file exists $file]} {
|
||||
msg-result "$file is unchanged"
|
||||
} else {
|
||||
writefile $file $buf\n
|
||||
uplevel 1 $script
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# @include-file infile mapping
|
||||
#
|
||||
# The core of make-template, called recursively for each @include
|
||||
# directive found within that template so that this proc's result
|
||||
# is the fully-expanded template.
|
||||
#
|
||||
# The mapping parameter is how we expand @varname@ within the template.
|
||||
# We do that inline within this step only for @include directives which
|
||||
# can have variables in the filename arg. A separate substitution pass
|
||||
# happens when this recursive function returns, expanding the rest of
|
||||
# the variables.
|
||||
#
|
||||
proc include-file {infile mapping} {
|
||||
# A stack of true/false conditions, one for each nested conditional
|
||||
# starting with "true"
|
||||
set condstack {1}
|
||||
set result {}
|
||||
set linenum 0
|
||||
foreach line [split [readfile $infile] \n] {
|
||||
incr linenum
|
||||
if {[regexp {^@(if|else|endif)(\s*)(.*)} $line -> condtype condspace condargs]} {
|
||||
if {$condtype eq "if"} {
|
||||
if {[string length $condspace] == 0} {
|
||||
autosetup-error "$infile:$linenum: Invalid expression: $line"
|
||||
}
|
||||
if {[llength $condargs] == 1} {
|
||||
# ABC => [get-define ABC] ni {0 ""}
|
||||
# !ABC => [get-define ABC] in {0 ""}
|
||||
lassign $condargs condvar
|
||||
if {[regexp {^!(.*)} $condvar -> condvar]} {
|
||||
set op in
|
||||
} else {
|
||||
set op ni
|
||||
}
|
||||
set condexpr "\[[list get-define $condvar]\] $op {0 {}}"
|
||||
} else {
|
||||
# Translate alphanumeric ABC into [get-define ABC] and leave the
|
||||
# rest of the expression untouched
|
||||
regsub -all {([A-Z][[:alnum:]_]*)} $condargs {[get-define \1]} condexpr
|
||||
}
|
||||
if {[catch [list expr $condexpr] condval]} {
|
||||
dputs $condval
|
||||
autosetup-error "$infile:$linenum: Invalid expression: $line"
|
||||
}
|
||||
dputs "@$condtype: $condexpr => $condval"
|
||||
}
|
||||
if {$condtype ne "if"} {
|
||||
if {[llength $condstack] <= 1} {
|
||||
autosetup-error "$infile:$linenum: Error: @$condtype missing @if"
|
||||
} elseif {[string length $condargs] && [string index $condargs 0] ne "#"} {
|
||||
autosetup-error "$infile:$linenum: Error: Extra arguments after @$condtype"
|
||||
}
|
||||
}
|
||||
switch -exact $condtype {
|
||||
if {
|
||||
# push condval
|
||||
lappend condstack $condval
|
||||
}
|
||||
else {
|
||||
# Toggle the last entry
|
||||
set condval [lpop condstack]
|
||||
set condval [expr {!$condval}]
|
||||
lappend condstack $condval
|
||||
}
|
||||
endif {
|
||||
if {[llength $condstack] == 0} {
|
||||
user-notice "$infile:$linenum: Error: @endif missing @if"
|
||||
}
|
||||
lpop condstack
|
||||
}
|
||||
}
|
||||
continue
|
||||
}
|
||||
# Only continue if the stack contains all "true"
|
||||
if {"0" in $condstack} {
|
||||
continue
|
||||
}
|
||||
if {[regexp {^@include\s+(.*)} $line -> filearg]} {
|
||||
set incfile [string map $mapping $filearg]
|
||||
if {[file exists $incfile]} {
|
||||
lappend ::autosetup(deps) [file-normalize $incfile]
|
||||
lappend result {*}[include-file $incfile $mapping]
|
||||
} else {
|
||||
user-error "$infile:$linenum: Include file $incfile is missing"
|
||||
}
|
||||
continue
|
||||
}
|
||||
if {[regexp {^@define\s+(\w+)\s+(.*)} $line -> var val]} {
|
||||
define $var $val
|
||||
continue
|
||||
}
|
||||
lappend result $line
|
||||
}
|
||||
return $result
|
||||
}
|
||||
|
||||
|
||||
# @make-template template ?outfile?
|
||||
#
|
||||
# Reads the input file '<srcdir>/$template' and writes the output file '$outfile'
|
||||
# (unless unchanged).
|
||||
# If '$outfile' is blank/omitted, '$template' should end with '.in' which
|
||||
# is removed to create the output file name.
|
||||
#
|
||||
# Each pattern of the form '@define@' is replaced with the corresponding
|
||||
# "define", if it exists, or left unchanged if not.
|
||||
#
|
||||
# The special value '@srcdir@' is substituted with the relative
|
||||
# path to the source directory from the directory where the output
|
||||
# file is created, while the special value '@top_srcdir@' is substituted
|
||||
# with the relative path to the top level source directory.
|
||||
#
|
||||
# Conditional sections may be specified as follows:
|
||||
## @if NAME eq "value"
|
||||
## lines
|
||||
## @else
|
||||
## lines
|
||||
## @endif
|
||||
#
|
||||
# Where 'NAME' is a defined variable name and '@else' is optional.
|
||||
# Note that variables names *must* start with an uppercase letter.
|
||||
# If the expression does not match, all lines through '@endif' are ignored.
|
||||
#
|
||||
# The alternative forms may also be used:
|
||||
## @if NAME (true if the variable is defined, but not empty and not "0")
|
||||
## @if !NAME (opposite of the form above)
|
||||
## @if <general-tcl-expression>
|
||||
#
|
||||
# In the general Tcl expression, any words beginning with an uppercase letter
|
||||
# are translated into [get-define NAME]
|
||||
#
|
||||
# Expressions may be nested
|
||||
#
|
||||
proc make-template {template {out {}}} {
|
||||
set infile [file join $::autosetup(srcdir) $template]
|
||||
|
||||
if {![file exists $infile]} {
|
||||
user-error "Template $template is missing"
|
||||
}
|
||||
|
||||
# Define this as late as possible
|
||||
define AUTODEPS $::autosetup(deps)
|
||||
|
||||
if {$out eq ""} {
|
||||
if {[file ext $template] ne ".in"} {
|
||||
autosetup-error "make_template $template has no target file and can't guess"
|
||||
}
|
||||
set out [file rootname $template]
|
||||
}
|
||||
|
||||
set outdir [file dirname $out]
|
||||
|
||||
# Make sure the directory exists
|
||||
file mkdir $outdir
|
||||
|
||||
# Set up srcdir and top_srcdir to be relative to the target dir
|
||||
define srcdir [relative-path [file join $::autosetup(srcdir) $outdir] $outdir]
|
||||
define top_srcdir [relative-path $::autosetup(srcdir) $outdir]
|
||||
|
||||
# Build map from global defines to their values so they can be
|
||||
# substituted into @include file names.
|
||||
proc build-define-mapping {} {
|
||||
set mapping {}
|
||||
foreach {n v} [array get ::define] {
|
||||
lappend mapping @$n@ $v
|
||||
}
|
||||
return $mapping
|
||||
}
|
||||
set mapping [build-define-mapping]
|
||||
|
||||
set result [include-file $infile $mapping]
|
||||
|
||||
# Rebuild the define mapping in case we ran across @define
|
||||
# directives in the template or a file it @included, then
|
||||
# apply that mapping to the expanded template.
|
||||
set mapping [build-define-mapping]
|
||||
write-if-changed $out [string map $mapping [join $result \n]] {
|
||||
msg-result "Created [relative-path $out] from [relative-path $template]"
|
||||
}
|
||||
}
|
||||
|
||||
proc system-init {} {
|
||||
global autosetup
|
||||
|
||||
# build/host tuples and cross-compilation prefix
|
||||
opt-str build build ""
|
||||
define build_alias $build
|
||||
if {$build eq ""} {
|
||||
define build [config_guess]
|
||||
} else {
|
||||
define build [config_sub $build]
|
||||
}
|
||||
|
||||
opt-str host host ""
|
||||
define host_alias $host
|
||||
if {$host eq ""} {
|
||||
define host [get-define build]
|
||||
set cross ""
|
||||
} else {
|
||||
define host [config_sub $host]
|
||||
set cross $host-
|
||||
}
|
||||
define cross [get-env CROSS $cross]
|
||||
|
||||
# build/host _cpu, _vendor and _os
|
||||
foreach type {build host} {
|
||||
set v [get-define $type]
|
||||
if {![regexp {^([^-]+)-([^-]+)-(.*)$} $v -> cpu vendor os]} {
|
||||
user-error "Invalid canonical $type: $v"
|
||||
}
|
||||
define ${type}_cpu $cpu
|
||||
define ${type}_vendor $vendor
|
||||
define ${type}_os $os
|
||||
}
|
||||
|
||||
opt-str prefix prefix /usr/local
|
||||
|
||||
# These are for compatibility with autoconf
|
||||
define target [get-define host]
|
||||
define prefix $prefix
|
||||
define builddir $autosetup(builddir)
|
||||
define srcdir $autosetup(srcdir)
|
||||
define top_srcdir $autosetup(srcdir)
|
||||
define abs_top_srcdir [file-normalize $autosetup(srcdir)]
|
||||
define abs_top_builddir [file-normalize $autosetup(builddir)]
|
||||
|
||||
# autoconf supports all of these
|
||||
define exec_prefix [opt-str exec-prefix exec_prefix $prefix]
|
||||
foreach {name defpath} {
|
||||
bindir /bin
|
||||
sbindir /sbin
|
||||
libexecdir /libexec
|
||||
libdir /lib
|
||||
} {
|
||||
define $name [opt-str $name o $exec_prefix$defpath]
|
||||
}
|
||||
foreach {name defpath} {
|
||||
datadir /share
|
||||
sharedstatedir /com
|
||||
infodir /share/info
|
||||
mandir /share/man
|
||||
includedir /include
|
||||
} {
|
||||
define $name [opt-str $name o $prefix$defpath]
|
||||
}
|
||||
if {$prefix ne {/usr}} {
|
||||
opt-str sysconfdir sysconfdir $prefix/etc
|
||||
} else {
|
||||
opt-str sysconfdir sysconfdir /etc
|
||||
}
|
||||
define sysconfdir $sysconfdir
|
||||
|
||||
define localstatedir [opt-str localstatedir o /var]
|
||||
define runstatedir [opt-str runstatedir o /run]
|
||||
|
||||
define SHELL [get-env SHELL [find-an-executable sh bash ksh]]
|
||||
|
||||
# These could be used to generate Makefiles following some automake conventions
|
||||
define AM_SILENT_RULES [opt-bool silent-rules]
|
||||
define AM_MAINTAINER_MODE [opt-bool maintainer-mode]
|
||||
define AM_DEPENDENCY_TRACKING [opt-bool dependency-tracking]
|
||||
|
||||
# Windows vs. non-Windows
|
||||
switch -glob -- [get-define host] {
|
||||
*-*-ming* - *-*-cygwin - *-*-msys {
|
||||
define-feature windows
|
||||
define EXEEXT .exe
|
||||
}
|
||||
default {
|
||||
define EXEEXT ""
|
||||
}
|
||||
}
|
||||
|
||||
# Display
|
||||
msg-result "Host System...[get-define host]"
|
||||
msg-result "Build System...[get-define build]"
|
||||
}
|
||||
|
||||
system-init
|
||||
-808
@@ -1,808 +0,0 @@
|
||||
#
|
||||
# The build process allows for using a cross-compiler. But the default
|
||||
# action is to target the same platform that we are running on. The
|
||||
# configure script needs to discover the following properties of the
|
||||
# build and target systems:
|
||||
#
|
||||
# srcdir
|
||||
#
|
||||
# The is the name of the directory that contains the
|
||||
# "configure" shell script. All source files are
|
||||
# located relative to this directory.
|
||||
#
|
||||
# bindir
|
||||
#
|
||||
# The name of the directory where executables should be
|
||||
# written by the "install" target of the makefile.
|
||||
#
|
||||
# program_prefix
|
||||
#
|
||||
# Add this prefix to the names of all executables that run
|
||||
# on the target machine. Default: ""
|
||||
#
|
||||
# ENABLE_SHARED
|
||||
#
|
||||
# True if shared libraries should be generated.
|
||||
#
|
||||
# BUILD_CC
|
||||
#
|
||||
# The name of a command that is used to convert C
|
||||
# source files into executables that run on the build
|
||||
# platform.
|
||||
#
|
||||
# BUILD_CFLAGS
|
||||
#
|
||||
# Switches that the build compiler needs in order to construct
|
||||
# command-line programs.
|
||||
#
|
||||
# BUILD_LIBS
|
||||
#
|
||||
# Libraries that the build compiler needs in order to construct
|
||||
# command-line programs.
|
||||
#
|
||||
# BUILD_EXEEXT
|
||||
#
|
||||
# The filename extension for executables on the build
|
||||
# platform. "" for Unix and ".exe" for Windows.
|
||||
#
|
||||
# TCL_*
|
||||
#
|
||||
# Lots of values are read in from the tclConfig.sh script,
|
||||
# if that script is available. This values are used for
|
||||
# constructing and installing the TCL extension.
|
||||
#
|
||||
# TARGET_READLINE_LIBS
|
||||
#
|
||||
# This is the library directives passed to the target linker
|
||||
# that cause the executable to link against the readline library.
|
||||
# This might be a switch like "-lreadline" or pathnames of library
|
||||
# file like "../../src/libreadline.a".
|
||||
#
|
||||
# TARGET_READLINE_INC
|
||||
#
|
||||
# This variables define the directory that contain header
|
||||
# files for the readline library. If the compiler is able
|
||||
# to find <readline.h> on its own, then this can be blank.
|
||||
#
|
||||
# TARGET_EXEEXT
|
||||
#
|
||||
# The filename extension for executables on the
|
||||
# target platform. "" for Unix and ".exe" for windows.
|
||||
#
|
||||
# This configure.in file is easy to reuse on other projects. Just
|
||||
# change the argument to AC_INIT. And disable any features that
|
||||
# you don't need (for example BLT) by erasing or commenting out
|
||||
# the corresponding code.
|
||||
#
|
||||
AC_INIT([sqlite],m4_esyscmd(cat VERSION | tr -d '\n'))
|
||||
|
||||
dnl Make sure the local VERSION file matches this configure script
|
||||
sqlite_version_sanity_check=`cat $srcdir/VERSION | tr -d '\n'`
|
||||
if test "$PACKAGE_VERSION" != "$sqlite_version_sanity_check" ; then
|
||||
AC_MSG_ERROR([configure script is out of date:
|
||||
configure \$PACKAGE_VERSION = $PACKAGE_VERSION
|
||||
top level VERSION file = $sqlite_version_sanity_check
|
||||
please regen with autoconf])
|
||||
fi
|
||||
|
||||
#########
|
||||
# Programs needed
|
||||
#
|
||||
LT_INIT
|
||||
AC_PROG_INSTALL
|
||||
|
||||
#########
|
||||
# Enable large file support (if special flags are necessary)
|
||||
#
|
||||
AC_SYS_LARGEFILE
|
||||
|
||||
#########
|
||||
# Check for needed/wanted data types
|
||||
AC_CHECK_TYPES([int8_t, int16_t, int32_t, int64_t, intptr_t, uint8_t,
|
||||
uint16_t, uint32_t, uint64_t, uintptr_t])
|
||||
|
||||
#########
|
||||
# Check for needed/wanted headers
|
||||
AC_CHECK_HEADERS([sys/types.h stdlib.h stdint.h inttypes.h malloc.h])
|
||||
|
||||
#########
|
||||
# Figure out whether or not we have these functions
|
||||
#
|
||||
AC_CHECK_FUNCS([fdatasync gmtime_r isnan localtime_r localtime_s malloc_usable_size strchrnul usleep utime pread pread64 pwrite pwrite64])
|
||||
|
||||
#########
|
||||
# By default, we use the amalgamation (this may be changed below...)
|
||||
#
|
||||
USE_AMALGAMATION=1
|
||||
|
||||
#########
|
||||
# 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, [tclsh9.0 tclsh8.6 tclsh],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.
|
||||
AC_MSG_WARN([Warning: can't find tclsh - defaulting to non-amalgamation build.])
|
||||
USE_AMALGAMATION=0
|
||||
TCLSH_CMD="tclsh"
|
||||
fi
|
||||
AC_SUBST(TCLSH_CMD)
|
||||
|
||||
AC_ARG_VAR([TCLLIBDIR], [Where to install tcl plugin])
|
||||
if test "x${TCLLIBDIR+set}" != "xset" ; then
|
||||
for i in `echo 'puts stdout $auto_path' | ${TCLSH_CMD}` ; do
|
||||
if test -d $i ; then
|
||||
TCLLIBDIR=$i
|
||||
break
|
||||
fi
|
||||
done
|
||||
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
|
||||
#
|
||||
if test "$program_prefix" = "NONE"; then
|
||||
program_prefix=""
|
||||
fi
|
||||
AC_SUBST(program_prefix)
|
||||
|
||||
VERSION=[`cat $srcdir/VERSION | sed 's/^\([0-9]*\.*[0-9]*\).*/\1/'`]
|
||||
AC_MSG_NOTICE(Version set to $VERSION)
|
||||
AC_SUBST(VERSION)
|
||||
RELEASE=`cat $srcdir/VERSION`
|
||||
AC_MSG_NOTICE(Release set to $RELEASE)
|
||||
AC_SUBST(RELEASE)
|
||||
|
||||
##########
|
||||
# Handle --with-wasi-sdk=DIR
|
||||
#
|
||||
# This must be early because it changes the toolchain.
|
||||
#
|
||||
AC_ARG_WITH(wasi-sdk,
|
||||
AS_HELP_STRING([--with-wasi-sdk=DIR],
|
||||
[directory containing the WASI SDK. Triggers cross-compile to WASM.]), with_wasisdk=${withval})
|
||||
AC_MSG_CHECKING([for WASI SDK directory])
|
||||
AC_CACHE_VAL(ac_cv_c_wasi_sdk,[
|
||||
# First check to see if --with-tcl was specified.
|
||||
if test x"${with_wasi_sdk}" != x ; then
|
||||
if ! test -d "${with_wasi_sdk}" ; then
|
||||
AC_MSG_ERROR([${with_wasi_sdk} directory doesn't exist])
|
||||
fi
|
||||
AC_MSG_RESULT([${with_wasi_sdk}: using wasi-sdk clang, disabling: tcl, CLI shell, DLL])
|
||||
use_wasi_sdk=yes
|
||||
else
|
||||
use_wasi_sdk=no
|
||||
fi
|
||||
])
|
||||
if test "${use_wasi_sdk}" = "no" ; then
|
||||
HAVE_WASI_SDK=""
|
||||
AC_MSG_RESULT([no])
|
||||
else
|
||||
HAVE_WASI_SDK=1
|
||||
# Changing --host and --target have no effect here except to possibly
|
||||
# cause confusion. autoconf has finished processing them by this
|
||||
# point.
|
||||
#
|
||||
# host_alias=wasm32-wasi
|
||||
# target=wasm32-wasi
|
||||
#
|
||||
# Merely changing CC and LD to the wasi-sdk's is enough to get
|
||||
# sqlite3.o building in WASM format.
|
||||
CC="${with_wasi_sdk}/bin/clang"
|
||||
LD="${with_wasi_sdk}/bin/wasm-ld"
|
||||
RANLIB="${with_wasi_sdk}/bin/llvm-ranlib"
|
||||
cross_compiling=yes
|
||||
enable_threadsafe=no
|
||||
use_tcl=no
|
||||
enable_tcl=no
|
||||
# libtool is apparently hard-coded to use gcc for linking DLLs, so
|
||||
# we disable the DLL build...
|
||||
enable_shared=no
|
||||
AC_MSG_RESULT([yes])
|
||||
fi
|
||||
AC_SUBST(HAVE_WASI_SDK)
|
||||
|
||||
|
||||
#########
|
||||
# Locate a compiler for the build machine. This compiler should
|
||||
# generate command-line programs that run on the build machine.
|
||||
#
|
||||
if test x"$cross_compiling" = xno; then
|
||||
BUILD_CC=$CC
|
||||
BUILD_CFLAGS=$CFLAGS
|
||||
else
|
||||
if test "${BUILD_CC+set}" != set; then
|
||||
AC_CHECK_PROGS(BUILD_CC, gcc cc cl)
|
||||
fi
|
||||
if test "${BUILD_CFLAGS+set}" != set; then
|
||||
BUILD_CFLAGS="-g"
|
||||
fi
|
||||
fi
|
||||
AC_SUBST(BUILD_CC)
|
||||
|
||||
##########
|
||||
# Do we want to support multithreaded use of sqlite
|
||||
#
|
||||
AC_ARG_ENABLE(threadsafe,
|
||||
AS_HELP_STRING([--disable-threadsafe],[Disable mutexing]))
|
||||
AC_MSG_CHECKING([whether to support threadsafe operation])
|
||||
if test "$enable_threadsafe" = "no"; then
|
||||
SQLITE_THREADSAFE=0
|
||||
AC_MSG_RESULT([no])
|
||||
else
|
||||
SQLITE_THREADSAFE=1
|
||||
AC_MSG_RESULT([yes])
|
||||
fi
|
||||
AC_SUBST(SQLITE_THREADSAFE)
|
||||
|
||||
if test "$SQLITE_THREADSAFE" = "1"; then
|
||||
AC_SEARCH_LIBS(pthread_create, pthread)
|
||||
AC_SEARCH_LIBS(pthread_mutexattr_init, pthread)
|
||||
fi
|
||||
|
||||
##########
|
||||
# Do we want to support release
|
||||
#
|
||||
AC_ARG_ENABLE(releasemode,
|
||||
AS_HELP_STRING([--enable-releasemode],[Support libtool link to release mode]),,enable_releasemode=no)
|
||||
AC_MSG_CHECKING([whether to support shared library linked as release mode or not])
|
||||
if test "$enable_releasemode" = "no"; then
|
||||
ALLOWRELEASE=""
|
||||
AC_MSG_RESULT([no])
|
||||
else
|
||||
ALLOWRELEASE="-release `cat $srcdir/VERSION`"
|
||||
AC_MSG_RESULT([yes])
|
||||
fi
|
||||
AC_SUBST(ALLOWRELEASE)
|
||||
|
||||
##########
|
||||
# Do we want temporary databases in memory
|
||||
#
|
||||
AC_ARG_ENABLE(tempstore,
|
||||
AS_HELP_STRING([--enable-tempstore],[Use an in-ram database for temporary tables (never,no,yes,always)]),,enable_tempstore=no)
|
||||
AC_MSG_CHECKING([whether to use an in-ram database for temporary tables])
|
||||
case "$enable_tempstore" in
|
||||
never )
|
||||
TEMP_STORE=0
|
||||
AC_MSG_RESULT([never])
|
||||
;;
|
||||
no )
|
||||
TEMP_STORE=1
|
||||
AC_MSG_RESULT([no])
|
||||
;;
|
||||
yes )
|
||||
TEMP_STORE=2
|
||||
AC_MSG_RESULT([yes])
|
||||
;;
|
||||
always )
|
||||
TEMP_STORE=3
|
||||
AC_MSG_RESULT([always])
|
||||
;;
|
||||
* )
|
||||
TEMP_STORE=1
|
||||
AC_MSG_RESULT([no])
|
||||
;;
|
||||
esac
|
||||
|
||||
AC_SUBST(TEMP_STORE)
|
||||
|
||||
###########
|
||||
# Lots of things are different if we are compiling for Windows using
|
||||
# the CYGWIN environment. So check for that special case and handle
|
||||
# things accordingly.
|
||||
#
|
||||
AC_MSG_CHECKING([if executables have the .exe suffix])
|
||||
if test "$config_BUILD_EXEEXT" = ".exe"; then
|
||||
CYGWIN=yes
|
||||
AC_MSG_RESULT(yes)
|
||||
else
|
||||
AC_MSG_RESULT(unknown)
|
||||
fi
|
||||
if test "$CYGWIN" != "yes"; then
|
||||
m4_warn([obsolete],
|
||||
[AC_CYGWIN is obsolete: use AC_CANONICAL_HOST and check if $host_os
|
||||
matches *cygwin*])dnl
|
||||
AC_CANONICAL_HOST
|
||||
case $host_os in
|
||||
*cygwin* ) CYGWIN=yes;;
|
||||
* ) CYGWIN=no;;
|
||||
esac
|
||||
|
||||
fi
|
||||
if test "$CYGWIN" = "yes"; then
|
||||
BUILD_EXEEXT=.exe
|
||||
else
|
||||
BUILD_EXEEXT=$EXEEXT
|
||||
fi
|
||||
if test x"$cross_compiling" = xno; then
|
||||
TARGET_EXEEXT=$BUILD_EXEEXT
|
||||
else
|
||||
TARGET_EXEEXT=$config_TARGET_EXEEXT
|
||||
fi
|
||||
if test "$TARGET_EXEEXT" = ".exe"; then
|
||||
SQLITE_OS_UNIX=0
|
||||
SQLITE_OS_WIN=1
|
||||
CFLAGS="$CFLAGS -DSQLITE_OS_WIN=1"
|
||||
else
|
||||
SQLITE_OS_UNIX=1
|
||||
SQLITE_OS_WIN=0
|
||||
CFLAGS="$CFLAGS -DSQLITE_OS_UNIX=1"
|
||||
fi
|
||||
|
||||
AC_SUBST(BUILD_EXEEXT)
|
||||
AC_SUBST(SQLITE_OS_UNIX)
|
||||
AC_SUBST(SQLITE_OS_WIN)
|
||||
AC_SUBST(TARGET_EXEEXT)
|
||||
|
||||
##########
|
||||
# Figure out what C libraries are required to compile programs
|
||||
# that use "readline()" library.
|
||||
#
|
||||
TARGET_READLINE_LIBS=""
|
||||
TARGET_READLINE_INC=""
|
||||
TARGET_HAVE_READLINE=0
|
||||
TARGET_HAVE_EDITLINE=0
|
||||
AC_ARG_ENABLE([editline],
|
||||
[AS_HELP_STRING([--enable-editline],[enable BSD editline support])],
|
||||
[with_editline=$enableval],
|
||||
[with_editline=auto])
|
||||
AC_ARG_ENABLE([readline],
|
||||
[AS_HELP_STRING([--disable-readline],[disable readline support])],
|
||||
[with_readline=$enableval],
|
||||
[with_readline=auto])
|
||||
|
||||
if test x"$with_editline" != xno; then
|
||||
sLIBS=$LIBS
|
||||
LIBS=""
|
||||
TARGET_HAVE_EDITLINE=1
|
||||
AC_SEARCH_LIBS(readline,edit,[with_readline=no],[TARGET_HAVE_EDITLINE=0])
|
||||
TARGET_READLINE_LIBS=$LIBS
|
||||
LIBS=$sLIBS
|
||||
fi
|
||||
if test x"$with_readline" != xno; then
|
||||
found="yes"
|
||||
|
||||
AC_ARG_WITH([readline-lib],
|
||||
[AS_HELP_STRING([--with-readline-lib],[specify readline library])],
|
||||
[with_readline_lib=$withval],
|
||||
[with_readline_lib="auto"])
|
||||
if test "x$with_readline_lib" = xauto; then
|
||||
save_LIBS="$LIBS"
|
||||
LIBS=""
|
||||
AC_SEARCH_LIBS(tgetent, [readline ncurses curses termcap], [term_LIBS="$LIBS"], [term_LIBS=""])
|
||||
AC_CHECK_LIB([readline], [readline], [TARGET_READLINE_LIBS="-lreadline"], [found="no"])
|
||||
TARGET_READLINE_LIBS="$TARGET_READLINE_LIBS $term_LIBS"
|
||||
LIBS="$save_LIBS"
|
||||
else
|
||||
TARGET_READLINE_LIBS="$with_readline_lib"
|
||||
fi
|
||||
|
||||
AC_ARG_WITH([readline-inc],
|
||||
[AS_HELP_STRING([--with-readline-inc],[specify readline include paths])],
|
||||
[with_readline_inc=$withval],
|
||||
[with_readline_inc="auto"])
|
||||
if test "x$with_readline_inc" = xauto; then
|
||||
AC_CHECK_HEADER(readline.h, [found="yes"], [
|
||||
found="no"
|
||||
if test "$cross_compiling" != yes; then
|
||||
for dir in /usr /usr/local /usr/local/readline /usr/contrib /mingw; do
|
||||
for subdir in include include/readline; do
|
||||
AC_CHECK_FILE($dir/$subdir/readline.h, found=yes)
|
||||
if test "$found" = "yes"; then
|
||||
TARGET_READLINE_INC="-I$dir/$subdir"
|
||||
break
|
||||
fi
|
||||
done
|
||||
test "$found" = "yes" && break
|
||||
done
|
||||
fi
|
||||
])
|
||||
else
|
||||
TARGET_READLINE_INC="$with_readline_inc"
|
||||
fi
|
||||
|
||||
if test x"$found" = xno; then
|
||||
TARGET_READLINE_LIBS=""
|
||||
TARGET_READLINE_INC=""
|
||||
TARGET_HAVE_READLINE=0
|
||||
else
|
||||
TARGET_HAVE_READLINE=1
|
||||
fi
|
||||
fi
|
||||
AC_ARG_WITH([linenoise],
|
||||
[AS_HELP_STRING([--with-linenoise=DIR],[source directory for linenoise library])],
|
||||
[with_linenoise=$withval],
|
||||
[with_linenoise="no"])
|
||||
if test "x$with_linenoise" != "xno"; then
|
||||
TARGET_HAVE_READLINE=0
|
||||
TARGET_HAVE_EDITLINE=0
|
||||
TARGET_HAVE_LINENOISE=1
|
||||
TARGET_READLINE_INC="-I${with_linenoise}"
|
||||
TARGET_READLINE_LIBS="${with_linenoise}/linenoise.c"
|
||||
echo "using linenoise source code at ${with_linenoise}"
|
||||
else
|
||||
TARGET_HAVE_LINENOISE=0
|
||||
echo "not using linenoise"
|
||||
fi
|
||||
|
||||
AC_SUBST(TARGET_READLINE_LIBS)
|
||||
AC_SUBST(TARGET_READLINE_INC)
|
||||
AC_SUBST(TARGET_HAVE_READLINE)
|
||||
AC_SUBST(TARGET_HAVE_EDITLINE)
|
||||
AC_SUBST(TARGET_HAVE_LINENOISE)
|
||||
|
||||
|
||||
##########
|
||||
# Figure out what C libraries are required to compile programs
|
||||
# that use "fdatasync()" function.
|
||||
#
|
||||
AC_SEARCH_LIBS(fdatasync, [rt])
|
||||
|
||||
#########
|
||||
# check for debug enabled
|
||||
AC_ARG_ENABLE(debug, AS_HELP_STRING([--enable-debug],[enable debugging & verbose explain]))
|
||||
AC_MSG_CHECKING([build type])
|
||||
if test "${enable_debug}" = "yes" ; then
|
||||
TARGET_DEBUG="-DSQLITE_DEBUG=1 -DSQLITE_ENABLE_SELECTTRACE -DSQLITE_ENABLE_WHERETRACE -O0 -Wall"
|
||||
AC_MSG_RESULT([debug])
|
||||
else
|
||||
TARGET_DEBUG="-DNDEBUG"
|
||||
AC_MSG_RESULT([release])
|
||||
fi
|
||||
AC_SUBST(TARGET_DEBUG)
|
||||
|
||||
#########
|
||||
# See whether we should use the amalgamation to build
|
||||
|
||||
AC_ARG_ENABLE(amalgamation, AS_HELP_STRING([--disable-amalgamation],
|
||||
[Disable the amalgamation and instead build all files separately]))
|
||||
if test "${enable_amalgamation}" = "no" ; then
|
||||
USE_AMALGAMATION=0
|
||||
fi
|
||||
AC_SUBST(USE_AMALGAMATION)
|
||||
|
||||
#########
|
||||
# Look for zlib. Only needed by extensions and by the sqlite3.exe shell
|
||||
AC_CHECK_HEADERS(zlib.h)
|
||||
AC_SEARCH_LIBS(deflate, z, [HAVE_ZLIB="-DSQLITE_HAVE_ZLIB=1"], [HAVE_ZLIB=""])
|
||||
AC_SUBST(HAVE_ZLIB)
|
||||
|
||||
#########
|
||||
# See whether we should allow loadable extensions
|
||||
AC_ARG_ENABLE(load-extension, AS_HELP_STRING([--disable-load-extension],
|
||||
[Disable loading of external extensions]),,[enable_load_extension=yes])
|
||||
if test "${enable_load_extension}" = "yes" ; then
|
||||
OPT_FEATURE_FLAGS=""
|
||||
AC_SEARCH_LIBS(dlopen, dl)
|
||||
else
|
||||
OPT_FEATURE_FLAGS="-DSQLITE_OMIT_LOAD_EXTENSION=1"
|
||||
fi
|
||||
|
||||
##########
|
||||
# Do we want to support math functions
|
||||
#
|
||||
AC_ARG_ENABLE(math,
|
||||
AS_HELP_STRING([--disable-math],[Disable math functions]))
|
||||
AC_MSG_CHECKING([whether to support math functions])
|
||||
if test "$enable_math" = "no"; then
|
||||
AC_MSG_RESULT([no])
|
||||
else
|
||||
AC_MSG_RESULT([yes])
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_MATH_FUNCTIONS"
|
||||
AC_SEARCH_LIBS(ceil, m)
|
||||
fi
|
||||
|
||||
##########
|
||||
# Do we want to support JSON functions
|
||||
#
|
||||
AC_ARG_ENABLE(json,
|
||||
AS_HELP_STRING([--disable-json],[Disable JSON functions]))
|
||||
AC_MSG_CHECKING([whether to support JSON functions])
|
||||
if test "$enable_json" = "no"; then
|
||||
AC_MSG_RESULT([no])
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_OMIT_JSON"
|
||||
else
|
||||
AC_MSG_RESULT([yes])
|
||||
fi
|
||||
|
||||
########
|
||||
# The --enable-all argument is short-hand to enable
|
||||
# multiple extensions.
|
||||
AC_ARG_ENABLE(all, AS_HELP_STRING([--enable-all],
|
||||
[Enable FTS4, FTS5, Geopoly, RTree, Sessions]))
|
||||
|
||||
##########
|
||||
# Do we want to support memsys3 and/or memsys5
|
||||
#
|
||||
AC_ARG_ENABLE(memsys5,
|
||||
AS_HELP_STRING([--enable-memsys5],[Enable MEMSYS5]))
|
||||
AC_MSG_CHECKING([whether to support MEMSYS5])
|
||||
if test "${enable_memsys5}" = "yes"; then
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_MEMSYS5"
|
||||
AC_MSG_RESULT([yes])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
fi
|
||||
AC_ARG_ENABLE(memsys3,
|
||||
AS_HELP_STRING([--enable-memsys3],[Enable MEMSYS3]))
|
||||
AC_MSG_CHECKING([whether to support MEMSYS3])
|
||||
if test "${enable_memsys3}" = "yes" -a "${enable_memsys5}" = "no"; then
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_MEMSYS3"
|
||||
AC_MSG_RESULT([yes])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
fi
|
||||
|
||||
#########
|
||||
# See whether we should enable Full Text Search extensions
|
||||
AC_ARG_ENABLE(fts3, AS_HELP_STRING([--enable-fts3],
|
||||
[Enable the FTS3 extension]))
|
||||
AC_MSG_CHECKING([whether to support FTS3])
|
||||
if test "${enable_fts3}" = "yes" ; then
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_FTS3"
|
||||
AC_MSG_RESULT([yes])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
fi
|
||||
AC_ARG_ENABLE(fts4, AS_HELP_STRING([--enable-fts4],
|
||||
[Enable the FTS4 extension]))
|
||||
AC_MSG_CHECKING([whether to support FTS4])
|
||||
if test "${enable_fts4}" = "yes" -o "${enable_all}" = "yes" ; then
|
||||
AC_MSG_RESULT([yes])
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_FTS4"
|
||||
AC_SEARCH_LIBS([log],[m])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
fi
|
||||
AC_ARG_ENABLE(fts5, AS_HELP_STRING([--enable-fts5],
|
||||
[Enable the FTS5 extension]))
|
||||
AC_MSG_CHECKING([whether to support FTS5])
|
||||
if test "${enable_fts5}" = "yes" -o "${enable_all}" = "yes" ; then
|
||||
AC_MSG_RESULT([yes])
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_FTS5"
|
||||
AC_SEARCH_LIBS([log],[m])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
fi
|
||||
|
||||
#########
|
||||
# See whether we should enable the LIMIT clause on UPDATE and DELETE
|
||||
# statements.
|
||||
AC_ARG_ENABLE(update-limit, AS_HELP_STRING([--enable-update-limit],
|
||||
[Enable the UPDATE/DELETE LIMIT clause]))
|
||||
AC_MSG_CHECKING([whether to support LIMIT on UPDATE and DELETE statements])
|
||||
if test "${enable_update_limit}" = "yes" ; then
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_UPDATE_DELETE_LIMIT"
|
||||
AC_MSG_RESULT([yes])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
fi
|
||||
|
||||
#########
|
||||
# See whether we should enable GEOPOLY
|
||||
AC_ARG_ENABLE(geopoly, AS_HELP_STRING([--enable-geopoly],
|
||||
[Enable the GEOPOLY extension]),
|
||||
[enable_geopoly=yes],[enable_geopoly=no])
|
||||
AC_MSG_CHECKING([whether to support GEOPOLY])
|
||||
if test "${enable_geopoly}" = "yes" -o "${enable_all}" = "yes" ; then
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_GEOPOLY"
|
||||
enable_rtree=yes
|
||||
AC_MSG_RESULT([yes])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
fi
|
||||
|
||||
#########
|
||||
# See whether we should enable RTREE
|
||||
AC_ARG_ENABLE(rtree, AS_HELP_STRING([--enable-rtree],
|
||||
[Enable the RTREE extension]))
|
||||
AC_MSG_CHECKING([whether to support RTREE])
|
||||
if test "${enable_rtree}" = "yes" ; then
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_RTREE"
|
||||
AC_MSG_RESULT([yes])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
fi
|
||||
|
||||
#########
|
||||
# See whether we should enable the SESSION extension
|
||||
AC_ARG_ENABLE(session, AS_HELP_STRING([--enable-session],
|
||||
[Enable the SESSION extension]))
|
||||
AC_MSG_CHECKING([whether to support SESSION])
|
||||
if test "${enable_session}" = "yes" -o "${enable_all}" = "yes" ; then
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_SESSION"
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_PREUPDATE_HOOK"
|
||||
AC_MSG_RESULT([yes])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
fi
|
||||
|
||||
#########
|
||||
# attempt to duplicate any OMITS and ENABLES into the ${OPT_FEATURE_FLAGS} parameter
|
||||
for option in $CFLAGS $CPPFLAGS
|
||||
do
|
||||
case $option in
|
||||
-DSQLITE_OMIT*) OPT_FEATURE_FLAGS="$OPT_FEATURE_FLAGS $option";;
|
||||
-DSQLITE_ENABLE*) OPT_FEATURE_FLAGS="$OPT_FEATURE_FLAGS $option";;
|
||||
esac
|
||||
done
|
||||
AC_SUBST(OPT_FEATURE_FLAGS)
|
||||
|
||||
|
||||
# attempt to remove any OMITS and ENABLES from the $(CFLAGS) parameter
|
||||
ac_temp_CFLAGS=""
|
||||
for option in $CFLAGS
|
||||
do
|
||||
case $option in
|
||||
-DSQLITE_OMIT*) ;;
|
||||
-DSQLITE_ENABLE*) ;;
|
||||
*) ac_temp_CFLAGS="$ac_temp_CFLAGS $option";;
|
||||
esac
|
||||
done
|
||||
CFLAGS=$ac_temp_CFLAGS
|
||||
|
||||
|
||||
# attempt to remove any OMITS and ENABLES from the $(CPPFLAGS) parameter
|
||||
ac_temp_CPPFLAGS=""
|
||||
for option in $CPPFLAGS
|
||||
do
|
||||
case $option in
|
||||
-DSQLITE_OMIT*) ;;
|
||||
-DSQLITE_ENABLE*) ;;
|
||||
*) ac_temp_CPPFLAGS="$ac_temp_CPPFLAGS $option";;
|
||||
esac
|
||||
done
|
||||
CPPFLAGS=$ac_temp_CPPFLAGS
|
||||
|
||||
|
||||
# attempt to remove any OMITS and ENABLES from the $(BUILD_CFLAGS) parameter
|
||||
ac_temp_BUILD_CFLAGS=""
|
||||
for option in $BUILD_CFLAGS
|
||||
do
|
||||
case $option in
|
||||
-DSQLITE_OMIT*) ;;
|
||||
-DSQLITE_ENABLE*) ;;
|
||||
*) ac_temp_BUILD_CFLAGS="$ac_temp_BUILD_CFLAGS $option";;
|
||||
esac
|
||||
done
|
||||
BUILD_CFLAGS=$ac_temp_BUILD_CFLAGS
|
||||
|
||||
|
||||
#########
|
||||
# See whether we should use GCOV
|
||||
AC_ARG_ENABLE(gcov, AS_HELP_STRING([--enable-gcov],
|
||||
[Enable coverage testing using gcov]))
|
||||
if test "${use_gcov}" = "yes" ; then
|
||||
USE_GCOV=1
|
||||
else
|
||||
USE_GCOV=0
|
||||
fi
|
||||
AC_SUBST(USE_GCOV)
|
||||
|
||||
#########
|
||||
# Enable/disabled amalagamation line macros
|
||||
########
|
||||
AMALGAMATION_LINE_MACROS=--linemacros=0
|
||||
if test "${amalgamation_line_macros}" = "yes" ; then
|
||||
AMALGAMATION_LINE_MACROS=--linemacros=1
|
||||
fi
|
||||
if test "${amalgamation_line_macros}" = "no" ; then
|
||||
AMALGAMATION_LINE_MACROS=--linemacros=0
|
||||
fi
|
||||
AC_SUBST(AMALGAMATION_LINE_MACROS)
|
||||
|
||||
#########
|
||||
# Output the config header
|
||||
AC_CONFIG_HEADERS(sqlite_cfg.h)
|
||||
|
||||
#########
|
||||
# Generate the output files.
|
||||
#
|
||||
AC_SUBST(BUILD_CFLAGS)
|
||||
AC_CONFIG_FILES([
|
||||
Makefile
|
||||
sqlite3.pc
|
||||
])
|
||||
AC_OUTPUT
|
||||
+20
-7
@@ -4,15 +4,18 @@ Here are step-by-step instructions on how to build SQLite from
|
||||
canonical source on any modern machine that isn't Windows. These
|
||||
notes are tested (on 2024-10-11) on Ubuntu and on MacOS, but they
|
||||
are general and should work on most any modern unix platform.
|
||||
See the companion document ([](./compile-for-windows.md>)) for
|
||||
guidance on building for Windows.
|
||||
|
||||
1. Install a C-compiler. GCC or Clang both work fine. If you are
|
||||
reading this document, you've probably already done that.
|
||||
|
||||
2. Install TCL9 development libraries. In this note, we'll do a
|
||||
private install in the $HOME/local directory, but you can make
|
||||
adjustments to install TCL9 wherever you like.
|
||||
<p>
|
||||
This document assumes you are working with <b>TCL version 9.0</b>.
|
||||
2. *(Optional):* Install TCL development libraries. In this note,
|
||||
we'll do a private install in the $HOME/local directory,
|
||||
but you can make adjustments to install TCL wherever you like.
|
||||
This document assumes you are working with TCL version 9.0.
|
||||
See also the [](./tcl-extension-testing.md) document that contains
|
||||
more details on compiling Tcl for use with SQLite.
|
||||
<ol type="a">
|
||||
<li>Get the TCL source archive, perhaps from
|
||||
<https://www.tcl.tk/software/tcltk/download.html>
|
||||
@@ -23,6 +26,12 @@ are general and should work on most any modern unix platform.
|
||||
<li>Run: `./configure --prefix=$HOME/local`
|
||||
<li>Run: `make install`
|
||||
</ol>
|
||||
<p>
|
||||
As of 2024-10-25, TCL is not longer required for many
|
||||
common build targets, such as "sqlite3.c" or the "sqlite3"
|
||||
command-line tool. So you can skip this step if that is all
|
||||
you want to build. TCL is still required to run "make test"
|
||||
and similar, or to build the TCL extension, of course.
|
||||
|
||||
4. Download the SQLite source tree and unpack it. CD into the
|
||||
toplevel directory of the source tree.
|
||||
@@ -30,7 +39,7 @@ are general and should work on most any modern unix platform.
|
||||
5. Run: `./configure --enable-all --with-tclsh=$HOME/local/bin/tclsh9.0`
|
||||
|
||||
You do not need to use --with-tclsh if the tclsh you want to use is the
|
||||
first one on your PATH.
|
||||
first one on your PATH or if you are building without TCL.
|
||||
|
||||
6. Run the "`Makefile`" makefile with an appropriate target.
|
||||
Examples:
|
||||
@@ -39,6 +48,10 @@ are general and should work on most any modern unix platform.
|
||||
<li> `make sqlite3`
|
||||
<li> `make sqldiff`
|
||||
<li> `make sqlite3_rsync`
|
||||
</ul>
|
||||
<p>None of the targets above require TCL. TCL is needed
|
||||
for the following targets:
|
||||
<ul>
|
||||
<li> `make tclextension-install`
|
||||
<li> `make devtest`
|
||||
<li> `make releasetest`
|
||||
@@ -54,4 +67,4 @@ are general and should work on most any modern unix platform.
|
||||
|
||||
|
||||
7. For a debugging build of the CLI, where the ".treetrace" and ".wheretrace"
|
||||
commands work, add the the --enable-debug argument to configure.
|
||||
commands work, add the the --with-debug argument to configure.
|
||||
|
||||
+39
-21
@@ -1,12 +1,23 @@
|
||||
# Notes On Compiling SQLite On Windows 11
|
||||
|
||||
Here are step-by-step instructions on how to build SQLite from
|
||||
canonical source on a new Windows 11 PC, as of 2024-10-09:
|
||||
Below are step-by-step instructions on how to build SQLite from
|
||||
canonical source on a new Windows 11 PC, as of 2024-10-09.
|
||||
See [](./compile-for-unix.md) for a similar guide for unix-like
|
||||
systems, including MacOS.
|
||||
|
||||
1. Install Microsoft Visual Studio. The free "community edition"
|
||||
will work fine. Do a standard install for C++ development.
|
||||
SQLite only needs the
|
||||
"cl" compiler and the "nmake" build tool.
|
||||
<ul><li><b>Note:</b>
|
||||
VS2015 or later is required for the procedures below to
|
||||
all work. You *might* be able to get the build to work with
|
||||
earlier versions of MSVC, but in that case the TCL installation
|
||||
of step 3 will be required, since the "jimsh0.c" program of
|
||||
Autosetup that is used as a substitute for "tclsh.exe" won't
|
||||
compile with versions of Visual Studio prior to VS2015. In any
|
||||
event, building SQLite from canonical source code on Windows
|
||||
is not supported for earlier versions of Visual Studio.</ul>
|
||||
|
||||
2. Under the "Start" menu, find "All Apps" then go to "Visual Studio 20XX"
|
||||
and find "x64 Native Tools Command Prompt for VS 20XX". Pin that
|
||||
@@ -16,23 +27,29 @@ canonical source on a new Windows 11 PC, as of 2024-10-09:
|
||||
a 32-bit build.) The subsequent steps will not work in a vanilla
|
||||
DOS prompt. Nor will they work in PowerShell.
|
||||
|
||||
3. Install TCL development libraries. This note assumes that you will
|
||||
3. *(Optional):* Install TCL development libraries.
|
||||
This note assumes that you will
|
||||
install the TCL development libraries in the "`c:\Tcl`" directory.
|
||||
Make adjustments
|
||||
if you want TCL installed somewhere else. SQLite needs both the
|
||||
"tclsh90.exe" command-line tool as part of the build process, and
|
||||
the "tcl90.lib" and "tclstub.lib" libraries in order to run tests.
|
||||
This document assumes you are working with <b>TCL version 9.0</b>.
|
||||
See versions of this document from prior to 2024-10-10 for
|
||||
instructions on how to build using TCL version 8.6.
|
||||
This document assumes you are working with TCL version 9.0.
|
||||
See [](./tcl-extension-testing.md#windows) for guidance on how
|
||||
to compile TCL version 8.6 for use with SQLite.
|
||||
<ol type="a">
|
||||
<li>Get the TCL source archive, perhaps from
|
||||
<https://www.tcl.tk/software/tcltk/download.html>
|
||||
or <https://sqlite.org/tmp/tcl9.0.0.tar.gz>.
|
||||
<li>Untar or unzip the source archive. CD into the "win/" subfolder
|
||||
of the source tree.
|
||||
<li>Run: `nmake /f makefile.vc release`
|
||||
<li>Run: `nmake /f makefile.vc INSTALLDIR=c:\Tcl install`
|
||||
<li>Run: `nmake /f makefile.vc INSTALLDIR=c:\Tcl release`
|
||||
<li>Run: `nmake /f makefile.vc INSTALLDIR=c:\Tcl install` <br>
|
||||
Notes:
|
||||
<ol type="i">
|
||||
<li> The previous two `nmake` commands must be run separately.
|
||||
<li> Also, the INSTALLDIR=... argument is required on both.
|
||||
</ol>
|
||||
<li><i>Optional:</i> CD to `c:\Tcl\bin` and make a copy of
|
||||
`tclsh90.exe` over into just `tclsh.exe`.
|
||||
<li><i>Optional:</i>
|
||||
@@ -43,22 +60,16 @@ canonical source on a new Windows 11 PC, as of 2024-10-09:
|
||||
making this change.
|
||||
</ol>
|
||||
|
||||
As of 2024-10-25, TCL is not longer required for many
|
||||
common build targets, such as "sqlite3.c" or the "sqlite3.exe"
|
||||
command-line tool. So you can skip this step if that is all
|
||||
you want to build. TCL is still required to run "make test"
|
||||
and similar, or to build the TCL extension, of course.
|
||||
|
||||
4. Download the SQLite source tree and unpack it. CD into the
|
||||
toplevel directory of the source tree.
|
||||
|
||||
5. Set the TCLDIR environment variable to point to your TCL installation.
|
||||
Like this:
|
||||
<ul>
|
||||
<li> `set TCLDIR=c:\Tcl`
|
||||
</ul>
|
||||
|
||||
If you install TCL in the "`c:\Tcl`" directory (as recommended
|
||||
in step 3 above), then this step is optional because
|
||||
"`c:\Tcl`" is the default value for TCLDIR. You can also skip this
|
||||
step by specifying "`TCLDIR=c:\Tcl`" as an argument to the nmake
|
||||
commands in step 6 below.
|
||||
|
||||
6. Run the "`Makefile.msc`" makefile with an appropriate target.
|
||||
5. Run the "`Makefile.msc`" makefile with an appropriate target.
|
||||
Examples:
|
||||
<ul>
|
||||
<li> `nmake /f makefile.msc`
|
||||
@@ -66,6 +77,13 @@ canonical source on a new Windows 11 PC, as of 2024-10-09:
|
||||
<li> `nmake /f makefile.msc sqlite3.exe`
|
||||
<li> `nmake /f makefile.msc sqldiff.exe`
|
||||
<li> `nmake /f makefile.msc sqlite3_rsync.exe`
|
||||
</ul>
|
||||
<p>No TCL is required for the nmake targets above. But for the ones
|
||||
that follow, you will need a TCL installation, as described in step 3
|
||||
above. If you install TCL in some directory other than C:\\Tcl, then
|
||||
you will also need to add the "TCLDIR=<i><dir></i>" option on the
|
||||
nmake command line to tell nmake where your TCL is installed.
|
||||
<ul>
|
||||
<li> `nmake /f makefile.msc tclextension-install`
|
||||
<li> `nmake /f makefile.msc devtest`
|
||||
<li> `nmake /f makefile.msc releasetest`
|
||||
|
||||
@@ -0,0 +1,208 @@
|
||||
# Test Procedures For The SQLite TCL Extension
|
||||
|
||||
## 1.0 Background
|
||||
|
||||
The SQLite TCL extension logic (in the
|
||||
"[tclsqlite.c](/file/src/tclsqlite.c)" source
|
||||
file) is statically linked into "textfixture" executable
|
||||
which is the program used to do most of the testing
|
||||
associated with "make test", "make devtest", and/or
|
||||
"make releasetest". So the functionality of the SQLite
|
||||
TCL extension is thoroughly vetted during normal testing. The
|
||||
procedures below are designed to test the loadable extension
|
||||
aspect of the SQLite TCL extension, and in particular to verify
|
||||
that the "make tclextension-install" build target works and that
|
||||
an ordinary tclsh can subsequently run "package require sqlite3".
|
||||
|
||||
This procedure can also be used as a template for how to set up
|
||||
a local TCL+SQLite development environment. In other words, it
|
||||
can be be used as a guide on how to compile per-user copies of
|
||||
Tcl that are used to develop, test, and debug SQLite. In that
|
||||
case, perhaps make minor changes to the procedure such as:
|
||||
|
||||
* Make TCLBUILD directory is permanent.
|
||||
* Enable debugging symbols on the Tcl library build.
|
||||
* Reduce the optimization level to -O0 for easier debugging.
|
||||
* Also compile "wish" to go with each "tclsh".
|
||||
|
||||
|
||||
<a id="unix"></a>
|
||||
## 2.0 Testing On Unix-like Systems (Including Mac)
|
||||
|
||||
See also the [](./compile-for-unix.md) document which provides another
|
||||
perspective on how to compile SQLite on unix-like systems.
|
||||
|
||||
### 2.1 Setup
|
||||
|
||||
<ol type="1">
|
||||
<li value="1">
|
||||
[Fossil](https://fossil-scm.org/) installed.
|
||||
<li> Check out source code and set environment variables:
|
||||
<ol type="a">
|
||||
<li> **TCLSOURCE** →
|
||||
The top-level directory of a Fossil check-out of the TCL source tree.
|
||||
<li> **SQLITESOURCE** →
|
||||
A Fossil check-out of the SQLite source tree.
|
||||
<li> **TCLBUILD** →
|
||||
A directory that does not exist at the start of the test and which
|
||||
will be deleted at the end of the test, and that will contain the
|
||||
test builds of the TCL libraries and the SQLite TCL Extensions.
|
||||
</ol>
|
||||
</ol>
|
||||
|
||||
### 2.2 Testing TCL 8.6 on unix
|
||||
|
||||
<ol type="1">
|
||||
<li value="3"> `mkdir -p $TCLBUILD/tcl86`
|
||||
<li> `cd $TCLSOURCE/unix`
|
||||
<li> `fossil up core-8-6-16` <br>
|
||||
↑ Or some other version of Tcl8.6.
|
||||
<li> `fossil clean -x`
|
||||
<li> `./configure --prefix=$TCLBUILD/tcl86 --disable-shared` <br>
|
||||
↑ The --disable-shared is to avoid the need to set LD_LIBRARY_PATH
|
||||
when using this Tcl build.
|
||||
<li> `make install`
|
||||
<li> `cd $SQLITESOURCE`
|
||||
<li> `fossil clean -x`
|
||||
<li> `./configure --with-tclsh=$TCLBUILD/tcl86/bin/tclsh8.6 --all`
|
||||
<li> `make tclextension-install` <br>
|
||||
↑ Verify extension installed at $TCLBUILD/tcl86/lib/tcl8.6/sqlite3.*
|
||||
<li> `make tclextension-list` <br>
|
||||
↑ Verify TCL extension correctly installed.
|
||||
<li> `make tclextension-verify` <br>
|
||||
↑ Verify that the correct version is installed.
|
||||
<li> `$TCLBUILD/tcl86/bin/tclsh8.6 test/testrunner.tcl release --explain` <br>
|
||||
↑ Verify thousands of lines of output with no errors. Or
|
||||
consider running "devtest" without --explain instead of "release".
|
||||
</ol>
|
||||
|
||||
### 2.3 Testing TCL 9.0 on unix
|
||||
|
||||
<ol>
|
||||
<li value="16"> `mkdir -p $TCLBUILD/tcl90`
|
||||
<li> `fossil up core-9-0-0` <br>
|
||||
↑ Or some other version of Tcl9
|
||||
<li> `fossil clean -x`
|
||||
<li> `./configure --prefix=$TCLBUILD/tcl90 --disable-shared` <br>
|
||||
↑ The --disable-shared is to avoid the need to set LD_LIBRARY_PATH
|
||||
when using this Tcl build.
|
||||
<li> `make install`
|
||||
<li> `cp -r ../library $TCLBUILD/tcl90/lib/tcl9.0` <br>
|
||||
↑ The Tcl library is not installed by "make install" for Tcl9.0 unless
|
||||
you also include the --disable-zipfs to ./configure. But if you do that
|
||||
then the generated tclsh9.0 is no longer stand-alone. On the other hand,
|
||||
if you don't install the Tcl library, other programs like testfixture
|
||||
won't be able to find the Tcl library and hence won't work. This
|
||||
extra installation step resolves the dilemma.
|
||||
This step is not required when building Tcl8.6, which lacks support for
|
||||
zipfs and hence always installs its Tcl library.
|
||||
<li> `cd $SQLITESOURCE`
|
||||
<li> `fossil clean -x`
|
||||
<li> `./configure --with-tclsh=$TCLBUILD/tcl90/bin/tclsh9.0 --all`
|
||||
<li> `make tclextension-install` <br>
|
||||
↑ Verify extension installed at $TCLBUILD/tcl90/lib/sqlite3.*
|
||||
<li> `make tclextension-list` <br>
|
||||
↑ Verify TCL extension correctly installed.
|
||||
<li> `make tclextension-verify`
|
||||
<li> `$TCLBUILD/tcl90/bin/tclsh9.0 test/testrunner.tcl release --explain` <br>
|
||||
↑ Verify thousands of lines of output with no errors. Or
|
||||
consider running "devtest" without --explain instead of "release".
|
||||
</ol>
|
||||
|
||||
### 2.4 Cleanup
|
||||
|
||||
<ol type="1">
|
||||
<li value="29"> `rm -rf $TCLBUILD`
|
||||
</ol>
|
||||
|
||||
<a id="windows"></a>
|
||||
## 3.0 Testing On Windows
|
||||
|
||||
See also the [](./compile-for-windows.md) document which provides another
|
||||
perspective on how to compile SQLite on Windows.
|
||||
|
||||
### 3.1 Setup for Windows
|
||||
|
||||
<ol type="1">
|
||||
<li value="1">
|
||||
[Fossil](https://fossil-scm.org/) installed.
|
||||
<li>
|
||||
Unix-like command-line tools installed. Example:
|
||||
[unxutils](https://unxutils.sourceforge.net/)
|
||||
<li> [Visual Studio](https://visualstudio.microsoft.com/vs/community/)
|
||||
installed. VS2015 or later required.
|
||||
<li> Check out source code and set environment variables.
|
||||
<ol type="a">
|
||||
<li> **TCLSOURCE** →
|
||||
The top-level directory of a Fossil check-out of the TCL source tree.
|
||||
<li> **SQLITESOURCE** →
|
||||
A Fossil check-out of the SQLite source tree.
|
||||
<li> **TCLBUILD** →
|
||||
A directory that does not exist at the start of the test and which
|
||||
will be deleted at the end of the test, and that will contain the
|
||||
test builds of the TCL libraries and the SQLite TCL Extensions.
|
||||
<li> **ORIGINALPATH** →
|
||||
The original value of %PATH%. In other words, set as follows:
|
||||
`set ORIGINALPATH %PATH%`
|
||||
</ol>
|
||||
</ol>
|
||||
|
||||
### 3.2 Testing TCL 8.6 on Windows
|
||||
|
||||
<ol type="1">
|
||||
<li value="5"> `mkdir %TCLBUILD%\tcl86`
|
||||
<li> `cd %TCLSOURCE%\win`
|
||||
<li> `fossil up core-8-6-16` <br>
|
||||
↑ Or some other version of Tcl8.6.
|
||||
<li> `fossil clean -x`
|
||||
<li> `set INSTALLDIR=%TCLBUILD%\tcl86`
|
||||
<li> `nmake /f makefile.vc release` <br>
|
||||
⇅ You *must* invoke the "release" and "install" targets
|
||||
using separate "nmake" commands or tclsh86t.exe won't be
|
||||
installed.
|
||||
<li> `nmake /f makefile.vc install`
|
||||
<li> `cd %SQLITESOURCE%`
|
||||
<li> `fossil clean -x`
|
||||
<li> `set TCLDIR=%TCLBUILD%\tcl86`
|
||||
<li> `set PATH=%TCLBUILD%\tcl86\bin;%ORIGINALPATH%`
|
||||
<li> `set TCLSH_CMD=%TCLBUILD%\tcl86\bin\tclsh86t.exe`
|
||||
<li> `nmake /f Makefile.msc tclextension-install` <br>
|
||||
↑ Verify extension installed at %TCLBUILD%\\tcl86\\lib\\tcl8.6\\sqlite3.*
|
||||
<li> `nmake /f Makefile.msc tclextension-verify`
|
||||
<li>`tclsh86t test/testrunner.tcl release --explain` <br>
|
||||
↑ Verify thousands of lines of output with no errors. Or
|
||||
consider running "devtest" without --explain instead of "release".
|
||||
</ol>
|
||||
|
||||
### 3.3 Testing TCL 9.0 on Windows
|
||||
|
||||
<ol>
|
||||
<li value="20"> `mkdir %TCLBUILD%\tcl90`
|
||||
<li> `cd %TCLSOURCE%\win`
|
||||
<li> `fossil up core-9-0-0` <br>
|
||||
↑ Or some other version of Tcl9
|
||||
<li> `fossil clean -x`
|
||||
<li> `set INSTALLDIR=%TCLBUILD%\tcl90`
|
||||
<li> `nmake /f makefile.vc release` <br>
|
||||
⇅ You *must* invoke the "release" and "install" targets
|
||||
using separate "nmake" commands or tclsh90.exe won't be
|
||||
installed.
|
||||
<li> `nmake /f makefile.vc install`
|
||||
<li> `cd %SQLITESOURCE%`
|
||||
<li> `fossil clean -x`
|
||||
<li> `set TCLDIR=%TCLBUILD%\tcl90`
|
||||
<li> `set PATH=%TCLBUILD%\tcl90\bin;%ORIGINALPATH%`
|
||||
<li> `set TCLSH_CMD=%TCLBUILD%\tcl90\bin\tclsh90.exe`
|
||||
<li> `nmake /f Makefile.msc tclextension-install` <br>
|
||||
↑ Verify extension installed at %TCLBUILD%\\tcl90\\lib\\sqlite3.*
|
||||
<li> `nmake /f Makefile.msc tclextension-verify`
|
||||
<li> `tclsh90 test/testrunner.tcl release --explain` <br>
|
||||
↑ Verify thousands of lines of output with no errors. Or
|
||||
consider running "devtest" without --explain instead of "release".
|
||||
</ol>
|
||||
|
||||
### 3.4 Cleanup
|
||||
|
||||
<ol type="1">
|
||||
<li value="35"> `rm -rf %TCLBUILD%`
|
||||
</ol>
|
||||
@@ -1,170 +0,0 @@
|
||||
NOTE (2012-11-29):
|
||||
|
||||
The functionality implemented by this extension has been superseded
|
||||
by WAL-mode. This module is no longer supported or maintained. The
|
||||
code is retained for historical reference only.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
Normally, when SQLite writes to a database file, it waits until the write
|
||||
operation is finished before returning control to the calling application.
|
||||
Since writing to the file-system is usually very slow compared with CPU
|
||||
bound operations, this can be a performance bottleneck. This directory
|
||||
contains an extension that causes SQLite to perform all write requests
|
||||
using a separate thread running in the background. Although this does not
|
||||
reduce the overall system resources (CPU, disk bandwidth etc.) at all, it
|
||||
allows SQLite to return control to the caller quickly even when writing to
|
||||
the database, eliminating the bottleneck.
|
||||
|
||||
1. Functionality
|
||||
|
||||
1.1 How it Works
|
||||
1.2 Limitations
|
||||
1.3 Locking and Concurrency
|
||||
|
||||
2. Compilation and Usage
|
||||
|
||||
3. Porting
|
||||
|
||||
|
||||
|
||||
1. FUNCTIONALITY
|
||||
|
||||
With asynchronous I/O, write requests are handled by a separate thread
|
||||
running in the background. This means that the thread that initiates
|
||||
a database write does not have to wait for (sometimes slow) disk I/O
|
||||
to occur. The write seems to happen very quickly, though in reality
|
||||
it is happening at its usual slow pace in the background.
|
||||
|
||||
Asynchronous I/O appears to give better responsiveness, but at a price.
|
||||
You lose the Durable property. With the default I/O backend of SQLite,
|
||||
once a write completes, you know that the information you wrote is
|
||||
safely on disk. With the asynchronous I/O, this is not the case. If
|
||||
your program crashes or if a power loss occurs after the database
|
||||
write but before the asynchronous write thread has completed, then the
|
||||
database change might never make it to disk and the next user of the
|
||||
database might not see your change.
|
||||
|
||||
You lose Durability with asynchronous I/O, but you still retain the
|
||||
other parts of ACID: Atomic, Consistent, and Isolated. Many
|
||||
appliations get along fine without the Durablity.
|
||||
|
||||
1.1 How it Works
|
||||
|
||||
Asynchronous I/O works by creating a special SQLite "vfs" structure
|
||||
and registering it with sqlite3_vfs_register(). When files opened via
|
||||
this vfs are written to (using the vfs xWrite() method), the data is not
|
||||
written directly to disk, but is placed in the "write-queue" to be
|
||||
handled by the background thread.
|
||||
|
||||
When files opened with the asynchronous vfs are read from
|
||||
(using the vfs xRead() method), the data is read from the file on
|
||||
disk and the write-queue, so that from the point of view of
|
||||
the vfs reader the xWrite() appears to have already completed.
|
||||
|
||||
The special vfs is registered (and unregistered) by calls to the
|
||||
API functions sqlite3async_initialize() and sqlite3async_shutdown().
|
||||
See section "Compilation and Usage" below for details.
|
||||
|
||||
1.2 Limitations
|
||||
|
||||
In order to gain experience with the main ideas surrounding asynchronous
|
||||
IO, this implementation is deliberately kept simple. Additional
|
||||
capabilities may be added in the future.
|
||||
|
||||
For example, as currently implemented, if writes are happening at a
|
||||
steady stream that exceeds the I/O capability of the background writer
|
||||
thread, the queue of pending write operations will grow without bound.
|
||||
If this goes on for long enough, the host system could run out of memory.
|
||||
A more sophisticated module could to keep track of the quantity of
|
||||
pending writes and stop accepting new write requests when the queue of
|
||||
pending writes grows too large.
|
||||
|
||||
1.3 Locking and Concurrency
|
||||
|
||||
Multiple connections from within a single process that use this
|
||||
implementation of asynchronous IO may access a single database
|
||||
file concurrently. From the point of view of the user, if all
|
||||
connections are from within a single process, there is no difference
|
||||
between the concurrency offered by "normal" SQLite and SQLite
|
||||
using the asynchronous backend.
|
||||
|
||||
If file-locking is enabled (it is enabled by default), then connections
|
||||
from multiple processes may also read and write the database file.
|
||||
However concurrency is reduced as follows:
|
||||
|
||||
* When a connection using asynchronous IO begins a database
|
||||
transaction, the database is locked immediately. However the
|
||||
lock is not released until after all relevant operations
|
||||
in the write-queue have been flushed to disk. This means
|
||||
(for example) that the database may remain locked for some
|
||||
time after a "COMMIT" or "ROLLBACK" is issued.
|
||||
|
||||
* If an application using asynchronous IO executes transactions
|
||||
in quick succession, other database users may be effectively
|
||||
locked out of the database. This is because when a BEGIN
|
||||
is executed, a database lock is established immediately. But
|
||||
when the corresponding COMMIT or ROLLBACK occurs, the lock
|
||||
is not released until the relevant part of the write-queue
|
||||
has been flushed through. As a result, if a COMMIT is followed
|
||||
by a BEGIN before the write-queue is flushed through, the database
|
||||
is never unlocked,preventing other processes from accessing
|
||||
the database.
|
||||
|
||||
File-locking may be disabled at runtime using the sqlite3async_control()
|
||||
API (see below). This may improve performance when an NFS or other
|
||||
network file-system, as the synchronous round-trips to the server be
|
||||
required to establish file locks are avoided. However, if multiple
|
||||
connections attempt to access the same database file when file-locking
|
||||
is disabled, application crashes and database corruption is a likely
|
||||
outcome.
|
||||
|
||||
|
||||
2. COMPILATION AND USAGE
|
||||
|
||||
The asynchronous IO extension consists of a single file of C code
|
||||
(sqlite3async.c), and a header file (sqlite3async.h) that defines the
|
||||
C API used by applications to activate and control the modules
|
||||
functionality.
|
||||
|
||||
To use the asynchronous IO extension, compile sqlite3async.c as
|
||||
part of the application that uses SQLite. Then use the API defined
|
||||
in sqlite3async.h to initialize and configure the module.
|
||||
|
||||
The asynchronous IO VFS API is described in detail in comments in
|
||||
sqlite3async.h. Using the API usually consists of the following steps:
|
||||
|
||||
1. Register the asynchronous IO VFS with SQLite by calling the
|
||||
sqlite3async_initialize() function.
|
||||
|
||||
2. Create a background thread to perform write operations and call
|
||||
sqlite3async_run().
|
||||
|
||||
3. Use the normal SQLite API to read and write to databases via
|
||||
the asynchronous IO VFS.
|
||||
|
||||
Refer to sqlite3async.h for details.
|
||||
|
||||
|
||||
3. PORTING
|
||||
|
||||
Currently the asynchronous IO extension is compatible with win32 systems
|
||||
and systems that support the pthreads interface, including Mac OSX, Linux,
|
||||
and other varieties of Unix.
|
||||
|
||||
To port the asynchronous IO extension to another platform, the user must
|
||||
implement mutex and condition variable primitives for the new platform.
|
||||
Currently there is no externally available interface to allow this, but
|
||||
modifying the code within sqlite3async.c to include the new platforms
|
||||
concurrency primitives is relatively easy. Search within sqlite3async.c
|
||||
for the comment string "PORTING FUNCTIONS" for details. Then implement
|
||||
new versions of each of the following:
|
||||
|
||||
static void async_mutex_enter(int eMutex);
|
||||
static void async_mutex_leave(int eMutex);
|
||||
static void async_cond_wait(int eCond, int eMutex);
|
||||
static void async_cond_signal(int eCond);
|
||||
static void async_sched_yield(void);
|
||||
|
||||
The functionality required of each of the above functions is described
|
||||
in comments in sqlite3async.c.
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,222 +0,0 @@
|
||||
|
||||
#ifndef __SQLITEASYNC_H_
|
||||
#define __SQLITEASYNC_H_ 1
|
||||
|
||||
/*
|
||||
** Make sure we can call this stuff from C++.
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define SQLITEASYNC_VFSNAME "sqlite3async"
|
||||
|
||||
/*
|
||||
** THREAD SAFETY NOTES:
|
||||
**
|
||||
** Of the four API functions in this file, the following are not threadsafe:
|
||||
**
|
||||
** sqlite3async_initialize()
|
||||
** sqlite3async_shutdown()
|
||||
**
|
||||
** Care must be taken that neither of these functions is called while
|
||||
** another thread may be calling either any sqlite3async_XXX() function
|
||||
** or an sqlite3_XXX() API function related to a database handle that
|
||||
** is using the asynchronous IO VFS.
|
||||
**
|
||||
** These functions:
|
||||
**
|
||||
** sqlite3async_run()
|
||||
** sqlite3async_control()
|
||||
**
|
||||
** are threadsafe. It is quite safe to call either of these functions even
|
||||
** if another thread may also be calling one of them or an sqlite3_XXX()
|
||||
** function related to a database handle that uses the asynchronous IO VFS.
|
||||
*/
|
||||
|
||||
/*
|
||||
** Initialize the asynchronous IO VFS and register it with SQLite using
|
||||
** sqlite3_vfs_register(). If the asynchronous VFS is already initialized
|
||||
** and registered, this function is a no-op. The asynchronous IO VFS
|
||||
** is registered as "sqlite3async".
|
||||
**
|
||||
** The asynchronous IO VFS does not make operating system IO requests
|
||||
** directly. Instead, it uses an existing VFS implementation for all
|
||||
** required file-system operations. If the first parameter to this function
|
||||
** is NULL, then the current default VFS is used for IO. If it is not
|
||||
** NULL, then it must be the name of an existing VFS. In other words, the
|
||||
** first argument to this function is passed to sqlite3_vfs_find() to
|
||||
** locate the VFS to use for all real IO operations. This VFS is known
|
||||
** as the "parent VFS".
|
||||
**
|
||||
** If the second parameter to this function is non-zero, then the
|
||||
** asynchronous IO VFS is registered as the default VFS for all SQLite
|
||||
** database connections within the process. Otherwise, the asynchronous IO
|
||||
** VFS is only used by connections opened using sqlite3_open_v2() that
|
||||
** specifically request VFS "sqlite3async".
|
||||
**
|
||||
** If a parent VFS cannot be located, then SQLITE_ERROR is returned.
|
||||
** In the unlikely event that operating system specific initialization
|
||||
** fails (win32 systems create the required critical section and event
|
||||
** objects within this function), then SQLITE_ERROR is also returned.
|
||||
** Finally, if the call to sqlite3_vfs_register() returns an error, then
|
||||
** the error code is returned to the user by this function. In all three
|
||||
** of these cases, intialization has failed and the asynchronous IO VFS
|
||||
** is not registered with SQLite.
|
||||
**
|
||||
** Otherwise, if no error occurs, SQLITE_OK is returned.
|
||||
*/
|
||||
int sqlite3async_initialize(const char *zParent, int isDefault);
|
||||
|
||||
/*
|
||||
** This function unregisters the asynchronous IO VFS using
|
||||
** sqlite3_vfs_unregister().
|
||||
**
|
||||
** On win32 platforms, this function also releases the small number of
|
||||
** critical section and event objects created by sqlite3async_initialize().
|
||||
*/
|
||||
void sqlite3async_shutdown(void);
|
||||
|
||||
/*
|
||||
** This function may only be called when the asynchronous IO VFS is
|
||||
** installed (after a call to sqlite3async_initialize()). It processes
|
||||
** zero or more queued write operations before returning. It is expected
|
||||
** (but not required) that this function will be called by a different
|
||||
** thread than those threads that use SQLite. The "background thread"
|
||||
** that performs IO.
|
||||
**
|
||||
** How many queued write operations are performed before returning
|
||||
** depends on the global setting configured by passing the SQLITEASYNC_HALT
|
||||
** verb to sqlite3async_control() (see below for details). By default
|
||||
** this function never returns - it processes all pending operations and
|
||||
** then blocks waiting for new ones.
|
||||
**
|
||||
** If multiple simultaneous calls are made to sqlite3async_run() from two
|
||||
** or more threads, then the calls are serialized internally.
|
||||
*/
|
||||
void sqlite3async_run(void);
|
||||
|
||||
/*
|
||||
** This function may only be called when the asynchronous IO VFS is
|
||||
** installed (after a call to sqlite3async_initialize()). It is used
|
||||
** to query or configure various parameters that affect the operation
|
||||
** of the asynchronous IO VFS. At present there are three parameters
|
||||
** supported:
|
||||
**
|
||||
** * The "halt" parameter, which configures the circumstances under
|
||||
** which the sqlite3async_run() parameter is configured.
|
||||
**
|
||||
** * The "delay" parameter. Setting the delay parameter to a non-zero
|
||||
** value causes the sqlite3async_run() function to sleep for the
|
||||
** configured number of milliseconds between each queued write
|
||||
** operation.
|
||||
**
|
||||
** * The "lockfiles" parameter. This parameter determines whether or
|
||||
** not the asynchronous IO VFS locks the database files it operates
|
||||
** on. Disabling file locking can improve throughput.
|
||||
**
|
||||
** This function is always passed two arguments. When setting the value
|
||||
** of a parameter, the first argument must be one of SQLITEASYNC_HALT,
|
||||
** SQLITEASYNC_DELAY or SQLITEASYNC_LOCKFILES. The second argument must
|
||||
** be passed the new value for the parameter as type "int".
|
||||
**
|
||||
** When querying the current value of a paramter, the first argument must
|
||||
** be one of SQLITEASYNC_GET_HALT, GET_DELAY or GET_LOCKFILES. The second
|
||||
** argument to this function must be of type (int *). The current value
|
||||
** of the queried parameter is copied to the memory pointed to by the
|
||||
** second argument. For example:
|
||||
**
|
||||
** int eCurrentHalt;
|
||||
** int eNewHalt = SQLITEASYNC_HALT_IDLE;
|
||||
**
|
||||
** sqlite3async_control(SQLITEASYNC_HALT, eNewHalt);
|
||||
** sqlite3async_control(SQLITEASYNC_GET_HALT, &eCurrentHalt);
|
||||
** assert( eNewHalt==eCurrentHalt );
|
||||
**
|
||||
** See below for more detail on each configuration parameter.
|
||||
**
|
||||
** SQLITEASYNC_HALT:
|
||||
**
|
||||
** This is used to set the value of the "halt" parameter. The second
|
||||
** argument must be one of the SQLITEASYNC_HALT_XXX symbols defined
|
||||
** below (either NEVER, IDLE and NOW).
|
||||
**
|
||||
** If the parameter is set to NEVER, then calls to sqlite3async_run()
|
||||
** never return. This is the default setting. If the parameter is set
|
||||
** to IDLE, then calls to sqlite3async_run() return as soon as the
|
||||
** queue of pending write operations is empty. If the parameter is set
|
||||
** to NOW, then calls to sqlite3async_run() return as quickly as
|
||||
** possible, without processing any pending write requests.
|
||||
**
|
||||
** If an attempt is made to set this parameter to an integer value other
|
||||
** than SQLITEASYNC_HALT_NEVER, IDLE or NOW, then sqlite3async_control()
|
||||
** returns SQLITE_MISUSE and the current value of the parameter is not
|
||||
** modified.
|
||||
**
|
||||
** Modifying the "halt" parameter affects calls to sqlite3async_run()
|
||||
** made by other threads that are currently in progress.
|
||||
**
|
||||
** SQLITEASYNC_DELAY:
|
||||
**
|
||||
** This is used to set the value of the "delay" parameter. If set to
|
||||
** a non-zero value, then after completing a pending write request, the
|
||||
** sqlite3async_run() function sleeps for the configured number of
|
||||
** milliseconds.
|
||||
**
|
||||
** If an attempt is made to set this parameter to a negative value,
|
||||
** sqlite3async_control() returns SQLITE_MISUSE and the current value
|
||||
** of the parameter is not modified.
|
||||
**
|
||||
** Modifying the "delay" parameter affects calls to sqlite3async_run()
|
||||
** made by other threads that are currently in progress.
|
||||
**
|
||||
** SQLITEASYNC_LOCKFILES:
|
||||
**
|
||||
** This is used to set the value of the "lockfiles" parameter. This
|
||||
** parameter must be set to either 0 or 1. If set to 1, then the
|
||||
** asynchronous IO VFS uses the xLock() and xUnlock() methods of the
|
||||
** parent VFS to lock database files being read and/or written. If
|
||||
** the parameter is set to 0, then these locks are omitted.
|
||||
**
|
||||
** This parameter may only be set when there are no open database
|
||||
** connections using the VFS and the queue of pending write requests
|
||||
** is empty. Attempting to set it when this is not true, or to set it
|
||||
** to a value other than 0 or 1 causes sqlite3async_control() to return
|
||||
** SQLITE_MISUSE and the value of the parameter to remain unchanged.
|
||||
**
|
||||
** If this parameter is set to zero, then it is only safe to access the
|
||||
** database via the asynchronous IO VFS from within a single process. If
|
||||
** while writing to the database via the asynchronous IO VFS the database
|
||||
** is also read or written from within another process, or via another
|
||||
** connection that does not use the asynchronous IO VFS within the same
|
||||
** process, the results are undefined (and may include crashes or database
|
||||
** corruption).
|
||||
**
|
||||
** Alternatively, if this parameter is set to 1, then it is safe to access
|
||||
** the database from multiple connections within multiple processes using
|
||||
** either the asynchronous IO VFS or the parent VFS directly.
|
||||
*/
|
||||
int sqlite3async_control(int op, ...);
|
||||
|
||||
/*
|
||||
** Values that can be used as the first argument to sqlite3async_control().
|
||||
*/
|
||||
#define SQLITEASYNC_HALT 1
|
||||
#define SQLITEASYNC_GET_HALT 2
|
||||
#define SQLITEASYNC_DELAY 3
|
||||
#define SQLITEASYNC_GET_DELAY 4
|
||||
#define SQLITEASYNC_LOCKFILES 5
|
||||
#define SQLITEASYNC_GET_LOCKFILES 6
|
||||
|
||||
/*
|
||||
** If the first argument to sqlite3async_control() is SQLITEASYNC_HALT,
|
||||
** the second argument should be one of the following.
|
||||
*/
|
||||
#define SQLITEASYNC_HALT_NEVER 0 /* Never halt (default value) */
|
||||
#define SQLITEASYNC_HALT_NOW 1 /* Halt as soon as possible */
|
||||
#define SQLITEASYNC_HALT_IDLE 2 /* Halt when write-queue is empty */
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* End of the 'extern "C"' block */
|
||||
#endif
|
||||
#endif /* ifndef __SQLITEASYNC_H_ */
|
||||
@@ -1,773 +0,0 @@
|
||||
/*
|
||||
** 2023 November 4
|
||||
**
|
||||
** The author disclaims copyright to this source code. In place of
|
||||
** a legal notice, here is a blessing:
|
||||
**
|
||||
** May you do good and not evil.
|
||||
** May you find forgiveness for yourself and forgive others.
|
||||
** May you share freely, never taking more than you give.
|
||||
**
|
||||
********************************************************************************
|
||||
** This file implements various interfaces used for console and stream I/O
|
||||
** by the SQLite project command-line tools, as explained in console_io.h .
|
||||
** Functions prefixed by "SQLITE_INTERNAL_LINKAGE" behave as described there.
|
||||
*/
|
||||
|
||||
#ifndef SQLITE_CDECL
|
||||
# define SQLITE_CDECL
|
||||
#endif
|
||||
|
||||
#ifndef SHELL_NO_SYSINC
|
||||
# include <stdarg.h>
|
||||
# include <string.h>
|
||||
# include <stdlib.h>
|
||||
# include <limits.h>
|
||||
# include <assert.h>
|
||||
# include "sqlite3.h"
|
||||
#endif
|
||||
#ifndef HAVE_CONSOLE_IO_H
|
||||
# include "console_io.h"
|
||||
#endif
|
||||
#if defined(_MSC_VER)
|
||||
# pragma warning(disable : 4204)
|
||||
#endif
|
||||
|
||||
#ifndef SQLITE_CIO_NO_TRANSLATE
|
||||
# if (defined(_WIN32) || defined(WIN32)) && !SQLITE_OS_WINRT
|
||||
# ifndef SHELL_NO_SYSINC
|
||||
# include <io.h>
|
||||
# include <fcntl.h>
|
||||
# undef WIN32_LEAN_AND_MEAN
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
# include <windows.h>
|
||||
# endif
|
||||
# define CIO_WIN_WC_XLATE 1 /* Use WCHAR Windows APIs for console I/O */
|
||||
# else
|
||||
# ifndef SHELL_NO_SYSINC
|
||||
# include <unistd.h>
|
||||
# endif
|
||||
# define CIO_WIN_WC_XLATE 0 /* Use plain C library stream I/O at console */
|
||||
# endif
|
||||
#else
|
||||
# define CIO_WIN_WC_XLATE 0 /* Not exposing translation routines at all */
|
||||
#endif
|
||||
|
||||
#if CIO_WIN_WC_XLATE
|
||||
static HANDLE handleOfFile(FILE *pf){
|
||||
int fileDesc = _fileno(pf);
|
||||
union { intptr_t osfh; HANDLE fh; } fid = {
|
||||
(fileDesc>=0)? _get_osfhandle(fileDesc) : (intptr_t)INVALID_HANDLE_VALUE
|
||||
};
|
||||
return fid.fh;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef SQLITE_CIO_NO_TRANSLATE
|
||||
typedef struct PerStreamTags {
|
||||
# if CIO_WIN_WC_XLATE
|
||||
HANDLE hx;
|
||||
DWORD consMode;
|
||||
char acIncomplete[4];
|
||||
# else
|
||||
short reachesConsole;
|
||||
# endif
|
||||
FILE *pf;
|
||||
} PerStreamTags;
|
||||
|
||||
/* Define NULL-like value for things which can validly be 0. */
|
||||
# define SHELL_INVALID_FILE_PTR ((FILE *)~0)
|
||||
# if CIO_WIN_WC_XLATE
|
||||
# define SHELL_INVALID_CONS_MODE 0xFFFF0000
|
||||
# endif
|
||||
|
||||
# if CIO_WIN_WC_XLATE
|
||||
# define PST_INITIALIZER { INVALID_HANDLE_VALUE, SHELL_INVALID_CONS_MODE, \
|
||||
{0,0,0,0}, SHELL_INVALID_FILE_PTR }
|
||||
# else
|
||||
# define PST_INITIALIZER { 0, SHELL_INVALID_FILE_PTR }
|
||||
# endif
|
||||
|
||||
/* Quickly say whether a known output is going to the console. */
|
||||
# if CIO_WIN_WC_XLATE
|
||||
static short pstReachesConsole(PerStreamTags *ppst){
|
||||
return (ppst->hx != INVALID_HANDLE_VALUE);
|
||||
}
|
||||
# else
|
||||
# define pstReachesConsole(ppst) 0
|
||||
# endif
|
||||
|
||||
# if CIO_WIN_WC_XLATE
|
||||
static void restoreConsoleArb(PerStreamTags *ppst){
|
||||
if( pstReachesConsole(ppst) ) SetConsoleMode(ppst->hx, ppst->consMode);
|
||||
}
|
||||
# else
|
||||
# define restoreConsoleArb(ppst)
|
||||
# endif
|
||||
|
||||
/* Say whether FILE* appears to be a console, collect associated info. */
|
||||
static short streamOfConsole(FILE *pf, /* out */ PerStreamTags *ppst){
|
||||
# if CIO_WIN_WC_XLATE
|
||||
short rv = 0;
|
||||
DWORD dwCM = SHELL_INVALID_CONS_MODE;
|
||||
HANDLE fh = handleOfFile(pf);
|
||||
ppst->pf = pf;
|
||||
if( INVALID_HANDLE_VALUE != fh ){
|
||||
rv = (GetFileType(fh) == FILE_TYPE_CHAR && GetConsoleMode(fh,&dwCM));
|
||||
}
|
||||
ppst->hx = (rv)? fh : INVALID_HANDLE_VALUE;
|
||||
ppst->consMode = dwCM;
|
||||
return rv;
|
||||
# else
|
||||
ppst->pf = pf;
|
||||
ppst->reachesConsole = ( (short)isatty(fileno(pf)) );
|
||||
return ppst->reachesConsole;
|
||||
# endif
|
||||
}
|
||||
|
||||
# ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
|
||||
# define ENABLE_VIRTUAL_TERMINAL_PROCESSING (0x4)
|
||||
# endif
|
||||
|
||||
# if CIO_WIN_WC_XLATE
|
||||
/* Define console modes for use with the Windows Console API. */
|
||||
# define SHELL_CONI_MODE \
|
||||
(ENABLE_ECHO_INPUT | ENABLE_INSERT_MODE | ENABLE_LINE_INPUT | 0x80 \
|
||||
| ENABLE_QUICK_EDIT_MODE | ENABLE_EXTENDED_FLAGS | ENABLE_PROCESSED_INPUT)
|
||||
# define SHELL_CONO_MODE (ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT \
|
||||
| ENABLE_VIRTUAL_TERMINAL_PROCESSING)
|
||||
# endif
|
||||
|
||||
typedef struct ConsoleInfo {
|
||||
PerStreamTags pstSetup[3];
|
||||
PerStreamTags pstDesignated[3];
|
||||
StreamsAreConsole sacSetup;
|
||||
} ConsoleInfo;
|
||||
|
||||
static short isValidStreamInfo(PerStreamTags *ppst){
|
||||
return (ppst->pf != SHELL_INVALID_FILE_PTR);
|
||||
}
|
||||
|
||||
static ConsoleInfo consoleInfo = {
|
||||
{ /* pstSetup */ PST_INITIALIZER, PST_INITIALIZER, PST_INITIALIZER },
|
||||
{ /* pstDesignated[] */ PST_INITIALIZER, PST_INITIALIZER, PST_INITIALIZER },
|
||||
SAC_NoConsole /* sacSetup */
|
||||
};
|
||||
|
||||
SQLITE_INTERNAL_LINKAGE FILE* invalidFileStream = (FILE *)~0;
|
||||
|
||||
# if CIO_WIN_WC_XLATE
|
||||
static void maybeSetupAsConsole(PerStreamTags *ppst, short odir){
|
||||
if( pstReachesConsole(ppst) ){
|
||||
DWORD cm = odir? SHELL_CONO_MODE : SHELL_CONI_MODE;
|
||||
SetConsoleMode(ppst->hx, cm);
|
||||
}
|
||||
}
|
||||
# else
|
||||
# define maybeSetupAsConsole(ppst,odir)
|
||||
# endif
|
||||
|
||||
SQLITE_INTERNAL_LINKAGE void consoleRenewSetup(void){
|
||||
# if CIO_WIN_WC_XLATE
|
||||
int ix = 0;
|
||||
while( ix < 6 ){
|
||||
PerStreamTags *ppst = (ix<3)?
|
||||
&consoleInfo.pstSetup[ix] : &consoleInfo.pstDesignated[ix-3];
|
||||
maybeSetupAsConsole(ppst, (ix % 3)>0);
|
||||
++ix;
|
||||
}
|
||||
# endif
|
||||
}
|
||||
|
||||
SQLITE_INTERNAL_LINKAGE StreamsAreConsole
|
||||
consoleClassifySetup( FILE *pfIn, FILE *pfOut, FILE *pfErr ){
|
||||
StreamsAreConsole rv = SAC_NoConsole;
|
||||
FILE* apf[3] = { pfIn, pfOut, pfErr };
|
||||
int ix;
|
||||
for( ix = 2; ix >= 0; --ix ){
|
||||
PerStreamTags *ppst = &consoleInfo.pstSetup[ix];
|
||||
if( streamOfConsole(apf[ix], ppst) ){
|
||||
rv |= (SAC_InConsole<<ix);
|
||||
}
|
||||
consoleInfo.pstDesignated[ix] = *ppst;
|
||||
if( ix > 0 ) fflush(apf[ix]);
|
||||
}
|
||||
consoleInfo.sacSetup = rv;
|
||||
consoleRenewSetup();
|
||||
return rv;
|
||||
}
|
||||
|
||||
SQLITE_INTERNAL_LINKAGE void SQLITE_CDECL consoleRestore( void ){
|
||||
# if CIO_WIN_WC_XLATE
|
||||
static ConsoleInfo *pci = &consoleInfo;
|
||||
if( pci->sacSetup ){
|
||||
int ix;
|
||||
for( ix=0; ix<3; ++ix ){
|
||||
if( pci->sacSetup & (SAC_InConsole<<ix) ){
|
||||
PerStreamTags *ppst = &pci->pstSetup[ix];
|
||||
SetConsoleMode(ppst->hx, ppst->consMode);
|
||||
}
|
||||
}
|
||||
}
|
||||
# endif
|
||||
}
|
||||
#endif /* !defined(SQLITE_CIO_NO_TRANSLATE) */
|
||||
|
||||
#ifdef SQLITE_CIO_INPUT_REDIR
|
||||
/* Say whether given FILE* is among those known, via either
|
||||
** consoleClassifySetup() or set{Output,Error}Stream, as
|
||||
** readable, and return an associated PerStreamTags pointer
|
||||
** if so. Otherwise, return 0.
|
||||
*/
|
||||
static PerStreamTags * isKnownReadable(FILE *pf){
|
||||
static PerStreamTags *apst[] = {
|
||||
&consoleInfo.pstDesignated[0], &consoleInfo.pstSetup[0], 0
|
||||
};
|
||||
int ix = 0;
|
||||
do {
|
||||
if( apst[ix]->pf == pf ) break;
|
||||
} while( apst[++ix] != 0 );
|
||||
return apst[ix];
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef SQLITE_CIO_NO_TRANSLATE
|
||||
/* Say whether given FILE* is among those known, via either
|
||||
** consoleClassifySetup() or set{Output,Error}Stream, as
|
||||
** writable, and return an associated PerStreamTags pointer
|
||||
** if so. Otherwise, return 0.
|
||||
*/
|
||||
static PerStreamTags * isKnownWritable(FILE *pf){
|
||||
static PerStreamTags *apst[] = {
|
||||
&consoleInfo.pstDesignated[1], &consoleInfo.pstDesignated[2],
|
||||
&consoleInfo.pstSetup[1], &consoleInfo.pstSetup[2], 0
|
||||
};
|
||||
int ix = 0;
|
||||
do {
|
||||
if( apst[ix]->pf == pf ) break;
|
||||
} while( apst[++ix] != 0 );
|
||||
return apst[ix];
|
||||
}
|
||||
|
||||
static FILE *designateEmitStream(FILE *pf, unsigned chix){
|
||||
FILE *rv = consoleInfo.pstDesignated[chix].pf;
|
||||
if( pf == invalidFileStream ) return rv;
|
||||
else{
|
||||
/* Setting a possibly new output stream. */
|
||||
PerStreamTags *ppst = isKnownWritable(pf);
|
||||
if( ppst != 0 ){
|
||||
PerStreamTags pst = *ppst;
|
||||
consoleInfo.pstDesignated[chix] = pst;
|
||||
}else streamOfConsole(pf, &consoleInfo.pstDesignated[chix]);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
SQLITE_INTERNAL_LINKAGE FILE *setOutputStream(FILE *pf){
|
||||
return designateEmitStream(pf, 1);
|
||||
}
|
||||
# ifdef CONSIO_SET_ERROR_STREAM
|
||||
SQLITE_INTERNAL_LINKAGE FILE *setErrorStream(FILE *pf){
|
||||
return designateEmitStream(pf, 2);
|
||||
}
|
||||
# endif
|
||||
#endif /* !defined(SQLITE_CIO_NO_TRANSLATE) */
|
||||
|
||||
#ifndef SQLITE_CIO_NO_SETMODE
|
||||
# if CIO_WIN_WC_XLATE
|
||||
static void setModeFlushQ(FILE *pf, short bFlush, int mode){
|
||||
if( bFlush ) fflush(pf);
|
||||
_setmode(_fileno(pf), mode);
|
||||
}
|
||||
# else
|
||||
# define setModeFlushQ(f, b, m) if(b) fflush(f)
|
||||
# endif
|
||||
|
||||
SQLITE_INTERNAL_LINKAGE void setBinaryMode(FILE *pf, short bFlush){
|
||||
setModeFlushQ(pf, bFlush, _O_BINARY);
|
||||
}
|
||||
SQLITE_INTERNAL_LINKAGE void setTextMode(FILE *pf, short bFlush){
|
||||
setModeFlushQ(pf, bFlush, _O_TEXT);
|
||||
}
|
||||
# undef setModeFlushQ
|
||||
|
||||
#else /* defined(SQLITE_CIO_NO_SETMODE) */
|
||||
# define setBinaryMode(f, bFlush) do{ if((bFlush)) fflush(f); }while(0)
|
||||
# define setTextMode(f, bFlush) do{ if((bFlush)) fflush(f); }while(0)
|
||||
#endif /* defined(SQLITE_CIO_NO_SETMODE) */
|
||||
|
||||
#ifndef SQLITE_CIO_NO_TRANSLATE
|
||||
# if CIO_WIN_WC_XLATE
|
||||
/* Write buffer cBuf as output to stream known to reach console,
|
||||
** limited to ncTake char's. Return ncTake on success, else 0. */
|
||||
static int conZstrEmit(PerStreamTags *ppst, const char *z, int ncTake){
|
||||
int rv = 0;
|
||||
if( z!=NULL ){
|
||||
int nwc = MultiByteToWideChar(CP_UTF8,0, z,ncTake, 0,0);
|
||||
if( nwc > 0 ){
|
||||
WCHAR *zw = sqlite3_malloc64(nwc*sizeof(WCHAR));
|
||||
if( zw!=NULL ){
|
||||
nwc = MultiByteToWideChar(CP_UTF8,0, z,ncTake, zw,nwc);
|
||||
if( nwc > 0 ){
|
||||
/* Translation from UTF-8 to UTF-16, then WCHARs out. */
|
||||
if( WriteConsoleW(ppst->hx, zw,nwc, 0, NULL) ){
|
||||
rv = ncTake;
|
||||
}
|
||||
}
|
||||
sqlite3_free(zw);
|
||||
}
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* For {f,o,e}PrintfUtf8() when stream is known to reach console. */
|
||||
static int conioVmPrintf(PerStreamTags *ppst, const char *zFormat, va_list ap){
|
||||
char *z = sqlite3_vmprintf(zFormat, ap);
|
||||
if( z ){
|
||||
int rv = conZstrEmit(ppst, z, (int)strlen(z));
|
||||
sqlite3_free(z);
|
||||
return rv;
|
||||
}else return 0;
|
||||
}
|
||||
# endif /* CIO_WIN_WC_XLATE */
|
||||
|
||||
# ifdef CONSIO_GET_EMIT_STREAM
|
||||
static PerStreamTags * getDesignatedEmitStream(FILE *pf, unsigned chix,
|
||||
PerStreamTags *ppst){
|
||||
PerStreamTags *rv = isKnownWritable(pf);
|
||||
short isValid = (rv!=0)? isValidStreamInfo(rv) : 0;
|
||||
if( rv != 0 && isValid ) return rv;
|
||||
streamOfConsole(pf, ppst);
|
||||
return ppst;
|
||||
}
|
||||
# endif
|
||||
|
||||
/* Get stream info, either for designated output or error stream when
|
||||
** chix equals 1 or 2, or for an arbitrary stream when chix == 0.
|
||||
** In either case, ppst references a caller-owned PerStreamTags
|
||||
** struct which may be filled in if none of the known writable
|
||||
** streams is being held by consoleInfo. The ppf parameter is a
|
||||
** byref output when chix!=0 and a byref input when chix==0.
|
||||
*/
|
||||
static PerStreamTags *
|
||||
getEmitStreamInfo(unsigned chix, PerStreamTags *ppst,
|
||||
/* in/out */ FILE **ppf){
|
||||
PerStreamTags *ppstTry;
|
||||
FILE *pfEmit;
|
||||
if( chix > 0 ){
|
||||
ppstTry = &consoleInfo.pstDesignated[chix];
|
||||
if( !isValidStreamInfo(ppstTry) ){
|
||||
ppstTry = &consoleInfo.pstSetup[chix];
|
||||
pfEmit = ppst->pf;
|
||||
}else pfEmit = ppstTry->pf;
|
||||
if( !isValidStreamInfo(ppstTry) ){
|
||||
pfEmit = (chix > 1)? stderr : stdout;
|
||||
ppstTry = ppst;
|
||||
streamOfConsole(pfEmit, ppstTry);
|
||||
}
|
||||
*ppf = pfEmit;
|
||||
}else{
|
||||
ppstTry = isKnownWritable(*ppf);
|
||||
if( ppstTry != 0 ) return ppstTry;
|
||||
streamOfConsole(*ppf, ppst);
|
||||
return ppst;
|
||||
}
|
||||
return ppstTry;
|
||||
}
|
||||
|
||||
SQLITE_INTERNAL_LINKAGE int oPrintfUtf8(const char *zFormat, ...){
|
||||
va_list ap;
|
||||
int rv;
|
||||
FILE *pfOut;
|
||||
PerStreamTags pst = PST_INITIALIZER; /* for unknown streams */
|
||||
# if CIO_WIN_WC_XLATE
|
||||
PerStreamTags *ppst = getEmitStreamInfo(1, &pst, &pfOut);
|
||||
# else
|
||||
getEmitStreamInfo(1, &pst, &pfOut);
|
||||
# endif
|
||||
assert(zFormat!=0);
|
||||
va_start(ap, zFormat);
|
||||
# if CIO_WIN_WC_XLATE
|
||||
if( pstReachesConsole(ppst) ){
|
||||
rv = conioVmPrintf(ppst, zFormat, ap);
|
||||
}else{
|
||||
# endif
|
||||
rv = vfprintf(pfOut, zFormat, ap);
|
||||
# if CIO_WIN_WC_XLATE
|
||||
}
|
||||
# endif
|
||||
va_end(ap);
|
||||
return rv;
|
||||
}
|
||||
|
||||
SQLITE_INTERNAL_LINKAGE int ePrintfUtf8(const char *zFormat, ...){
|
||||
va_list ap;
|
||||
int rv;
|
||||
FILE *pfErr;
|
||||
PerStreamTags pst = PST_INITIALIZER; /* for unknown streams */
|
||||
# if CIO_WIN_WC_XLATE
|
||||
PerStreamTags *ppst = getEmitStreamInfo(2, &pst, &pfErr);
|
||||
# else
|
||||
getEmitStreamInfo(2, &pst, &pfErr);
|
||||
# endif
|
||||
assert(zFormat!=0);
|
||||
va_start(ap, zFormat);
|
||||
# if CIO_WIN_WC_XLATE
|
||||
if( pstReachesConsole(ppst) ){
|
||||
rv = conioVmPrintf(ppst, zFormat, ap);
|
||||
}else{
|
||||
# endif
|
||||
rv = vfprintf(pfErr, zFormat, ap);
|
||||
# if CIO_WIN_WC_XLATE
|
||||
}
|
||||
# endif
|
||||
va_end(ap);
|
||||
return rv;
|
||||
}
|
||||
|
||||
SQLITE_INTERNAL_LINKAGE int fPrintfUtf8(FILE *pfO, const char *zFormat, ...){
|
||||
va_list ap;
|
||||
int rv;
|
||||
PerStreamTags pst = PST_INITIALIZER; /* for unknown streams */
|
||||
# if CIO_WIN_WC_XLATE
|
||||
PerStreamTags *ppst = getEmitStreamInfo(0, &pst, &pfO);
|
||||
# else
|
||||
getEmitStreamInfo(0, &pst, &pfO);
|
||||
# endif
|
||||
assert(zFormat!=0);
|
||||
va_start(ap, zFormat);
|
||||
# if CIO_WIN_WC_XLATE
|
||||
if( pstReachesConsole(ppst) ){
|
||||
maybeSetupAsConsole(ppst, 1);
|
||||
rv = conioVmPrintf(ppst, zFormat, ap);
|
||||
if( 0 == isKnownWritable(ppst->pf) ) restoreConsoleArb(ppst);
|
||||
}else{
|
||||
# endif
|
||||
rv = vfprintf(pfO, zFormat, ap);
|
||||
# if CIO_WIN_WC_XLATE
|
||||
}
|
||||
# endif
|
||||
va_end(ap);
|
||||
return rv;
|
||||
}
|
||||
|
||||
SQLITE_INTERNAL_LINKAGE int fPutsUtf8(const char *z, FILE *pfO){
|
||||
PerStreamTags pst = PST_INITIALIZER; /* for unknown streams */
|
||||
# if CIO_WIN_WC_XLATE
|
||||
PerStreamTags *ppst = getEmitStreamInfo(0, &pst, &pfO);
|
||||
# else
|
||||
getEmitStreamInfo(0, &pst, &pfO);
|
||||
# endif
|
||||
assert(z!=0);
|
||||
# if CIO_WIN_WC_XLATE
|
||||
if( pstReachesConsole(ppst) ){
|
||||
int rv;
|
||||
maybeSetupAsConsole(ppst, 1);
|
||||
rv = conZstrEmit(ppst, z, (int)strlen(z));
|
||||
if( 0 == isKnownWritable(ppst->pf) ) restoreConsoleArb(ppst);
|
||||
return rv;
|
||||
}else {
|
||||
# endif
|
||||
return (fputs(z, pfO)<0)? 0 : (int)strlen(z);
|
||||
# if CIO_WIN_WC_XLATE
|
||||
}
|
||||
# endif
|
||||
}
|
||||
|
||||
SQLITE_INTERNAL_LINKAGE int ePutsUtf8(const char *z){
|
||||
FILE *pfErr;
|
||||
PerStreamTags pst = PST_INITIALIZER; /* for unknown streams */
|
||||
# if CIO_WIN_WC_XLATE
|
||||
PerStreamTags *ppst = getEmitStreamInfo(2, &pst, &pfErr);
|
||||
# else
|
||||
getEmitStreamInfo(2, &pst, &pfErr);
|
||||
# endif
|
||||
assert(z!=0);
|
||||
# if CIO_WIN_WC_XLATE
|
||||
if( pstReachesConsole(ppst) ) return conZstrEmit(ppst, z, (int)strlen(z));
|
||||
else {
|
||||
# endif
|
||||
return (fputs(z, pfErr)<0)? 0 : (int)strlen(z);
|
||||
# if CIO_WIN_WC_XLATE
|
||||
}
|
||||
# endif
|
||||
}
|
||||
|
||||
SQLITE_INTERNAL_LINKAGE int oPutsUtf8(const char *z){
|
||||
FILE *pfOut;
|
||||
PerStreamTags pst = PST_INITIALIZER; /* for unknown streams */
|
||||
# if CIO_WIN_WC_XLATE
|
||||
PerStreamTags *ppst = getEmitStreamInfo(1, &pst, &pfOut);
|
||||
# else
|
||||
getEmitStreamInfo(1, &pst, &pfOut);
|
||||
# endif
|
||||
assert(z!=0);
|
||||
# if CIO_WIN_WC_XLATE
|
||||
if( pstReachesConsole(ppst) ) return conZstrEmit(ppst, z, (int)strlen(z));
|
||||
else {
|
||||
# endif
|
||||
return (fputs(z, pfOut)<0)? 0 : (int)strlen(z);
|
||||
# if CIO_WIN_WC_XLATE
|
||||
}
|
||||
# endif
|
||||
}
|
||||
|
||||
#endif /* !defined(SQLITE_CIO_NO_TRANSLATE) */
|
||||
|
||||
#if !(defined(SQLITE_CIO_NO_UTF8SCAN) && defined(SQLITE_CIO_NO_TRANSLATE))
|
||||
/* Skip over as much z[] input char sequence as is valid UTF-8,
|
||||
** limited per nAccept char's or whole characters and containing
|
||||
** no char cn such that ((1<<cn) & ccm)!=0. On return, the
|
||||
** sequence z:return (inclusive:exclusive) is validated UTF-8.
|
||||
** Limit: nAccept>=0 => char count, nAccept<0 => character
|
||||
*/
|
||||
SQLITE_INTERNAL_LINKAGE const char*
|
||||
zSkipValidUtf8(const char *z, int nAccept, long ccm){
|
||||
int ng = (nAccept<0)? -nAccept : 0;
|
||||
const char *pcLimit = (nAccept>=0)? z+nAccept : 0;
|
||||
assert(z!=0);
|
||||
while( (pcLimit)? (z<pcLimit) : (ng-- != 0) ){
|
||||
char c = *z;
|
||||
if( (c & 0x80) == 0 ){
|
||||
if( ccm != 0L && c < 0x20 && ((1L<<c) & ccm) != 0 ) return z;
|
||||
++z; /* ASCII */
|
||||
}else if( (c & 0xC0) != 0xC0 ) return z; /* not a lead byte */
|
||||
else{
|
||||
const char *zt = z+1; /* Got lead byte, look at trail bytes.*/
|
||||
do{
|
||||
if( pcLimit && zt >= pcLimit ) return z;
|
||||
else{
|
||||
char ct = *zt++;
|
||||
if( ct==0 || (zt-z)>4 || (ct & 0xC0)!=0x80 ){
|
||||
/* Trailing bytes are too few, too many, or invalid. */
|
||||
return z;
|
||||
}
|
||||
}
|
||||
} while( ((c <<= 1) & 0x40) == 0x40 ); /* Eat lead byte's count. */
|
||||
z = zt;
|
||||
}
|
||||
}
|
||||
return z;
|
||||
}
|
||||
#endif /*!(defined(SQLITE_CIO_NO_UTF8SCAN)&&defined(SQLITE_CIO_NO_TRANSLATE))*/
|
||||
|
||||
#ifndef SQLITE_CIO_NO_TRANSLATE
|
||||
# ifdef CONSIO_SPUTB
|
||||
SQLITE_INTERNAL_LINKAGE int
|
||||
fPutbUtf8(FILE *pfO, const char *cBuf, int nAccept){
|
||||
assert(pfO!=0);
|
||||
# if CIO_WIN_WC_XLATE
|
||||
PerStreamTags pst = PST_INITIALIZER; /* for unknown streams */
|
||||
PerStreamTags *ppst = getEmitStreamInfo(0, &pst, &pfO);
|
||||
if( pstReachesConsole(ppst) ){
|
||||
int rv;
|
||||
maybeSetupAsConsole(ppst, 1);
|
||||
rv = conZstrEmit(ppst, cBuf, nAccept);
|
||||
if( 0 == isKnownWritable(ppst->pf) ) restoreConsoleArb(ppst);
|
||||
return rv;
|
||||
}else {
|
||||
# endif
|
||||
return (int)fwrite(cBuf, 1, nAccept, pfO);
|
||||
# if CIO_WIN_WC_XLATE
|
||||
}
|
||||
# endif
|
||||
}
|
||||
# endif
|
||||
|
||||
SQLITE_INTERNAL_LINKAGE int
|
||||
oPutbUtf8(const char *cBuf, int nAccept){
|
||||
FILE *pfOut;
|
||||
PerStreamTags pst = PST_INITIALIZER; /* for unknown streams */
|
||||
# if CIO_WIN_WC_XLATE
|
||||
PerStreamTags *ppst = getEmitStreamInfo(1, &pst, &pfOut);
|
||||
# else
|
||||
getEmitStreamInfo(1, &pst, &pfOut);
|
||||
# endif
|
||||
# if CIO_WIN_WC_XLATE
|
||||
if( pstReachesConsole(ppst) ){
|
||||
return conZstrEmit(ppst, cBuf, nAccept);
|
||||
}else {
|
||||
# endif
|
||||
return (int)fwrite(cBuf, 1, nAccept, pfOut);
|
||||
# if CIO_WIN_WC_XLATE
|
||||
}
|
||||
# endif
|
||||
}
|
||||
|
||||
/*
|
||||
** Flush the given output stream. Return non-zero for success, else 0.
|
||||
*/
|
||||
#if !defined(SQLITE_CIO_NO_FLUSH) && !defined(SQLITE_CIO_NO_SETMODE)
|
||||
SQLITE_INTERNAL_LINKAGE int
|
||||
fFlushBuffer(FILE *pfOut){
|
||||
# if CIO_WIN_WC_XLATE && !defined(SHELL_OMIT_FIO_DUPE)
|
||||
return FlushFileBuffers(handleOfFile(pfOut))? 1 : 0;
|
||||
# else
|
||||
return fflush(pfOut);
|
||||
# endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CIO_WIN_WC_XLATE \
|
||||
&& !defined(SHELL_OMIT_FIO_DUPE) \
|
||||
&& defined(SQLITE_USE_ONLY_WIN32)
|
||||
static struct FileAltIds {
|
||||
int fd;
|
||||
HANDLE fh;
|
||||
} altIdsOfFile(FILE *pf){
|
||||
struct FileAltIds rv = { _fileno(pf) };
|
||||
union { intptr_t osfh; HANDLE fh; } fid = {
|
||||
(rv.fd>=0)? _get_osfhandle(rv.fd) : (intptr_t)INVALID_HANDLE_VALUE
|
||||
};
|
||||
rv.fh = fid.fh;
|
||||
return rv;
|
||||
}
|
||||
|
||||
SQLITE_INTERNAL_LINKAGE size_t
|
||||
cfWrite(const void *buf, size_t osz, size_t ocnt, FILE *pf){
|
||||
size_t rv = 0;
|
||||
struct FileAltIds fai = altIdsOfFile(pf);
|
||||
int fmode = _setmode(fai.fd, _O_BINARY);
|
||||
_setmode(fai.fd, fmode);
|
||||
while( rv < ocnt ){
|
||||
size_t nbo = osz;
|
||||
while( nbo > 0 ){
|
||||
DWORD dwno = (nbo>(1L<<24))? 1L<<24 : (DWORD)nbo;
|
||||
BOOL wrc = TRUE;
|
||||
BOOL genCR = (fmode & _O_TEXT)!=0;
|
||||
if( genCR ){
|
||||
const char *pnl = (const char*)memchr(buf, '\n', nbo);
|
||||
if( pnl ) nbo = pnl - (const char*)buf;
|
||||
else genCR = 0;
|
||||
}
|
||||
if( dwno>0 ) wrc = WriteFile(fai.fh, buf, dwno, 0,0);
|
||||
if( genCR && wrc ){
|
||||
wrc = WriteFile(fai.fh, "\r\n", 2, 0,0);
|
||||
++dwno; /* Skip over the LF */
|
||||
}
|
||||
if( !wrc ) return rv;
|
||||
buf = (const char*)buf + dwno;
|
||||
nbo += dwno;
|
||||
}
|
||||
++rv;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* An fgets() equivalent, using Win32 file API for actual input.
|
||||
** Input ends when given buffer is filled or a newline is read.
|
||||
** If the FILE object is in text mode, swallows 0x0D. (ASCII CR)
|
||||
*/
|
||||
SQLITE_INTERNAL_LINKAGE char *
|
||||
cfGets(char *cBuf, int n, FILE *pf){
|
||||
int nci = 0;
|
||||
struct FileAltIds fai = altIdsOfFile(pf);
|
||||
int fmode = _setmode(fai.fd, _O_BINARY);
|
||||
BOOL eatCR = (fmode & _O_TEXT)!=0;
|
||||
_setmode(fai.fd, fmode);
|
||||
while( nci < n-1 ){
|
||||
DWORD nr;
|
||||
if( !ReadFile(fai.fh, cBuf+nci, 1, &nr, 0) || nr==0 ) break;
|
||||
if( nr>0 && (!eatCR || cBuf[nci]!='\r') ){
|
||||
nci += nr;
|
||||
if( cBuf[nci-nr]=='\n' ) break;
|
||||
}
|
||||
}
|
||||
if( nci < n ) cBuf[nci] = 0;
|
||||
return (nci>0)? cBuf : 0;
|
||||
}
|
||||
# else
|
||||
# define cfWrite(b,os,no,f) fwrite(b,os,no,f)
|
||||
# define cfGets(b,n,f) fgets(b,n,f)
|
||||
# endif
|
||||
|
||||
# ifdef CONSIO_EPUTB
|
||||
SQLITE_INTERNAL_LINKAGE int
|
||||
ePutbUtf8(const char *cBuf, int nAccept){
|
||||
FILE *pfErr;
|
||||
PerStreamTags pst = PST_INITIALIZER; /* for unknown streams */
|
||||
PerStreamTags *ppst = getEmitStreamInfo(2, &pst, &pfErr);
|
||||
# if CIO_WIN_WC_XLATE
|
||||
if( pstReachesConsole(ppst) ){
|
||||
return conZstrEmit(ppst, cBuf, nAccept);
|
||||
}else {
|
||||
# endif
|
||||
return (int)cfWrite(cBuf, 1, nAccept, pfErr);
|
||||
# if CIO_WIN_WC_XLATE
|
||||
}
|
||||
# endif
|
||||
}
|
||||
# endif /* defined(CONSIO_EPUTB) */
|
||||
|
||||
SQLITE_INTERNAL_LINKAGE char* fGetsUtf8(char *cBuf, int ncMax, FILE *pfIn){
|
||||
if( pfIn==0 ) pfIn = stdin;
|
||||
# if CIO_WIN_WC_XLATE
|
||||
if( pfIn == consoleInfo.pstSetup[0].pf
|
||||
&& (consoleInfo.sacSetup & SAC_InConsole)!=0 ){
|
||||
# if CIO_WIN_WC_XLATE==1
|
||||
# define SHELL_GULP 150 /* Count of WCHARS to be gulped at a time */
|
||||
WCHAR wcBuf[SHELL_GULP+1];
|
||||
int lend = 0, noc = 0;
|
||||
if( ncMax > 0 ) cBuf[0] = 0;
|
||||
while( noc < ncMax-8-1 && !lend ){
|
||||
/* There is room for at least 2 more characters and a 0-terminator. */
|
||||
int na = (ncMax > SHELL_GULP*4+1 + noc)? SHELL_GULP : (ncMax-1 - noc)/4;
|
||||
# undef SHELL_GULP
|
||||
DWORD nbr = 0;
|
||||
BOOL bRC = ReadConsoleW(consoleInfo.pstSetup[0].hx, wcBuf, na, &nbr, 0);
|
||||
if( bRC && nbr>0 && (wcBuf[nbr-1]&0xF800)==0xD800 ){
|
||||
/* Last WHAR read is first of a UTF-16 surrogate pair. Grab its mate. */
|
||||
DWORD nbrx;
|
||||
bRC &= ReadConsoleW(consoleInfo.pstSetup[0].hx, wcBuf+nbr, 1, &nbrx, 0);
|
||||
if( bRC ) nbr += nbrx;
|
||||
}
|
||||
if( !bRC || (noc==0 && nbr==0) ) return 0;
|
||||
if( nbr > 0 ){
|
||||
int nmb = WideCharToMultiByte(CP_UTF8, 0, wcBuf,nbr,0,0,0,0);
|
||||
if( nmb != 0 && noc+nmb <= ncMax ){
|
||||
int iseg = noc;
|
||||
nmb = WideCharToMultiByte(CP_UTF8, 0, wcBuf,nbr,cBuf+noc,nmb,0,0);
|
||||
noc += nmb;
|
||||
/* Fixup line-ends as coded by Windows for CR (or "Enter".)
|
||||
** This is done without regard for any setMode{Text,Binary}()
|
||||
** call that might have been done on the interactive input.
|
||||
*/
|
||||
if( noc > 0 ){
|
||||
if( cBuf[noc-1]=='\n' ){
|
||||
lend = 1;
|
||||
if( noc > 1 && cBuf[noc-2]=='\r' ) cBuf[--noc-1] = '\n';
|
||||
}
|
||||
}
|
||||
/* Check for ^Z (anywhere in line) too, to act as EOF. */
|
||||
while( iseg < noc ){
|
||||
if( cBuf[iseg]=='\x1a' ){
|
||||
noc = iseg; /* Chop ^Z and anything following. */
|
||||
lend = 1; /* Counts as end of line too. */
|
||||
break;
|
||||
}
|
||||
++iseg;
|
||||
}
|
||||
}else break; /* Drop apparent garbage in. (Could assert.) */
|
||||
}else break;
|
||||
}
|
||||
/* If got nothing, (after ^Z chop), must be at end-of-file. */
|
||||
if( noc > 0 ){
|
||||
cBuf[noc] = 0;
|
||||
return cBuf;
|
||||
}else return 0;
|
||||
# endif
|
||||
}else{
|
||||
# endif
|
||||
return cfGets(cBuf, ncMax, pfIn);
|
||||
# if CIO_WIN_WC_XLATE
|
||||
}
|
||||
# endif
|
||||
}
|
||||
#endif /* !defined(SQLITE_CIO_NO_TRANSLATE) */
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
# pragma warning(default : 4204)
|
||||
#endif
|
||||
|
||||
#undef SHELL_INVALID_FILE_PTR
|
||||
@@ -1,287 +0,0 @@
|
||||
/*
|
||||
** 2023 November 1
|
||||
**
|
||||
** The author disclaims copyright to this source code. In place of
|
||||
** a legal notice, here is a blessing:
|
||||
**
|
||||
** May you do good and not evil.
|
||||
** May you find forgiveness for yourself and forgive others.
|
||||
** May you share freely, never taking more than you give.
|
||||
**
|
||||
********************************************************************************
|
||||
** This file exposes various interfaces used for console and other I/O
|
||||
** by the SQLite project command-line tools. These interfaces are used
|
||||
** at either source conglomeration time, compilation time, or run time.
|
||||
** This source provides for either inclusion into conglomerated,
|
||||
** "single-source" forms or separate compilation then linking.
|
||||
**
|
||||
** Platform dependencies are "hidden" here by various stratagems so
|
||||
** that, provided certain conditions are met, the programs using this
|
||||
** source or object code compiled from it need no explicit conditional
|
||||
** compilation in their source for their console and stream I/O.
|
||||
**
|
||||
** The symbols and functionality exposed here are not a public API.
|
||||
** This code may change in tandem with other project code as needed.
|
||||
**
|
||||
** When this .h file and its companion .c are directly incorporated into
|
||||
** a source conglomeration (such as shell.c), the preprocessor symbol
|
||||
** CIO_WIN_WC_XLATE is defined as 0 or 1, reflecting whether console I/O
|
||||
** translation for Windows is effected for the build.
|
||||
*/
|
||||
#define HAVE_CONSOLE_IO_H 1
|
||||
#ifndef SQLITE_INTERNAL_LINKAGE
|
||||
# define SQLITE_INTERNAL_LINKAGE extern /* external to translation unit */
|
||||
# include <stdio.h>
|
||||
#else
|
||||
# define SHELL_NO_SYSINC /* Better yet, modify mkshellc.tcl for this. */
|
||||
#endif
|
||||
|
||||
#ifndef SQLITE3_H
|
||||
# include "sqlite3.h"
|
||||
#endif
|
||||
|
||||
#ifndef SQLITE_CIO_NO_CLASSIFY
|
||||
|
||||
/* Define enum for use with following function. */
|
||||
typedef enum StreamsAreConsole {
|
||||
SAC_NoConsole = 0,
|
||||
SAC_InConsole = 1, SAC_OutConsole = 2, SAC_ErrConsole = 4,
|
||||
SAC_AnyConsole = 0x7
|
||||
} StreamsAreConsole;
|
||||
|
||||
/*
|
||||
** Classify the three standard I/O streams according to whether
|
||||
** they are connected to a console attached to the process.
|
||||
**
|
||||
** Returns the bit-wise OR of SAC_{In,Out,Err}Console values,
|
||||
** or SAC_NoConsole if none of the streams reaches a console.
|
||||
**
|
||||
** This function should be called before any I/O is done with
|
||||
** the given streams. As a side-effect, the given inputs are
|
||||
** recorded so that later I/O operations on them may be done
|
||||
** differently than the C library FILE* I/O would be done,
|
||||
** iff the stream is used for the I/O functions that follow,
|
||||
** and to support the ones that use an implicit stream.
|
||||
**
|
||||
** On some platforms, stream or console mode alteration (aka
|
||||
** "Setup") may be made which is undone by consoleRestore().
|
||||
*/
|
||||
SQLITE_INTERNAL_LINKAGE StreamsAreConsole
|
||||
consoleClassifySetup( FILE *pfIn, FILE *pfOut, FILE *pfErr );
|
||||
/* A usual call for convenience: */
|
||||
#define SQLITE_STD_CONSOLE_INIT() consoleClassifySetup(stdin,stdout,stderr)
|
||||
|
||||
/*
|
||||
** After an initial call to consoleClassifySetup(...), renew
|
||||
** the same setup it effected. (A call not after is an error.)
|
||||
** This will restore state altered by consoleRestore();
|
||||
**
|
||||
** Applications which run an inferior (child) process which
|
||||
** inherits the same I/O streams may call this function after
|
||||
** such a process exits to guard against console mode changes.
|
||||
*/
|
||||
SQLITE_INTERNAL_LINKAGE void consoleRenewSetup(void);
|
||||
|
||||
/*
|
||||
** Undo any side-effects left by consoleClassifySetup(...).
|
||||
**
|
||||
** This should be called after consoleClassifySetup() and
|
||||
** before the process terminates normally. It is suitable
|
||||
** for use with the atexit() C library procedure. After
|
||||
** this call, no console I/O should be done until one of
|
||||
** console{Classify or Renew}Setup(...) is called again.
|
||||
**
|
||||
** Applications which run an inferior (child) process that
|
||||
** inherits the same I/O streams might call this procedure
|
||||
** before so that said process will have a console setup
|
||||
** however users have configured it or come to expect.
|
||||
*/
|
||||
SQLITE_INTERNAL_LINKAGE void SQLITE_CDECL consoleRestore( void );
|
||||
|
||||
#else /* defined(SQLITE_CIO_NO_CLASSIFY) */
|
||||
# define consoleClassifySetup(i,o,e)
|
||||
# define consoleRenewSetup()
|
||||
# define consoleRestore()
|
||||
#endif /* defined(SQLITE_CIO_NO_CLASSIFY) */
|
||||
|
||||
#ifndef SQLITE_CIO_NO_REDIRECT
|
||||
/*
|
||||
** Set stream to be used for the functions below which write
|
||||
** to "the designated X stream", where X is Output or Error.
|
||||
** Returns the previous value.
|
||||
**
|
||||
** Alternatively, pass the special value, invalidFileStream,
|
||||
** to get the designated stream value without setting it.
|
||||
**
|
||||
** Before the designated streams are set, they default to
|
||||
** those passed to consoleClassifySetup(...), and before
|
||||
** that is called they default to stdout and stderr.
|
||||
**
|
||||
** It is error to close a stream so designated, then, without
|
||||
** designating another, use the corresponding {o,e}Emit(...).
|
||||
*/
|
||||
SQLITE_INTERNAL_LINKAGE FILE *invalidFileStream;
|
||||
SQLITE_INTERNAL_LINKAGE FILE *setOutputStream(FILE *pf);
|
||||
# ifdef CONSIO_SET_ERROR_STREAM
|
||||
SQLITE_INTERNAL_LINKAGE FILE *setErrorStream(FILE *pf);
|
||||
# endif
|
||||
#else
|
||||
# define setOutputStream(pf)
|
||||
# define setErrorStream(pf)
|
||||
#endif /* !defined(SQLITE_CIO_NO_REDIRECT) */
|
||||
|
||||
#ifndef SQLITE_CIO_NO_TRANSLATE
|
||||
/*
|
||||
** Emit output like fprintf(). If the output is going to the
|
||||
** console and translation from UTF-8 is necessary, perform
|
||||
** the needed translation. Otherwise, write formatted output
|
||||
** to the provided stream almost as-is, possibly with newline
|
||||
** translation as specified by set{Binary,Text}Mode().
|
||||
*/
|
||||
SQLITE_INTERNAL_LINKAGE int fPrintfUtf8(FILE *pfO, const char *zFormat, ...);
|
||||
/* Like fPrintfUtf8 except stream is always the designated output. */
|
||||
SQLITE_INTERNAL_LINKAGE int oPrintfUtf8(const char *zFormat, ...);
|
||||
/* Like fPrintfUtf8 except stream is always the designated error. */
|
||||
SQLITE_INTERNAL_LINKAGE int ePrintfUtf8(const char *zFormat, ...);
|
||||
|
||||
/*
|
||||
** Emit output like fputs(). If the output is going to the
|
||||
** console and translation from UTF-8 is necessary, perform
|
||||
** the needed translation. Otherwise, write given text to the
|
||||
** provided stream almost as-is, possibly with newline
|
||||
** translation as specified by set{Binary,Text}Mode().
|
||||
*/
|
||||
SQLITE_INTERNAL_LINKAGE int fPutsUtf8(const char *z, FILE *pfO);
|
||||
/* Like fPutsUtf8 except stream is always the designated output. */
|
||||
SQLITE_INTERNAL_LINKAGE int oPutsUtf8(const char *z);
|
||||
/* Like fPutsUtf8 except stream is always the designated error. */
|
||||
SQLITE_INTERNAL_LINKAGE int ePutsUtf8(const char *z);
|
||||
|
||||
/*
|
||||
** Emit output like fPutsUtf8(), except that the length of the
|
||||
** accepted char or character sequence is limited by nAccept.
|
||||
**
|
||||
** Returns the number of accepted char values.
|
||||
*/
|
||||
#ifdef CONSIO_SPUTB
|
||||
SQLITE_INTERNAL_LINKAGE int
|
||||
fPutbUtf8(FILE *pfOut, const char *cBuf, int nAccept);
|
||||
/* Like fPutbUtf8 except stream is always the designated output. */
|
||||
#endif
|
||||
SQLITE_INTERNAL_LINKAGE int
|
||||
oPutbUtf8(const char *cBuf, int nAccept);
|
||||
/* Like fPutbUtf8 except stream is always the designated error. */
|
||||
#ifdef CONSIO_EPUTB
|
||||
SQLITE_INTERNAL_LINKAGE int
|
||||
ePutbUtf8(const char *cBuf, int nAccept);
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Flush the given output stream. Return non-zero for success, else 0.
|
||||
*/
|
||||
#if !defined(SQLITE_CIO_NO_FLUSH) && !defined(SQLITE_CIO_NO_SETMODE)
|
||||
SQLITE_INTERNAL_LINKAGE int
|
||||
fFlushBuffer(FILE *pfOut);
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Collect input like fgets(...) with special provisions for input
|
||||
** from the console on such platforms as require same. Newline
|
||||
** translation may be done as set by set{Binary,Text}Mode().
|
||||
** As a convenience, pfIn==NULL is treated as stdin.
|
||||
*/
|
||||
SQLITE_INTERNAL_LINKAGE char* fGetsUtf8(char *cBuf, int ncMax, FILE *pfIn);
|
||||
/* Like fGetsUtf8 except stream is always the designated input. */
|
||||
/* SQLITE_INTERNAL_LINKAGE char* iGetsUtf8(char *cBuf, int ncMax); */
|
||||
|
||||
#endif /* !defined(SQLITE_CIO_NO_TRANSLATE) */
|
||||
|
||||
#ifndef SQLITE_CIO_NO_SETMODE
|
||||
/*
|
||||
** Set given stream for binary mode, where newline translation is
|
||||
** not done, or for text mode where, for some platforms, newlines
|
||||
** are translated to the platform's conventional char sequence.
|
||||
** If bFlush true, flush the stream.
|
||||
**
|
||||
** An additional side-effect is that if the stream is one passed
|
||||
** to consoleClassifySetup() as an output, it is flushed first.
|
||||
**
|
||||
** Note that binary/text mode has no effect on console I/O
|
||||
** translation. On all platforms, newline to the console starts
|
||||
** a new line and CR,LF chars from the console become a newline.
|
||||
*/
|
||||
SQLITE_INTERNAL_LINKAGE void setBinaryMode(FILE *, short bFlush);
|
||||
SQLITE_INTERNAL_LINKAGE void setTextMode(FILE *, short bFlush);
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_CIO_PROMPTED_IN
|
||||
typedef struct Prompts {
|
||||
int numPrompts;
|
||||
const char **azPrompts;
|
||||
} Prompts;
|
||||
|
||||
/*
|
||||
** Macros for use of a line editor.
|
||||
**
|
||||
** The following macros define operations involving use of a
|
||||
** line-editing library or simple console interaction.
|
||||
** A "T" argument is a text (char *) buffer or filename.
|
||||
** A "N" argument is an integer.
|
||||
**
|
||||
** SHELL_ADD_HISTORY(T) // Record text as line(s) of history.
|
||||
** SHELL_READ_HISTORY(T) // Read history from file named by T.
|
||||
** SHELL_WRITE_HISTORY(T) // Write history to file named by T.
|
||||
** SHELL_STIFLE_HISTORY(N) // Limit history to N entries.
|
||||
**
|
||||
** A console program which does interactive console input is
|
||||
** expected to call:
|
||||
** SHELL_READ_HISTORY(T) before collecting such input;
|
||||
** SHELL_ADD_HISTORY(T) as record-worthy input is taken;
|
||||
** SHELL_STIFLE_HISTORY(N) after console input ceases; then
|
||||
** SHELL_WRITE_HISTORY(T) before the program exits.
|
||||
*/
|
||||
|
||||
/*
|
||||
** Retrieve a single line of input text from an input stream.
|
||||
**
|
||||
** If pfIn is the input stream passed to consoleClassifySetup(),
|
||||
** and azPrompt is not NULL, then a prompt is issued before the
|
||||
** line is collected, as selected by the isContinuation flag.
|
||||
** Array azPrompt[{0,1}] holds the {main,continuation} prompt.
|
||||
**
|
||||
** If zBufPrior is not NULL then it is a buffer from a prior
|
||||
** call to this routine that can be reused, or will be freed.
|
||||
**
|
||||
** The result is stored in space obtained from malloc() and
|
||||
** must either be freed by the caller or else passed back to
|
||||
** this function as zBufPrior for reuse.
|
||||
**
|
||||
** This function may call upon services of a line-editing
|
||||
** library to interactively collect line edited input.
|
||||
*/
|
||||
SQLITE_INTERNAL_LINKAGE char *
|
||||
shellGetLine(FILE *pfIn, char *zBufPrior, int nLen,
|
||||
short isContinuation, Prompts azPrompt);
|
||||
#endif /* defined(SQLITE_CIO_PROMPTED_IN) */
|
||||
/*
|
||||
** TBD: Define an interface for application(s) to generate
|
||||
** completion candidates for use by the line-editor.
|
||||
**
|
||||
** This may be premature; the CLI is the only application
|
||||
** that does this. Yet, getting line-editing melded into
|
||||
** console I/O is desirable because a line-editing library
|
||||
** may have to establish console operating mode, possibly
|
||||
** in a way that interferes with the above functionality.
|
||||
*/
|
||||
|
||||
#if !(defined(SQLITE_CIO_NO_UTF8SCAN)&&defined(SQLITE_CIO_NO_TRANSLATE))
|
||||
/* Skip over as much z[] input char sequence as is valid UTF-8,
|
||||
** limited per nAccept char's or whole characters and containing
|
||||
** no char cn such that ((1<<cn) & ccm)!=0. On return, the
|
||||
** sequence z:return (inclusive:exclusive) is validated UTF-8.
|
||||
** Limit: nAccept>=0 => char count, nAccept<0 => character
|
||||
*/
|
||||
SQLITE_INTERNAL_LINKAGE const char*
|
||||
zSkipValidUtf8(const char *z, int nAccept, long ccm);
|
||||
|
||||
#endif
|
||||
@@ -1491,7 +1491,7 @@ static int idxCreateVtabSchema(sqlite3expert *p, char **pzErrmsg){
|
||||
}else{
|
||||
IdxTable *pTab;
|
||||
rc = idxGetTableInfo(p->db, zName, &pTab, pzErrmsg);
|
||||
if( rc==SQLITE_OK ){
|
||||
if( rc==SQLITE_OK && ALWAYS(pTab!=0) ){
|
||||
int i;
|
||||
char *zInner = 0;
|
||||
char *zOuter = 0;
|
||||
|
||||
+25
-2
@@ -2344,10 +2344,15 @@ static int fts3PoslistPhraseMerge(
|
||||
if( *p1==POS_COLUMN ){
|
||||
p1++;
|
||||
p1 += fts3GetVarint32(p1, &iCol1);
|
||||
/* iCol1==0 indicates corruption. Column 0 does not have a POS_COLUMN
|
||||
** entry, so this is actually end-of-doclist. */
|
||||
if( iCol1==0 ) return 0;
|
||||
}
|
||||
if( *p2==POS_COLUMN ){
|
||||
p2++;
|
||||
p2 += fts3GetVarint32(p2, &iCol2);
|
||||
/* As above, iCol2==0 indicates corruption. */
|
||||
if( iCol2==0 ) return 0;
|
||||
}
|
||||
|
||||
while( 1 ){
|
||||
@@ -5518,7 +5523,7 @@ static int fts3EvalNearTest(Fts3Expr *pExpr, int *pRc){
|
||||
nTmp += p->pRight->pPhrase->doclist.nList;
|
||||
}
|
||||
nTmp += p->pPhrase->doclist.nList;
|
||||
aTmp = sqlite3_malloc64(nTmp*2);
|
||||
aTmp = sqlite3_malloc64(nTmp*2 + FTS3_VARINT_MAX);
|
||||
if( !aTmp ){
|
||||
*pRc = SQLITE_NOMEM;
|
||||
res = 0;
|
||||
@@ -5782,6 +5787,24 @@ static void fts3EvalRestart(
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Expression node pExpr is an MSR phrase. This function restarts pExpr
|
||||
** so that it is a regular phrase query, not an MSR. SQLITE_OK is returned
|
||||
** if successful, or an SQLite error code otherwise.
|
||||
*/
|
||||
int sqlite3Fts3MsrCancel(Fts3Cursor *pCsr, Fts3Expr *pExpr){
|
||||
int rc = SQLITE_OK;
|
||||
if( pExpr->bEof==0 ){
|
||||
i64 iDocid = pExpr->iDocid;
|
||||
fts3EvalRestart(pCsr, pExpr, &rc);
|
||||
while( rc==SQLITE_OK && pExpr->iDocid!=iDocid ){
|
||||
fts3EvalNextRow(pCsr, pExpr, &rc);
|
||||
if( pExpr->bEof ) rc = FTS_CORRUPT_VTAB;
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** After allocating the Fts3Expr.aMI[] array for each phrase in the
|
||||
** expression rooted at pExpr, the cursor iterates through all rows matched
|
||||
@@ -6169,7 +6192,7 @@ int sqlite3Fts3Corrupt(){
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !SQLITE_CORE
|
||||
#if !defined(SQLITE_CORE)
|
||||
/*
|
||||
** Initialize API pointer table, if required.
|
||||
*/
|
||||
|
||||
@@ -640,6 +640,7 @@ int sqlite3Fts3MsrIncrNext(
|
||||
int sqlite3Fts3EvalPhrasePoslist(Fts3Cursor *, Fts3Expr *, int iCol, char **);
|
||||
int sqlite3Fts3MsrOvfl(Fts3Cursor *, Fts3MultiSegReader *, int *);
|
||||
int sqlite3Fts3MsrIncrRestart(Fts3MultiSegReader *pCsr);
|
||||
int sqlite3Fts3MsrCancel(Fts3Cursor*, Fts3Expr*);
|
||||
|
||||
/* fts3_tokenize_vtab.c */
|
||||
int sqlite3Fts3InitTok(sqlite3*, Fts3Hash *, void(*xDestroy)(void*));
|
||||
|
||||
+16
-17
@@ -319,10 +319,11 @@ static int getNextString(
|
||||
Fts3PhraseToken *pToken;
|
||||
|
||||
p = fts3ReallocOrFree(p, nSpace + ii*sizeof(Fts3PhraseToken));
|
||||
if( !p ) goto no_mem;
|
||||
|
||||
zTemp = fts3ReallocOrFree(zTemp, nTemp + nByte);
|
||||
if( !zTemp ) goto no_mem;
|
||||
if( !zTemp || !p ){
|
||||
rc = SQLITE_NOMEM;
|
||||
goto getnextstring_out;
|
||||
}
|
||||
|
||||
assert( nToken==ii );
|
||||
pToken = &((Fts3Phrase *)(&p[1]))->aToken[ii];
|
||||
@@ -337,9 +338,6 @@ static int getNextString(
|
||||
nToken = ii+1;
|
||||
}
|
||||
}
|
||||
|
||||
pModule->xClose(pCursor);
|
||||
pCursor = 0;
|
||||
}
|
||||
|
||||
if( rc==SQLITE_DONE ){
|
||||
@@ -347,7 +345,10 @@ static int getNextString(
|
||||
char *zBuf = 0;
|
||||
|
||||
p = fts3ReallocOrFree(p, nSpace + nToken*sizeof(Fts3PhraseToken) + nTemp);
|
||||
if( !p ) goto no_mem;
|
||||
if( !p ){
|
||||
rc = SQLITE_NOMEM;
|
||||
goto getnextstring_out;
|
||||
}
|
||||
memset(p, 0, (char *)&(((Fts3Phrase *)&p[1])->aToken[0])-(char *)p);
|
||||
p->eType = FTSQUERY_PHRASE;
|
||||
p->pPhrase = (Fts3Phrase *)&p[1];
|
||||
@@ -355,11 +356,9 @@ static int getNextString(
|
||||
p->pPhrase->nToken = nToken;
|
||||
|
||||
zBuf = (char *)&p->pPhrase->aToken[nToken];
|
||||
assert( nTemp==0 || zTemp );
|
||||
if( zTemp ){
|
||||
memcpy(zBuf, zTemp, nTemp);
|
||||
sqlite3_free(zTemp);
|
||||
}else{
|
||||
assert( nTemp==0 );
|
||||
}
|
||||
|
||||
for(jj=0; jj<p->pPhrase->nToken; jj++){
|
||||
@@ -369,17 +368,17 @@ static int getNextString(
|
||||
rc = SQLITE_OK;
|
||||
}
|
||||
|
||||
*ppExpr = p;
|
||||
return rc;
|
||||
no_mem:
|
||||
|
||||
getnextstring_out:
|
||||
if( pCursor ){
|
||||
pModule->xClose(pCursor);
|
||||
}
|
||||
sqlite3_free(zTemp);
|
||||
sqlite3_free(p);
|
||||
*ppExpr = 0;
|
||||
return SQLITE_NOMEM;
|
||||
if( rc!=SQLITE_OK ){
|
||||
sqlite3_free(p);
|
||||
p = 0;
|
||||
}
|
||||
*ppExpr = p;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -1586,6 +1586,22 @@ static int fts3ExprTermOffsetInit(Fts3Expr *pExpr, int iPhrase, void *ctx){
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** If expression pExpr is a phrase expression that uses an MSR query,
|
||||
** restart it as a regular, non-incremental query. Return SQLITE_OK
|
||||
** if successful, or an SQLite error code otherwise.
|
||||
*/
|
||||
static int fts3ExprRestartIfCb(Fts3Expr *pExpr, int iPhrase, void *ctx){
|
||||
TermOffsetCtx *p = (TermOffsetCtx*)ctx;
|
||||
int rc = SQLITE_OK;
|
||||
UNUSED_PARAMETER(iPhrase);
|
||||
if( pExpr->pPhrase && pExpr->pPhrase->bIncr ){
|
||||
rc = sqlite3Fts3MsrCancel(p->pCsr, pExpr);
|
||||
pExpr->pPhrase->bIncr = 0;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Implementation of offsets() function.
|
||||
*/
|
||||
@@ -1622,6 +1638,12 @@ void sqlite3Fts3Offsets(
|
||||
sCtx.iDocid = pCsr->iPrevId;
|
||||
sCtx.pCsr = pCsr;
|
||||
|
||||
/* If a query restart will be required, do it here, rather than later of
|
||||
** after pointers to poslist buffers that may be invalidated by a restart
|
||||
** have been saved. */
|
||||
rc = sqlite3Fts3ExprIterate(pCsr->pExpr, fts3ExprRestartIfCb, (void*)&sCtx);
|
||||
if( rc!=SQLITE_OK ) goto offsets_out;
|
||||
|
||||
/* Loop through the table columns, appending offset information to
|
||||
** string-buffer res for each column.
|
||||
*/
|
||||
|
||||
+19
-4
@@ -298,16 +298,31 @@ struct Fts5PhraseIter {
|
||||
** value returned by xInstCount(), SQLITE_RANGE is returned. Otherwise,
|
||||
** output variable (*ppToken) is set to point to a buffer containing the
|
||||
** matching document token, and (*pnToken) to the size of that buffer in
|
||||
** bytes. This API is not available if the specified token matches a
|
||||
** prefix query term. In that case both output variables are always set
|
||||
** to 0.
|
||||
** bytes.
|
||||
**
|
||||
** The output text is not a copy of the document text that was tokenized.
|
||||
** It is the output of the tokenizer module. For tokendata=1 tables, this
|
||||
** includes any embedded 0x00 and trailing data.
|
||||
**
|
||||
** This API may be slow in some cases if the token identified by parameters
|
||||
** iIdx and iToken matched a prefix token in the query. In most cases, the
|
||||
** first call to this API for each prefix token in the query is forced
|
||||
** to scan the portion of the full-text index that matches the prefix
|
||||
** token to collect the extra data required by this API. If the prefix
|
||||
** token matches a large number of token instances in the document set,
|
||||
** this may be a performance problem.
|
||||
**
|
||||
** If the user knows in advance that a query may use this API for a
|
||||
** prefix token, FTS5 may be configured to collect all required data as part
|
||||
** of the initial querying of the full-text index, avoiding the second scan
|
||||
** entirely. This also causes prefix queries that do not use this API to
|
||||
** run more slowly and use more memory. FTS5 may be configured in this way
|
||||
** either on a per-table basis using the [FTS5 insttoken | 'insttoken']
|
||||
** option, or on a per-query basis using the
|
||||
** [fts5_insttoken | fts5_insttoken()] user function.
|
||||
**
|
||||
** This API can be quite slow if used with an FTS5 table created with the
|
||||
** "detail=none" or "detail=column" option.
|
||||
** "detail=none" or "detail=column" option.
|
||||
**
|
||||
** xColumnLocale(pFts5, iIdx, pzLocale, pnLocale)
|
||||
** If parameter iCol is less than zero, or greater than or equal to the
|
||||
|
||||
+10
-2
@@ -247,7 +247,8 @@ struct Fts5Config {
|
||||
char *zRank; /* Name of rank function */
|
||||
char *zRankArgs; /* Arguments to rank function */
|
||||
int bSecureDelete; /* 'secure-delete' */
|
||||
int nDeleteMerge; /* 'deletemerge' */
|
||||
int nDeleteMerge; /* 'deletemerge' */
|
||||
int bPrefixInsttoken; /* 'prefix-insttoken' */
|
||||
|
||||
/* If non-NULL, points to sqlite3_vtab.base.zErrmsg. Often NULL. */
|
||||
char **pzErrmsg;
|
||||
@@ -504,7 +505,14 @@ int sqlite3Fts5StructureTest(Fts5Index*, void*);
|
||||
/*
|
||||
** Used by xInstToken():
|
||||
*/
|
||||
int sqlite3Fts5IterToken(Fts5IndexIter*, i64, int, int, const char**, int*);
|
||||
int sqlite3Fts5IterToken(
|
||||
Fts5IndexIter *pIndexIter,
|
||||
const char *pToken, int nToken,
|
||||
i64 iRowid,
|
||||
int iCol,
|
||||
int iOff,
|
||||
const char **ppOut, int *pnOut
|
||||
);
|
||||
|
||||
/*
|
||||
** Insert or remove data to or from the index. Each time a document is
|
||||
|
||||
@@ -1026,6 +1026,19 @@ int sqlite3Fts5ConfigSetValue(
|
||||
}else{
|
||||
pConfig->bSecureDelete = (bVal ? 1 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
else if( 0==sqlite3_stricmp(zKey, "insttoken") ){
|
||||
int bVal = -1;
|
||||
if( SQLITE_INTEGER==sqlite3_value_numeric_type(pVal) ){
|
||||
bVal = sqlite3_value_int(pVal);
|
||||
}
|
||||
if( bVal<0 ){
|
||||
*pbBadkey = 1;
|
||||
}else{
|
||||
pConfig->bPrefixInsttoken = (bVal ? 1 : 0);
|
||||
}
|
||||
|
||||
}else{
|
||||
*pbBadkey = 1;
|
||||
}
|
||||
|
||||
+9
-10
@@ -3046,7 +3046,7 @@ static int fts5ExprPopulatePoslistsCb(
|
||||
int rc = sqlite3Fts5PoslistWriterAppend(
|
||||
&pExpr->apExprPhrase[i]->poslist, &p->aPopulator[i].writer, p->iOff
|
||||
);
|
||||
if( rc==SQLITE_OK && pExpr->pConfig->bTokendata && !pT->bPrefix ){
|
||||
if( rc==SQLITE_OK && (pExpr->pConfig->bTokendata || pT->bPrefix) ){
|
||||
int iCol = p->iOff>>32;
|
||||
int iTokOff = p->iOff & 0x7FFFFFFF;
|
||||
rc = sqlite3Fts5IndexIterWriteTokendata(
|
||||
@@ -3239,15 +3239,14 @@ int sqlite3Fts5ExprInstToken(
|
||||
return SQLITE_RANGE;
|
||||
}
|
||||
pTerm = &pPhrase->aTerm[iToken];
|
||||
if( pTerm->bPrefix==0 ){
|
||||
if( pExpr->pConfig->bTokendata ){
|
||||
rc = sqlite3Fts5IterToken(
|
||||
pTerm->pIter, iRowid, iCol, iOff+iToken, ppOut, pnOut
|
||||
);
|
||||
}else{
|
||||
*ppOut = pTerm->pTerm;
|
||||
*pnOut = pTerm->nFullTerm;
|
||||
}
|
||||
if( pExpr->pConfig->bTokendata || pTerm->bPrefix ){
|
||||
rc = sqlite3Fts5IterToken(
|
||||
pTerm->pIter, pTerm->pTerm, pTerm->nQueryTerm,
|
||||
iRowid, iCol, iOff+iToken, ppOut, pnOut
|
||||
);
|
||||
}else{
|
||||
*ppOut = pTerm->pTerm;
|
||||
*pnOut = pTerm->nFullTerm;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
+599
-219
File diff suppressed because it is too large
Load Diff
+31
-21
@@ -93,6 +93,7 @@ struct Fts5Global {
|
||||
#define FTS5_LOCALE_HDR_SIZE ((int)sizeof( ((Fts5Global*)0)->aLocaleHdr ))
|
||||
#define FTS5_LOCALE_HDR(pConfig) ((const u8*)(pConfig->pGlobal->aLocaleHdr))
|
||||
|
||||
#define FTS5_INSTTOKEN_SUBTYPE 73
|
||||
|
||||
/*
|
||||
** Each auxiliary function registered with the FTS5 module is represented
|
||||
@@ -632,6 +633,7 @@ static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
|
||||
if( p->usable==0 || iCol<0 ){
|
||||
/* As there exists an unusable MATCH constraint this is an
|
||||
** unusable plan. Return SQLITE_CONSTRAINT. */
|
||||
idxStr[iIdxStr] = 0;
|
||||
return SQLITE_CONSTRAINT;
|
||||
}else{
|
||||
if( iCol==nCol+1 ){
|
||||
@@ -1417,6 +1419,7 @@ static int fts5FilterMethod(
|
||||
sqlite3_value *pRowidGe = 0; /* rowid >= ? expression (or NULL) */
|
||||
int iCol; /* Column on LHS of MATCH operator */
|
||||
char **pzErrmsg = pConfig->pzErrmsg;
|
||||
int bPrefixInsttoken = pConfig->bPrefixInsttoken;
|
||||
int i;
|
||||
int iIdxStr = 0;
|
||||
Fts5Expr *pExpr = 0;
|
||||
@@ -1452,6 +1455,9 @@ static int fts5FilterMethod(
|
||||
rc = fts5ExtractExprText(pConfig, apVal[i], &zText, &bFreeAndReset);
|
||||
if( rc!=SQLITE_OK ) goto filter_out;
|
||||
if( zText==0 ) zText = "";
|
||||
if( sqlite3_value_subtype(apVal[i])==FTS5_INSTTOKEN_SUBTYPE ){
|
||||
pConfig->bPrefixInsttoken = 1;
|
||||
}
|
||||
|
||||
iCol = 0;
|
||||
do{
|
||||
@@ -1592,6 +1598,7 @@ static int fts5FilterMethod(
|
||||
filter_out:
|
||||
sqlite3Fts5ExprFree(pExpr);
|
||||
pConfig->pzErrmsg = pzErrmsg;
|
||||
pConfig->bPrefixInsttoken = bPrefixInsttoken;
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -1894,7 +1901,6 @@ static int fts5UpdateMethod(
|
||||
Fts5Config *pConfig = pTab->p.pConfig;
|
||||
int eType0; /* value_type() of apVal[0] */
|
||||
int rc = SQLITE_OK; /* Return code */
|
||||
int bUpdateOrDelete = 0;
|
||||
|
||||
/* A transaction must be open when this is called. */
|
||||
assert( pTab->ts.eState==1 || pTab->ts.eState==2 );
|
||||
@@ -1906,7 +1912,7 @@ static int fts5UpdateMethod(
|
||||
);
|
||||
assert( pTab->p.pConfig->pzErrmsg==0 );
|
||||
if( pConfig->pgsz==0 ){
|
||||
rc = sqlite3Fts5IndexLoadConfig(pTab->p.pIndex);
|
||||
rc = sqlite3Fts5ConfigLoad(pTab->p.pConfig, pTab->p.pConfig->iCookie);
|
||||
if( rc!=SQLITE_OK ) return rc;
|
||||
}
|
||||
|
||||
@@ -1931,7 +1937,6 @@ static int fts5UpdateMethod(
|
||||
rc = SQLITE_ERROR;
|
||||
}else{
|
||||
rc = fts5SpecialDelete(pTab, apVal);
|
||||
bUpdateOrDelete = 1;
|
||||
}
|
||||
}else{
|
||||
rc = fts5SpecialInsert(pTab, z, apVal[2 + pConfig->nCol + 1]);
|
||||
@@ -1968,7 +1973,6 @@ static int fts5UpdateMethod(
|
||||
}else{
|
||||
i64 iDel = sqlite3_value_int64(apVal[0]); /* Rowid to delete */
|
||||
rc = sqlite3Fts5StorageDelete(pTab->pStorage, iDel, 0, 0);
|
||||
bUpdateOrDelete = 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1996,7 +2000,6 @@ static int fts5UpdateMethod(
|
||||
if( eConflict==SQLITE_REPLACE && eType1==SQLITE_INTEGER ){
|
||||
i64 iNew = sqlite3_value_int64(apVal[1]); /* Rowid to delete */
|
||||
rc = sqlite3Fts5StorageDelete(pTab->pStorage, iNew, 0, 0);
|
||||
bUpdateOrDelete = 1;
|
||||
}
|
||||
fts5StorageInsert(&rc, pTab, apVal, pRowid);
|
||||
}
|
||||
@@ -2050,23 +2053,8 @@ static int fts5UpdateMethod(
|
||||
rc = sqlite3Fts5StorageDelete(pStorage, iOld, 0, 1);
|
||||
fts5StorageInsert(&rc, pTab, apVal, pRowid);
|
||||
}
|
||||
bUpdateOrDelete = 1;
|
||||
sqlite3Fts5StorageReleaseDeleteRow(pStorage);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK
|
||||
&& bUpdateOrDelete
|
||||
&& pConfig->bSecureDelete
|
||||
&& pConfig->iVersion==FTS5_CURRENT_VERSION
|
||||
){
|
||||
rc = sqlite3Fts5StorageConfigValue(
|
||||
pTab->pStorage, "version", 0, FTS5_CURRENT_VERSION_SECUREDELETE
|
||||
);
|
||||
if( rc==SQLITE_OK ){
|
||||
pConfig->iVersion = FTS5_CURRENT_VERSION_SECUREDELETE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2119,6 +2107,7 @@ static int fts5RollbackMethod(sqlite3_vtab *pVtab){
|
||||
Fts5FullTable *pTab = (Fts5FullTable*)pVtab;
|
||||
fts5CheckTransactionState(pTab, FTS5_ROLLBACK, 0);
|
||||
rc = sqlite3Fts5StorageRollback(pTab->pStorage);
|
||||
pTab->p.pConfig->pgsz = 0;
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -3651,6 +3640,20 @@ static void fts5LocaleFunc(
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Implementation of fts5_insttoken() function.
|
||||
*/
|
||||
static void fts5InsttokenFunc(
|
||||
sqlite3_context *pCtx, /* Function call context */
|
||||
int nArg, /* Number of args */
|
||||
sqlite3_value **apArg /* Function arguments */
|
||||
){
|
||||
assert( nArg==1 );
|
||||
(void)nArg;
|
||||
sqlite3_result_value(pCtx, apArg[0]);
|
||||
sqlite3_result_subtype(pCtx, FTS5_INSTTOKEN_SUBTYPE);
|
||||
}
|
||||
|
||||
/*
|
||||
** Return true if zName is the extension on one of the shadow tables used
|
||||
** by this module.
|
||||
@@ -3780,10 +3783,17 @@ static int fts5Init(sqlite3 *db){
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3_create_function(
|
||||
db, "fts5_locale", 2,
|
||||
SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_RESULT_SUBTYPE,
|
||||
SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_RESULT_SUBTYPE|SQLITE_SUBTYPE,
|
||||
p, fts5LocaleFunc, 0, 0
|
||||
);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3_create_function(
|
||||
db, "fts5_insttoken", 1,
|
||||
SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_RESULT_SUBTYPE,
|
||||
p, fts5InsttokenFunc, 0, 0
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/* If SQLITE_FTS5_ENABLE_TEST_MI is defined, assume that the file
|
||||
|
||||
@@ -205,6 +205,11 @@ static int fts5StorageGetStmt(
|
||||
if( rc!=SQLITE_OK && pzErrMsg ){
|
||||
*pzErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(pC->db));
|
||||
}
|
||||
if( rc==SQLITE_ERROR && eStmt>FTS5_STMT_LOOKUP2 && eStmt<FTS5_STMT_SCAN ){
|
||||
/* One of the internal tables - not the %_content table - is missing.
|
||||
** This counts as a corrupted table. */
|
||||
rc = SQLITE_CORRUPT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+77
-6
@@ -21,6 +21,7 @@
|
||||
#include "fts5.h"
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef SQLITE_DEBUG
|
||||
extern int sqlite3_fts5_may_be_corrupt;
|
||||
@@ -729,8 +730,9 @@ static int SQLITE_TCLAPI f5tTokenize(
|
||||
int objc,
|
||||
Tcl_Obj *CONST objv[]
|
||||
){
|
||||
char *zText;
|
||||
Tcl_Size nText;
|
||||
char *pCopy = 0;
|
||||
char *zText = 0;
|
||||
Tcl_Size nText = 0;
|
||||
sqlite3 *db = 0;
|
||||
fts5_api *pApi = 0;
|
||||
Fts5Tokenizer *pTok = 0;
|
||||
@@ -777,22 +779,33 @@ static int SQLITE_TCLAPI f5tTokenize(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
if( nText>0 ){
|
||||
pCopy = sqlite3_malloc(nText);
|
||||
if( pCopy==0 ){
|
||||
tokenizer.xDelete(pTok);
|
||||
Tcl_AppendResult(interp, "error in sqlite3_malloc()", (char*)0);
|
||||
return TCL_ERROR;
|
||||
}else{
|
||||
memcpy(pCopy, zText, nText);
|
||||
}
|
||||
}
|
||||
|
||||
pRet = Tcl_NewObj();
|
||||
Tcl_IncrRefCount(pRet);
|
||||
ctx.bSubst = (objc==5);
|
||||
ctx.pRet = pRet;
|
||||
ctx.zInput = zText;
|
||||
ctx.zInput = pCopy;
|
||||
rc = tokenizer.xTokenize(
|
||||
pTok, (void*)&ctx, FTS5_TOKENIZE_DOCUMENT, zText,(int)nText, xTokenizeCb2
|
||||
pTok, (void*)&ctx, FTS5_TOKENIZE_DOCUMENT, pCopy,(int)nText, xTokenizeCb2
|
||||
);
|
||||
tokenizer.xDelete(pTok);
|
||||
sqlite3_free(pCopy);
|
||||
if( rc!=SQLITE_OK ){
|
||||
Tcl_AppendResult(interp, "error in tokenizer.xTokenize()", (char*)0);
|
||||
Tcl_DecrRefCount(pRet);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
|
||||
Tcl_Free((void*)azArg);
|
||||
Tcl_SetObjResult(interp, pRet);
|
||||
Tcl_DecrRefCount(pRet);
|
||||
@@ -1626,6 +1639,63 @@ static int SQLITE_TCLAPI f5tDropCorruptTable(
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Free a buffer returned to SQLite by the str() function.
|
||||
*/
|
||||
void f5tFree(void *p){
|
||||
char *x = (char *)p;
|
||||
ckfree(&x[-8]);
|
||||
}
|
||||
|
||||
/*
|
||||
** Implementation of str().
|
||||
*/
|
||||
void f5tStrFunc(sqlite3_context *pCtx, int nArg, sqlite3_value **apArg){
|
||||
const char *zText = 0;
|
||||
assert( nArg==1 );
|
||||
|
||||
zText = (const char*)sqlite3_value_text(apArg[0]);
|
||||
if( zText ){
|
||||
sqlite3_int64 nText = strlen(zText);
|
||||
char *zCopy = (char*)ckalloc(nText+8);
|
||||
if( zCopy==0 ){
|
||||
sqlite3_result_error_nomem(pCtx);
|
||||
}else{
|
||||
zCopy += 8;
|
||||
memcpy(zCopy, zText, nText);
|
||||
sqlite3_result_text64(pCtx, zCopy, nText, f5tFree, SQLITE_UTF8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** sqlite3_fts5_register_str DB
|
||||
**
|
||||
** Register the str() function with database handle DB. str() interprets
|
||||
** its only argument as text and returns a copy of the value in a
|
||||
** non-nul-terminated buffer.
|
||||
*/
|
||||
static int SQLITE_TCLAPI f5tRegisterStr(
|
||||
void * clientData,
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
Tcl_Obj *CONST objv[]
|
||||
){
|
||||
sqlite3 *db = 0;
|
||||
|
||||
if( objc!=2 ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "DB");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if( f5tDbPointer(interp, objv[1], &db) ){
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
sqlite3_create_function(db, "str", 1, SQLITE_UTF8, 0, f5tStrFunc, 0, 0);
|
||||
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Entry point.
|
||||
*/
|
||||
@@ -1645,7 +1715,8 @@ int Fts5tcl_Init(Tcl_Interp *interp){
|
||||
{ "sqlite3_fts5_register_matchinfo", f5tRegisterMatchinfo, 0 },
|
||||
{ "sqlite3_fts5_register_fts5tokenize", f5tRegisterTok, 0 },
|
||||
{ "sqlite3_fts5_register_origintext",f5tRegisterOriginText, 0 },
|
||||
{ "sqlite3_fts5_drop_corrupt_table", f5tDropCorruptTable, 0 }
|
||||
{ "sqlite3_fts5_drop_corrupt_table", f5tDropCorruptTable, 0 },
|
||||
{ "sqlite3_fts5_register_str", f5tRegisterStr, 0 }
|
||||
};
|
||||
int i;
|
||||
F5tTokenizerContext *pContext;
|
||||
|
||||
@@ -1353,8 +1353,8 @@ static int fts5TriTokenize(
|
||||
char *zOut = aBuf;
|
||||
int ii;
|
||||
const unsigned char *zIn = (const unsigned char*)pText;
|
||||
const unsigned char *zEof = &zIn[nText];
|
||||
u32 iCode;
|
||||
const unsigned char *zEof = (zIn ? &zIn[nText] : 0);
|
||||
u32 iCode = 0;
|
||||
int aStart[3]; /* Input offset of each character in aBuf[] */
|
||||
|
||||
UNUSED_PARAM(unusedFlags);
|
||||
@@ -1363,8 +1363,8 @@ static int fts5TriTokenize(
|
||||
for(ii=0; ii<3; ii++){
|
||||
do {
|
||||
aStart[ii] = zIn - (const unsigned char*)pText;
|
||||
if( zIn>=zEof ) return SQLITE_OK;
|
||||
READ_UTF8(zIn, zEof, iCode);
|
||||
if( iCode==0 ) return SQLITE_OK;
|
||||
if( p->bFold ) iCode = sqlite3Fts5UnicodeFold(iCode, p->iFoldParam);
|
||||
}while( iCode==0 );
|
||||
WRITE_UTF8(zOut, iCode);
|
||||
@@ -1385,8 +1385,11 @@ static int fts5TriTokenize(
|
||||
/* Read characters from the input up until the first non-diacritic */
|
||||
do {
|
||||
iNext = zIn - (const unsigned char*)pText;
|
||||
if( zIn>=zEof ){
|
||||
iCode = 0;
|
||||
break;
|
||||
}
|
||||
READ_UTF8(zIn, zEof, iCode);
|
||||
if( iCode==0 ) break;
|
||||
if( p->bFold ) iCode = sqlite3Fts5UnicodeFold(iCode, p->iFoldParam);
|
||||
}while( iCode==0 );
|
||||
|
||||
|
||||
@@ -72,7 +72,7 @@ foreach {tn schema sql} {
|
||||
} {
|
||||
db_restore_and_reopen
|
||||
do_execsql_test 1.1.$tn.1 $schema
|
||||
do_catchsql_test 1.1.$tn.2 $sql {1 {SQL logic error}}
|
||||
do_catchsql_test 1.1.$tn.2 $sql {1 {database disk image is malformed}}
|
||||
db close
|
||||
}
|
||||
|
||||
|
||||
@@ -15678,6 +15678,239 @@ do_catchsql_test 81.2 {
|
||||
UPDATE t1 SET b=zeroblob(299);
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_test 82.0 {
|
||||
sqlite3 db {}
|
||||
db deserialize [decode_hexdb {
|
||||
.open --hexdb
|
||||
| size 32768 pagesize 4096 filename c0.txt.db
|
||||
| page 1 offset 0
|
||||
| 0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00 SQLite format 3.
|
||||
| 16: 10 00 01 01 00 40 20 20 00 00 00 00 00 00 00 08 .....@ ........
|
||||
| 32: 00 00 00 02 00 00 00 01 00 00 00 09 00 00 00 04 ................
|
||||
| 96: 00 00 00 00 0d 0f c7 00 07 0d 92 00 0f 8d 0f 36 ...............6
|
||||
| 112: 0e cb 0e 6b 0e 0e 0d b6 0d 92 0d 92 00 00 00 00 ...k............
|
||||
| 3472: 00 00 22 08 06 17 11 11 01 31 74 61 62 6c 65 74 .........1tablet
|
||||
| 3488: 32 74 32 08 43 52 45 41 54 45 20 54 41 42 4c 45 2t2.CREATE TABLE
|
||||
| 3504: 20 74 32 28 78 29 56 07 06 17 1f 1f 01 7d 74 61 t2(x)V.......ta
|
||||
| 3520: 62 6c 65 74 31 5f 63 6f 6e 66 69 67 74 31 5f 63 blet1_configt1_c
|
||||
| 3536: 6f 6e 66 69 67 07 43 52 45 41 54 45 20 54 41 42 onfig.CREATE TAB
|
||||
| 3552: 4c 45 20 27 74 31 5f 63 6f 6e 66 69 67 27 28 6b LE 't1_config'(k
|
||||
| 3568: 20 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 76 29 PRIMARY KEY, v)
|
||||
| 3584: 20 57 49 54 48 4f 55 54 20 52 4f 57 49 44 5b 06 WITHOUT ROWID[.
|
||||
| 3600: 07 17 21 21 01 81 01 74 61 62 6c 65 74 31 5f 64 ..!!...tablet1_d
|
||||
| 3616: 6f 63 73 69 7a 65 74 31 5f 64 6f 63 73 69 7a 65 ocsizet1_docsize
|
||||
| 3632: 06 43 52 45 41 54 45 20 54 41 42 4c 45 20 27 74 .CREATE TABLE 't
|
||||
| 3648: 31 5f 64 6f 63 73 69 7a 65 27 28 69 64 20 49 4e 1_docsize'(id IN
|
||||
| 3664: 54 45 47 45 52 20 50 52 49 4d 41 52 59 20 4b 45 TEGER PRIMARY KE
|
||||
| 3680: 59 2c 20 73 7a 20 42 4c 4f 42 29 5e 05 07 17 21 Y, sz BLOB)^...!
|
||||
| 3696: 21 01 81 07 74 61 62 6c 65 74 31 5f 63 6f 6e 74 !...tablet1_cont
|
||||
| 3712: 65 6e 74 74 31 5f 63 6f 6e 74 65 6e 74 05 43 52 entt1_content.CR
|
||||
| 3728: 45 41 54 45 20 54 41 42 4c 45 20 27 74 31 5f 63 EATE TABLE 't1_c
|
||||
| 3744: 6f 6e 74 65 6e 74 27 28 69 64 20 49 4e 54 45 47 ontent'(id INTEG
|
||||
| 3760: 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 ER PRIMARY KEY,
|
||||
| 3776: 63 30 2c 20 63 31 2c 20 63 32 29 69 04 07 17 19 c0, c1, c2)i....
|
||||
| 3792: 19 01 81 2d 74 61 62 6c 65 74 31 5f 69 64 78 74 ...-tablet1_idxt
|
||||
| 3808: 31 5f 69 64 78 04 43 52 45 41 54 45 20 54 41 42 1_idx.CREATE TAB
|
||||
| 3824: 4c 45 20 27 74 31 5f 69 64 78 27 28 73 65 67 69 LE 't1_idx'(segi
|
||||
| 3840: 64 2c 20 74 65 72 6d 2c 20 70 67 6e 6f 2c 20 50 d, term, pgno, P
|
||||
| 3856: 52 49 4d 41 52 59 20 4b 45 59 28 73 65 67 69 64 RIMARY KEY(segid
|
||||
| 3872: 2c 20 74 65 72 6d 29 29 20 57 49 54 48 4f 55 54 , term)) WITHOUT
|
||||
| 3888: 20 52 4f 57 49 44 55 03 07 17 1b 1b 01 81 01 74 ROWIDU........t
|
||||
| 3904: 61 62 6c 65 74 31 5f 64 61 74 61 74 31 5f 64 61 ablet1_datat1_da
|
||||
| 3920: 74 61 03 43 52 45 41 54 45 20 54 41 42 4c 45 20 ta.CREATE TABLE
|
||||
| 3936: 27 74 31 5f 64 61 74 61 27 28 69 64 20 49 4e 54 't1_data'(id INT
|
||||
| 3952: 45 47 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59 EGER PRIMARY KEY
|
||||
| 3968: 2c 20 62 6c 6f 63 6b 20 42 4c 4f 42 29 38 02 06 , block BLOB)8..
|
||||
| 3984: 17 11 11 08 5f 74 61 62 6c 65 74 31 74 31 43 52 ...._tablet1t1CR
|
||||
| 4000: 45 41 54 45 20 56 49 52 54 55 41 4c 20 54 41 42 EATE VIRTUAL TAB
|
||||
| 4016: 4c 45 20 74 31 20 55 53 49 4e 47 20 66 74 73 35 LE t1 USING fts5
|
||||
| 4032: 28 61 2c 62 2c 63 29 00 00 00 00 00 00 00 00 00 (a,b,c).........
|
||||
| page 3 offset 8192
|
||||
| 0: 0d 00 00 00 03 0c 94 00 0f e6 0f ef 0c 94 00 00 ................
|
||||
| 3216: 00 00 00 00 86 4a 84 80 80 80 80 01 04 00 8d 18 .....J..........
|
||||
| 3232: 00 00 03 2b 02 30 30 01 02 06 01 02 06 01 02 06 ...+.00.........
|
||||
| 3248: 1f 02 03 01 02 03 01 02 03 01 08 32 30 31 36 30 ...........20160
|
||||
| 3264: 36 30 39 01 02 07 01 02 07 01 02 07 01 01 34 01 609...........4.
|
||||
| 3280: 02 05 01 02 05 01 02 05 01 01 35 01 02 04 01 02 ..........5.....
|
||||
| 3296: 04 01 02 04 02 07 30 30 30 30 30 30 30 1c 02 04 ......0000000...
|
||||
| 3312: 01 02 04 01 02 04 01 06 62 69 6e 61 72 79 03 06 ........binary..
|
||||
| 3328: 01 02 02 03 06 01 02 02 03 06 01 02 02 03 06 01 ................
|
||||
| 3344: 02 02 03 06 01 02 02 03 06 01 02 02 03 06 01 02 ................
|
||||
| 3360: 02 03 06 01 02 02 03 06 01 02 02 03 06 01 02 02 ................
|
||||
| 3376: 03 06 01 02 02 03 06 01 02 02 01 08 63 6f 6d 70 ............comp
|
||||
| 3392: 69 6c 65 72 01 02 02 01 02 02 01 02 02 01 06 64 iler...........d
|
||||
| 3408: 62 73 74 61 74 07 02 03 01 02 03 01 02 03 02 04 bstat...........
|
||||
| 3424: 65 62 75 67 04 02 02 01 02 02 01 02 02 01 06 65 ebug...........e
|
||||
| 3440: 6e 61 62 6c 65 07 02 02 01 02 02 01 02 02 01 02 nable...........
|
||||
| 3456: 02 01 02 02 01 02 02 01 02 02 01 02 02 01 02 02 ................
|
||||
| 3472: 01 02 02 01 02 02 01 02 02 01 02 02 01 02 02 01 ................
|
||||
| 3488: 02 02 01 02 02 01 02 02 01 02 02 01 02 02 01 02 ................
|
||||
| 3504: 02 01 02 02 02 08 78 74 65 6e 73 69 6f 6e 1f 02 ......xtension..
|
||||
| 3520: 04 01 02 04 01 02 04 01 04 66 74 73 34 0a 02 03 .........fts4...
|
||||
| 3536: 01 02 03 01 02 03 04 01 35 0d 02 03 01 02 03 01 ........5.......
|
||||
| 3552: 02 03 01 03 67 63 63 01 02 03 01 02 03 01 02 03 ....gcc.........
|
||||
| 3568: 02 06 65 6f 70 6f 6c 79 10 02 03 01 02 03 01 02 ..eopoly........
|
||||
| 3584: 03 01 05 6a 73 6f 6e 31 13 02 03 01 02 03 01 02 ...json1........
|
||||
| 3600: 03 01 04 6c 6f 61 64 1f 02 03 01 02 03 01 02 03 ...load.........
|
||||
| 3616: 01 03 6d 61 78 1c 02 02 01 02 02 01 02 02 02 05 ..max...........
|
||||
| 3632: 65 6d 6f 72 79 1c 02 03 01 02 03 01 02 03 04 04 emory...........
|
||||
| 3648: 73 79 73 35 16 02 03 01 02 02 03 01 03 01 06 6e sys5...........n
|
||||
| 3664: 6f 63 61 73 65 02 06 01 02 02 03 06 01 02 02 03 ocase...........
|
||||
| 3680: 06 01 02 02 03 06 01 02 02 03 06 01 02 02 03 06 ................
|
||||
| 3696: 01 02 02 03 06 01 02 02 03 06 01 02 02 03 06 01 ................
|
||||
| 3712: 02 02 03 06 01 02 02 03 06 01 02 02 03 06 01 02 ................
|
||||
| 3728: 02 01 04 6f 6d 69 74 1f 02 02 01 02 02 01 02 02 ...omit.........
|
||||
| 3744: 01 05 72 74 72 65 65 19 02 03 01 02 03 01 02 03 ..rtree.........
|
||||
| 3760: 04 02 69 6d 01 06 01 02 02 03 06 01 02 02 03 06 ..im............
|
||||
| 3776: 01 02 02 03 06 01 02 02 03 06 01 02 02 03 06 01 ................
|
||||
| 3792: 02 02 03 06 01 02 02 03 06 01 02 02 03 06 01 02 ................
|
||||
| 3808: 02 03 06 01 02 02 03 06 01 02 02 03 06 01 02 02 ................
|
||||
| 3824: 01 0a 74 68 72 65 61 64 73 61 66 65 03 57 34 56 ..threadsafe.W4V
|
||||
| 3840: 94 64 91 46 85 84 04 76 74 61 62 07 02 04 01 02 .d.F...vtab.....
|
||||
| 3856: 04 01 02 04 01 01 78 01 06 01 01 02 01 06 01 01 ......x.........
|
||||
| 3872: 02 01 06 01 01 02 01 06 01 01 02 01 06 01 10 02 ................
|
||||
| 3888: 01 06 01 01 02 01 06 01 01 02 01 06 01 01 02 01 ................
|
||||
| 3904: 06 01 01 02 01 06 01 01 02 01 06 01 01 02 01 06 ................
|
||||
| 3920: 01 01 02 01 06 01 01 02 01 06 01 01 02 01 06 01 ................
|
||||
| 3936: 01 02 01 06 01 01 10 01 06 01 01 02 01 06 01 01 ................
|
||||
| 3952: 02 01 06 01 01 02 01 06 01 01 02 01 06 01 01 02 ................
|
||||
| 3968: 01 06 01 01 02 01 06 01 01 02 01 06 01 01 02 01 ................
|
||||
| 3984: 06 01 01 02 01 06 01 01 02 01 06 01 01 02 01 06 ................
|
||||
| 4000: 01 01 02 01 06 01 01 02 01 06 01 01 02 01 06 01 ................
|
||||
| 4016: 01 02 01 06 01 01 02 01 06 01 01 02 01 06 01 01 ................
|
||||
| 4032: 02 01 06 01 01 02 01 06 01 01 02 04 15 13 0c 0c ................
|
||||
| 4048: 12 44 13 11 0f 47 13 0f 0c 0e 11 10 0f 0e 10 0f .D...G..........
|
||||
| 4064: 44 0f 10 40 15 0f 07 01 03 00 14 24 5a 24 24 0f D..@.......$Z$$.
|
||||
| 4080: 0a 03 00 24 00 00 00 00 01 01 01 00 01 01 01 01 ...$............
|
||||
| page 4 offset 12288
|
||||
| 0: 0a 00 00 00 01 0f fa 00 00 00 00 00 00 00 00 00 ................
|
||||
| 4080: 00 00 00 00 00 00 00 00 00 00 05 04 09 0c 01 02 ................
|
||||
| page 5 offset 16384
|
||||
| 0: 0d 00 00 00 24 0c 0a 00 0f d8 0f af 0f 86 0f 74 ....$..........t
|
||||
| 16: 0f 61 0f 4e 0f 2f 0f 0f 0e ef 0e d7 0e be 0e a5 .a.N./..........
|
||||
| 32: 0e 8d 0e 74 0e 5b 0e 40 0e 24 0e 08 0d ef 0d d5 ...t.[.@.$......
|
||||
| 48: 0d bb 0d a0 0d 84 0d 68 0d 4f 0d 35 0d 1b 0c fb .......h.O.5....
|
||||
| 64: 0c da 0c b9 0c 99 0c 78 0c 57 00 00 00 00 00 00 .......x.W......
|
||||
| 3072: 00 00 00 00 00 00 00 00 00 00 18 24 05 00 25 0f ...........$..%.
|
||||
| 3088: 19 54 48 52 45 41 44 53 41 46 45 3d 30 58 42 49 .THREADSAFE=0XBI
|
||||
| 3104: 4e 41 52 59 18 23 05 00 25 0f 19 54 48 52 45 41 NARY.#..%..THREA
|
||||
| 3120: 44 53 41 46 45 3d 30 58 4e 4f 43 41 53 45 17 22 DSAFE=0XNOCASE..
|
||||
| 3136: 05 00 25 0f 17 54 48 52 45 41 44 53 31 46 45 3d ..%..THREADS1FE=
|
||||
| 3152: 30 58 52 64 52 49 4d 1f 21 05 00 33 0f 19 4f 4d 0XRdRIM.!..3..OM
|
||||
| 3168: 49 54 20 4c 4f 41 44 20 45 58 54 45 4e 53 49 4f IT LOAD EXTENSIO
|
||||
| 3184: 4e 58 42 49 4e 41 52 59 1f 20 05 00 33 0f 19 4f NXBINARY. ..3..O
|
||||
| 3200: 4d 49 54 20 4c 4f 41 44 20 45 58 54 45 4e 53 49 MIT LOAD EXTENSI
|
||||
| 3216: 4f 4e 58 4e 4f 43 41 53 45 1e 1f 05 00 33 0f 17 ONXNOCASE....3..
|
||||
| 3232: 4f 4d 49 54 20 4c 4f 41 44 20 45 58 54 45 4e 53 OMIT LOAD EXTENS
|
||||
| 3248: 49 4f 4e 58 52 54 52 49 4d 1f 1e 05 00 33 0f 19 IONXRTRIM....3..
|
||||
| 3264: 4d 41 58 20 4d 45 4d 4f 52 59 3d 35 30 30 30 30 MAX MEMORY=50000
|
||||
| 3280: 30 30 30 58 42 49 4e 41 52 59 1f 1d 05 00 33 0f 000XBINARY....3.
|
||||
| 3296: 19 4d 41 58 20 4d 45 4d 4f 52 59 3d 35 30 30 30 .MAX MEMORY=5000
|
||||
| 3312: 30 30 30 30 58 4e 4f 43 41 53 45 1e 1c 05 00 33 0000XNOCASE....3
|
||||
| 3328: 0f 17 4d 41 58 20 4d 45 4d 4f 52 59 3d 35 30 30 ..MAX MEMORY=500
|
||||
| 3344: 30 30 30 30 30 58 52 54 52 49 4d 18 1b 05 00 25 00000XRTRIM....%
|
||||
| 3360: 0f 19 45 4e 41 42 4c 45 20 52 54 52 45 45 58 42 ..ENABLE RTREEXB
|
||||
| 3376: 49 4e 41 52 59 18 1a 05 00 25 0f 19 45 4e 41 42 INARY....%..ENAB
|
||||
| 3392: 4c 45 20 52 54 52 45 45 58 4e 4f 43 41 53 45 17 LE RTREEXNOCASE.
|
||||
| 3408: 19 05 00 25 0f 17 45 4e 41 42 4c 45 20 52 54 52 ...%..ENABLE RTR
|
||||
| 3424: 45 45 58 52 54 52 49 4d 1a 18 05 00 29 0f 19 45 EEXRTRIM....)..E
|
||||
| 3440: 4e 41 42 4b 45 20 4d 45 4d 53 59 53 35 58 42 49 NABKE MEMSYS5XBI
|
||||
| 3456: 4e 41 52 59 1a 17 05 00 29 0f 19 45 4e 41 42 4c NARY....)..ENABL
|
||||
| 3472: 42 60 2d 45 4d 53 59 53 35 58 4e 4f 43 41 53 45 B`-EMSYS5XNOCASE
|
||||
| 3488: 19 16 05 00 29 0f 17 45 4e 41 42 4c 45 20 4d 45 ....)..ENABLE ME
|
||||
| 3504: 4d 53 59 53 35 58 52 54 52 49 4d 18 15 05 00 25 MSYS5XRTRIM....%
|
||||
| 3520: 0f 19 45 4e 41 42 4c 45 20 4a 53 4f 4e 31 58 42 ..ENABLE JSON1XB
|
||||
| 3536: 49 4e 41 52 59 18 14 05 00 25 0f 19 45 4e 41 42 INARY....%..ENAB
|
||||
| 3552: 4c 45 20 4a 53 4f 4e 31 58 4e 4f 43 41 53 45 17 LE JSON1XNOCASE.
|
||||
| 3568: 13 05 00 25 0f 17 45 4e 41 42 4c 45 20 4a 53 4f ...%..ENABLE JSO
|
||||
| 3584: 4e 31 58 52 54 52 49 4d 1a 12 05 00 29 0f 19 45 N1XRTRIM....)..E
|
||||
| 3600: 42 4c 45 20 47 45 4f 50 4f 4c 59 58 42 49 4e 41 BLE GEOPOLYXBINA
|
||||
| 3616: 52 59 1a 11 05 00 39 0f 19 45 4e 41 42 4c 45 2e RY....9..ENABLE.
|
||||
| 3632: 41 40 47 45 4f 50 4f 4c 59 58 4e 4f 43 41 53 40 A@GEOPOLYXNOCAS@
|
||||
| 3648: 4f 4c 59 58 55 19 10 05 00 29 0f 17 45 4e 41 42 OLYXU....)..ENAB
|
||||
| 3664: 4c 45 20 47 45 4f 52 54 52 49 4d 17 0f 05 00 23 LE GEORTRIM....#
|
||||
| 3680: 0f 19 45 4e 41 42 4c 45 20 46 54 53 35 58 42 49 ..ENABLE FTS5XBI
|
||||
| 3696: 4e 41 52 59 17 0e 05 00 23 0f 19 45 4e 41 42 4c NARY....#..ENABL
|
||||
| 3712: 45 20 46 54 53 35 58 4e 4f 43 41 53 45 16 0d 05 E FTS5XNOCASE...
|
||||
| 3728: 00 23 0f 17 45 4e 41 42 4c 45 20 46 54 53 35 58 .#..ENABLE FTS5X
|
||||
| 3744: 52 54 52 49 4d 17 0c 05 00 23 0f 19 45 4e 41 42 RTRIM....#..ENAB
|
||||
| 3760: 4c 45 20 46 54 53 34 58 42 49 4e 41 52 59 17 0b LE FTS4XBINARY..
|
||||
| 3776: 05 00 23 0f 19 45 4e 41 42 4c 45 20 46 54 53 34 ..#..ENABLE FTS4
|
||||
| 3792: 58 4e 4f 43 41 53 45 16 0a 05 00 23 0f 17 45 4e XNOCASE....#..EN
|
||||
| 3808: 41 42 4c 45 20 46 54 53 34 58 52 54 52 49 4d 1e ABLE FTS4XRTRIM.
|
||||
| 3824: 09 05 00 31 0f 19 45 4e 41 42 4c 45 20 44 42 53 ...1..ENABLE DBS
|
||||
| 3840: 54 41 54 20 56 54 41 42 58 42 49 4e 41 52 59 1e TAT VTABXBINARY.
|
||||
| 3856: 08 05 00 31 0f 19 45 4e 41 42 4c 45 20 44 42 53 ...1..ENABLE DBS
|
||||
| 3872: 54 41 54 20 56 54 24 15 48 4e 4f 43 41 53 45 1d TAT VT$.HNOCASE.
|
||||
| 3888: 07 05 00 31 0f 17 45 4e 41 42 4c 45 20 44 42 53 ...1..ENABLE DBS
|
||||
| 3904: 54 41 54 20 56 54 41 42 58 52 54 52 49 4d 11 06 TAT VTABXRTRIM..
|
||||
| 3920: 05 00 17 0f 19 44 45 42 55 47 58 42 49 4e 41 52 .....DEBUGXBINAR
|
||||
| 3936: 59 11 05 05 00 17 0f 19 44 45 42 55 47 58 4e 4f Y.......DEBUGXNO
|
||||
| 3952: 43 41 53 45 10 04 05 00 17 0f 17 44 45 42 55 47 CASE.......DEBUG
|
||||
| 3968: 58 52 54 52 49 4d 27 03 05 00 43 0f 19 43 4f 4d XRTRIM'...C..COM
|
||||
| 3984: 50 49 4c 45 52 3d 67 63 63 2d 35 2e 34 2e 30 20 PILER=gcc-5.4.0
|
||||
| 4000: 32 30 31 36 30 36 30 39 58 42 49 4e 41 52 59 27 20160609XBINARY'
|
||||
| 4016: 02 05 00 43 0f 19 43 4f 4d 50 49 4c 45 52 3d 67 ...C..COMPILER=g
|
||||
| 4032: 63 63 2d 35 2e 34 2e 30 20 32 30 31 36 30 36 30 cc-5.4.0 2016060
|
||||
| 4048: 39 58 4e 4f 43 41 53 45 26 01 05 00 43 0f 17 43 9XNOCASE&...C..C
|
||||
| 4064: 4f 4d 50 49 4c 45 52 3d 67 63 63 2d 35 2e 34 2e OMPILER=gcc-5.4.
|
||||
| 4080: 30 20 32 30 31 36 30 36 30 39 58 52 54 52 49 4d 0 20160609XRTRIM
|
||||
| page 6 offset 20480
|
||||
| 0: 0d 00 00 00 24 0e e0 00 0f f8 0f f0 0f e8 0f e0 ....$...........
|
||||
| 16: 0f d8 0f d0 0f c8 0f c0 0f b8 0f b0 0f a8 0f a0 ................
|
||||
| 32: 1f 98 0f 90 0f 88 0f 80 0f 78 0f 70 0f 68 0f 60 .........x.p.h.`
|
||||
| 48: 0f 58 0f 50 0f 48 0f 40 0f 38 0f 30 0f 28 0f 20 .X.P.H.@.8.0.(.
|
||||
| 64: 0f 18 0f 10 0f 08 0f 00 0e f8 0e f0 0e e8 00 00 ................
|
||||
| 3808: 06 24 03 00 12 02 01 01 06 23 03 00 12 02 01 01 .$.......#......
|
||||
| 3824: 06 22 03 00 12 02 01 01 06 21 03 00 12 03 01 01 .........!......
|
||||
| 3840: 06 20 03 00 12 03 01 01 06 1f 03 00 12 03 01 01 . ..............
|
||||
| 3856: 06 1e 03 00 12 03 01 01 06 1d 03 00 12 03 01 01 ................
|
||||
| 3872: 06 1c 03 00 12 03 01 01 06 1b 03 00 12 02 01 01 ................
|
||||
| 3888: 06 1a 03 00 12 02 01 01 06 19 03 00 12 02 01 01 ................
|
||||
| 3904: 06 18 03 00 12 02 01 01 06 17 03 00 12 02 01 01 ................
|
||||
| 3920: 06 15 f3 00 12 02 01 01 06 15 03 00 12 02 01 01 ................
|
||||
| 3936: 06 14 03 00 12 02 01 01 06 13 03 00 12 02 01 01 ................
|
||||
| 3952: 06 12 03 00 12 02 01 01 06 11 03 00 12 02 01 01 ................
|
||||
| 3968: 06 10 03 00 12 02 01 01 06 0f 03 00 12 02 01 01 ................
|
||||
| 3984: 06 0e 03 00 12 02 01 01 06 0d 03 00 12 02 01 01 ................
|
||||
| 4000: 06 0c 03 00 12 02 01 01 06 0b 03 00 12 02 01 01 ................
|
||||
| 4016: 06 0a 03 00 12 02 01 01 06 09 03 00 12 03 01 01 ................
|
||||
| 4032: 06 08 03 00 12 03 01 01 06 07 03 00 12 03 01 01 ................
|
||||
| 4048: 06 06 03 00 12 01 01 01 06 05 03 00 12 01 01 01 ................
|
||||
| 4064: 06 04 03 00 12 01 01 01 06 03 03 00 12 06 01 01 ................
|
||||
| 4080: 06 02 03 00 12 06 01 01 06 01 03 00 12 06 01 01 ................
|
||||
| page 7 offset 24576
|
||||
| 0: 0a 00 00 00 01 0f f4 00 0f f4 00 00 00 00 00 00 ................
|
||||
| 4080: 00 00 00 00 0b 03 1b 01 76 65 72 73 69 6f 6e 04 ........version.
|
||||
| page 8 offset 28672
|
||||
| 0: 0d 00 00 00 03 0f d6 00 0f f4 0f e9 0f d6 00 00 ................
|
||||
| 4048: 00 00 00 00 00 00 11 03 02 2b 69 6e 74 65 67 72 .........+integr
|
||||
| 4064: 69 74 79 2d 63 68 65 63 6b 09 02 02 1b 72 65 62 ity-check....reb
|
||||
| 4080: 75 69 6c 64 0a 01 02 1d 6f 70 74 69 00 00 00 00 uild....opti....
|
||||
| end c0.txt.db
|
||||
}]} {}
|
||||
|
||||
do_execsql_test 82.2 {
|
||||
UPDATE t1 SET b=quote(zeroblob(current_date)) WHERE t1 MATCH 't*';
|
||||
PRAGMA writable_schema=ON;
|
||||
|
||||
UPDATE sqlite_schema SET sql='SELECT * FROM t1' WHERE rowid=6;
|
||||
INSERT INTO t1(t1,rank) VALUES('secure-delete',1);
|
||||
}
|
||||
|
||||
do_catchsql_test 82.3 {
|
||||
CREATE VIRTUAL TABLE IF NOT EXISTS t USING rtree(x,c);
|
||||
} {1 {Too few columns for an rtree table}}
|
||||
|
||||
do_catchsql_test 82.4 {
|
||||
BEGIN;
|
||||
REPLACE INTO t1(rowid,b,a,rowid) VALUES(x'44023b9eb002d28b0ee90c',1,2,3);
|
||||
SAVEPOINT b;
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
|
||||
|
||||
sqlite3_fts5_may_be_corrupt 0
|
||||
finish_test
|
||||
|
||||
@@ -1451,6 +1451,473 @@ do_catchsql_test 9.2 {
|
||||
DELETE FROM t1;
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_test 10.0 {
|
||||
sqlite3 db {}
|
||||
db deserialize [decode_hexdb {
|
||||
.open --hexdb
|
||||
| size 32768 pagesize 4096 filename crash-b06f016068bcea.db
|
||||
| page 1 offset 0
|
||||
| 0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00 SQLite format 3.
|
||||
| 16: 10 00 01 01 00 40 20 20 00 00 00 00 00 00 00 08 .....@ ........
|
||||
| 32: 00 00 00 02 00 00 00 01 00 00 00 09 00 00 00 04 ................
|
||||
| 96: 00 00 00 00 0d 0f c7 00 07 0d 92 00 0f 8d 0f 36 ...............6
|
||||
| 112: 0e cb 0e 6b 0e 0e 0d b6 0d 92 0d 92 00 00 00 00 ...k............
|
||||
| 3472: 00 00 22 08 06 17 11 11 01 31 74 61 62 6c 65 74 .........1tablet
|
||||
| 3488: 32 74 32 08 43 52 45 41 54 45 20 54 41 42 4c 45 2t2.CREATE TABLE
|
||||
| 3504: 20 74 32 28 78 29 56 07 06 17 1f 1f 01 7d 74 61 t2(x)V.......ta
|
||||
| 3520: 62 6c 65 74 31 5f 63 6f 6e 66 69 67 74 31 5f 63 blet1_configt1_c
|
||||
| 3536: 6f 6e 66 69 67 07 43 52 45 41 54 45 20 54 41 42 onfig.CREATE TAB
|
||||
| 3552: 4c 45 20 27 74 31 5f 63 6f 6e 66 69 67 27 28 6b LE 't1_config'(k
|
||||
| 3568: 20 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 76 29 PRIMARY KEY, v)
|
||||
| 3584: 20 57 49 54 48 4f 55 54 20 52 4f 57 49 44 5b 06 WITHOUT ROWID[.
|
||||
| 3600: 07 17 21 21 01 81 01 74 61 62 6c 65 74 31 5f 64 ..!!...tablet1_d
|
||||
| 3616: 6f 63 73 69 7a 65 74 31 5f 64 6f 63 73 69 7a 65 ocsizet1_docsize
|
||||
| 3632: 06 43 52 45 41 54 45 20 54 41 42 4c 45 20 27 74 .CREATE TABLE 't
|
||||
| 3648: 31 5f 64 6f 63 73 69 7a 65 27 28 69 64 20 49 4e 1_docsize'(id IN
|
||||
| 3664: 54 45 47 45 52 20 50 52 49 4d 41 52 59 20 4b 45 TEGER PRIMARY KE
|
||||
| 3680: 59 2c 20 73 7a 20 42 4c 4f 42 29 5e 05 07 17 21 Y, sz BLOB)^...!
|
||||
| 3696: 21 01 81 07 74 61 62 6c 65 74 31 5f 63 6f 6e 74 !...tablet1_cont
|
||||
| 3712: 65 6e 74 74 31 5f 63 6f 6e 74 65 6e 74 05 43 52 entt1_content.CR
|
||||
| 3728: 45 41 54 45 20 54 41 42 4c 45 20 27 74 31 5f 63 EATE TABLE 't1_c
|
||||
| 3744: 6f 6e 74 65 6e 74 27 28 69 64 20 49 4e 54 45 47 ontent'(id INTEG
|
||||
| 3760: 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 ER PRIMARY KEY,
|
||||
| 3776: 63 30 2c 20 63 31 2c 20 63 32 29 69 04 07 17 19 c0, c1, c2)i....
|
||||
| 3792: 19 01 81 2d 74 61 62 6c 65 74 31 5f 69 64 78 74 ...-tablet1_idxt
|
||||
| 3808: 31 5f 69 64 78 04 43 52 45 41 54 45 20 54 41 42 1_idx.CREATE TAB
|
||||
| 3824: 4c 45 20 27 74 31 5f 69 64 78 27 28 73 65 67 69 LE 't1_idx'(segi
|
||||
| 3840: 64 2c 20 74 65 72 6d 2c 20 70 67 6e 6f 2c 20 50 d, term, pgno, P
|
||||
| 3856: 52 49 4d 41 52 59 20 4b 45 59 28 73 65 67 69 64 RIMARY KEY(segid
|
||||
| 3872: 2c 20 74 65 72 6d 29 29 20 57 49 54 48 4f 55 54 , term)) WITHOUT
|
||||
| 3888: 20 52 4f 57 49 44 55 03 07 17 1b 1b 01 81 01 74 ROWIDU........t
|
||||
| 3904: 61 62 6c 65 74 31 5f 64 61 74 61 74 31 5f 64 61 ablet1_datat1_da
|
||||
| 3920: 74 61 03 43 52 45 41 54 45 20 54 41 42 4c 45 20 ta.CREATE TABLE
|
||||
| 3936: 27 74 31 5f 64 61 74 61 27 28 69 64 20 49 4e 54 't1_data'(id INT
|
||||
| 3952: 45 47 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59 EGER PRIMARY KEY
|
||||
| 3968: 2c 20 62 6c 6f 63 6b 20 42 4c 4f 42 29 38 02 06 , block BLOB)8..
|
||||
| 3984: 17 11 11 08 5f 74 61 62 6c 65 74 31 74 31 43 52 ...._tablet1t1CR
|
||||
| 4000: 45 41 54 45 20 56 49 52 54 55 41 4c 20 54 41 42 EATE VIRTUAL TAB
|
||||
| 4016: 4c 45 20 74 31 20 55 53 49 4e 47 20 66 74 73 35 LE t1 USING fts5
|
||||
| 4032: 28 61 2c 62 2c 63 29 00 00 00 00 00 00 00 00 00 (a,b,c).........
|
||||
| page 3 offset 8192
|
||||
| 0: 0d 00 00 00 03 0c 94 00 0f e6 0f ef 0c 94 00 00 ................
|
||||
| 3216: 00 00 00 00 86 4a 84 80 80 80 80 01 04 00 8d 18 .....J..........
|
||||
| 3232: 00 00 03 2b 02 30 30 01 02 06 01 02 06 01 02 06 ...+.00.........
|
||||
| 3248: 1f 02 03 01 02 03 01 02 03 01 08 32 30 31 36 30 ...........20160
|
||||
| 3264: 36 30 39 01 02 07 01 02 07 01 02 07 01 01 34 01 609...........4.
|
||||
| 3280: 02 05 01 02 05 01 02 05 01 01 35 01 02 04 01 02 ..........5.....
|
||||
| 3296: 04 01 02 04 02 07 30 30 30 30 30 30 30 1c 02 04 ......0000000...
|
||||
| 3312: 01 02 04 01 02 04 01 06 62 69 6e 61 72 79 03 06 ........binary..
|
||||
| 3328: 01 02 02 03 06 01 02 02 03 06 01 02 02 03 06 01 ................
|
||||
| 3344: 02 02 03 06 01 02 02 03 06 01 02 02 03 06 01 02 ................
|
||||
| 3360: 02 03 06 01 02 02 03 06 01 02 02 03 06 01 02 02 ................
|
||||
| 3376: 03 06 01 02 02 03 06 01 02 02 01 08 63 6f 6d 70 ............comp
|
||||
| 3392: 69 6c 65 72 01 02 02 01 02 02 01 02 02 01 06 64 iler...........d
|
||||
| 3408: 62 73 74 61 74 07 02 03 01 02 03 01 02 03 02 04 bstat...........
|
||||
| 3424: 65 62 75 67 04 02 02 01 02 02 01 02 02 01 06 65 ebug...........e
|
||||
| 3440: 6e 61 62 6c 65 07 02 02 01 02 02 01 02 02 01 02 nable...........
|
||||
| 3456: 02 01 02 02 01 02 02 01 02 02 01 02 02 01 02 02 ................
|
||||
| 3472: 01 02 02 01 02 02 01 02 02 01 02 02 01 02 02 01 ................
|
||||
| 3488: 02 02 01 02 02 01 02 02 01 02 02 01 02 02 01 02 ................
|
||||
| 3504: 02 01 02 02 02 08 78 74 65 6e 73 69 6f 6e 1f 02 ......xtension..
|
||||
| 3520: 04 01 02 04 01 02 04 01 04 66 74 73 34 0a 02 03 .........fts4...
|
||||
| 3536: 01 02 03 01 02 03 04 01 35 0d 02 03 01 02 03 01 ........5.......
|
||||
| 3552: 02 03 01 03 67 63 63 01 02 03 01 02 03 01 02 03 ....gcc.........
|
||||
| 3568: 02 06 65 6f 70 6f 6c 79 10 02 03 01 02 03 01 02 ..eopoly........
|
||||
| 3584: 03 01 05 6a 73 6f 6e 31 13 02 03 01 02 03 01 02 ...json1........
|
||||
| 3600: 03 01 04 6c 6f 61 64 1f 02 03 01 02 03 01 02 03 ...load.........
|
||||
| 3616: 01 03 6d 61 78 1c 02 02 01 02 02 01 02 02 02 05 ..max...........
|
||||
| 3632: 65 6d 6f 72 79 1c 02 03 01 02 03 01 02 03 04 04 emory...........
|
||||
| 3648: 73 79 73 35 16 02 03 01 02 02 03 01 03 01 06 6e sys5...........n
|
||||
| 3664: 6f 63 61 73 65 02 06 01 02 02 03 06 01 02 02 03 ocase...........
|
||||
| 3680: 06 01 02 02 03 06 01 02 02 03 06 01 02 02 03 06 ................
|
||||
| 3696: 01 02 02 03 06 01 02 02 03 06 01 02 02 03 06 01 ................
|
||||
| 3712: 02 02 03 06 01 02 02 03 06 01 02 02 03 06 01 02 ................
|
||||
| 3728: 02 01 04 6f 6d 69 74 1f 02 02 01 02 02 01 02 02 ...omit.........
|
||||
| 3744: 01 05 72 74 72 65 65 19 02 03 01 02 03 01 02 03 ..rtree.........
|
||||
| 3760: 04 02 69 6d 01 06 01 02 02 03 06 01 02 02 03 06 ..im............
|
||||
| 3776: 01 02 02 03 06 01 02 02 03 06 01 02 02 03 06 01 ................
|
||||
| 3792: 02 02 03 06 01 02 02 03 06 01 02 02 03 06 01 02 ................
|
||||
| 3808: 02 03 06 01 02 02 03 06 01 02 02 03 06 01 02 02 ................
|
||||
| 3824: 01 0a 74 68 72 65 61 64 73 61 66 65 03 57 34 56 ..threadsafe.W4V
|
||||
| 3840: 94 64 91 46 85 84 04 76 74 61 62 07 02 04 01 02 .d.F...vtab.....
|
||||
| 3856: 04 01 02 04 01 01 78 01 06 01 01 02 01 06 01 01 ......x.........
|
||||
| 3872: 02 01 06 01 01 02 01 06 01 01 02 01 06 01 10 02 ................
|
||||
| 3888: 01 06 01 01 02 01 06 01 01 02 01 06 01 01 02 01 ................
|
||||
| 3904: 06 01 01 02 01 06 01 01 02 01 06 01 01 02 01 06 ................
|
||||
| 3920: 01 01 02 01 06 01 01 02 01 06 01 01 02 01 06 01 ................
|
||||
| 3936: 01 02 01 06 01 01 10 01 06 01 01 02 01 06 01 01 ................
|
||||
| 3952: 02 01 06 01 01 02 01 06 01 01 02 01 06 01 01 02 ................
|
||||
| 3968: 01 06 01 01 02 01 06 01 01 02 01 06 01 01 02 01 ................
|
||||
| 3984: 06 01 01 02 01 06 01 01 02 01 06 01 01 02 01 06 ................
|
||||
| 4000: 01 01 02 01 06 01 01 02 01 06 01 01 02 01 06 01 ................
|
||||
| 4016: 01 02 01 06 01 01 02 01 06 01 01 02 01 06 01 01 ................
|
||||
| 4032: 02 01 06 01 01 02 01 06 01 01 02 04 15 13 0c 0c ................
|
||||
| 4048: 12 44 13 11 0f 47 13 0f 0c 0e 11 10 0f 0e 10 0f .D...G..........
|
||||
| 4064: 44 0f 10 40 15 0f 07 01 03 00 14 24 5a 24 24 0f D..@.......$Z$$.
|
||||
| 4080: 0a 03 00 24 00 00 00 00 01 01 01 00 01 01 01 01 ...$............
|
||||
| page 4 offset 12288
|
||||
| 0: 0a 00 00 00 01 0f fa 00 00 00 00 00 00 00 00 00 ................
|
||||
| 4080: 00 00 00 00 00 00 00 00 00 00 05 04 09 0c 01 02 ................
|
||||
| page 5 offset 16384
|
||||
| 0: 0d 00 00 00 24 0c 0a 00 0f d8 0f af 0f 86 0f 74 ....$..........t
|
||||
| 16: 0f 61 0f 4e 0f 2f 0f 0f 0e ef 0e d7 0e be 0e a5 .a.N./..........
|
||||
| 32: 0e 8d 0e 74 0e 5b 0e 40 0e 24 0e 08 0d ef 0d d5 ...t.[.@.$......
|
||||
| 48: 0d bb 0d a0 0d 84 0d 68 0d 4f 0d 35 0d 1b 0c fb .......h.O.5....
|
||||
| 64: 0c da 0c b9 0c 99 0c 00 00 00 00 00 00 00 00 00 ................
|
||||
| 3072: 00 00 00 00 00 00 00 00 00 00 18 24 05 00 25 0f ...........$..%.
|
||||
| 3088: 19 54 48 52 45 41 44 53 41 46 45 3d 30 58 42 49 .THREADSAFE=0XBI
|
||||
| 3104: 4e 41 52 59 18 23 05 00 25 0f 19 54 48 52 45 41 NARY.#..%..THREA
|
||||
| 3120: 44 53 41 46 45 3d 30 58 4e 4f 43 41 53 45 17 22 DSAFE=0XNOCASE..
|
||||
| 3136: 05 00 25 0f 17 54 48 52 45 41 44 53 31 46 45 3d ..%..THREADS1FE=
|
||||
| 3152: 30 58 52 64 52 49 4d 1f 21 05 00 33 0f 19 4f 4d 0XRdRIM.!..3..OM
|
||||
| 3168: 49 54 20 4c 4f 41 44 20 45 58 54 45 4e 53 49 4f IT LOAD EXTENSIO
|
||||
| 3184: 4e 58 42 49 4e 41 52 59 1f 20 05 00 33 0f 19 4f NXBINARY. ..3..O
|
||||
| 3200: 4d 49 54 20 4c 4f 41 44 20 45 58 54 45 4e 53 49 MIT LOAD EXTENSI
|
||||
| 3216: 4f 4e 58 4e 4f 43 41 53 45 1e 1f 05 00 33 0f 17 ONXNOCASE....3..
|
||||
| 3232: 4f 4d 49 54 20 4c 4f 41 44 20 45 58 54 45 4e 53 OMIT LOAD EXTENS
|
||||
| 3248: 49 4f 4e 58 52 54 52 49 4d 1f 1e 05 00 33 0f 19 IONXRTRIM....3..
|
||||
| 3264: 4d 41 58 20 4d 45 4d 4f 52 59 3d 35 30 30 30 30 MAX MEMORY=50000
|
||||
| 3280: 30 30 30 58 42 49 4e 41 52 59 1f 1d 05 00 33 0f 000XBINARY....3.
|
||||
| 3296: 19 4d 41 58 20 4d 45 4d 4f 52 59 3d 35 30 30 30 .MAX MEMORY=5000
|
||||
| 3312: 30 30 30 30 58 4e 4f 43 41 53 45 1e 1c 05 00 33 0000XNOCASE....3
|
||||
| 3328: 0f 17 4d 41 58 20 4d 45 4d 4f 52 59 3d 35 30 30 ..MAX MEMORY=500
|
||||
| 3344: 30 30 30 30 30 58 52 54 52 49 4d 18 1b 05 00 25 00000XRTRIM....%
|
||||
| 3360: 0f 19 45 4e 41 42 4c 45 20 52 54 52 45 45 58 42 ..ENABLE RTREEXB
|
||||
| 3376: 49 4e 41 52 59 18 1a 05 00 25 0f 19 45 4e 41 42 INARY....%..ENAB
|
||||
| 3392: 4c 45 20 52 54 52 45 45 58 4e 4f 43 41 53 45 17 LE RTREEXNOCASE.
|
||||
| 3408: 19 05 00 25 0f 17 45 4e 41 42 4c 45 20 52 54 52 ...%..ENABLE RTR
|
||||
| 3424: 45 45 58 52 54 52 49 4d 1a 18 05 00 29 0f 19 45 EEXRTRIM....)..E
|
||||
| 3440: 4e 41 42 4b 45 20 4d 45 4d 53 59 53 35 58 42 49 NABKE MEMSYS5XBI
|
||||
| 3456: 4e 41 52 59 1a 17 05 00 29 0f 19 45 4e 41 42 4c NARY....)..ENABL
|
||||
| 3472: 42 60 2d 45 4d 53 59 53 35 58 4e 4f 43 41 53 45 B`-EMSYS5XNOCASE
|
||||
| 3488: 19 16 05 00 29 0f 17 45 4e 41 42 4c 45 20 4d 46 ....)..ENABLE MF
|
||||
| 3504: 4d 53 59 53 35 58 52 54 52 49 4d 18 15 05 00 25 MSYS5XRTRIM....%
|
||||
| 3520: 0f 19 45 4e 41 42 4c 45 20 4a 53 4f 4e 31 58 42 ..ENABLE JSON1XB
|
||||
| 3536: 49 4e 41 52 59 18 14 05 00 25 0f 19 45 4e 41 42 INARY....%..ENAB
|
||||
| 3552: 4c 45 20 4a 53 4f 4e 31 58 4e 4f 43 41 53 45 17 LE JSON1XNOCASE.
|
||||
| 3568: 13 05 00 25 0f 17 45 4e 41 42 4c 45 20 4a 53 4f ...%..ENABLE JSO
|
||||
| 3584: 4e 31 58 52 54 52 49 4d 1a 12 05 00 29 0f 19 45 N1XRTRIM....)..E
|
||||
| 3600: 42 4c 45 20 47 45 4f 50 4f 4c 59 58 42 49 4e 41 BLE GEOPOLYXBINA
|
||||
| 3616: 52 59 1a 11 05 00 39 0f 19 45 4e 41 42 4c 45 2e RY....9..ENABLE.
|
||||
| 3632: 41 40 47 45 4f 50 4f 4c 59 58 4e 4f 43 41 53 40 A@GEOPOLYXNOCAS@
|
||||
| 3648: 4f 4c 59 58 55 09 10 05 00 29 0f 17 45 4e 41 42 OLYXU....)..ENAB
|
||||
| 3664: 4c 45 20 47 45 4f 52 54 52 49 4d 17 0f 05 00 23 LE GEORTRIM....#
|
||||
| 3680: 0f 19 45 4e 41 42 4c 45 20 46 54 53 35 58 42 49 ..ENABLE FTS5XBI
|
||||
| 3696: 4e 41 52 59 17 0e 05 00 23 0f 19 45 4e 41 42 4c NARY....#..ENABL
|
||||
| 3712: 45 20 46 54 53 35 58 4e 4f 43 41 53 45 16 0d 05 E FTS5XNOCASE...
|
||||
| 3728: 00 23 0f 17 45 4e 41 42 4c 45 20 46 54 53 35 58 .#..ENABLE FTS5X
|
||||
| 3744: 52 54 52 49 4d 17 0c 05 00 23 0f 19 45 4e 41 42 RTRIM....#..ENAB
|
||||
| 3760: 4c 45 20 46 54 53 34 58 42 49 4e 41 52 59 17 0b LE FTS4XBINARY..
|
||||
| 3776: 05 00 23 0f 19 45 4e 41 42 4c 45 20 46 54 53 34 ..#..ENABLE FTS4
|
||||
| 3792: 58 4e 4f 43 41 53 45 16 0a 05 00 23 0f 17 45 4e XNOCASE....#..EN
|
||||
| 3808: 41 42 4c 45 20 46 54 53 34 58 52 54 52 49 4d 1e ABLE FTS4XRTRIM.
|
||||
| 3824: 09 05 00 31 0f 19 45 4e 41 42 4c 45 20 44 42 53 ...1..ENABLE DBS
|
||||
| 3840: 54 41 54 20 56 54 41 42 58 42 49 4e 41 52 59 1e TAT VTABXBINARY.
|
||||
| 3856: 08 05 00 31 0f 19 45 4e 41 42 4c 45 20 44 42 53 ...1..ENABLE DBS
|
||||
| 3872: 54 41 54 20 56 54 24 15 48 4e 4f 43 41 53 45 1d TAT VT$.HNOCASE.
|
||||
| 3888: 07 05 00 31 0f 17 45 4e 41 42 4c 45 20 44 42 53 ...1..ENABLE DBS
|
||||
| 3904: 54 41 54 20 56 54 41 42 58 52 54 52 49 4d 11 06 TAT VTABXRTRIM..
|
||||
| 3920: 05 00 17 0f 19 44 45 42 55 47 58 42 49 4e 41 52 .....DEBUGXBINAR
|
||||
| 3936: 59 11 05 05 00 17 0f 19 44 45 42 55 47 58 4e 4f Y.......DEBUGXNO
|
||||
| 3952: 43 41 53 45 10 04 05 00 17 0f 17 44 45 42 55 47 CASE.......DEBUG
|
||||
| 3968: 58 52 54 52 49 4d 27 03 05 00 43 0f 19 43 4f 4d XRTRIM'...C..COM
|
||||
| 3984: 50 49 4c 45 52 3d 67 63 63 2d 35 2e 34 2e 30 20 PILER=gcc-5.4.0
|
||||
| 4000: 32 30 31 36 30 36 30 39 58 42 49 4e 41 52 59 27 20160609XBINARY'
|
||||
| 4016: 02 05 00 43 0f 19 43 4f 4d 50 49 4c 45 52 3d 67 ...C..COMPILER=g
|
||||
| 4032: 63 63 2d 35 2e 34 2e 30 20 32 30 31 36 30 36 30 cc-5.4.0 2016060
|
||||
| 4048: 39 58 4e 4f 43 41 53 45 26 01 05 00 43 0f 17 43 9XNOCASE&...C..C
|
||||
| 4064: 4f 4d 50 49 4c 45 52 3d 67 63 63 2d 35 2e 34 2e OMPILER=gcc-5.4.
|
||||
| 4080: 30 20 32 30 31 36 30 36 30 39 58 52 54 52 49 4d 0 20160609XRTRIM
|
||||
| page 6 offset 20480
|
||||
| 0: 0d 00 00 00 24 0e e0 00 0f f8 0f f0 0f e8 0f e0 ....$...........
|
||||
| 16: 0f d8 0f d0 0f c8 0f c0 0f b8 0f b0 0f a8 0f a0 ................
|
||||
| 32: 1f 98 0f 90 0f 88 0f 80 0f 78 0f 70 0f 68 0f 60 .........x.p.h.`
|
||||
| 48: 0f 58 0f 50 0f 48 0f 40 0f 38 0f 30 0f 28 0f 20 .X.P.H.@.8.0.(.
|
||||
| 64: 0f 18 0f 10 0f 08 0f 00 0e f8 0e f0 0e e8 00 00 ................
|
||||
| 3808: 06 24 03 00 12 02 01 01 06 23 03 00 12 02 01 01 .$.......#......
|
||||
| 3824: 06 22 03 00 12 02 01 01 06 21 03 00 12 03 01 01 .........!......
|
||||
| 3840: 06 20 03 00 12 03 01 01 06 1f 03 00 12 03 01 01 . ..............
|
||||
| 3856: 06 1e 03 00 12 03 01 01 06 1d 03 00 12 03 01 01 ................
|
||||
| 3872: 06 1c 03 00 12 03 01 01 06 1b 03 00 12 02 01 01 ................
|
||||
| 3888: 06 1a 03 00 12 02 01 01 06 19 03 00 12 02 01 01 ................
|
||||
| 3904: 06 18 03 00 12 02 01 01 06 17 03 00 12 02 01 01 ................
|
||||
| 3920: 06 15 f3 00 12 02 01 01 06 15 03 00 12 02 01 01 ................
|
||||
| 3936: 06 14 03 00 12 02 01 01 06 13 03 00 12 02 01 01 ................
|
||||
| 3952: 06 12 03 00 12 02 01 01 06 11 03 00 12 02 01 01 ................
|
||||
| 3968: 06 10 03 00 12 02 01 01 06 0f 03 00 12 02 01 01 ................
|
||||
| 3984: 06 0e 03 00 12 02 01 01 06 0d 03 00 12 02 01 01 ................
|
||||
| 4000: 06 0c 03 00 12 02 01 01 06 0b 03 00 12 02 01 01 ................
|
||||
| 4016: 06 0a 03 00 12 02 01 01 06 09 03 00 12 03 01 01 ................
|
||||
| 4032: 06 08 03 00 12 03 01 01 06 07 03 00 12 03 01 01 ................
|
||||
| 4048: 06 06 03 00 12 01 01 01 06 05 03 00 12 01 01 01 ................
|
||||
| 4064: 06 04 03 00 12 01 01 01 06 03 03 00 12 06 01 01 ................
|
||||
| 4080: 06 02 03 00 12 06 01 01 06 01 03 00 12 06 01 01 ................
|
||||
| page 7 offset 24576
|
||||
| 0: 0a 00 00 00 01 0f f4 00 0f f4 00 00 00 00 00 00 ................
|
||||
| 4080: 00 00 00 00 0b 03 1b 01 76 65 72 73 69 6f 6e 04 ........version.
|
||||
| page 8 offset 28672
|
||||
| 0: 0d 00 00 00 03 0f d6 00 0f f4 0f 00 00 00 00 00 ................
|
||||
| 4048: 00 00 00 00 00 00 11 03 02 2b 69 6e 74 65 67 72 .........+integr
|
||||
| 4064: 69 74 79 2d 63 68 65 63 6b 09 02 02 1b 72 65 62 ity-check....reb
|
||||
| 4080: 75 69 6c 64 0a 01 02 1d 6f 70 74 69 00 00 00 00 uild....opti....
|
||||
| end crash-b06f016068bcea.db
|
||||
.testctrl prng_seed 1 db
|
||||
.testctrl internal_functions
|
||||
.testctrl json_selfcheck on
|
||||
}]} {}
|
||||
|
||||
do_execsql_test 10.1 {
|
||||
UPDATE t1 SET b=quote(zeroblob(current_date)) WHERE t1 MATCH 't*';
|
||||
}
|
||||
|
||||
do_catchsql_test 10.2 {
|
||||
BEGIN;
|
||||
INSERT INTO t1(t1,rank) VALUES('secure-delete',1);
|
||||
REPLACE INTO t1(b,a,rowid) VALUES(1,2,3);
|
||||
} {0 {}}
|
||||
|
||||
do_catchsql_test 10.3 {
|
||||
COMMIT
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
do_catchsql_test 10.4 {
|
||||
REPLACE INTO t1(b,a,rowid) VALUES(1,2,3);
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_test 11.0 {
|
||||
sqlite3 db {}
|
||||
db deserialize [decode_hexdb {
|
||||
.open --hexdb
|
||||
| size 32768 pagesize 4096 filename crash-3d05232c78871b.db
|
||||
| page 1 offset 0
|
||||
| 0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00 SQLite format 3.
|
||||
| 16: 10 00 01 01 00 40 20 20 00 00 00 00 00 00 00 08 .....@ ........
|
||||
| 32: 00 00 00 02 00 00 00 01 00 00 00 09 00 00 00 04 ................
|
||||
| 96: 00 00 00 00 0d 0f c7 00 07 0d 92 00 0f 8d 0f 36 ...............6
|
||||
| 112: 0e cb 0e 6b 0e 0e 0d b6 0d 92 0d 92 00 00 00 00 ...k............
|
||||
| 3472: 00 00 22 08 06 17 11 11 01 31 74 61 62 6c 65 74 .........1tablet
|
||||
| 3488: 32 74 32 08 43 52 45 41 54 45 20 54 41 42 4c 45 2t2.CREATE TABLE
|
||||
| 3504: 20 74 32 28 78 29 56 07 06 17 1f 1f 01 7d 74 61 t2(x)V.......ta
|
||||
| 3520: 62 6c 65 74 31 5f 63 6f 6e 66 69 67 74 31 5f 63 blet1_configt1_c
|
||||
| 3536: 6f 6e 66 69 67 07 43 52 45 41 54 45 20 54 41 42 onfig.CREATE TAB
|
||||
| 3552: 4c 45 20 27 74 31 5f 63 6f 6e 66 69 67 27 28 6b LE 't1_config'(k
|
||||
| 3568: 20 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 76 29 PRIMARY KEY, v)
|
||||
| 3584: 20 57 49 54 48 4f 55 54 20 52 4f 57 49 44 5b 06 WITHOUT ROWID[.
|
||||
| 3600: 07 17 21 21 01 81 01 74 61 62 6c 65 74 31 5f 64 ..!!...tablet1_d
|
||||
| 3616: 6f 63 73 69 7a 65 74 31 5f 64 6f 63 73 69 7a 65 ocsizet1_docsize
|
||||
| 3632: 06 43 52 45 41 54 45 20 54 41 42 4c 45 20 27 74 .CREATE TABLE 't
|
||||
| 3648: 31 5f 64 6f 63 73 69 7a 65 27 28 69 64 20 49 4e 1_docsize'(id IN
|
||||
| 3664: 54 45 47 45 52 20 50 52 49 4d 41 52 59 20 4b 45 TEGER PRIMARY KE
|
||||
| 3680: 59 2c 20 73 7a 20 42 4c 4f 42 29 5e 05 07 17 21 Y, sz BLOB)^...!
|
||||
| 3696: 21 01 81 07 74 61 62 6c 65 74 31 5f 63 6f 6e 74 !...tablet1_cont
|
||||
| 3712: 65 6e 74 74 31 5f 63 6f 6e 74 65 6e 74 05 43 52 entt1_content.CR
|
||||
| 3728: 45 41 54 45 20 54 41 42 4c 45 20 27 74 31 5f 63 EATE TABLE 't1_c
|
||||
| 3744: 6f 6e 74 65 6e 74 27 28 69 64 20 49 4e 54 45 47 ontent'(id INTEG
|
||||
| 3760: 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 ER PRIMARY KEY,
|
||||
| 3776: 63 30 2c 20 63 31 2c 20 63 32 29 69 04 07 17 19 c0, c1, c2)i....
|
||||
| 3792: 19 01 81 2d 74 61 62 6c 65 74 31 5f 69 64 78 74 ...-tablet1_idxt
|
||||
| 3808: 31 5f 69 64 78 04 43 52 45 41 54 45 20 54 41 42 1_idx.CREATE TAB
|
||||
| 3824: 4c 45 20 27 74 31 5f 69 64 78 27 28 73 65 67 69 LE 't1_idx'(segi
|
||||
| 3840: 64 2c 20 74 65 72 6d 2c 20 70 67 6e 6f 2c 20 50 d, term, pgno, P
|
||||
| 3856: 52 49 4d 41 52 59 20 4b 45 59 28 73 65 67 69 64 RIMARY KEY(segid
|
||||
| 3872: 2c 20 74 65 72 6d 29 29 20 57 49 54 48 4f 55 54 , term)) WITHOUT
|
||||
| 3888: 20 52 4f 57 49 44 55 03 07 17 1b 1b 01 81 01 74 ROWIDU........t
|
||||
| 3904: 61 62 6c 65 74 31 5f 64 61 74 61 74 31 5f 64 61 ablet1_datat1_da
|
||||
| 3920: 74 61 03 43 52 45 41 54 45 20 54 41 42 4c 45 20 ta.CREATE TABLE
|
||||
| 3936: 27 74 31 5f 64 61 74 61 27 28 69 64 20 49 4e 54 't1_data'(id INT
|
||||
| 3952: 45 47 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59 EGER PRIMARY KEY
|
||||
| 3968: 2c 20 62 6c 6f 63 6b 20 42 4c 4f 42 29 38 02 06 , block BLOB)8..
|
||||
| 3984: 17 11 11 08 5f 74 61 62 6c 65 74 31 74 31 43 52 ...._tablet1t1CR
|
||||
| 4000: 45 41 54 45 20 56 49 52 54 55 41 4c 20 54 41 42 EATE VIRTUAL TAB
|
||||
| 4016: 4c 45 20 74 31 20 55 53 49 4e 47 20 66 74 73 35 LE t1 USING fts5
|
||||
| 4032: 28 61 2c 62 2c 63 29 00 00 00 00 00 00 00 00 00 (a,b,c).........
|
||||
| page 3 offset 8192
|
||||
| 0: 0d 00 00 00 03 0c 94 00 0f e6 0f ef 0c 94 00 00 ................
|
||||
| 3216: 00 00 00 00 86 4a 84 80 80 80 80 01 04 00 8d 18 .....J..........
|
||||
| 3232: 00 00 03 2b 02 30 30 01 02 06 01 02 06 01 02 06 ...+.00.........
|
||||
| 3248: 1f 02 03 01 02 03 01 02 03 01 08 32 30 31 36 30 ...........20160
|
||||
| 3264: 36 30 39 01 02 07 01 02 07 01 02 07 01 01 34 01 609...........4.
|
||||
| 3280: 02 05 01 02 05 01 02 05 01 01 35 01 02 04 01 02 ..........5.....
|
||||
| 3296: 04 01 02 04 02 07 30 30 30 30 30 30 30 1c 02 04 ......0000000...
|
||||
| 3312: 01 02 04 01 02 04 01 06 62 69 6e 61 72 79 03 06 ........binary..
|
||||
| 3328: 01 02 02 03 06 01 02 02 03 06 01 02 02 03 06 01 ................
|
||||
| 3344: 02 02 03 06 01 02 02 03 06 01 02 02 03 06 01 02 ................
|
||||
| 3360: 02 03 06 01 02 02 03 06 01 02 02 03 06 01 02 02 ................
|
||||
| 3376: 03 06 01 02 02 03 06 01 02 02 01 08 63 6f 6d 70 ............comp
|
||||
| 3392: 69 6c 65 72 01 02 02 01 02 02 01 02 02 01 06 64 iler...........d
|
||||
| 3408: 62 73 74 61 74 07 02 03 01 02 03 01 02 03 02 04 bstat...........
|
||||
| 3424: 65 62 75 67 04 02 02 01 02 02 01 02 02 01 06 65 ebug...........e
|
||||
| 3440: 6e 61 62 6c 65 07 02 02 01 02 02 01 02 02 01 02 nable...........
|
||||
| 3456: 02 01 02 02 01 02 02 01 02 02 01 02 02 01 02 02 ................
|
||||
| 3472: 01 02 02 01 02 02 01 02 02 01 02 02 01 02 02 01 ................
|
||||
| 3488: 02 02 01 02 02 01 02 02 01 02 02 01 02 02 01 02 ................
|
||||
| 3504: 02 01 02 02 02 08 78 74 65 6e 73 69 6f 6e 1f 02 ......xtension..
|
||||
| 3520: 04 01 02 04 01 02 04 01 04 66 74 73 34 0a 02 03 .........fts4...
|
||||
| 3536: 01 02 03 01 02 03 04 01 35 0d 02 03 01 02 03 01 ........5.......
|
||||
| 3552: 02 03 01 03 67 63 63 01 02 03 01 02 03 01 02 03 ....gcc.........
|
||||
| 3568: 02 06 65 6f 70 6f 6c 79 10 02 03 01 02 03 01 02 ..eopoly........
|
||||
| 3584: 03 01 05 6a 73 6f 6e 31 13 02 03 01 02 03 01 02 ...json1........
|
||||
| 3600: 03 01 04 6c 6f 61 64 1f 02 03 01 02 03 01 02 03 ...load.........
|
||||
| 3616: 01 03 6d 61 78 1c 02 02 01 02 02 01 02 02 02 05 ..max...........
|
||||
| 3632: 65 6d 6f 72 79 1c 02 03 01 02 03 01 02 03 04 04 emory...........
|
||||
| 3648: 73 79 73 35 16 02 03 01 02 02 03 01 03 01 06 6e sys5...........n
|
||||
| 3664: 6f 63 61 73 65 02 06 01 02 02 03 06 01 02 02 03 ocase...........
|
||||
| 3680: 06 01 02 02 03 06 01 02 02 03 06 01 02 02 03 06 ................
|
||||
| 3696: 01 02 02 03 06 01 02 02 03 06 01 02 02 03 06 01 ................
|
||||
| 3712: 02 02 03 06 01 02 02 03 06 01 02 02 03 06 01 02 ................
|
||||
| 3728: 02 01 04 6f 6d 69 74 1f 02 02 01 02 02 01 02 02 ...omit.........
|
||||
| 3744: 01 05 72 74 72 65 65 19 02 03 01 02 03 01 02 03 ..rtree.........
|
||||
| 3760: 04 02 69 6d 01 06 01 02 02 03 06 01 02 02 03 06 ..im............
|
||||
| 3776: 01 02 02 03 06 01 02 02 03 06 01 02 02 03 06 01 ................
|
||||
| 3792: 02 02 03 06 01 02 02 03 06 01 02 02 03 06 01 02 ................
|
||||
| 3808: 02 03 06 01 02 02 03 06 01 02 02 03 06 01 02 02 ................
|
||||
| 3824: 01 0a 74 68 72 65 61 64 73 61 66 65 03 57 34 56 ..threadsafe.W4V
|
||||
| 3840: 94 64 91 46 85 84 04 76 74 61 62 07 02 04 01 02 .d.F...vtab.....
|
||||
| 3856: 04 01 02 04 01 01 78 01 06 01 01 02 01 06 01 01 ......x.........
|
||||
| 3872: 02 01 06 01 01 02 01 06 01 01 02 01 06 01 10 02 ................
|
||||
| 3888: 01 06 01 01 02 01 06 01 01 02 01 06 01 01 02 01 ................
|
||||
| 3904: 06 01 01 02 01 06 01 01 02 01 06 01 01 02 01 06 ................
|
||||
| 3920: 01 01 02 01 06 01 01 02 01 06 01 01 02 01 06 01 ................
|
||||
| 3936: 01 02 01 06 01 01 10 01 06 01 01 02 01 06 01 01 ................
|
||||
| 3952: 02 01 06 01 01 02 01 06 01 01 02 01 06 01 01 02 ................
|
||||
| 3968: 01 06 01 01 02 01 06 01 01 02 01 06 01 01 02 01 ................
|
||||
| 3984: 06 01 01 02 01 06 01 01 02 01 06 01 01 02 01 06 ................
|
||||
| 4000: 01 01 02 01 06 01 01 02 01 06 01 01 02 01 06 01 ................
|
||||
| 4016: 01 02 01 06 01 01 02 01 06 01 01 02 01 06 01 01 ................
|
||||
| 4032: 02 01 06 01 01 02 01 06 01 01 02 04 15 13 0c 0c ................
|
||||
| 4048: 12 44 13 11 0f 47 13 0f 0c 0e 11 10 0f 0e 10 0f .D...G..........
|
||||
| 4064: 44 0f 10 40 15 0f 07 01 03 00 14 24 5a 24 24 0f D..@.......$Z$$.
|
||||
| 4080: 0a 03 00 24 00 00 00 00 01 01 01 00 01 01 01 01 ...$............
|
||||
| page 4 offset 12288
|
||||
| 0: 0a 00 00 00 01 0f fa 00 00 00 00 00 00 00 00 00 ................
|
||||
| 4080: 00 00 00 00 00 00 00 00 00 00 05 04 09 0c 01 02 ................
|
||||
| page 5 offset 16384
|
||||
| 0: 0d 00 00 00 24 0c 0a 00 0f d8 0f af 0f 86 0f 74 ....$..........t
|
||||
| 16: 0f 61 0f 4e 0f 2f 0f 0f 0e ef 0e d7 0e be 0e a5 .a.N./..........
|
||||
| 32: 0e 8d 0e 74 0e 5b 0e 40 0e 24 0e 08 0d ef 0d d5 ...t.[.@.$......
|
||||
| 48: 0d bb 0d a0 0d 84 0d 68 0d 4f 0d 35 0d 1b 0c fb .......h.O.5....
|
||||
| 64: 0c da 0c b9 0c 99 0c 00 00 00 00 00 00 00 00 00 ................
|
||||
| 3072: 00 00 00 00 00 00 00 00 00 00 18 24 05 00 25 0f ...........$..%.
|
||||
| 3088: 19 54 48 52 45 41 44 53 41 46 45 3d 30 58 42 49 .THREADSAFE=0XBI
|
||||
| 3104: 4e 41 52 59 18 23 05 00 25 0f 19 54 48 52 45 41 NARY.#..%..THREA
|
||||
| 3120: 44 53 41 46 45 3d 30 58 4e 4f 43 41 53 45 17 22 DSAFE=0XNOCASE..
|
||||
| 3136: 05 00 25 0f 17 54 48 52 45 41 44 53 31 46 45 3d ..%..THREADS1FE=
|
||||
| 3152: 30 58 52 64 52 49 4d 1f 21 05 00 33 0f 19 4f 4d 0XRdRIM.!..3..OM
|
||||
| 3168: 49 54 20 4c 4f 41 44 20 45 58 54 45 4e 53 49 4f IT LOAD EXTENSIO
|
||||
| 3184: 4e 58 42 49 4e 41 52 59 1f 20 05 00 33 0f 19 4f NXBINARY. ..3..O
|
||||
| 3200: 4d 49 54 20 4c 4f 41 44 20 45 58 54 45 4e 53 49 MIT LOAD EXTENSI
|
||||
| 3216: 4f 4e 58 4e 4f 43 41 53 45 1e 1f 05 00 33 0f 17 ONXNOCASE....3..
|
||||
| 3232: 4f 4d 49 54 20 4c 4f 41 44 20 45 58 54 45 4e 53 OMIT LOAD EXTENS
|
||||
| 3248: 49 4f 4e 58 52 54 52 49 4d 1f 1e 05 00 33 0f 19 IONXRTRIM....3..
|
||||
| 3264: 4d 41 58 20 4d 45 4d 4f 52 59 3d 35 30 30 30 30 MAX MEMORY=50000
|
||||
| 3280: 30 30 30 58 42 49 4e 41 52 59 1f 1d 05 00 33 0f 000XBINARY....3.
|
||||
| 3296: 19 4d 41 58 20 4d 45 4d 4f 52 59 3d 35 30 30 30 .MAX MEMORY=5000
|
||||
| 3312: 30 30 30 30 58 4e 4f 43 41 53 45 1e 1c 05 00 33 0000XNOCASE....3
|
||||
| 3328: 0f 17 4d 41 58 20 4d 45 4d 4f 52 59 3d 35 30 30 ..MAX MEMORY=500
|
||||
| 3344: 30 30 30 30 30 58 52 54 52 49 4d 18 1b 05 00 25 00000XRTRIM....%
|
||||
| 3360: 0f 19 45 4e 41 42 4c 45 20 52 54 52 45 45 58 42 ..ENABLE RTREEXB
|
||||
| 3376: 49 4e 41 52 59 18 1a 05 00 25 0f 19 45 4e 41 42 INARY....%..ENAB
|
||||
| 3392: 4c 45 20 52 54 52 45 45 58 4e 4f 43 41 53 45 17 LE RTREEXNOCASE.
|
||||
| 3408: 19 05 00 25 0f 17 45 4e 41 42 4c 45 20 52 54 52 ...%..ENABLE RTR
|
||||
| 3424: 45 45 58 52 54 52 49 4d 1a 18 05 00 29 0f 19 45 EEXRTRIM....)..E
|
||||
| 3440: 4e 41 42 4b 45 20 4d 45 4d 53 59 53 35 58 42 49 NABKE MEMSYS5XBI
|
||||
| 3456: 4e 41 52 59 1a 17 05 00 29 0f 19 45 4e 41 42 4c NARY....)..ENABL
|
||||
| 3472: 42 60 2d 45 4d 53 59 53 35 58 4e 4f 43 41 53 45 B`-EMSYS5XNOCASE
|
||||
| 3488: 19 16 05 00 29 0f 17 45 4e 41 42 4c 45 20 4d 46 ....)..ENABLE MF
|
||||
| 3504: 4d 53 59 53 35 58 52 54 52 49 4d 18 15 05 00 25 MSYS5XRTRIM....%
|
||||
| 3520: 0f 19 45 4e 41 42 4c 45 20 4a 53 4f 4e 31 58 42 ..ENABLE JSON1XB
|
||||
| 3536: 49 4e 41 52 59 18 14 05 00 25 0f 19 45 4e 41 42 INARY....%..ENAB
|
||||
| 3552: 4c 45 20 4a 53 4f 4e 31 58 4e 4f 43 41 53 45 17 LE JSON1XNOCASE.
|
||||
| 3568: 13 05 00 25 0f 17 45 4e 41 42 4c 45 20 4a 53 4f ...%..ENABLE JSO
|
||||
| 3584: 4e 31 58 52 54 52 49 4d 1a 12 05 00 29 0f 19 45 N1XRTRIM....)..E
|
||||
| 3600: 42 4c 45 20 47 45 4f 50 4f 4c 59 58 42 49 4e 41 BLE GEOPOLYXBINA
|
||||
| 3616: 52 59 1a 11 05 00 39 0f 19 45 4e 41 42 4c 45 2e RY....9..ENABLE.
|
||||
| 3632: 41 40 47 45 4f 50 4f 4c 59 58 4e 4f 43 41 53 40 A@GEOPOLYXNOCAS@
|
||||
| 3648: 4f 4c 59 58 55 09 10 05 00 29 0f 17 45 4e 41 42 OLYXU....)..ENAB
|
||||
| 3664: 4c 45 20 47 45 4f 52 54 52 49 4d 17 0f 05 00 23 LE GEORTRIM....#
|
||||
| 3680: 0f 19 45 4e 41 42 4c 45 20 46 54 53 35 58 42 49 ..ENABLE FTS5XBI
|
||||
| 3696: 4e 41 52 59 17 0e 05 00 23 0f 19 45 4e 41 42 4c NARY....#..ENABL
|
||||
| 3712: 45 20 46 54 53 35 58 4e 4f 43 41 53 45 16 0d 05 E FTS5XNOCASE...
|
||||
| 3728: 00 23 0f 17 45 4e 41 42 4c 45 20 46 54 53 35 58 .#..ENABLE FTS5X
|
||||
| 3744: 52 54 52 49 4d 17 0c 05 00 23 0f 19 45 4e 41 42 RTRIM....#..ENAB
|
||||
| 3760: 4c 45 20 46 54 53 34 58 42 49 4e 41 52 59 17 0b LE FTS4XBINARY..
|
||||
| 3776: 05 00 23 0f 19 45 4e 41 42 4c 45 20 46 54 53 34 ..#..ENABLE FTS4
|
||||
| 3792: 58 4e 4f 43 41 53 45 16 0a 05 00 23 0f 17 45 4e XNOCASE....#..EN
|
||||
| 3808: 41 42 4c 45 20 46 54 53 34 58 52 54 52 49 4d 1e ABLE FTS4XRTRIM.
|
||||
| 3824: 09 05 00 31 0f 19 45 4e 41 42 4c 45 20 44 42 53 ...1..ENABLE DBS
|
||||
| 3840: 54 41 54 20 56 54 41 42 58 42 49 4e 41 52 59 1e TAT VTABXBINARY.
|
||||
| 3856: 08 05 00 31 0f 19 45 4e 41 42 4c 45 20 44 42 53 ...1..ENABLE DBS
|
||||
| 3872: 54 41 54 20 56 54 24 15 48 4e 4f 43 41 53 45 1d TAT VT$.HNOCASE.
|
||||
| 3888: 07 05 00 31 0f 17 45 4e 41 42 4c 45 20 44 42 53 ...1..ENABLE DBS
|
||||
| 3904: 54 41 54 20 56 54 41 42 58 52 54 52 49 4d 11 06 TAT VTABXRTRIM..
|
||||
| 3920: 05 00 17 0f 19 44 45 42 55 47 58 42 49 4e 41 52 .....DEBUGXBINAR
|
||||
| 3936: 59 11 05 05 00 17 0f 19 44 45 42 55 47 58 4e 4f Y.......DEBUGXNO
|
||||
| 3952: 43 41 53 45 10 04 05 00 17 0f 17 44 45 42 55 47 CASE.......DEBUG
|
||||
| 3968: 58 52 54 52 49 4d 27 03 05 00 43 0f 19 43 4f 4d XRTRIM'...C..COM
|
||||
| 3984: 50 49 4c 45 52 3d 67 63 63 2d 35 2e 34 2e 30 20 PILER=gcc-5.4.0
|
||||
| 4000: 32 30 31 36 30 36 30 39 58 42 49 4e 41 52 59 27 20160609XBINARY'
|
||||
| 4016: 02 05 00 43 0f 19 43 4f 4d 50 49 4c 45 52 3d 67 ...C..COMPILER=g
|
||||
| 4032: 63 63 2d 35 2e 34 2e 30 20 32 30 31 36 30 36 30 cc-5.4.0 2016060
|
||||
| 4048: 39 58 4e 4f 43 41 53 45 26 01 05 00 43 0f 17 43 9XNOCASE&...C..C
|
||||
| 4064: 4f 4d 50 49 4c 45 52 3d 67 63 63 2d 35 2e 34 2e OMPILER=gcc-5.4.
|
||||
| 4080: 30 20 32 30 31 36 30 36 30 39 58 52 54 52 49 4d 0 20160609XRTRIM
|
||||
| page 6 offset 20480
|
||||
| 0: 0d 00 00 00 24 0e e0 00 0f f8 0f f0 0f e8 0f e0 ....$...........
|
||||
| 16: 0f d8 0f d0 0f c8 0f c0 0f b8 0f b0 0f a8 0f a0 ................
|
||||
| 32: 1f 98 0f 90 0f 88 0f 80 0f 78 0f 70 0f 68 0f 60 .........x.p.h.`
|
||||
| 48: 0f 58 0f 50 0f 48 0f 40 0f 38 0f 30 0f 28 0f 20 .X.P.H.@.8.0.(.
|
||||
| 64: 0f 18 0f 10 0f 08 0f 00 0e f8 0e f0 0e e8 00 00 ................
|
||||
| 3808: 06 24 03 00 12 02 01 01 06 23 03 00 12 02 01 01 .$.......#......
|
||||
| 3824: 06 22 03 00 12 02 01 01 06 21 03 00 12 03 01 01 .........!......
|
||||
| 3840: 06 20 03 00 12 03 01 01 06 1f 03 00 12 03 01 01 . ..............
|
||||
| 3856: 06 1e 03 00 12 03 01 01 06 1d 03 00 12 03 01 01 ................
|
||||
| 3872: 06 1c 03 00 12 03 01 01 06 1b 03 00 12 02 01 01 ................
|
||||
| 3888: 06 1a 03 00 12 02 01 01 06 19 03 00 12 02 01 01 ................
|
||||
| 3904: 06 18 03 00 12 02 01 01 06 17 03 00 12 02 01 01 ................
|
||||
| 3920: 06 15 f3 00 12 02 01 01 06 15 03 00 12 02 01 01 ................
|
||||
| 3936: 06 14 03 00 12 02 01 01 06 13 03 00 12 02 01 01 ................
|
||||
| 3952: 06 12 03 00 12 02 01 01 06 11 03 00 12 02 01 01 ................
|
||||
| 3968: 06 10 03 00 12 02 01 01 06 0f 03 00 12 02 01 01 ................
|
||||
| 3984: 06 0e 03 00 12 02 01 01 06 0d 03 00 12 02 01 01 ................
|
||||
| 4000: 06 0c 03 00 12 02 01 01 06 0b 03 00 12 02 01 01 ................
|
||||
| 4016: 06 0a 03 00 12 02 01 01 06 09 03 00 12 03 01 01 ................
|
||||
| 4032: 06 08 03 00 12 03 01 01 06 07 03 00 12 03 01 01 ................
|
||||
| 4048: 06 06 03 00 12 01 01 01 06 05 03 00 12 01 01 01 ................
|
||||
| 4064: 06 04 03 00 12 01 01 01 06 03 03 00 12 06 01 01 ................
|
||||
| 4080: 06 02 03 00 12 06 01 01 06 01 03 00 12 06 01 01 ................
|
||||
| page 7 offset 24576
|
||||
| 0: 0a 00 00 00 01 0f f4 00 0f f4 00 00 00 00 00 00 ................
|
||||
| 4080: 00 00 00 00 0b 03 1b 01 76 65 72 73 69 6f 6e 04 ........version.
|
||||
| page 8 offset 28672
|
||||
| 0: 0d 00 00 00 03 0f d6 00 0f f4 0f 00 00 00 00 00 ................
|
||||
| 4048: 00 00 00 00 00 00 11 03 02 2b 69 6e 74 65 67 72 .........+integr
|
||||
| 4064: 69 74 79 2d 63 68 65 63 6b 09 02 02 1b 72 65 62 ity-check....reb
|
||||
| 4080: 75 69 6c 64 0a 01 02 1d 6f 00 00 00 00 00 00 00 uild....o.......
|
||||
| end crash-3d05232c78871b.db
|
||||
}]} {}
|
||||
|
||||
do_execsql_test 11.1 {
|
||||
UPDATE t1 SET b=quote(zeroblob('2025-01-09')) WHERE t1 MATCH 't*';
|
||||
INSERT INTO t1(t1,rank) VALUES('secure-delete',1);
|
||||
}
|
||||
|
||||
do_catchsql_test 11.2 {
|
||||
BEGIN;
|
||||
REPLACE INTO t1(rowid,b,a,rowid) VALUES(x'44023b9eb002d28b0ee90c',1,2,3);
|
||||
PRAGMA writable_schema=RESET;
|
||||
INSERT INTO t1(t1) SELECT x FROM t2;
|
||||
ROLLBACK;
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
do_catchsql_test 11.3 {
|
||||
REPLACE INTO t1(rowid,b,a,rowid) VALUES(x'44023b9eb002d28b0ee90c',1,2,3);
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
|
||||
sqlite3_fts5_may_be_corrupt 0
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -290,5 +290,40 @@ do_faultsim_test 11 -faults oom* -prep {
|
||||
faultsim_test_result {0 {}}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
|
||||
ifcapable foreignkey {
|
||||
do_execsql_test 12.0 {
|
||||
CREATE VIRTUAL TABLE f1 USING fts5(content);
|
||||
CREATE TABLE p1(a INTEGER PRIMARY KEY);
|
||||
CREATE TABLE c1(b REFERENCES p1 DEFERRABLE INITIALLY DEFERRED);
|
||||
}
|
||||
|
||||
faultsim_save_and_close
|
||||
|
||||
do_faultsim_test 11 -faults oom* -prep {
|
||||
faultsim_restore_and_reopen
|
||||
execsql {
|
||||
PRAGMA foreign_keys = 1;
|
||||
BEGIN;
|
||||
INSERT INTO c1 VALUES(123);
|
||||
SAVEPOINT xyz;
|
||||
}
|
||||
} -body {
|
||||
execsql {
|
||||
INSERT INTO f1 VALUES('a b c');
|
||||
ROLLBACK TO xyz;
|
||||
COMMIT;
|
||||
}
|
||||
} -test {
|
||||
execsql { SELECT 123 }
|
||||
faultsim_test_result \
|
||||
{1 {FOREIGN KEY constraint failed}} \
|
||||
{1 {out of memory}} \
|
||||
{1 {constraint failed}}
|
||||
}
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -591,7 +591,6 @@ do_execsql_test 21.2 {
|
||||
PRAGMA integrity_check
|
||||
} {ok}
|
||||
|
||||
breakpoint
|
||||
sqlite3_db_config db DEFENSIVE 1
|
||||
do_execsql_test 21.3 {
|
||||
CREATE TABLE xyz_notashadow(x, y);
|
||||
@@ -665,5 +664,26 @@ do_execsql_test 25.0 {
|
||||
SELECT fts5_test_poslist(t1) FROM t1('b') ORDER BY rank;
|
||||
} {{}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
|
||||
do_execsql_test 26.0 {
|
||||
PRAGMA foreign_keys = ON;
|
||||
CREATE TABLE t1(x INTEGER PRIMARY KEY);
|
||||
CREATE TABLE t2(y INTEGER PRIMARY KEY,
|
||||
z INTEGER REFERENCES t1(x) DEFERRABLE INITIALLY DEFERRED
|
||||
);
|
||||
CREATE VIRTUAL TABLE t3 USING fts5(a, b, content='', tokendata=1);
|
||||
}
|
||||
|
||||
do_execsql_test 26.1 {
|
||||
BEGIN;
|
||||
INSERT INTO t2 VALUES(1,111);
|
||||
INSERT INTO t3 VALUES(3,3);
|
||||
PRAGMA defer_foreign_keys=ON;
|
||||
DELETE FROM t2 WHERE y+1;
|
||||
COMMIT;
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -22,34 +22,40 @@ ifcapable !fts5 {
|
||||
}
|
||||
|
||||
foreach_detail_mode $testprefix {
|
||||
foreach {tn insttoken} {
|
||||
1 0
|
||||
2 1
|
||||
} {
|
||||
reset_db
|
||||
|
||||
sqlite3_fts5_register_origintext db
|
||||
do_execsql_test 1.0 {
|
||||
do_execsql_test $tn.1.0 {
|
||||
CREATE VIRTUAL TABLE ft USING fts5(
|
||||
x, tokenize="origintext unicode61", detail=%DETAIL%
|
||||
);
|
||||
INSERT INTO ft(ft, rank) VALUES('insttoken', $insttoken);
|
||||
CREATE VIRTUAL TABLE vocab USING fts5vocab(ft, instance);
|
||||
}
|
||||
|
||||
do_execsql_test 1.1 {
|
||||
do_execsql_test $tn.1.1 {
|
||||
INSERT INTO ft VALUES('Hello world');
|
||||
}
|
||||
|
||||
do_execsql_test 1.2 {
|
||||
do_execsql_test $tn.1.2 {
|
||||
INSERT INTO ft(ft) VALUES('integrity-check');
|
||||
}
|
||||
|
||||
proc b {x} { string map [list "\0" "."] $x }
|
||||
db func b b
|
||||
|
||||
do_execsql_test 1.3 {
|
||||
do_execsql_test $tn.1.3 {
|
||||
select b(term) from vocab;
|
||||
} {
|
||||
hello.Hello
|
||||
world
|
||||
}
|
||||
|
||||
do_execsql_test 1.4 {
|
||||
do_execsql_test $tn.1.4 {
|
||||
SELECT rowid FROM ft('Hello');
|
||||
} {1}
|
||||
|
||||
@@ -88,33 +94,34 @@ proc document {} {
|
||||
db func document document
|
||||
|
||||
sqlite3_fts5_register_origintext db
|
||||
do_execsql_test 2.0 {
|
||||
do_execsql_test $tn.2.0 {
|
||||
CREATE VIRTUAL TABLE ft USING fts5(
|
||||
x, tokenize="origintext unicode61", detail=%DETAIL%
|
||||
);
|
||||
INSERT INTO ft(ft, rank) VALUES('insttoken', $insttoken);
|
||||
INSERT INTO ft(ft, rank) VALUES('pgsz', 128);
|
||||
CREATE VIRTUAL TABLE vocab USING fts5vocab(ft, instance);
|
||||
}
|
||||
|
||||
do_test 2.1 {
|
||||
do_test $tn.2.1 {
|
||||
for {set ii 0} {$ii < 500} {incr ii} {
|
||||
execsql { INSERT INTO ft VALUES( document() ) }
|
||||
}
|
||||
} {}
|
||||
|
||||
do_execsql_test 2.2 {
|
||||
do_execsql_test $tn.2.2 {
|
||||
INSERT INTO ft(ft) VALUES('integrity-check');
|
||||
}
|
||||
|
||||
do_execsql_test 2.3 {
|
||||
do_execsql_test $tn.2.3 {
|
||||
INSERT INTO ft(ft, rank) VALUES('merge', 16);
|
||||
}
|
||||
|
||||
do_execsql_test 2.4 {
|
||||
do_execsql_test $tn.2.4 {
|
||||
INSERT INTO ft(ft) VALUES('integrity-check');
|
||||
}
|
||||
|
||||
do_execsql_test 2.5 {
|
||||
do_execsql_test $tn.2.5 {
|
||||
INSERT INTO ft(ft) VALUES('optimize');
|
||||
}
|
||||
|
||||
@@ -122,10 +129,11 @@ do_execsql_test 2.5 {
|
||||
reset_db
|
||||
|
||||
sqlite3_fts5_register_origintext db
|
||||
do_execsql_test 3.0 {
|
||||
do_execsql_test $tn.3.0 {
|
||||
CREATE VIRTUAL TABLE ft USING fts5(
|
||||
x, tokenize="origintext unicode61", detail=%DETAIL%
|
||||
);
|
||||
INSERT INTO ft(ft, rank) VALUES('insttoken', $insttoken);
|
||||
CREATE VIRTUAL TABLE vocab USING fts5vocab(ft, instance);
|
||||
|
||||
INSERT INTO ft(rowid, x) VALUES(1, 'hello');
|
||||
@@ -137,16 +145,17 @@ do_execsql_test 3.0 {
|
||||
#db func b b
|
||||
#execsql_pp { SELECT b(term) FROM vocab }
|
||||
|
||||
do_execsql_test 3.1.1 { SELECT rowid FROM ft('hello') } 1
|
||||
do_execsql_test 3.1.2 { SELECT rowid FROM ft('Hello') } 2
|
||||
do_execsql_test 3.1.3 { SELECT rowid FROM ft('HELLO') } 3
|
||||
do_execsql_test $tn.3.1.1 { SELECT rowid FROM ft('hello') } 1
|
||||
do_execsql_test $tn.3.1.2 { SELECT rowid FROM ft('Hello') } 2
|
||||
do_execsql_test $tn.3.1.3 { SELECT rowid FROM ft('HELLO') } 3
|
||||
|
||||
do_execsql_test 3.2 {
|
||||
do_execsql_test $tn.3.2 {
|
||||
CREATE VIRTUAL TABLE ft2 USING fts5(x,
|
||||
tokenize="origintext unicode61",
|
||||
tokendata=1,
|
||||
detail=%DETAIL%
|
||||
);
|
||||
INSERT INTO ft2(ft2, rank) VALUES('insttoken', $insttoken);
|
||||
CREATE VIRTUAL TABLE vocab2 USING fts5vocab(ft2, instance);
|
||||
|
||||
INSERT INTO ft2(rowid, x) VALUES(1, 'hello');
|
||||
@@ -160,11 +169,18 @@ do_execsql_test 3.2 {
|
||||
#db func b b
|
||||
#execsql_pp { SELECT b(term) FROM vocab }
|
||||
|
||||
do_execsql_test 3.3.1 { SELECT rowid FROM ft2('hello') } {1 2 3}
|
||||
do_execsql_test 3.3.2 { SELECT rowid FROM ft2('Hello') } {1 2 3}
|
||||
do_execsql_test 3.3.3 { SELECT rowid FROM ft2('HELLO') } {1 2 3}
|
||||
do_execsql_test $tn.3.3.1 { SELECT rowid FROM ft2('hello') } {1 2 3}
|
||||
do_execsql_test $tn.3.3.2 { SELECT rowid FROM ft2('Hello') } {1 2 3}
|
||||
do_execsql_test $tn.3.3.3 { SELECT rowid FROM ft2('HELLO') } {1 2 3}
|
||||
|
||||
do_execsql_test 3.3.4 { SELECT rowid FROM ft2('hello*') } {1 2 3 10}
|
||||
do_execsql_test $tn.3.3.4 { SELECT rowid FROM ft2('hello*') } {1 2 3 10}
|
||||
|
||||
do_execsql_test $tn.3.3.5.1 { SELECT rowid FROM ft2('HELLO') ORDER BY rowid DESC} {
|
||||
3 2 1
|
||||
}
|
||||
do_execsql_test $tn.3.3.5.2 { SELECT rowid FROM ft2('HELLO') ORDER BY +rowid DESC} {
|
||||
3 2 1
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
@@ -176,36 +192,37 @@ proc querytoken {cmd iPhrase iToken} {
|
||||
}
|
||||
sqlite3_fts5_create_function db querytoken querytoken
|
||||
|
||||
do_execsql_test 4.0 {
|
||||
do_execsql_test $tn.4.0 {
|
||||
CREATE VIRTUAL TABLE ft USING fts5(
|
||||
x, tokenize='origintext unicode61', tokendata=1, detail=%DETAIL%
|
||||
);
|
||||
INSERT INTO ft(ft, rank) VALUES('insttoken', $insttoken);
|
||||
INSERT INTO ft VALUES('one two three four');
|
||||
}
|
||||
|
||||
do_execsql_test 4.1 {
|
||||
do_execsql_test $tn.4.1 {
|
||||
SELECT rowid, querytoken(ft, 0, 0) FROM ft('TwO')
|
||||
} {1 two.TwO}
|
||||
do_execsql_test 4.2 {
|
||||
do_execsql_test $tn.4.2 {
|
||||
SELECT rowid, querytoken(ft, 0, 0) FROM ft('one TWO ThreE')
|
||||
} {1 one}
|
||||
do_execsql_test 4.3 {
|
||||
do_execsql_test $tn.4.3 {
|
||||
SELECT rowid, querytoken(ft, 1, 0) FROM ft('one TWO ThreE')
|
||||
} {1 two.TWO}
|
||||
|
||||
if {"%DETAIL%"=="full"} {
|
||||
# Phrase queries are only supported for detail=full.
|
||||
#
|
||||
do_execsql_test 4.4 {
|
||||
do_execsql_test $tn.4.4 {
|
||||
SELECT rowid, querytoken(ft, 0, 2) FROM ft('"one TWO ThreE"')
|
||||
} {1 three.ThreE}
|
||||
do_catchsql_test 4.5 {
|
||||
do_catchsql_test $tn.4.5 {
|
||||
SELECT rowid, querytoken(ft, 0, 3) FROM ft('"one TWO ThreE"')
|
||||
} {1 SQLITE_RANGE}
|
||||
do_catchsql_test 4.6 {
|
||||
do_catchsql_test $tn.4.6 {
|
||||
SELECT rowid, querytoken(ft, 1, 0) FROM ft('"one TWO ThreE"')
|
||||
} {1 SQLITE_RANGE}
|
||||
do_catchsql_test 4.7 {
|
||||
do_catchsql_test $tn.4.7 {
|
||||
SELECT rowid, querytoken(ft, -1, 0) FROM ft('"one TWO ThreE"')
|
||||
} {1 SQLITE_RANGE}
|
||||
}
|
||||
@@ -221,14 +238,15 @@ proc insttoken {cmd iIdx iToken} {
|
||||
sqlite3_fts5_create_function db insttoken insttoken
|
||||
fts5_aux_test_functions db
|
||||
|
||||
do_execsql_test 5.0 {
|
||||
do_execsql_test $tn.5.0 {
|
||||
CREATE VIRTUAL TABLE ft USING fts5(
|
||||
x, tokenize='origintext unicode61', tokendata=1, detail=%DETAIL%
|
||||
);
|
||||
INSERT INTO ft(ft, rank) VALUES('insttoken', $insttoken);
|
||||
INSERT INTO ft VALUES('one ONE One oNe oNE one');
|
||||
}
|
||||
|
||||
do_execsql_test 5.1 {
|
||||
do_execsql_test $tn.5.1 {
|
||||
SELECT insttoken(ft, 0, 0),
|
||||
insttoken(ft, 1, 0),
|
||||
insttoken(ft, 2, 0),
|
||||
@@ -240,13 +258,37 @@ do_execsql_test 5.1 {
|
||||
one one.ONE one.One one.oNe one.oNE one
|
||||
}
|
||||
|
||||
do_execsql_test 5.2 {
|
||||
do_execsql_test $tn.5.2 {
|
||||
SELECT insttoken(ft, 0, 0),
|
||||
insttoken(ft, 1, 0),
|
||||
insttoken(ft, 2, 0),
|
||||
insttoken(ft, 3, 0),
|
||||
insttoken(ft, 4, 0),
|
||||
insttoken(ft, 5, 0)
|
||||
FROM ft('on*');
|
||||
} {
|
||||
one one.ONE one.One one.oNe one.oNE one
|
||||
}
|
||||
|
||||
do_execsql_test $tn.5.3 {
|
||||
SELECT insttoken(ft, 0, 0),
|
||||
insttoken(ft, 1, 0),
|
||||
insttoken(ft, 2, 0),
|
||||
insttoken(ft, 3, 0),
|
||||
insttoken(ft, 4, 0),
|
||||
insttoken(ft, 5, 0)
|
||||
FROM ft(fts5_insttoken('on*'));
|
||||
} {
|
||||
one one.ONE one.One one.oNe one.oNE one
|
||||
}
|
||||
|
||||
do_execsql_test $tn.5.4 {
|
||||
SELECT insttoken(ft, 1, 0) FROM ft('one');
|
||||
} {
|
||||
one.ONE
|
||||
}
|
||||
|
||||
do_execsql_test 5.3 {
|
||||
do_execsql_test $tn.5.5 {
|
||||
SELECT fts5_test_poslist(ft) FROM ft('one');
|
||||
} {
|
||||
{0.0.0 0.0.1 0.0.2 0.0.3 0.0.4 0.0.5}
|
||||
@@ -260,10 +302,11 @@ do_execsql_test 5.3 {
|
||||
#
|
||||
reset_db
|
||||
sqlite3_fts5_register_origintext db
|
||||
do_execsql_test 6.0 {
|
||||
do_execsql_test $tn.6.0 {
|
||||
CREATE VIRTUAL TABLE ft USING fts5(
|
||||
x, y, tokenize='origintext unicode61', detail=%DETAIL%, tokendata=0
|
||||
);
|
||||
INSERT INTO ft(ft, rank) VALUES('insttoken', $insttoken);
|
||||
|
||||
INSERT INTO ft VALUES('One Two', 'Three two');
|
||||
INSERT INTO ft VALUES('three Three', 'one One');
|
||||
@@ -279,34 +322,35 @@ proc tokens {cmd} {
|
||||
}
|
||||
sqlite3_fts5_create_function db tokens tokens
|
||||
|
||||
do_execsql_test 6.1 {
|
||||
do_execsql_test $tn.6.1 {
|
||||
SELECT rowid, tokens(ft) FROM ft('One');
|
||||
} {1 one.One 2 one.One}
|
||||
|
||||
do_execsql_test 6.2 {
|
||||
do_execsql_test $tn.6.2 {
|
||||
SELECT rowid, tokens(ft) FROM ft('on*');
|
||||
} {1 {{}} 2 {{} {}}}
|
||||
} {1 one.One 2 {one one.One}}
|
||||
|
||||
do_execsql_test 6.3 {
|
||||
do_execsql_test $tn.6.3 {
|
||||
SELECT rowid, tokens(ft) FROM ft('Three*');
|
||||
} {1 {{}} 2 {{}}}
|
||||
} {1 three.Three 2 three.Three}
|
||||
|
||||
fts5_aux_test_functions db
|
||||
do_catchsql_test 6.4 {
|
||||
do_catchsql_test $tn.6.4 {
|
||||
SELECT fts5_test_insttoken(ft, -1, 0) FROM ft('one');
|
||||
} {1 SQLITE_RANGE}
|
||||
|
||||
do_catchsql_test 6.5 {
|
||||
do_catchsql_test $tn.6.5 {
|
||||
SELECT fts5_test_insttoken(ft, 1, 0) FROM ft('one');
|
||||
} {1 SQLITE_RANGE}
|
||||
|
||||
do_catchsql_test 6.6 {
|
||||
do_catchsql_test $tn.6.6 {
|
||||
CREATE VIRTUAL TABLE ft2 USING fts5(x, tokendata=2);
|
||||
} {1 {malformed tokendata=... directive}}
|
||||
do_catchsql_test 6.7 {
|
||||
do_catchsql_test $tn.6.7 {
|
||||
CREATE VIRTUAL TABLE ft2 USING fts5(x, content='', tokendata=11);
|
||||
} {1 {malformed tokendata=... directive}}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -22,6 +22,11 @@ ifcapable !fts5 {
|
||||
}
|
||||
|
||||
foreach_detail_mode $testprefix {
|
||||
foreach {tn insttoken} {
|
||||
1 0
|
||||
2 1
|
||||
} {
|
||||
|
||||
reset_db
|
||||
|
||||
sqlite3_fts5_register_origintext db
|
||||
@@ -32,21 +37,25 @@ foreach_detail_mode $testprefix {
|
||||
}
|
||||
sqlite3_fts5_create_function db insttoken insttoken
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
do_execsql_test $tn.1.0 {
|
||||
CREATE VIRTUAL TABLE ft USING fts5(
|
||||
x, tokenize="origintext unicode61", tokendata=1, detail=%DETAIL%
|
||||
);
|
||||
}
|
||||
|
||||
do_execsql_test $tn.1.0.1 {
|
||||
INSERT INTO ft(ft, rank) VALUES('insttoken', 1);
|
||||
}
|
||||
|
||||
do_execsql_test 1.1 {
|
||||
do_execsql_test $tn.1.1 {
|
||||
INSERT INTO ft VALUES('Hello world HELLO WORLD hello');
|
||||
}
|
||||
|
||||
do_execsql_test 1.2 {
|
||||
do_execsql_test $tn.1.2 {
|
||||
SELECT fts5_test_poslist(ft) FROM ft('hello');
|
||||
} {{0.0.0 0.0.2 0.0.4}}
|
||||
|
||||
do_execsql_test 1.3 {
|
||||
do_execsql_test $tn.1.3 {
|
||||
SELECT
|
||||
insttoken(ft, 0, 0),
|
||||
insttoken(ft, 1, 0),
|
||||
@@ -54,7 +63,15 @@ foreach_detail_mode $testprefix {
|
||||
FROM ft('hello');
|
||||
} {hello.Hello hello.HELLO hello}
|
||||
|
||||
do_execsql_test 1.4 {
|
||||
do_execsql_test $tn.1.3.1 {
|
||||
SELECT
|
||||
insttoken(ft, 0, 0),
|
||||
insttoken(ft, 1, 0),
|
||||
insttoken(ft, 2, 0)
|
||||
FROM ft('hel*');
|
||||
} {hello.Hello hello.HELLO hello}
|
||||
|
||||
do_execsql_test $tn.1.4 {
|
||||
SELECT
|
||||
insttoken(ft, 0, 0),
|
||||
insttoken(ft, 1, 0),
|
||||
@@ -62,7 +79,7 @@ foreach_detail_mode $testprefix {
|
||||
FROM ft('hello') ORDER BY rank;
|
||||
} {hello.Hello hello.HELLO hello}
|
||||
|
||||
do_execsql_test 1.5 {
|
||||
do_execsql_test $tn.1.5 {
|
||||
CREATE VIRTUAL TABLE ft2 USING fts5(
|
||||
x, tokenize="origintext unicode61", tokendata=1, detail=%DETAIL%
|
||||
);
|
||||
@@ -71,11 +88,11 @@ foreach_detail_mode $testprefix {
|
||||
INSERT INTO ft2(rowid, x) VALUES(3, 'THREE one two three THREE');
|
||||
}
|
||||
|
||||
do_execsql_test 1.6 {
|
||||
do_execsql_test $tn.1.6 {
|
||||
SELECT insttoken(ft2, 0, 0), rowid FROM ft2('three') ORDER BY rank;
|
||||
} {three.THREE 3 three 1 three 2}
|
||||
|
||||
do_execsql_test 1.7 {
|
||||
do_execsql_test $tn.1.7 {
|
||||
INSERT INTO ft2(rowid, x) VALUES(10, 'aaa bbb BBB');
|
||||
INSERT INTO ft2(rowid, x) VALUES(12, 'bbb bbb bbb');
|
||||
INSERT INTO ft2(rowid, x) VALUES(13, 'bbb bbb bbb');
|
||||
@@ -92,9 +109,32 @@ foreach_detail_mode $testprefix {
|
||||
INSERT INTO ft2(rowid, x) VALUES(24, 'aaa bbb BBB');
|
||||
}
|
||||
|
||||
do_execsql_test 1.8 { SELECT rowid FROM ft2('aaa AND bbb'); } {10 24}
|
||||
do_execsql_test 1.9 { SELECT rowid FROM ft2('bbb AND aaa'); } {10 24}
|
||||
do_execsql_test $tn.1.8 { SELECT rowid FROM ft2('aaa AND bbb'); } {10 24}
|
||||
do_execsql_test $tn.1.9 { SELECT rowid FROM ft2('bbb AND aaa'); } {10 24}
|
||||
|
||||
do_execsql_test $tn.2.0 {
|
||||
CREATE VIRTUAL TABLE ft3 USING fts5(
|
||||
x, tokenize="origintext unicode61", tokendata=1, detail=%DETAIL%,
|
||||
prefix=2
|
||||
);
|
||||
}
|
||||
do_execsql_test $tn.2.1 {
|
||||
INSERT INTO ft3(rowid, x) VALUES(1, 'one');
|
||||
INSERT INTO ft3(rowid, x) VALUES(2, 'ONE');
|
||||
INSERT INTO ft3(rowid, x) VALUES(3, 'ONT');
|
||||
INSERT INTO ft3(rowid, x) VALUES(4, 'on');
|
||||
INSERT INTO ft3(rowid, x) VALUES(5, 'On');
|
||||
}
|
||||
|
||||
do_execsql_test $tn.2.2 {
|
||||
SELECT rowid FROM ft3('on*');
|
||||
} {1 2 3 4 5}
|
||||
|
||||
do_execsql_test $tn.2.3 {
|
||||
SELECT rowid, insttoken(ft3, 0, 0) FROM ft3('on*');
|
||||
} {1 one 2 one.ONE 3 ont.ONT 4 on 5 on.On}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -0,0 +1,209 @@
|
||||
# 2014 Jan 08
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
# Tests focused on phrase queries.
|
||||
#
|
||||
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5origintext6
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
proc insert_data {tbl} {
|
||||
db eval "
|
||||
INSERT INTO $tbl (rowid, x, y) VALUES
|
||||
(1, 'ChH BDd HhG efc BjJ BGi GBG FdD','ciJ AFf ADf fBJ fhC GFI JEH fcA'),
|
||||
(2, 'deg AIG Fie jII cCd Hbf igF fEE','GeA Ija gJg EDc HFi DDI dCf aDd'),
|
||||
(3, 'IJC hga deC Jfa Aeg hfh CcH dfb','ajD hgC Jaf IfH CHe jIG AjD adF'),
|
||||
(4, 'FiH GJH IDA AiG bBc CGG Eih bIH','hHg JaH aii IHE Ggd gcH gji CGc'),
|
||||
(5, 'ceg CAd jFI GAB BGg EeC IdH acG','bBC eIG ifH eDE Adj bjb GCj ebA'),
|
||||
(6, 'Eac Fbh aFF Eea jeG EIj HCc JJH','hbd giE Gfe eiI dEF abE cJf cAb'),
|
||||
(7, 'dic hAc jEC AiG FEF jHc HiD HBI','aEd ebE Gfi AJG EBA faj GiG jjE'),
|
||||
(8, 'Fca iEe EgE jjJ gce ijf EGc EBi','gaI dhH bFg CFc HeC CjI Jfg ccH'),
|
||||
(9, 'cfd iaa HCf iHJ HjG ffh ABb ibi','CfG bia Dai eii Ejg Jeg fCg hDb'),
|
||||
(10, 'Jjf hJC IID HJj bGB EbJ cgg eBj','jci jhi JAF jIg Bei Bcd cAC AJd'),
|
||||
(11, 'egG Cdi bFf fEB hfH jDH jia Efd','FAd eCg fAi aiC baC eJG acF iGE'),
|
||||
(12, 'Ada Gde CJI ADG gJA Cbb ccF iAB','eAE ajC FBB ccd Jgh fJg ieg hGE'),
|
||||
(13, 'gBb fDG Jdd HdD fiJ Bed Cig iGg','heC FeI iaj gdg ebB giC HaD FIe'),
|
||||
(14, 'FiI iDd Ffe igI bgB EJf FHG hDF','cjC AeI abf Fah cbJ ffH jEb aib'),
|
||||
(15, 'jaF hBI jIH Gdh FEc Fij hgj jFh','dGA ADH feh AAI AfJ DbC gBi hGH'),
|
||||
(16, 'gjH BGg iGj aFE CAH edI idf HEH','hIf DDg fjB hGi cHF BCH FjG Bgd'),
|
||||
(17, 'iaI JGH hji gcj Dda eeG jDd CBi','cHg jeh caG gIc feF ihG hgJ Abj'),
|
||||
(18, 'jHI iDB eFf AiH EFB CDb IAj GbC','Ghe dEI gdI jai gib dAG BIa djb'),
|
||||
(19, 'abI fHG Ccf aAc FDa fiC agF bdB','afi hde IgE bGF cfg DHD diE aca'),
|
||||
(20, 'IFh eDJ jfh cDg dde JGJ GAf fIJ','IBa EfH faE aeI FIF baJ FGj EIH'),
|
||||
(21, 'Dee bFC bBA dEI CEj aJI ghA dCH','hBA ddA HJh dfj egI Dij dFE bGE'),
|
||||
(22, 'JFE BCj FgA afc Jda FGD iHJ HDh','eAI jHe BHD Gah bbD Bgj gbh eGB'),
|
||||
(23, 'edE CJE FjG aFI edA Cea FId iFe','ABG jcA ddj EEc Dcg hAI agA biA'),
|
||||
(24, 'AgE cfc eef cGh aFB DcH efJ hcH','eGF HaB diG fgi bdc iGJ FGJ fFB'),
|
||||
(25, 'aCa AgI GhC DDI hGJ Hgc Gcg bbG','iID Fga jHa jIj idj DFD bAC AFJ'),
|
||||
(26, 'gjC JGh Fge faa eCA iGG gHE Gai','bDi hFE BbI DHD Adb Fgi hCa Hij'),
|
||||
(27, 'Eji jEI jhF DFC afH cDh AGc dHA','IDe GcA ChF DIb Bif HfH agD DGh'),
|
||||
(28, 'gDD AEE Dfg ICf Cbi JdE jgH eEi','eEb dBG FDE jgf cAI FaJ jaA cDd'),
|
||||
(29, 'cbe Gec hgB Egi bca dHg bAJ jBf','EFB DgD GJc fDb EeE bBA GFC Hbe'),
|
||||
(30, 'Adc eHB afI hDc Bhh baE hcJ BBd','JAH deg bcF Dab Bgj Gbb JHi FIB'),
|
||||
(31, 'agF dIj AJJ Hfg cCG hED Igc fHC','JEf eia dHf Ggc Agj geD bEE Gei'),
|
||||
(32, 'DAd cCe cbJ FjG gJe gba dJA GCf','eAf hFc bGE ABI hHA IcE abF CCE'),
|
||||
(33, 'fFh jJe DhJ cDJ EBi AfD eFI IhG','fEG GCc Bjd EFF ggg CFe EHd ciB'),
|
||||
(34, 'Ejb BjI eAF HaD eEJ FaG Eda AHC','Iah hgD EJG fdD cIE Daj IFf eJh'),
|
||||
(35, 'aHG eCe FjA djJ dAJ jiJ IaE GGB','Acg iEF JfB FIC Eei ggj dic Iii'),
|
||||
(36, 'Fdb EDF GaF JjB ehH IgC hgi DCG','cag DHI Fah hAJ bbh egG Hia hgJ'),
|
||||
(37, 'HGg icC JEC AFJ Ddh dhi hfC Ich','fEg bED Bff hCJ EiA cIf bfG cGA'),
|
||||
(38, 'aEJ jGI BCi FaA ebA BHj cIJ GcC','dCH ADd bGB cFE AgF geD cbG jIc'),
|
||||
(39, 'JFB bBi heA BFA hgB Ahj EIE CgI','EIJ JFG FJE GeA Hdg HeH ACh GiA'),
|
||||
(40, 'agB DDC CED igC Dfc DhI eiC fHi','dAB dcg iJF cej Fcc cAc AfB Fdd'),
|
||||
(41, 'BdF DHj Ege hcG DEd eFa dCf gBb','FBG ChB cej iGd Hbh fCc Ibe Abh'),
|
||||
(42, 'Bgc DjI cbC jGD bdb hHB IJA IJH','heg cii abb IGf eDe hJc dii fcE'),
|
||||
(43, 'fhf ECa FiA aDh Jbf CiB Jhe ajD','GFE bIF aeD gDE BIE Jea DfC BEc'),
|
||||
(44, 'GjE dBj DbJ ICF aDh EEH Ejb jFb','dJj aEc IBg bEG Faf fjA hjf FAF'),
|
||||
(45, 'BfA efd IIJ AHG dDF eGg dIJ Gcb','Bfj jeb Ahc dAE ACH Dfb ieb dhC'),
|
||||
(46, 'Ibj ege geC dJh CIi hbD EAG fGA','DEb BFe Bjg FId Fhg HeF JAc BbE'),
|
||||
(47, 'dhB afC hgG bEJ aIe Cbe iEE JCD','bdg Ajc FGA jbh Jge iAj fIA jbE'),
|
||||
(48, 'egH iDi bfH iiI hGC jFF Hfd AHB','bjE Beb iCc haB gIH Dea bga dfd'),
|
||||
(49, 'jgf chc jGc Baj HBb jdE hgh heI','FFB aBd iEB EIG HGf Bbj EIi JbI'),
|
||||
(50, 'jhe EGi ajA fbH geh EHe FdC bij','jDE bBC gbH HeE dcH iBH IFE AHi'),
|
||||
(51, 'aCb JiD cgJ Bjj iAI Hbe IAF FhH','ijf bhE Jdf FED dCH bbG HcJ ebH');
|
||||
"
|
||||
}
|
||||
|
||||
foreach_detail_mode $testprefix {
|
||||
foreach external {0 1 2} {
|
||||
reset_db
|
||||
|
||||
proc tokens {cmd} {
|
||||
set ret [list]
|
||||
for {set iTok 0} {$iTok < [$cmd xInstCount]} {incr iTok} {
|
||||
set txt [$cmd xInstToken $iTok 0]
|
||||
set txt [string map [list "\0" "."] $txt]
|
||||
lappend ret $txt
|
||||
}
|
||||
set ret
|
||||
}
|
||||
sqlite3_fts5_create_function db tokens tokens
|
||||
sqlite3_fts5_register_origintext db
|
||||
|
||||
set E(0) internal
|
||||
set E(1) external
|
||||
set E(2) contentless
|
||||
set e $E($external)
|
||||
|
||||
db eval { CREATE TABLE ex(x, y) }
|
||||
switch -- $external {
|
||||
0 {
|
||||
do_execsql_test 1.$e.0 {
|
||||
CREATE VIRTUAL TABLE ft USING fts5(
|
||||
x, y, tokenize="origintext unicode61", tokendata=1, detail=%DETAIL%
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
1 {
|
||||
do_execsql_test 1.$e.0 {
|
||||
CREATE VIRTUAL TABLE ft USING fts5(
|
||||
x, y, tokenize="origintext unicode61", tokendata=1, detail=%DETAIL%,
|
||||
content=ex
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
2 {
|
||||
do_execsql_test 1.$e.0 {
|
||||
CREATE VIRTUAL TABLE ft USING fts5(
|
||||
x, y, tokenize="origintext unicode61", tokendata=1, detail=%DETAIL%,
|
||||
content=
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
insert_data ex
|
||||
insert_data ft
|
||||
|
||||
proc prefixquery {prefix bInst bYOnly} {
|
||||
set ret [list]
|
||||
db eval { SELECT rowid, x, y FROM ex ORDER BY rowid } {
|
||||
set row [list]
|
||||
set bSeen 0
|
||||
|
||||
set T [concat $x $y]
|
||||
if {$bYOnly} { set T $y }
|
||||
|
||||
foreach w $T {
|
||||
if {[string match -nocase $prefix $w]} {
|
||||
set bSeen 1
|
||||
if {$bInst} {
|
||||
set v [string tolower $w]
|
||||
if {$w != $v} { append v ".$w" }
|
||||
lappend row $v
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if {$bSeen} {
|
||||
lappend ret $rowid
|
||||
lappend ret $row
|
||||
}
|
||||
}
|
||||
|
||||
set ret
|
||||
}
|
||||
|
||||
proc do_prefixquery_test {tn prefix} {
|
||||
set bInst [expr {$::e!="contentless" || "%DETAIL%"=="full"}]
|
||||
set expect [prefixquery $prefix $bInst 0]
|
||||
set expect2 [prefixquery $prefix $bInst 1]
|
||||
|
||||
uplevel [list do_execsql_test $tn.1 "
|
||||
SELECT rowid, tokens(ft) FROM ft('$prefix')
|
||||
" $expect]
|
||||
uplevel [list do_execsql_test $tn.2 "
|
||||
SELECT rowid, tokens(ft) FROM ft(fts5_insttoken('$prefix'))
|
||||
" $expect]
|
||||
db eval { INSERT INTO ft(ft, rank) VALUES('insttoken', 1) }
|
||||
uplevel [list do_execsql_test $tn.3 "
|
||||
SELECT rowid, tokens(ft) FROM ft('$prefix')
|
||||
" $expect]
|
||||
db eval { INSERT INTO ft(ft, rank) VALUES('insttoken', 0) }
|
||||
|
||||
if {"%DETAIL%"!="none"} {
|
||||
uplevel [list do_execsql_test $tn.4 "
|
||||
SELECT rowid, tokens(ft) FROM ft('y: $prefix')
|
||||
" $expect2]
|
||||
uplevel [list do_execsql_test $tn.5 "
|
||||
SELECT rowid, tokens(ft) FROM ft(fts5_insttoken('y: $prefix'))
|
||||
" $expect2]
|
||||
db eval { INSERT INTO ft(ft, rank) VALUES('insttoken', 1) }
|
||||
uplevel [list do_execsql_test $tn.6 "
|
||||
SELECT rowid, tokens(ft) FROM ft('y: $prefix')
|
||||
" $expect2]
|
||||
db eval { INSERT INTO ft(ft, rank) VALUES('insttoken', 0) }
|
||||
}
|
||||
}
|
||||
|
||||
do_prefixquery_test 1.$e.1 a*
|
||||
do_prefixquery_test 1.$e.2 b*
|
||||
do_prefixquery_test 1.$e.3 c*
|
||||
do_prefixquery_test 1.$e.4 d*
|
||||
do_prefixquery_test 1.$e.5 e*
|
||||
do_prefixquery_test 1.$e.6 f*
|
||||
do_prefixquery_test 1.$e.7 g*
|
||||
do_prefixquery_test 1.$e.8 h*
|
||||
do_prefixquery_test 1.$e.9 i*
|
||||
do_prefixquery_test 1.$e.10 j*
|
||||
}}
|
||||
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -48,7 +48,7 @@ do_catchsql_test 2.0 {
|
||||
SAVEPOINT two;
|
||||
INSERT INTO ft1 VALUES('b');
|
||||
COMMIT;
|
||||
} {1 {SQL logic error}}
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
reset_db
|
||||
ifcapable fts3 {
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
# 2014 Jan 08
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
# Tests focused on phrase queries.
|
||||
#
|
||||
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5tokendata
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
foreach_detail_mode $testprefix {
|
||||
|
||||
sqlite3_fts5_register_origintext db
|
||||
fts5_aux_test_functions db
|
||||
proc b {x} { string map [list "\0" "."] $x }
|
||||
db func b b
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE VIRTUAL TABLE ft USING fts5(a, b, tokendata=1,
|
||||
tokenize="origintext unicode61", detail=%DETAIL%
|
||||
);
|
||||
CREATE VIRTUAL TABLE vocab USING fts5vocab(ft, instance);
|
||||
}
|
||||
|
||||
do_execsql_test 1.1 {
|
||||
INSERT INTO ft(rowid, a, b) VALUES
|
||||
(1, 'Pedagog Pedal Pedant', 'Peculier Day Today'),
|
||||
(2, 'Pedant pedantic pecked', 'Peck Penalize Pen');
|
||||
|
||||
INSERT INTO ft(rowid, a, b) VALUES
|
||||
(3, 'Penalty Pence Penciled', 'One Two Three'),
|
||||
(4, 'Pedant Pedal Pedant', 'Peculier Day Today');
|
||||
}
|
||||
|
||||
do_execsql_test 1.2 {
|
||||
SELECT DISTINCT b(term) FROM vocab
|
||||
} {
|
||||
day.Day one.One peck.Peck pecked peculier.Peculier pedagog.Pedagog
|
||||
pedal.Pedal pedant.Pedant pedantic pen.Pen penalize.Penalize
|
||||
penalty.Penalty pence.Pence penciled.Penciled three.Three
|
||||
today.Today two.Two
|
||||
}
|
||||
|
||||
do_execsql_test 1.3.1 {
|
||||
SELECT rowid FROM ft('pe*')
|
||||
} {
|
||||
1 2 3 4
|
||||
}
|
||||
|
||||
do_execsql_test 1.3.2 {
|
||||
SELECT rowid FROM ft('pe*') ORDER BY rowid DESC
|
||||
} {
|
||||
4 3 2 1
|
||||
}
|
||||
|
||||
if {"%DETAIL%"!="none"} {
|
||||
do_execsql_test 1.3.3 {
|
||||
SELECT rowid FROM ft WHERE a MATCH 'pe*' ORDER BY rowid DESC
|
||||
} {
|
||||
4 3 2 1
|
||||
}
|
||||
}
|
||||
|
||||
do_execsql_test 1.4 {
|
||||
SELECT rowid, b( fts5_test_insttoken(ft, 0, 0) ) FROM ft('pedant')
|
||||
} {
|
||||
1 pedant.Pedant
|
||||
2 pedant.Pedant
|
||||
4 pedant.Pedant
|
||||
}
|
||||
|
||||
do_execsql_test 1.5 {
|
||||
SELECT rowid, b( fts5_test_insttoken(ft, 0, 0) ) FROM ft('pe*')
|
||||
} {
|
||||
1 pedagog.Pedagog
|
||||
2 pedant.Pedant
|
||||
3 penalty.Penalty
|
||||
4 pedant.Pedant
|
||||
}
|
||||
|
||||
do_execsql_test 1.6 {
|
||||
SELECT rowid, fts5_test_poslist(ft) FROM ft('pe*')
|
||||
} {
|
||||
1 {0.0.0 0.0.1 0.0.2 0.1.0}
|
||||
2 {0.0.0 0.0.1 0.0.2 0.1.0 0.1.1 0.1.2}
|
||||
3 {0.0.0 0.0.1 0.0.2}
|
||||
4 {0.0.0 0.0.1 0.0.2 0.1.0}
|
||||
}
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -342,6 +342,25 @@ do_test 10.3 {
|
||||
}
|
||||
} {}
|
||||
|
||||
do_execsql_test 11.0 {
|
||||
CREATE VIRTUAL TABLE t4 USING fts5(y, tokenize=trigram);
|
||||
}
|
||||
sqlite3_fts5_register_str db
|
||||
do_execsql_test 11.1 {
|
||||
INSERT INTO t4 VALUES( str('') );
|
||||
}
|
||||
|
||||
do_test 12.0 {
|
||||
sqlite3_fts5_tokenize db trigram "abcd"
|
||||
} {abc 0 3 bcd 1 4}
|
||||
|
||||
do_test 12.1 {
|
||||
sqlite3_fts5_tokenize db trigram "a"
|
||||
} {}
|
||||
|
||||
do_test 12.2 {
|
||||
sqlite3_fts5_tokenize db trigram ""
|
||||
} {}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -112,7 +112,7 @@ do_execsql_test 2.1 {
|
||||
|
||||
do_execsql_test 2.2 {
|
||||
SELECT v FROM xyz_config WHERE k='version';
|
||||
} {5}
|
||||
} {4}
|
||||
|
||||
do_execsql_test 2.3 {
|
||||
ROLLBACK TO one;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# restart with tclsh \
|
||||
exec tclsh "$0" "$@"
|
||||
|
||||
set srcdir [file dirname [file dirname [info script]]]
|
||||
set srcdir [file dirname [file dirname [file normalize [info script]]]]
|
||||
set G(src) [string map [list %dir% $srcdir] {
|
||||
%dir%/fts5.h
|
||||
%dir%/fts5Int.h
|
||||
@@ -23,7 +23,27 @@ set G(src) [string map [list %dir% $srcdir] {
|
||||
}]
|
||||
|
||||
set G(hdr) {
|
||||
|
||||
/*
|
||||
** This, the "fts5.c" source file, is a composite file that is itself
|
||||
** assembled from the following files:
|
||||
**
|
||||
** fts5.h
|
||||
** fts5Int.h
|
||||
** fts5parse.h <--- Generated from fts5parse.y by Lemon
|
||||
** fts5parse.c <--- Generated from fts5parse.y by Lemon
|
||||
** fts5_aux.c
|
||||
** fts5_buffer.c
|
||||
** fts5_config.c
|
||||
** fts5_expr.c
|
||||
** fts5_hash.c
|
||||
** fts5_index.c
|
||||
** fts5_main.c
|
||||
** fts5_storage.c
|
||||
** fts5_tokenize.c
|
||||
** fts5_unicode2.c
|
||||
** fts5_varint.c
|
||||
** fts5_vocab.c
|
||||
*/
|
||||
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS5)
|
||||
|
||||
#if !defined(NDEBUG) && !defined(SQLITE_DEBUG)
|
||||
@@ -33,10 +53,16 @@ set G(hdr) {
|
||||
# undef NDEBUG
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_STDINT_H
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
#ifdef HAVE_INTTYPES_H
|
||||
#include <inttypes.h>
|
||||
#endif
|
||||
}
|
||||
|
||||
set G(footer) {
|
||||
|
||||
/* Here ends the fts5.c composite file. */
|
||||
#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS5) */
|
||||
}
|
||||
|
||||
|
||||
+20
-16
@@ -1,19 +1,18 @@
|
||||
|
||||
This directory contains source code for the SQLite "ICU" extension, an
|
||||
integration of the "International Components for Unicode" library with
|
||||
SQLite. Documentation follows.
|
||||
|
||||
1. Features
|
||||
|
||||
|
||||
1.1 SQL Scalars upper() and lower()
|
||||
1.2 Unicode Aware LIKE Operator
|
||||
1.3 ICU Collation Sequences
|
||||
1.4 SQL REGEXP Operator
|
||||
|
||||
|
||||
2. Compilation and Usage
|
||||
|
||||
|
||||
3. Bugs, Problems and Security Issues
|
||||
|
||||
|
||||
3.1 The "case_sensitive_like" Pragma
|
||||
3.2 The SQLITE_MAX_LIKE_PATTERN_LENGTH Macro
|
||||
3.3 Collation Sequence Security Issue
|
||||
@@ -23,10 +22,10 @@ SQLite. Documentation follows.
|
||||
|
||||
1.1 SQL Scalars upper() and lower()
|
||||
|
||||
SQLite's built-in implementations of these two functions only
|
||||
SQLite's built-in implementations of these two functions only
|
||||
provide case mapping for the 26 letters used in the English
|
||||
language. The ICU based functions provided by this extension
|
||||
provide case mapping, where defined, for the full range of
|
||||
provide case mapping, where defined, for the full range of
|
||||
unicode characters.
|
||||
|
||||
ICU provides two types of case mapping, "general" case mapping and
|
||||
@@ -36,7 +35,7 @@ SQLite. Documentation follows.
|
||||
http://www.icu-project.org/userguide/caseMappings.html
|
||||
http://www.icu-project.org/userguide/posix.html#case_mappings
|
||||
|
||||
To utilise "general" case mapping, the upper() or lower() scalar
|
||||
To utilise "general" case mapping, the upper() or lower() scalar
|
||||
functions are invoked with one argument:
|
||||
|
||||
upper('abc') -> 'ABC'
|
||||
@@ -57,7 +56,7 @@ SQLite. Documentation follows.
|
||||
operator understands case equivalence for the 26 letters of the English
|
||||
language alphabet. The implementation of LIKE included in this
|
||||
extension uses the ICU function u_foldCase() to provide case
|
||||
independent comparisons for the full range of unicode characters.
|
||||
independent comparisons for the full range of unicode characters.
|
||||
|
||||
The U_FOLD_CASE_DEFAULT flag is passed to u_foldCase(), meaning the
|
||||
dotless 'I' character used in the Turkish language is considered
|
||||
@@ -66,9 +65,9 @@ SQLite. Documentation follows.
|
||||
|
||||
1.3 ICU Collation Sequences
|
||||
|
||||
A special SQL scalar function, icu_load_collation() is provided that
|
||||
A special SQL scalar function, icu_load_collation() is provided that
|
||||
may be used to register ICU collation sequences with SQLite. It
|
||||
is always called with exactly two arguments, the ICU locale
|
||||
is always called with exactly two arguments, the ICU locale
|
||||
identifying the collation sequence to ICU, and the name of the
|
||||
SQLite collation sequence to create. For example, to create an
|
||||
SQLite collation sequence named "turkish" using Turkish language
|
||||
@@ -87,7 +86,7 @@ SQLite. Documentation follows.
|
||||
australian_penpal_name TEXT COLLATE australian,
|
||||
turkish_penpal_name TEXT COLLATE turkish
|
||||
);
|
||||
|
||||
|
||||
1.4 SQL REGEXP Operator
|
||||
|
||||
This extension provides an implementation of the SQL binary
|
||||
@@ -116,7 +115,7 @@ SQLite. Documentation follows.
|
||||
and use it as a dynamically loadable SQLite extension. To do this
|
||||
using gcc on *nix:
|
||||
|
||||
gcc -fPIC -shared icu.c `pkg-config --libs --cflags icu-uc icu-io` \
|
||||
gcc -fPIC -shared icu.c `pkg-config --libs --cflags icu-io` \
|
||||
-o libSqliteIcu.so
|
||||
|
||||
You may need to add "-I" flags so that gcc can find sqlite3ext.h
|
||||
@@ -124,6 +123,11 @@ SQLite. Documentation follows.
|
||||
loaded into sqlite in the same way as any other dynamically loadable
|
||||
extension.
|
||||
|
||||
As of version 3.48, it can be enabled in the canonical build process
|
||||
by passing one of --with-icu-config or --with-icu-ldflags to the
|
||||
configure script, optionally together with --enable-icu-collations.
|
||||
See the configure --help for more details.
|
||||
|
||||
|
||||
3 BUGS, PROBLEMS AND SECURITY ISSUES
|
||||
|
||||
@@ -144,13 +148,13 @@ SQLite. Documentation follows.
|
||||
SQLITE_MAX_LIKE_PATTERN_LENGTH macro as the maximum length of a
|
||||
pattern in bytes (irrespective of encoding). The default value is
|
||||
defined in internal header file "limits.h".
|
||||
|
||||
The ICU extension LIKE implementation suffers from the same
|
||||
|
||||
The ICU extension LIKE implementation suffers from the same
|
||||
problem and uses the same solution. However, since the ICU extension
|
||||
code does not include the SQLite file "limits.h", modifying
|
||||
the default value therein does not affect the ICU extension.
|
||||
The default value of SQLITE_MAX_LIKE_PATTERN_LENGTH used by
|
||||
the ICU extension LIKE operator is 50000, defined in source
|
||||
the ICU extension LIKE operator is 50000, defined in source
|
||||
file "icu.c".
|
||||
|
||||
3.3 Collation Sequence Security
|
||||
|
||||
+1
-1
@@ -571,7 +571,7 @@ int sqlite3IcuInit(sqlite3 *db){
|
||||
return rc;
|
||||
}
|
||||
|
||||
#if !SQLITE_CORE
|
||||
#ifndef SQLITE_CORE
|
||||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
|
||||
+5
-5
@@ -46,11 +46,11 @@ LSMTESTSRC = $(LSMDIR)/lsm-test/lsmtest1.c $(LSMDIR)/lsm-test/lsmtest2.c \
|
||||
LSMOPTS += -fPIC -DLSM_MUTEX_PTHREADS=1 -I$(LSMDIR) -DHAVE_ZLIB
|
||||
|
||||
lsm.so: $(LSMOBJ)
|
||||
$(TCCX) -shared -fPIC -o lsm.so $(LSMOBJ)
|
||||
$(T.link) -shared -fPIC -o lsm.so $(LSMOBJ)
|
||||
|
||||
%.o: $(LSMDIR)/%.c $(LSMHDR) sqlite3.h
|
||||
$(TCCX) $(LSMOPTS) -c $<
|
||||
|
||||
$(T.link) $(LSMOPTS) -c $<
|
||||
|
||||
lsmtest$(EXE): $(LSMOBJ) $(LSMTESTSRC) $(LSMTESTHDR) sqlite3.o
|
||||
# $(TCPPX) -c $(TOP)/lsm-test/lsmtest_tdb2.cc
|
||||
$(TCCX) $(LSMOPTS) $(LSMTESTSRC) $(LSMOBJ) sqlite3.o -o lsmtest$(EXE) $(THREADLIB) -lz
|
||||
# $(T.link) -c $(TOP)/lsm-test/lsmtest_tdb2.cc
|
||||
$(T.link) $(LSMOPTS) $(LSMTESTSRC) $(LSMOBJ) sqlite3.o -o lsmtest$(EXE) $(THREADLIB) -lz
|
||||
|
||||
+6
-3
@@ -175,15 +175,15 @@ static u8* fromBase64( char *pIn, int ncIn, u8 *pOut ){
|
||||
case ND:
|
||||
/* Treat dark non-digits as pad, but they terminate decode too. */
|
||||
ncIn = 0;
|
||||
deliberate_fall_through;
|
||||
deliberate_fall_through; /* FALLTHRU */
|
||||
case WS:
|
||||
/* Treat whitespace as pad and terminate this group.*/
|
||||
nti = nac;
|
||||
deliberate_fall_through;
|
||||
deliberate_fall_through; /* FALLTHRU */
|
||||
case PC:
|
||||
bdp = 0;
|
||||
--nbo;
|
||||
deliberate_fall_through;
|
||||
deliberate_fall_through; /* FALLTHRU */
|
||||
default: /* bdp is the digit value. */
|
||||
qv = qv<<6 | bdp;
|
||||
break;
|
||||
@@ -192,10 +192,13 @@ static u8* fromBase64( char *pIn, int ncIn, u8 *pOut ){
|
||||
switch( nbo ){
|
||||
case 3:
|
||||
pOut[2] = (qv) & 0xff;
|
||||
deliberate_fall_through; /* FALLTHRU */
|
||||
case 2:
|
||||
pOut[1] = (qv>>8) & 0xff;
|
||||
deliberate_fall_through; /* FALLTHRU */
|
||||
case 1:
|
||||
pOut[0] = (qv>>16) & 0xff;
|
||||
break;
|
||||
}
|
||||
pOut += nbo;
|
||||
}
|
||||
|
||||
@@ -232,12 +232,16 @@ static u8* fromBase85( char *pIn, int ncIn, u8 *pOut ){
|
||||
switch( nbo ){
|
||||
case 4:
|
||||
*pOut++ = (qv >> 24)&0xff;
|
||||
/* FALLTHRU */
|
||||
case 3:
|
||||
*pOut++ = (qv >> 16)&0xff;
|
||||
/* FALLTHRU */
|
||||
case 2:
|
||||
*pOut++ = (qv >> 8)&0xff;
|
||||
/* FALLTHRU */
|
||||
case 1:
|
||||
*pOut++ = qv&0xff;
|
||||
/* FALLTHRU */
|
||||
case 0:
|
||||
break;
|
||||
}
|
||||
|
||||
+6
-1
@@ -588,12 +588,17 @@ static int closureOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Wrapper around sqlite3_free
|
||||
*/
|
||||
static void closureMemFree(closure_avl *p){ sqlite3_free(p); }
|
||||
|
||||
/*
|
||||
** Free up all the memory allocated by a cursor. Set it rLimit to 0
|
||||
** to indicate that it is at EOF.
|
||||
*/
|
||||
static void closureClearCursor(closure_cursor *pCur){
|
||||
closureAvlDestroy(pCur->pClosure, (void(*)(closure_avl*))sqlite3_free);
|
||||
closureAvlDestroy(pCur->pClosure, closureMemFree);
|
||||
sqlite3_free(pCur->zTableName);
|
||||
sqlite3_free(pCur->zIdColumn);
|
||||
sqlite3_free(pCur->zParentColumn);
|
||||
|
||||
+1
-1
@@ -437,7 +437,7 @@ static int writeFile(
|
||||
|
||||
GetSystemTime(¤tTime);
|
||||
SystemTimeToFileTime(¤tTime, &lastAccess);
|
||||
intervals = Int32x32To64(mtime, 10000000) + 116444736000000000;
|
||||
intervals = (mtime*10000000) + 116444736000000000;
|
||||
lastWrite.dwLowDateTime = (DWORD)intervals;
|
||||
lastWrite.dwHighDateTime = intervals >> 32;
|
||||
zUnicodeName = sqlite3_win32_utf8_to_unicode(zFile);
|
||||
|
||||
@@ -484,10 +484,10 @@ int sqlite3_percentile_init(
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
unsigned int i;
|
||||
#if defined(SQLITE3_H) || defined(SQLITE_STATIC_PERCENTILE)
|
||||
(void)pApi; /* Unused parameter */
|
||||
#else
|
||||
#ifdef SQLITE3EXT_H
|
||||
SQLITE_EXTENSION_INIT2(pApi);
|
||||
#else
|
||||
(void)pApi; /* Unused parameter */
|
||||
#endif
|
||||
(void)pzErrMsg; /* Unused parameter */
|
||||
for(i=0; i<sizeof(aPercentFunc)/sizeof(aPercentFunc[0]); i++){
|
||||
|
||||
+2
-1
@@ -656,7 +656,8 @@ static const char *re_subcompile_string(ReCompiled *p){
|
||||
** regular expression. Applications should invoke this routine once
|
||||
** for every call to re_compile() to avoid memory leaks.
|
||||
*/
|
||||
static void re_free(ReCompiled *pRe){
|
||||
static void re_free(void *p){
|
||||
ReCompiled *pRe = (ReCompiled*)p;
|
||||
if( pRe ){
|
||||
sqlite3_free(pRe->aOp);
|
||||
sqlite3_free(pRe->aArg);
|
||||
|
||||
+7
-1
@@ -659,7 +659,7 @@ static int seriesBestIndex(
|
||||
continue;
|
||||
}
|
||||
if( pConstraint->iColumn<SERIES_COLUMN_START ){
|
||||
if( pConstraint->iColumn==SERIES_COLUMN_VALUE ){
|
||||
if( pConstraint->iColumn==SERIES_COLUMN_VALUE && pConstraint->usable ){
|
||||
switch( op ){
|
||||
case SQLITE_INDEX_CONSTRAINT_EQ:
|
||||
case SQLITE_INDEX_CONSTRAINT_IS: {
|
||||
@@ -667,7 +667,9 @@ static int seriesBestIndex(
|
||||
idxNum &= ~0x3300;
|
||||
aIdx[5] = i;
|
||||
aIdx[6] = -1;
|
||||
#ifndef ZERO_ARGUMENT_GENERATE_SERIES
|
||||
bStartSeen = 1;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case SQLITE_INDEX_CONSTRAINT_GE: {
|
||||
@@ -675,7 +677,9 @@ static int seriesBestIndex(
|
||||
idxNum |= 0x0100;
|
||||
idxNum &= ~0x0200;
|
||||
aIdx[5] = i;
|
||||
#ifndef ZERO_ARGUMENT_GENERATE_SERIES
|
||||
bStartSeen = 1;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case SQLITE_INDEX_CONSTRAINT_GT: {
|
||||
@@ -683,7 +687,9 @@ static int seriesBestIndex(
|
||||
idxNum |= 0x0200;
|
||||
idxNum &= ~0x0100;
|
||||
aIdx[5] = i;
|
||||
#ifndef ZERO_ARGUMENT_GENERATE_SERIES
|
||||
bStartSeen = 1;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case SQLITE_INDEX_CONSTRAINT_LE: {
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@
|
||||
**
|
||||
** This SQLite extension implements functions that compute SHA3 hashes
|
||||
** in the way described by the (U.S.) NIST FIPS 202 SHA-3 Standard.
|
||||
** Two SQL functions are implemented:
|
||||
** Three SQL functions are implemented:
|
||||
**
|
||||
** sha3(X,SIZE)
|
||||
** sha3_agg(Y,SIZE)
|
||||
|
||||
+51
-22
@@ -46,6 +46,11 @@
|
||||
** use O_U8TEXT when writing to the Windows console (or anything
|
||||
** else for which _isatty() returns true) and to use O_BINARY or O_TEXT
|
||||
** for all other output channels.
|
||||
**
|
||||
** The SQLITE_USE_W32_FOR_CONSOLE_IO macro is also available. If
|
||||
** defined, it forces the use of Win32 APIs for all console I/O, both
|
||||
** input and output. This is necessary for some non-Microsoft run-times
|
||||
** that implement stdio differently from Microsoft/Visual-Studio.
|
||||
*/
|
||||
#if defined(SQLITE_U8TEXT_ONLY)
|
||||
# define UseWtextForOutput(fd) 1
|
||||
@@ -96,8 +101,8 @@ FILE *sqlite3_fopen(const char *zFilename, const char *zMode){
|
||||
|
||||
sz1 = (int)strlen(zFilename);
|
||||
sz2 = (int)strlen(zMode);
|
||||
b1 = malloc( (sz1+1)*sizeof(b1[0]) );
|
||||
b2 = malloc( (sz2+1)*sizeof(b1[0]) );
|
||||
b1 = sqlite3_malloc( (sz1+1)*sizeof(b1[0]) );
|
||||
b2 = sqlite3_malloc( (sz2+1)*sizeof(b1[0]) );
|
||||
if( b1 && b2 ){
|
||||
sz1 = MultiByteToWideChar(CP_UTF8, 0, zFilename, sz1, b1, sz1);
|
||||
b1[sz1] = 0;
|
||||
@@ -105,8 +110,8 @@ FILE *sqlite3_fopen(const char *zFilename, const char *zMode){
|
||||
b2[sz2] = 0;
|
||||
fp = _wfopen(b1, b2);
|
||||
}
|
||||
free(b1);
|
||||
free(b2);
|
||||
sqlite3_free(b1);
|
||||
sqlite3_free(b2);
|
||||
simBinaryOther = 0;
|
||||
return fp;
|
||||
}
|
||||
@@ -122,8 +127,8 @@ FILE *sqlite3_popen(const char *zCommand, const char *zMode){
|
||||
|
||||
sz1 = (int)strlen(zCommand);
|
||||
sz2 = (int)strlen(zMode);
|
||||
b1 = malloc( (sz1+1)*sizeof(b1[0]) );
|
||||
b2 = malloc( (sz2+1)*sizeof(b1[0]) );
|
||||
b1 = sqlite3_malloc( (sz1+1)*sizeof(b1[0]) );
|
||||
b2 = sqlite3_malloc( (sz2+1)*sizeof(b1[0]) );
|
||||
if( b1 && b2 ){
|
||||
sz1 = MultiByteToWideChar(CP_UTF8, 0, zCommand, sz1, b1, sz1);
|
||||
b1[sz1] = 0;
|
||||
@@ -131,8 +136,8 @@ FILE *sqlite3_popen(const char *zCommand, const char *zMode){
|
||||
b2[sz2] = 0;
|
||||
fp = _wpopen(b1, b2);
|
||||
}
|
||||
free(b1);
|
||||
free(b2);
|
||||
sqlite3_free(b1);
|
||||
sqlite3_free(b2);
|
||||
return fp;
|
||||
}
|
||||
|
||||
@@ -146,12 +151,22 @@ char *sqlite3_fgets(char *buf, int sz, FILE *in){
|
||||
** that into UTF-8. Otherwise, non-ASCII characters all get translated
|
||||
** into '?'.
|
||||
*/
|
||||
wchar_t *b1 = malloc( sz*sizeof(wchar_t) );
|
||||
wchar_t *b1 = sqlite3_malloc( sz*sizeof(wchar_t) );
|
||||
if( b1==0 ) return 0;
|
||||
_setmode(_fileno(in), IsConsole(in) ? _O_WTEXT : _O_U8TEXT);
|
||||
if( fgetws(b1, sz/4, in)==0 ){
|
||||
sqlite3_free(b1);
|
||||
return 0;
|
||||
#ifdef SQLITE_USE_W32_FOR_CONSOLE_IO
|
||||
DWORD nRead = 0;
|
||||
if( IsConsole(in)
|
||||
&& ReadConsoleW(GetStdHandle(STD_INPUT_HANDLE), b1, sz-1, &nRead, 0)
|
||||
){
|
||||
b1[nRead] = 0;
|
||||
}else
|
||||
#endif
|
||||
{
|
||||
_setmode(_fileno(in), IsConsole(in) ? _O_WTEXT : _O_U8TEXT);
|
||||
if( fgetws(b1, sz/4, in)==0 ){
|
||||
sqlite3_free(b1);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
WideCharToMultiByte(CP_UTF8, 0, b1, -1, buf, sz, 0, 0);
|
||||
sqlite3_free(b1);
|
||||
@@ -207,20 +222,34 @@ int sqlite3_fputs(const char *z, FILE *out){
|
||||
** any translation. */
|
||||
return fputs(z, out);
|
||||
}else{
|
||||
/* When writing to the command-prompt in Windows, it is necessary
|
||||
** to use O_U8TEXT to render Unicode U+0080 and greater. Go ahead
|
||||
** use O_U8TEXT for everything in text mode.
|
||||
/* One must use UTF16 in order to get unicode support when writing
|
||||
** to the console on Windows.
|
||||
*/
|
||||
int sz = (int)strlen(z);
|
||||
wchar_t *b1 = malloc( (sz+1)*sizeof(wchar_t) );
|
||||
wchar_t *b1 = sqlite3_malloc( (sz+1)*sizeof(wchar_t) );
|
||||
if( b1==0 ) return 0;
|
||||
sz = MultiByteToWideChar(CP_UTF8, 0, z, sz, b1, sz);
|
||||
b1[sz] = 0;
|
||||
_setmode(_fileno(out), _O_U8TEXT);
|
||||
if( UseBinaryWText(out) ){
|
||||
piecemealOutput(b1, sz, out);
|
||||
}else{
|
||||
fputws(b1, out);
|
||||
|
||||
#ifdef SQLITE_USE_W32_FOR_CONSOLE_IO
|
||||
DWORD nWr = 0;
|
||||
if( IsConsole(out)
|
||||
&& WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE),b1,sz,&nWr,0)
|
||||
){
|
||||
/* If writing to the console, then the WriteConsoleW() is all we
|
||||
** need to do. */
|
||||
}else
|
||||
#endif
|
||||
{
|
||||
/* As long as SQLITE_USE_W32_FOR_CONSOLE_IO is not defined, or for
|
||||
** non-console I/O even if that macro is defined, write using the
|
||||
** standard library. */
|
||||
_setmode(_fileno(out), _O_U8TEXT);
|
||||
if( UseBinaryWText(out) ){
|
||||
piecemealOutput(b1, sz, out);
|
||||
}else{
|
||||
fputws(b1, out);
|
||||
}
|
||||
}
|
||||
sqlite3_free(b1);
|
||||
return 0;
|
||||
|
||||
+239
-15
@@ -105,7 +105,27 @@
|
||||
** invariants are (1) you must have -DSQLITE_ENABLE_VFSTRACE so that
|
||||
** the shell.c source file will know to include the -vfstrace command-line
|
||||
** option and (2) you must compile and link the three source files
|
||||
** shell,c, test_vfstrace.c, and sqlite3.c.
|
||||
** shell,c, test_vfstrace.c, and sqlite3.c.
|
||||
**
|
||||
** RUNTIME CONTROL OF VFSTRACE OUTPUT
|
||||
**
|
||||
** The application can use the "vfstrace" pragma to control which VFS
|
||||
** APIs are traced. To disable all output:
|
||||
**
|
||||
** PRAGMA vfstrace('-all');
|
||||
**
|
||||
** To enable all output (which is the default setting):
|
||||
**
|
||||
** PRAGMA vfstrace('+all');
|
||||
**
|
||||
** Individual APIs can be enabled or disabled by name, with or without
|
||||
** the initial "x" character. For example, to set up for tracing lock
|
||||
** primatives only:
|
||||
**
|
||||
** PRAGMA vfstrace('-all, +Lock,Unlock,ShmLock');
|
||||
**
|
||||
** The argument to the vfstrace pragma ignores capitalization and any
|
||||
** characters other than alphabetics, '+', and '-'.
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@@ -119,6 +139,8 @@ typedef struct vfstrace_info vfstrace_info;
|
||||
struct vfstrace_info {
|
||||
sqlite3_vfs *pRootVfs; /* The underlying real VFS */
|
||||
int (*xOut)(const char*, void*); /* Send output here */
|
||||
unsigned int mTrace; /* Mask of interfaces to trace */
|
||||
u8 bOn; /* Tracing on/off */
|
||||
void *pOutArg; /* First argument to xOut */
|
||||
const char *zVfsName; /* Name of this trace-VFS */
|
||||
sqlite3_vfs *pTraceVfs; /* Pointer back to the trace VFS */
|
||||
@@ -135,6 +157,39 @@ struct vfstrace_file {
|
||||
sqlite3_file *pReal; /* The real underlying file */
|
||||
};
|
||||
|
||||
/*
|
||||
** Bit values for vfstrace_info.mTrace.
|
||||
*/
|
||||
#define VTR_CLOSE 0x00000001
|
||||
#define VTR_READ 0x00000002
|
||||
#define VTR_WRITE 0x00000004
|
||||
#define VTR_TRUNC 0x00000008
|
||||
#define VTR_SYNC 0x00000010
|
||||
#define VTR_FSIZE 0x00000020
|
||||
#define VTR_LOCK 0x00000040
|
||||
#define VTR_UNLOCK 0x00000080
|
||||
#define VTR_CRL 0x00000100
|
||||
#define VTR_FCTRL 0x00000200
|
||||
#define VTR_SECSZ 0x00000400
|
||||
#define VTR_DEVCHAR 0x00000800
|
||||
#define VTR_SHMLOCK 0x00001000
|
||||
#define VTR_SHMMAP 0x00002000
|
||||
#define VTR_SHMBAR 0x00004000
|
||||
#define VTR_SHMUNMAP 0x00008000
|
||||
#define VTR_OPEN 0x00010000
|
||||
#define VTR_DELETE 0x00020000
|
||||
#define VTR_ACCESS 0x00040000
|
||||
#define VTR_FULLPATH 0x00080000
|
||||
#define VTR_DLOPEN 0x00100000
|
||||
#define VTR_DLERR 0x00200000
|
||||
#define VTR_DLSYM 0x00400000
|
||||
#define VTR_DLCLOSE 0x00800000
|
||||
#define VTR_RAND 0x01000000
|
||||
#define VTR_SLEEP 0x02000000
|
||||
#define VTR_CURTIME 0x04000000
|
||||
#define VTR_LASTERR 0x08000000
|
||||
#define VTR_FETCH 0x10000000 /* Also coverse xUnfetch */
|
||||
|
||||
/*
|
||||
** Method declarations for vfstrace_file.
|
||||
*/
|
||||
@@ -199,11 +254,13 @@ static void vfstrace_printf(
|
||||
){
|
||||
va_list ap;
|
||||
char *zMsg;
|
||||
va_start(ap, zFormat);
|
||||
zMsg = sqlite3_vmprintf(zFormat, ap);
|
||||
va_end(ap);
|
||||
pInfo->xOut(zMsg, pInfo->pOutArg);
|
||||
sqlite3_free(zMsg);
|
||||
if( pInfo->bOn ){
|
||||
va_start(ap, zFormat);
|
||||
zMsg = sqlite3_vmprintf(zFormat, ap);
|
||||
va_end(ap);
|
||||
pInfo->xOut(zMsg, pInfo->pOutArg);
|
||||
sqlite3_free(zMsg);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -302,6 +359,13 @@ static void strappend(char *z, int *pI, const char *zAppend){
|
||||
*pI = i;
|
||||
}
|
||||
|
||||
/*
|
||||
** Turn tracing output on or off according to mMask.
|
||||
*/
|
||||
static void vfstraceOnOff(vfstrace_info *pInfo, unsigned int mMask){
|
||||
pInfo->bOn = (pInfo->mTrace & mMask)!=0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Close an vfstrace-file.
|
||||
*/
|
||||
@@ -309,6 +373,7 @@ static int vfstraceClose(sqlite3_file *pFile){
|
||||
vfstrace_file *p = (vfstrace_file *)pFile;
|
||||
vfstrace_info *pInfo = p->pInfo;
|
||||
int rc;
|
||||
vfstraceOnOff(pInfo, VTR_CLOSE);
|
||||
vfstrace_printf(pInfo, "%s.xClose(%s)", pInfo->zVfsName, p->zFName);
|
||||
rc = p->pReal->pMethods->xClose(p->pReal);
|
||||
vfstrace_print_errcode(pInfo, " -> %s\n", rc);
|
||||
@@ -331,6 +396,7 @@ static int vfstraceRead(
|
||||
vfstrace_file *p = (vfstrace_file *)pFile;
|
||||
vfstrace_info *pInfo = p->pInfo;
|
||||
int rc;
|
||||
vfstraceOnOff(pInfo, VTR_READ);
|
||||
vfstrace_printf(pInfo, "%s.xRead(%s,n=%d,ofst=%lld)",
|
||||
pInfo->zVfsName, p->zFName, iAmt, iOfst);
|
||||
rc = p->pReal->pMethods->xRead(p->pReal, zBuf, iAmt, iOfst);
|
||||
@@ -350,6 +416,7 @@ static int vfstraceWrite(
|
||||
vfstrace_file *p = (vfstrace_file *)pFile;
|
||||
vfstrace_info *pInfo = p->pInfo;
|
||||
int rc;
|
||||
vfstraceOnOff(pInfo, VTR_WRITE);
|
||||
vfstrace_printf(pInfo, "%s.xWrite(%s,n=%d,ofst=%lld)",
|
||||
pInfo->zVfsName, p->zFName, iAmt, iOfst);
|
||||
rc = p->pReal->pMethods->xWrite(p->pReal, zBuf, iAmt, iOfst);
|
||||
@@ -364,6 +431,7 @@ static int vfstraceTruncate(sqlite3_file *pFile, sqlite_int64 size){
|
||||
vfstrace_file *p = (vfstrace_file *)pFile;
|
||||
vfstrace_info *pInfo = p->pInfo;
|
||||
int rc;
|
||||
vfstraceOnOff(pInfo, VTR_TRUNC);
|
||||
vfstrace_printf(pInfo, "%s.xTruncate(%s,%lld)", pInfo->zVfsName, p->zFName,
|
||||
size);
|
||||
rc = p->pReal->pMethods->xTruncate(p->pReal, size);
|
||||
@@ -388,6 +456,7 @@ static int vfstraceSync(sqlite3_file *pFile, int flags){
|
||||
if( flags & ~(SQLITE_SYNC_FULL|SQLITE_SYNC_DATAONLY) ){
|
||||
sqlite3_snprintf(sizeof(zBuf)-i, &zBuf[i], "|0x%x", flags);
|
||||
}
|
||||
vfstraceOnOff(pInfo, VTR_SYNC);
|
||||
vfstrace_printf(pInfo, "%s.xSync(%s,%s)", pInfo->zVfsName, p->zFName,
|
||||
&zBuf[1]);
|
||||
rc = p->pReal->pMethods->xSync(p->pReal, flags);
|
||||
@@ -402,6 +471,7 @@ static int vfstraceFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
|
||||
vfstrace_file *p = (vfstrace_file *)pFile;
|
||||
vfstrace_info *pInfo = p->pInfo;
|
||||
int rc;
|
||||
vfstraceOnOff(pInfo, VTR_FSIZE);
|
||||
vfstrace_printf(pInfo, "%s.xFileSize(%s)", pInfo->zVfsName, p->zFName);
|
||||
rc = p->pReal->pMethods->xFileSize(p->pReal, pSize);
|
||||
vfstrace_print_errcode(pInfo, " -> %s,", rc);
|
||||
@@ -430,6 +500,7 @@ static int vfstraceLock(sqlite3_file *pFile, int eLock){
|
||||
vfstrace_file *p = (vfstrace_file *)pFile;
|
||||
vfstrace_info *pInfo = p->pInfo;
|
||||
int rc;
|
||||
vfstraceOnOff(pInfo, VTR_LOCK);
|
||||
vfstrace_printf(pInfo, "%s.xLock(%s,%s)", pInfo->zVfsName, p->zFName,
|
||||
lockName(eLock));
|
||||
rc = p->pReal->pMethods->xLock(p->pReal, eLock);
|
||||
@@ -444,6 +515,7 @@ static int vfstraceUnlock(sqlite3_file *pFile, int eLock){
|
||||
vfstrace_file *p = (vfstrace_file *)pFile;
|
||||
vfstrace_info *pInfo = p->pInfo;
|
||||
int rc;
|
||||
vfstraceOnOff(pInfo, VTR_UNLOCK);
|
||||
vfstrace_printf(pInfo, "%s.xUnlock(%s,%s)", pInfo->zVfsName, p->zFName,
|
||||
lockName(eLock));
|
||||
rc = p->pReal->pMethods->xUnlock(p->pReal, eLock);
|
||||
@@ -458,6 +530,7 @@ static int vfstraceCheckReservedLock(sqlite3_file *pFile, int *pResOut){
|
||||
vfstrace_file *p = (vfstrace_file *)pFile;
|
||||
vfstrace_info *pInfo = p->pInfo;
|
||||
int rc;
|
||||
vfstraceOnOff(pInfo, VTR_CRL);
|
||||
vfstrace_printf(pInfo, "%s.xCheckReservedLock(%s,%d)",
|
||||
pInfo->zVfsName, p->zFName);
|
||||
rc = p->pReal->pMethods->xCheckReservedLock(p->pReal, pResOut);
|
||||
@@ -477,6 +550,7 @@ static int vfstraceFileControl(sqlite3_file *pFile, int op, void *pArg){
|
||||
char zBuf2[100];
|
||||
char *zOp;
|
||||
char *zRVal = 0;
|
||||
vfstraceOnOff(pInfo, VTR_FCTRL);
|
||||
switch( op ){
|
||||
case SQLITE_FCNTL_LOCKSTATE: zOp = "LOCKSTATE"; break;
|
||||
case SQLITE_GET_LOCKPROXYFILE: zOp = "GET_LOCKPROXYFILE"; break;
|
||||
@@ -505,6 +579,80 @@ static int vfstraceFileControl(sqlite3_file *pFile, int op, void *pArg){
|
||||
case SQLITE_FCNTL_POWERSAFE_OVERWRITE: zOp = "POWERSAFE_OVERWRITE"; break;
|
||||
case SQLITE_FCNTL_PRAGMA: {
|
||||
const char *const* a = (const char*const*)pArg;
|
||||
if( a[1] && strcmp(a[1],"vfstrace")==0 && a[2] ){
|
||||
const u8 *zArg = (const u8*)a[2];
|
||||
if( zArg[0]>='0' && zArg[0]<=9 ){
|
||||
pInfo->mTrace = (sqlite3_uint64)strtoll(a[2], 0, 0);
|
||||
}else{
|
||||
static const struct {
|
||||
const char *z;
|
||||
unsigned int m;
|
||||
} aKw[] = {
|
||||
{ "all", 0xffffffff },
|
||||
{ "close", VTR_CLOSE },
|
||||
{ "read", VTR_READ },
|
||||
{ "write", VTR_WRITE },
|
||||
{ "truncate", VTR_TRUNC },
|
||||
{ "sync", VTR_SYNC },
|
||||
{ "filesize", VTR_FSIZE },
|
||||
{ "lock", VTR_LOCK },
|
||||
{ "unlock", VTR_UNLOCK },
|
||||
{ "checkreservedlock", VTR_CRL },
|
||||
{ "filecontrol", VTR_FCTRL },
|
||||
{ "sectorsize", VTR_SECSZ },
|
||||
{ "devicecharacteristics", VTR_DEVCHAR },
|
||||
{ "shmlock", VTR_SHMLOCK },
|
||||
{ "shmmap", VTR_SHMMAP },
|
||||
{ "shmummap", VTR_SHMUNMAP },
|
||||
{ "shmbarrier", VTR_SHMBAR },
|
||||
{ "open", VTR_OPEN },
|
||||
{ "delete", VTR_DELETE },
|
||||
{ "access", VTR_ACCESS },
|
||||
{ "fullpathname", VTR_FULLPATH },
|
||||
{ "dlopen", VTR_DLOPEN },
|
||||
{ "dlerror", VTR_DLERR },
|
||||
{ "dlsym", VTR_DLSYM },
|
||||
{ "dlclose", VTR_DLCLOSE },
|
||||
{ "randomness", VTR_RAND },
|
||||
{ "sleep", VTR_SLEEP },
|
||||
{ "currenttime", VTR_CURTIME },
|
||||
{ "currenttimeint64", VTR_CURTIME },
|
||||
{ "getlasterror", VTR_LASTERR },
|
||||
{ "fetch", VTR_FETCH },
|
||||
};
|
||||
int onOff = 1;
|
||||
while( zArg[0] ){
|
||||
int jj, n;
|
||||
while( zArg[0]!=0 && zArg[0]!='-' && zArg[0]!='+'
|
||||
&& !isalpha(zArg[0]) ) zArg++;
|
||||
if( zArg[0]==0 ) break;
|
||||
if( zArg[0]=='-' ){
|
||||
onOff = 0;
|
||||
zArg++;
|
||||
}else if( zArg[0]=='+' ){
|
||||
onOff = 1;
|
||||
zArg++;
|
||||
}
|
||||
while( !isalpha(zArg[0]) ){
|
||||
if( zArg[0]==0 ) break;
|
||||
zArg++;
|
||||
}
|
||||
if( zArg[0]=='x' && isalpha(zArg[1]) ) zArg++;
|
||||
for(n=0; isalpha(zArg[n]); n++){}
|
||||
for(jj=0; jj<(int)(sizeof(aKw)/sizeof(aKw[0])); jj++){
|
||||
if( sqlite3_strnicmp(aKw[jj].z,(const char*)zArg,n)==0 ){
|
||||
if( onOff ){
|
||||
pInfo->mTrace |= aKw[jj].m;
|
||||
}else{
|
||||
pInfo->mTrace &= ~aKw[jj].m;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
zArg += n;
|
||||
}
|
||||
}
|
||||
}
|
||||
sqlite3_snprintf(sizeof(zBuf), zBuf, "PRAGMA,[%s,%s]",a[1],a[2]);
|
||||
zOp = zBuf;
|
||||
break;
|
||||
@@ -600,6 +748,7 @@ static int vfstraceSectorSize(sqlite3_file *pFile){
|
||||
vfstrace_file *p = (vfstrace_file *)pFile;
|
||||
vfstrace_info *pInfo = p->pInfo;
|
||||
int rc;
|
||||
vfstraceOnOff(pInfo, VTR_SECSZ);
|
||||
vfstrace_printf(pInfo, "%s.xSectorSize(%s)", pInfo->zVfsName, p->zFName);
|
||||
rc = p->pReal->pMethods->xSectorSize(p->pReal);
|
||||
vfstrace_printf(pInfo, " -> %d\n", rc);
|
||||
@@ -613,6 +762,7 @@ static int vfstraceDeviceCharacteristics(sqlite3_file *pFile){
|
||||
vfstrace_file *p = (vfstrace_file *)pFile;
|
||||
vfstrace_info *pInfo = p->pInfo;
|
||||
int rc;
|
||||
vfstraceOnOff(pInfo, VTR_DEVCHAR);
|
||||
vfstrace_printf(pInfo, "%s.xDeviceCharacteristics(%s)",
|
||||
pInfo->zVfsName, p->zFName);
|
||||
rc = p->pReal->pMethods->xDeviceCharacteristics(p->pReal);
|
||||
@@ -624,11 +774,22 @@ static int vfstraceDeviceCharacteristics(sqlite3_file *pFile){
|
||||
** Shared-memory operations.
|
||||
*/
|
||||
static int vfstraceShmLock(sqlite3_file *pFile, int ofst, int n, int flags){
|
||||
static const char *azLockName[] = {
|
||||
"WRITE",
|
||||
"CKPT",
|
||||
"RECOVER",
|
||||
"READ0",
|
||||
"READ1",
|
||||
"READ2",
|
||||
"READ3",
|
||||
"READ4",
|
||||
};
|
||||
vfstrace_file *p = (vfstrace_file *)pFile;
|
||||
vfstrace_info *pInfo = p->pInfo;
|
||||
int rc;
|
||||
char zLck[100];
|
||||
int i = 0;
|
||||
vfstraceOnOff(pInfo, VTR_SHMLOCK);
|
||||
memcpy(zLck, "|0", 3);
|
||||
if( flags & SQLITE_SHM_UNLOCK ) strappend(zLck, &i, "|UNLOCK");
|
||||
if( flags & SQLITE_SHM_LOCK ) strappend(zLck, &i, "|LOCK");
|
||||
@@ -637,8 +798,15 @@ static int vfstraceShmLock(sqlite3_file *pFile, int ofst, int n, int flags){
|
||||
if( flags & ~(0xf) ){
|
||||
sqlite3_snprintf(sizeof(zLck)-i, &zLck[i], "|0x%x", flags);
|
||||
}
|
||||
vfstrace_printf(pInfo, "%s.xShmLock(%s,ofst=%d,n=%d,%s)",
|
||||
pInfo->zVfsName, p->zFName, ofst, n, &zLck[1]);
|
||||
if( ofst>=0 && ofst<(int)(sizeof(azLockName)/sizeof(azLockName[0])) ){
|
||||
vfstrace_printf(pInfo, "%s.xShmLock(%s,ofst=%d(%s),n=%d,%s)",
|
||||
pInfo->zVfsName, p->zFName, ofst, azLockName[ofst],
|
||||
n, &zLck[1]);
|
||||
}else{
|
||||
vfstrace_printf(pInfo, "%s.xShmLock(%s,ofst=5d,n=%d,%s)",
|
||||
pInfo->zVfsName, p->zFName, ofst,
|
||||
n, &zLck[1]);
|
||||
}
|
||||
rc = p->pReal->pMethods->xShmLock(p->pReal, ofst, n, flags);
|
||||
vfstrace_print_errcode(pInfo, " -> %s\n", rc);
|
||||
return rc;
|
||||
@@ -653,6 +821,7 @@ static int vfstraceShmMap(
|
||||
vfstrace_file *p = (vfstrace_file *)pFile;
|
||||
vfstrace_info *pInfo = p->pInfo;
|
||||
int rc;
|
||||
vfstraceOnOff(pInfo, VTR_SHMMAP);
|
||||
vfstrace_printf(pInfo, "%s.xShmMap(%s,iRegion=%d,szRegion=%d,isWrite=%d,*)",
|
||||
pInfo->zVfsName, p->zFName, iRegion, szRegion, isWrite);
|
||||
rc = p->pReal->pMethods->xShmMap(p->pReal, iRegion, szRegion, isWrite, pp);
|
||||
@@ -662,6 +831,7 @@ static int vfstraceShmMap(
|
||||
static void vfstraceShmBarrier(sqlite3_file *pFile){
|
||||
vfstrace_file *p = (vfstrace_file *)pFile;
|
||||
vfstrace_info *pInfo = p->pInfo;
|
||||
vfstraceOnOff(pInfo, VTR_SHMBAR);
|
||||
vfstrace_printf(pInfo, "%s.xShmBarrier(%s)\n", pInfo->zVfsName, p->zFName);
|
||||
p->pReal->pMethods->xShmBarrier(p->pReal);
|
||||
}
|
||||
@@ -669,13 +839,35 @@ static int vfstraceShmUnmap(sqlite3_file *pFile, int delFlag){
|
||||
vfstrace_file *p = (vfstrace_file *)pFile;
|
||||
vfstrace_info *pInfo = p->pInfo;
|
||||
int rc;
|
||||
vfstraceOnOff(pInfo, VTR_SHMUNMAP);
|
||||
vfstrace_printf(pInfo, "%s.xShmUnmap(%s,delFlag=%d)",
|
||||
pInfo->zVfsName, p->zFName, delFlag);
|
||||
rc = p->pReal->pMethods->xShmUnmap(p->pReal, delFlag);
|
||||
vfstrace_print_errcode(pInfo, " -> %s\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int vfstraceFetch(sqlite3_file *pFile, i64 iOff, int nAmt, void **pptr){
|
||||
vfstrace_file *p = (vfstrace_file *)pFile;
|
||||
vfstrace_info *pInfo = p->pInfo;
|
||||
int rc;
|
||||
vfstraceOnOff(pInfo, VTR_FETCH);
|
||||
vfstrace_printf(pInfo, "%s.xFetch(%s,iOff=%lld,nAmt=%d,p=%p)",
|
||||
pInfo->zVfsName, p->zFName, iOff, nAmt, *pptr);
|
||||
rc = p->pReal->pMethods->xFetch(p->pReal, iOff, nAmt, pptr);
|
||||
vfstrace_print_errcode(pInfo, " -> %s\n", rc);
|
||||
return rc;
|
||||
}
|
||||
static int vfstraceUnfetch(sqlite3_file *pFile, i64 iOff, void *ptr){
|
||||
vfstrace_file *p = (vfstrace_file *)pFile;
|
||||
vfstrace_info *pInfo = p->pInfo;
|
||||
int rc;
|
||||
vfstraceOnOff(pInfo, VTR_FETCH);
|
||||
vfstrace_printf(pInfo, "%s.xUnfetch(%s,iOff=%lld,p=%p)",
|
||||
pInfo->zVfsName, p->zFName, iOff, ptr);
|
||||
rc = p->pReal->pMethods->xUnfetch(p->pReal, iOff, ptr);
|
||||
vfstrace_print_errcode(pInfo, " -> %s\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
@@ -696,6 +888,7 @@ static int vfstraceOpen(
|
||||
p->zFName = zName ? fileTail(zName) : "<temp>";
|
||||
p->pReal = (sqlite3_file *)&p[1];
|
||||
rc = pRoot->xOpen(pRoot, zName, p->pReal, flags, pOutFlags);
|
||||
vfstraceOnOff(pInfo, VTR_OPEN);
|
||||
vfstrace_printf(pInfo, "%s.xOpen(%s,flags=0x%x)",
|
||||
pInfo->zVfsName, p->zFName, flags);
|
||||
if( p->pReal->pMethods ){
|
||||
@@ -721,6 +914,10 @@ static int vfstraceOpen(
|
||||
pNew->xShmBarrier = pSub->xShmBarrier ? vfstraceShmBarrier : 0;
|
||||
pNew->xShmUnmap = pSub->xShmUnmap ? vfstraceShmUnmap : 0;
|
||||
}
|
||||
if( pNew->iVersion>=3 ){
|
||||
pNew->xFetch = pSub->xFetch ? vfstraceFetch : 0;
|
||||
pNew->xUnfetch = pSub->xUnfetch ? vfstraceUnfetch : 0;
|
||||
}
|
||||
pFile->pMethods = pNew;
|
||||
}
|
||||
vfstrace_print_errcode(pInfo, " -> %s", rc);
|
||||
@@ -741,6 +938,7 @@ static int vfstraceDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
|
||||
vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
|
||||
sqlite3_vfs *pRoot = pInfo->pRootVfs;
|
||||
int rc;
|
||||
vfstraceOnOff(pInfo, VTR_DELETE);
|
||||
vfstrace_printf(pInfo, "%s.xDelete(\"%s\",%d)",
|
||||
pInfo->zVfsName, zPath, dirSync);
|
||||
rc = pRoot->xDelete(pRoot, zPath, dirSync);
|
||||
@@ -761,6 +959,7 @@ static int vfstraceAccess(
|
||||
vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
|
||||
sqlite3_vfs *pRoot = pInfo->pRootVfs;
|
||||
int rc;
|
||||
vfstraceOnOff(pInfo, VTR_ACCESS);
|
||||
vfstrace_printf(pInfo, "%s.xAccess(\"%s\",%d)",
|
||||
pInfo->zVfsName, zPath, flags);
|
||||
rc = pRoot->xAccess(pRoot, zPath, flags, pResOut);
|
||||
@@ -783,6 +982,7 @@ static int vfstraceFullPathname(
|
||||
vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
|
||||
sqlite3_vfs *pRoot = pInfo->pRootVfs;
|
||||
int rc;
|
||||
vfstraceOnOff(pInfo, VTR_FULLPATH);
|
||||
vfstrace_printf(pInfo, "%s.xFullPathname(\"%s\")",
|
||||
pInfo->zVfsName, zPath);
|
||||
rc = pRoot->xFullPathname(pRoot, zPath, nOut, zOut);
|
||||
@@ -797,6 +997,7 @@ static int vfstraceFullPathname(
|
||||
static void *vfstraceDlOpen(sqlite3_vfs *pVfs, const char *zPath){
|
||||
vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
|
||||
sqlite3_vfs *pRoot = pInfo->pRootVfs;
|
||||
vfstraceOnOff(pInfo, VTR_DLOPEN);
|
||||
vfstrace_printf(pInfo, "%s.xDlOpen(\"%s\")\n", pInfo->zVfsName, zPath);
|
||||
return pRoot->xDlOpen(pRoot, zPath);
|
||||
}
|
||||
@@ -809,6 +1010,7 @@ static void *vfstraceDlOpen(sqlite3_vfs *pVfs, const char *zPath){
|
||||
static void vfstraceDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){
|
||||
vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
|
||||
sqlite3_vfs *pRoot = pInfo->pRootVfs;
|
||||
vfstraceOnOff(pInfo, VTR_DLERR);
|
||||
vfstrace_printf(pInfo, "%s.xDlError(%d)", pInfo->zVfsName, nByte);
|
||||
pRoot->xDlError(pRoot, nByte, zErrMsg);
|
||||
vfstrace_printf(pInfo, " -> \"%s\"", zErrMsg);
|
||||
@@ -830,7 +1032,8 @@ static void (*vfstraceDlSym(sqlite3_vfs *pVfs,void *p,const char *zSym))(void){
|
||||
static void vfstraceDlClose(sqlite3_vfs *pVfs, void *pHandle){
|
||||
vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
|
||||
sqlite3_vfs *pRoot = pInfo->pRootVfs;
|
||||
vfstrace_printf(pInfo, "%s.xDlOpen()\n", pInfo->zVfsName);
|
||||
vfstraceOnOff(pInfo, VTR_DLCLOSE);
|
||||
vfstrace_printf(pInfo, "%s.xDlClose()\n", pInfo->zVfsName);
|
||||
pRoot->xDlClose(pRoot, pHandle);
|
||||
}
|
||||
|
||||
@@ -841,6 +1044,7 @@ static void vfstraceDlClose(sqlite3_vfs *pVfs, void *pHandle){
|
||||
static int vfstraceRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
|
||||
vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
|
||||
sqlite3_vfs *pRoot = pInfo->pRootVfs;
|
||||
vfstraceOnOff(pInfo, VTR_RAND);
|
||||
vfstrace_printf(pInfo, "%s.xRandomness(%d)\n", pInfo->zVfsName, nByte);
|
||||
return pRoot->xRandomness(pRoot, nByte, zBufOut);
|
||||
}
|
||||
@@ -852,6 +1056,8 @@ static int vfstraceRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
|
||||
static int vfstraceSleep(sqlite3_vfs *pVfs, int nMicro){
|
||||
vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
|
||||
sqlite3_vfs *pRoot = pInfo->pRootVfs;
|
||||
vfstraceOnOff(pInfo, VTR_SLEEP);
|
||||
vfstrace_printf(pInfo, "%s.xSleep(%d)\n", pInfo->zVfsName, nMicro);
|
||||
return pRoot->xSleep(pRoot, nMicro);
|
||||
}
|
||||
|
||||
@@ -861,21 +1067,37 @@ static int vfstraceSleep(sqlite3_vfs *pVfs, int nMicro){
|
||||
static int vfstraceCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
|
||||
vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
|
||||
sqlite3_vfs *pRoot = pInfo->pRootVfs;
|
||||
return pRoot->xCurrentTime(pRoot, pTimeOut);
|
||||
int rc;
|
||||
vfstraceOnOff(pInfo, VTR_CURTIME);
|
||||
vfstrace_printf(pInfo, "%s.xCurrentTime()", pInfo->zVfsName);
|
||||
rc = pRoot->xCurrentTime(pRoot, pTimeOut);
|
||||
vfstrace_printf(pInfo, " -> %.17g\n", *pTimeOut);
|
||||
return rc;
|
||||
}
|
||||
static int vfstraceCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *pTimeOut){
|
||||
vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
|
||||
sqlite3_vfs *pRoot = pInfo->pRootVfs;
|
||||
return pRoot->xCurrentTimeInt64(pRoot, pTimeOut);
|
||||
int rc;
|
||||
vfstraceOnOff(pInfo, VTR_CURTIME);
|
||||
vfstrace_printf(pInfo, "%s.xCurrentTimeInt64()", pInfo->zVfsName);
|
||||
rc = pRoot->xCurrentTimeInt64(pRoot, pTimeOut);
|
||||
vfstrace_printf(pInfo, " -> %lld\n", *pTimeOut);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return th3 most recent error code and message
|
||||
** Return the most recent error code and message
|
||||
*/
|
||||
static int vfstraceGetLastError(sqlite3_vfs *pVfs, int iErr, char *zErr){
|
||||
static int vfstraceGetLastError(sqlite3_vfs *pVfs, int nErr, char *zErr){
|
||||
vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
|
||||
sqlite3_vfs *pRoot = pInfo->pRootVfs;
|
||||
return pRoot->xGetLastError(pRoot, iErr, zErr);
|
||||
int rc;
|
||||
vfstraceOnOff(pInfo, VTR_LASTERR);
|
||||
vfstrace_printf(pInfo, "%s.xGetLastError(%d,zBuf)", pInfo->zVfsName, nErr);
|
||||
if( nErr ) zErr[0] = 0;
|
||||
rc = pRoot->xGetLastError(pRoot, nErr, zErr);
|
||||
vfstrace_printf(pInfo, " -> zBuf[] = \"%s\", rc = %d\n", nErr?zErr:"", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -969,6 +1191,8 @@ int vfstrace_register(
|
||||
pInfo->pOutArg = pOutArg;
|
||||
pInfo->zVfsName = pNew->zName;
|
||||
pInfo->pTraceVfs = pNew;
|
||||
pInfo->mTrace = 0xffffffff;
|
||||
pInfo->bOn = 1;
|
||||
vfstrace_printf(pInfo, "%s.enabled_for(\"%s\")\n",
|
||||
pInfo->zVfsName, pRoot->zName);
|
||||
return sqlite3_vfs_register(pNew, makeDefault);
|
||||
|
||||
@@ -525,7 +525,6 @@ do_test 7.1 {
|
||||
} {1 {file is not a database}}
|
||||
|
||||
reset_db
|
||||
breakpoint
|
||||
do_test 8.0 {
|
||||
sqlite3 db {}
|
||||
db deserialize [decode_hexdb {
|
||||
@@ -552,5 +551,58 @@ do_test 8.1 {
|
||||
list [catch { $R finish } msg] $msg
|
||||
} {0 {}}
|
||||
|
||||
reset_db
|
||||
do_test 9.0 {
|
||||
sqlite3 db {}
|
||||
db deserialize [decode_hexdb {
|
||||
| size 16384 pagesize 4096t 0
|
||||
| 0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00
|
||||
| 16: 10 00 01 01 00 40 20 20 00 00 00 00 00 00 00 06 ........
|
||||
| 32: 00 00 00 0r 00 00 00 00 00 00 00 06 00 00 00 04 ..
|
||||
| 48: 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 ........
|
||||
| 96: 00 00 00 00 0d 00 00 00 06 0d e2 00 0f c4 0f 6a .......j
|
||||
| 112: 0e fc 0e 9d 0e 3d 0d e2 00 00 00 00 00 00 00 00 .
|
||||
| 3552: 00 00 59 06 06 17 21 21 01 7f 74 61 62 6c 65 74 ..tablet
|
||||
| 3568: 74 74 5f 63 6f 6e 66 69 67 74 74 74 5f 63 6f 6econ
|
||||
| 3584: 66 69 67 06 43 52 45 41 54 45 20 54 41 42 4c 45
|
||||
| 3616: 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 76 29 20 )
|
||||
| 3632: 57 49 54 48 4f 55 54 20 52 4f 57 49 44 5e 05 07 WOWID^..
|
||||
| 3648: 17 23 23 01 81 03 74 61 62 6c 65 74 74 74 5f 6tt_d
|
||||
| 3664: 6f 63 73 69 7a 65 74 74 74 5f 64 6f 63 73 69 7a z
|
||||
| 3680: 65 05 43 52 45 41 54 45 20 54 41 42 4c 45 20 27 e.ABLE '
|
||||
| 3696: 74 74 74 5f 64 6f 63 73 69 7a 65 27 28 69 64 20id
|
||||
| 3712: 49 4e 54 45 47 45 52 20 50 52 49 4d 41 52 59 20
|
||||
| 3728: 4b 45 59 2c 20 73 7a 20 42 4c 4f 42 29 5d 04 07 KEYB)]..
|
||||
| 3744: 17 23 23 01 81 B1 74 61 62 6c 65 74 74 74 5f 63 _c
|
||||
| 3760: 6f 6e 74 65 6e 74 74 74 74 5f 63 6f 6e 74 65 6e o_conten
|
||||
| 3776: 7 04 01 03 00 011 54 45 20 54 41 42 4c 45 20 27 t.CRLE '
|
||||
| 3792: 74 74 74 5f 63 6f 6e 74 65 6e 74 27 28 69 64 20
|
||||
| 3808: 49 4e 54 45 47 45 52 20 50 52 49 4d 41 52 59 20 INIMARY
|
||||
| 3904: 6f 2c 20 50 52 49 4d 41 52 59 20 4b 45 59 28 7EY(s
|
||||
| 3920: 65 67 69 64 2c 20 74 65 72 6d 29 29 20 57 49 54 T
|
||||
| 3936: 48 4f 55 54 20 52 4f 57 49 4 58 58 02 07 17 1d 1d ..
|
||||
| 3952: 01 81 03 74 61 62 6c 65 74 74 74 5f 64 61 74 61 .tt_data
|
||||
| 3968: 74 74 74 5f 64 61 74 61 02 43 52 45 41 54 45 2ATE
|
||||
| 3984: 54 41 42 4c 45 20 27 74 74 74 5f 64 61 74 61 27 '
|
||||
| 4000: 28 69 64 20 49 4e 54 45 47 45 52 20 50 52 49 4d (iR PRIM
|
||||
| 4016: 41 52 59 20 4b 45 59 2c 20 62 6c 6f 63 6b 20 42k B
|
||||
| 4032: 4c 4f 42 29 3a 01 06 17 13 13 08 5f 74 61 62 6c
|
||||
| 4048: 65 74 74 74 74 74 74 43 52 45 41 54 45 20 56 49 ettTE VI
|
||||
| 4064: 52 54 55 41 4c 20 54 41 42 4c 45 20 74 74 74 20 t
|
||||
| 4080: 55 53 49 4e 47 20 66 74 73 35 28 61 2c 20 62 29 U5(a, b)
|
||||
| page 4 offset 12288
|
||||
| 0: 0a 00 00 00 03 0f ea 00 0f fa 0f f2 0f ea 00 00 ........
|
||||
| 4064: 00 00 00 00 00 00 00 00 00 00 07 04 01 01 01 05 ..
|
||||
| 4080: 06 03 07 04 01 01 01 03 04 02 05 04 09 01 09 02 ........
|
||||
| end ro2.t
|
||||
}]} {}
|
||||
|
||||
do_test 9.1 {
|
||||
set R [sqlite3_recover_init db main test.db2]
|
||||
catch { $R run }
|
||||
list [catch { $R finish } msg] $msg
|
||||
} {0 {}}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -1825,6 +1825,8 @@ static int recoverWriteDataStep(sqlite3_recover *p){
|
||||
recoverError(p, SQLITE_NOMEM, 0);
|
||||
}
|
||||
p1->nVal = iField+1;
|
||||
}else if( pTab->nCol==0 ){
|
||||
p1->nVal = pTab->nCol;
|
||||
}
|
||||
p1->iPrevCell = iCell;
|
||||
p1->iPrevPage = iPage;
|
||||
|
||||
+2
-2
@@ -3775,8 +3775,8 @@ static void rtreenode(sqlite3_context *ctx, int nArg, sqlite3_value **apArg){
|
||||
sqlite3_str_append(pOut, "}", 1);
|
||||
}
|
||||
errCode = sqlite3_str_errcode(pOut);
|
||||
sqlite3_result_text(ctx, sqlite3_str_finish(pOut), -1, sqlite3_free);
|
||||
sqlite3_result_error_code(ctx, errCode);
|
||||
sqlite3_result_text(ctx, sqlite3_str_finish(pOut), -1, sqlite3_free);
|
||||
}
|
||||
|
||||
/* This routine implements an SQL function that returns the "depth" parameter
|
||||
@@ -4449,7 +4449,7 @@ int sqlite3_rtree_query_callback(
|
||||
);
|
||||
}
|
||||
|
||||
#if !SQLITE_CORE
|
||||
#ifndef SQLITE_CORE
|
||||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
|
||||
@@ -198,7 +198,7 @@ if {[permutation]=="inmemory_journal"} {
|
||||
} else {
|
||||
do_catchsql_test 6.1 {
|
||||
SELECT ( 'elvis' IN(SELECT rtreecheck('t1')) ) FROM (SELECT 1) GROUP BY 1;
|
||||
} {1 {database table is locked}}
|
||||
} {0 0}
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -204,7 +204,9 @@ proc do_conflict_test {tn args} {
|
||||
foreach t $O(-tables) { S attach $t }
|
||||
execsql $O(-sql)
|
||||
set ::xConflict [list]
|
||||
sqlite3changeset_apply db2 [S changeset] xConflict
|
||||
catch {
|
||||
sqlite3changeset_apply db2 [S changeset] xConflict
|
||||
}
|
||||
|
||||
set conflicts [list]
|
||||
foreach c $O(-conflicts) {
|
||||
|
||||
@@ -80,8 +80,10 @@ foreach {tn delrow trans conflictargs conflictret} {
|
||||
8 3 1 {FOREIGN_KEY 1} ABORT
|
||||
} {
|
||||
|
||||
set A(OMIT) {0 {}}
|
||||
set A(ABORT) {1 SQLITE_CONSTRAINT}
|
||||
set A(OMIT,0) {0 {}}
|
||||
set A(OMIT,1) {0 {}}
|
||||
set A(ABORT,0) {1 SQLITE_CONSTRAINT}
|
||||
set A(ABORT,1) {1 SQLITE_CONSTRAINT}
|
||||
do_test 1.2.$tn.1 {
|
||||
populate_db
|
||||
execsql { DELETE FROM p1 WHERE a=($delrow+0) }
|
||||
@@ -89,20 +91,24 @@ foreach {tn delrow trans conflictargs conflictret} {
|
||||
|
||||
set ::xConflict [list]
|
||||
list [catch {sqlite3changeset_apply db $::cc xConflict} msg] $msg
|
||||
} $A($conflictret)
|
||||
} $A($conflictret,$trans)
|
||||
|
||||
do_test 1.2.$tn.2 { set ::xConflict } $conflictargs
|
||||
|
||||
set A(OMIT) {1 1}
|
||||
set A(ABORT) {0 0}
|
||||
set A(OMIT,0) {1 1}
|
||||
set A(OMIT,1) {1 1}
|
||||
set A(ABORT,0) {0 0}
|
||||
set A(ABORT,1) {0 0}
|
||||
|
||||
do_test 1.2.$tn.3 {
|
||||
execsql { SELECT count(*) FROM c1 UNION ALL SELECT count(*) FROM c2 }
|
||||
} $A($conflictret)
|
||||
} $A($conflictret,$trans)
|
||||
|
||||
do_test 1.2.$tn.4 { expr ![sqlite3_get_autocommit db] } $trans
|
||||
do_test 1.2.$tn.5 {
|
||||
if { $trans } { execsql COMMIT }
|
||||
if { $trans && $conflictret=="ABORT" } { execsql COMMIT }
|
||||
} {}
|
||||
catchsql ROLLBACK
|
||||
}
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
|
||||
@@ -201,12 +201,16 @@ proc compare_db {db1 db2} {
|
||||
foreach tbl $lot1 {
|
||||
set col1 [list]
|
||||
set col2 [list]
|
||||
set quoted [list]
|
||||
|
||||
$db1 eval "PRAGMA table_info = $tbl" { lappend col1 $name }
|
||||
$db2 eval "PRAGMA table_info = $tbl" { lappend col2 $name }
|
||||
$db2 eval "PRAGMA table_info = $tbl" {
|
||||
lappend col2 $name
|
||||
lappend quoted "\"[string map {\" \"\"} $name]\""
|
||||
}
|
||||
if {$col1 != $col2} { error "table $tbl schema mismatch" }
|
||||
|
||||
set sql "SELECT * FROM $tbl ORDER BY [join $col1 ,]"
|
||||
set sql "SELECT * FROM $tbl ORDER BY [join $quoted ,]"
|
||||
set data1 [$db1 eval $sql]
|
||||
set data2 [$db2 eval $sql]
|
||||
if {$data1 != $data2} {
|
||||
|
||||
@@ -0,0 +1,191 @@
|
||||
# 2025 Jan 28
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
# This file implements regression tests for SQLite library.
|
||||
#
|
||||
|
||||
if {![info exists testdir]} {
|
||||
set testdir [file join [file dirname [info script]] .. .. test]
|
||||
}
|
||||
source [file join [file dirname [info script]] session_common.tcl]
|
||||
source $testdir/tester.tcl
|
||||
ifcapable !session {finish_test; return}
|
||||
|
||||
set testprefix session_gen
|
||||
|
||||
|
||||
foreach {otn sct} {
|
||||
1 VIRTUAL
|
||||
2 STORED
|
||||
} {
|
||||
eval [string map [list %TYPE% $sct] {
|
||||
reset_db
|
||||
set testprefix $testprefix-$otn
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
|
||||
|
||||
CREATE TABLE t2(a INTEGER PRIMARY KEY, b AS (c+1) %TYPE%, c);
|
||||
|
||||
CREATE TABLE t3(
|
||||
a,
|
||||
b AS (a+10) %TYPE%,
|
||||
c,
|
||||
d AS (c+1) %TYPE%,
|
||||
e,
|
||||
PRIMARY KEY(c, e)
|
||||
) WITHOUT ROWID;
|
||||
|
||||
CREATE TABLE t4(a AS (c*100) %TYPE%, b INTEGER PRIMARY KEY, c);
|
||||
|
||||
CREATE TABLE t5(x, y);
|
||||
}
|
||||
|
||||
foreach {tn sql changeset} {
|
||||
|
||||
0.1 {
|
||||
INSERT INTO t5 VALUES('abc', 'def');
|
||||
} {
|
||||
{INSERT t5 0 X.. {} {i 1 t abc t def}}
|
||||
}
|
||||
0.2 {
|
||||
UPDATE t5 SET y='xyz' WHERE rowid=1;
|
||||
} {
|
||||
{UPDATE t5 0 X.. {i 1 {} {} t def} {{} {} {} {} t xyz}}
|
||||
}
|
||||
0.3 {
|
||||
DELETE FROM t5;
|
||||
} {
|
||||
{DELETE t5 0 X.. {i 1 t abc t xyz} {}}
|
||||
}
|
||||
|
||||
1.1 {
|
||||
INSERT INTO t2 VALUES(1, 2);
|
||||
INSERT INTO t2 VALUES(2, 123);
|
||||
} {
|
||||
{INSERT t2 0 X. {} {i 1 i 2}}
|
||||
{INSERT t2 0 X. {} {i 2 i 123}}
|
||||
}
|
||||
1.2 {
|
||||
UPDATE t2 SET c=456 WHERE a=1
|
||||
} {
|
||||
{UPDATE t2 0 X. {i 1 i 2} {{} {} i 456}}
|
||||
}
|
||||
|
||||
1.3 {
|
||||
DELETE FROM t2 WHERE a=2
|
||||
} {
|
||||
{DELETE t2 0 X. {i 2 i 123} {}}
|
||||
}
|
||||
|
||||
1.4 {
|
||||
UPDATE t2 SET a=15
|
||||
} {
|
||||
{INSERT t2 0 X. {} {i 15 i 456}}
|
||||
{DELETE t2 0 X. {i 1 i 456} {}}
|
||||
}
|
||||
|
||||
2.1 {
|
||||
INSERT INTO t3 VALUES(5, 6, 7);
|
||||
INSERT INTO t3 VALUES(8, 9, 10);
|
||||
} {
|
||||
{INSERT t3 0 .XX {} {i 8 i 9 i 10}}
|
||||
{INSERT t3 0 .XX {} {i 5 i 6 i 7}}
|
||||
}
|
||||
|
||||
2.2 {
|
||||
UPDATE t3 SET a = 505 WHERE (c, e) = (6, 7);
|
||||
} {
|
||||
{UPDATE t3 0 .XX {i 5 i 6 i 7} {i 505 {} {} {} {}}}
|
||||
}
|
||||
|
||||
2.3 {
|
||||
DELETE FROM t3 WHERE (c, e) = (9, 10);
|
||||
} {
|
||||
{DELETE t3 0 .XX {i 8 i 9 i 10} {}}
|
||||
}
|
||||
|
||||
2.4 {
|
||||
UPDATE t3 SET c=1000
|
||||
} {
|
||||
{DELETE t3 0 .XX {i 505 i 6 i 7} {}}
|
||||
{INSERT t3 0 .XX {} {i 505 i 1000 i 7}}
|
||||
}
|
||||
|
||||
3.1 {
|
||||
INSERT INTO t4 VALUES(100, 100);
|
||||
} {
|
||||
{INSERT t4 0 X. {} {i 100 i 100}}
|
||||
}
|
||||
|
||||
} {
|
||||
do_test 1.$tn.1 {
|
||||
sqlite3session S db main
|
||||
S object_config rowid 1
|
||||
S attach *
|
||||
execsql $sql
|
||||
} {}
|
||||
|
||||
do_changeset_test 1.$tn.2 S $changeset
|
||||
|
||||
S delete
|
||||
}
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
|
||||
forcedelete test.db2
|
||||
sqlite3 db2 test.db2
|
||||
|
||||
do_common_sql {
|
||||
CREATE TABLE t0(x INTEGER PRIMARY KEY, y);
|
||||
INSERT INTO t0 VALUES(1, 'one');
|
||||
INSERT INTO t0 VALUES(2, 'two');
|
||||
|
||||
CREATE TABLE t1(a AS (c*10) %TYPE%, b INTEGER PRIMARY KEY, c);
|
||||
INSERT INTO t1 VALUES(1, 5);
|
||||
INSERT INTO t1 VALUES(2, 10);
|
||||
INSERT INTO t1 VALUES(3, 5);
|
||||
|
||||
CREATE TABLE t2(
|
||||
a, b, c AS (a*b) %TYPE%,
|
||||
'k 1', 'k 2', PRIMARY KEY('k 1', 'k 2')
|
||||
) WITHOUT ROWID;
|
||||
INSERT INTO t2 VALUES('a', 'b', 1, 11);
|
||||
INSERT INTO t2 VALUES('A', 'B', 2, 22);
|
||||
INSERT INTO t2 VALUES('Aa', 'Bb', 3, 33);
|
||||
}
|
||||
|
||||
foreach {tn sql} {
|
||||
1.1 { INSERT INTO t0 VALUES(4, 15) }
|
||||
1.2 { INSERT INTO t1 VALUES(4, 15) }
|
||||
1.3 { INSERT INTO t2 VALUES(1, 2, 3, 4) }
|
||||
|
||||
2.1 { UPDATE t1 SET c=100 WHERE b=2 }
|
||||
2.2 { UPDATE t2 SET a=11 }
|
||||
|
||||
3.1 { DELETE FROM t2 WHERE (t2.'k 1') = 2 }
|
||||
3.2 { DELETE FROM t1 }
|
||||
} {
|
||||
do_test 2.$tn.1 {
|
||||
# execsql { PRAGMA vdbe_listing = 1 } db2
|
||||
do_then_apply_sql $sql
|
||||
} {}
|
||||
do_test 2.$tn.2 {
|
||||
compare_db db db2
|
||||
} {}
|
||||
}
|
||||
db2 close
|
||||
|
||||
}]}
|
||||
|
||||
|
||||
|
||||
|
||||
finish_test
|
||||
@@ -0,0 +1,55 @@
|
||||
# 2024 November 04
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
|
||||
if {![info exists testdir]} {
|
||||
set testdir [file join [file dirname [info script]] .. .. test]
|
||||
}
|
||||
source [file join [file dirname [info script]] session_common.tcl]
|
||||
source $testdir/tester.tcl
|
||||
ifcapable !session {finish_test; return}
|
||||
|
||||
if {$::tcl_platform(pointerSize)<8} {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
set testprefix sessionblob
|
||||
|
||||
forcedelete test.db2
|
||||
sqlite3 db2 test.db2
|
||||
|
||||
set NBLOB 2000000
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
|
||||
INSERT INTO t1 VALUES(123, zeroblob($NBLOB));
|
||||
}
|
||||
|
||||
do_test 1.1 {
|
||||
sqlite3session S db main
|
||||
S attach t1
|
||||
} {}
|
||||
|
||||
set b2 [string repeat x 1000]
|
||||
do_test 1.2 {
|
||||
set ::blob [db incrblob t1 b 123]
|
||||
for {set ii 0} {$ii < $NBLOB} {incr ii [string length $b2]} {
|
||||
seek $::blob $ii
|
||||
puts -nonewline $::blob $b2
|
||||
}
|
||||
close $::blob
|
||||
} {}
|
||||
|
||||
S delete
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -59,7 +59,7 @@ do_execsql_test 1.2 {
|
||||
set ::nConflict 0
|
||||
proc conflict {args} {
|
||||
incr ::nConflict
|
||||
return "OMIT"
|
||||
return "ABORT"
|
||||
}
|
||||
|
||||
sqlite3changeset_apply_v2 db $C conflict
|
||||
@@ -82,7 +82,6 @@ do_execsql_test 1.5 {
|
||||
UPDATE p1 SET c=12345 WHERE a = 45;
|
||||
}
|
||||
|
||||
breakpoint
|
||||
sqlite3changeset_apply_v2 -noaction db $C conflict
|
||||
do_execsql_test 1.6 {
|
||||
SELECT * FROM c1
|
||||
@@ -108,4 +107,126 @@ do_execsql_test 1.8 {
|
||||
PRAGMA foreign_key_check
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Check that a changeset that causes an FK violation may not be applied,
|
||||
# even if SQLITE_CHANGESETAPPLY_FKNOACTION is specified.
|
||||
#
|
||||
# UPDATE: Unless the conflict-handler returns OMIT. In that case it can
|
||||
# be committed. See test cases 3.* in this file.
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 2.0 {
|
||||
CREATE TABLE p1(a INTEGER PRIMARY KEY, b, c UNIQUE);
|
||||
INSERT INTO p1 VALUES(1, 1, 'one');
|
||||
INSERT INTO p1 VALUES(2, 2, 'two');
|
||||
|
||||
CREATE TABLE c1(x REFERENCES p1(c) ON DELETE CASCADE);
|
||||
INSERT INTO c1 VALUES('two');
|
||||
}
|
||||
|
||||
db_save
|
||||
|
||||
set C [changeset_from_sql {
|
||||
DELETE FROM p1 WHERE a=2;
|
||||
}]
|
||||
|
||||
db_restore_and_reopen
|
||||
|
||||
do_test 2.1 {
|
||||
sqlite3changeset_apply_v2 -noaction db $C conflict
|
||||
} {}
|
||||
do_execsql_test 2.2 {
|
||||
SELECT * FROM p1
|
||||
} {1 1 one}
|
||||
|
||||
db_restore_and_reopen
|
||||
db eval { PRAGMA foreign_keys = 1 }
|
||||
|
||||
do_test 2.3 {
|
||||
list [catch { sqlite3changeset_apply_v2 -noaction db $C conflict } msg] $msg
|
||||
} {1 SQLITE_CONSTRAINT}
|
||||
do_execsql_test 2.4 {
|
||||
SELECT * FROM p1;
|
||||
} {1 1 one 2 2 two}
|
||||
do_execsql_test 2.5 {
|
||||
SELECT * FROM c1;
|
||||
} {two}
|
||||
|
||||
db_restore_and_reopen
|
||||
db eval { PRAGMA foreign_keys = 1 }
|
||||
|
||||
do_test 2.6 {
|
||||
list [catch {
|
||||
sqlite3changeset_apply_v2 -ignorenoop -noaction db $C conflict
|
||||
} msg] $msg
|
||||
} {1 SQLITE_CONSTRAINT}
|
||||
do_execsql_test 2.7 {
|
||||
SELECT * FROM p1;
|
||||
} {1 1 one 2 2 two}
|
||||
do_execsql_test 2.8 {
|
||||
SELECT * FROM c1;
|
||||
} {two}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 3.0 {
|
||||
CREATE TABLE p1(a INTEGER PRIMARY KEY, b, c UNIQUE);
|
||||
INSERT INTO p1 VALUES(1, 1, 'one');
|
||||
INSERT INTO p1 VALUES(2, 2, 'two');
|
||||
|
||||
CREATE TABLE c1(x REFERENCES p1(c) ON DELETE CASCADE);
|
||||
INSERT INTO c1 VALUES('two');
|
||||
}
|
||||
|
||||
set ::nConflict 0
|
||||
proc conflict {args} {
|
||||
incr ::nConflict
|
||||
return "OMIT"
|
||||
}
|
||||
|
||||
db_save
|
||||
|
||||
set C [changeset_from_sql {
|
||||
DELETE FROM p1 WHERE a=2;
|
||||
}]
|
||||
|
||||
db_restore_and_reopen
|
||||
|
||||
do_test 3.1 {
|
||||
sqlite3changeset_apply_v2 -noaction db $C conflict
|
||||
} {}
|
||||
do_execsql_test 3.2 {
|
||||
SELECT * FROM p1
|
||||
} {1 1 one}
|
||||
|
||||
db_restore_and_reopen
|
||||
db eval { PRAGMA foreign_keys = 1 }
|
||||
|
||||
do_test 3.3 {
|
||||
list [catch { sqlite3changeset_apply_v2 -noaction db $C conflict } msg] $msg
|
||||
} {0 {}}
|
||||
do_execsql_test 3.4 {
|
||||
SELECT * FROM p1;
|
||||
} {1 1 one}
|
||||
do_execsql_test 3.5 {
|
||||
SELECT * FROM c1;
|
||||
} {two}
|
||||
|
||||
db_restore_and_reopen
|
||||
db eval { PRAGMA foreign_keys = 1 }
|
||||
|
||||
do_test 3.6 {
|
||||
list [catch {
|
||||
sqlite3changeset_apply_v2 -ignorenoop -noaction db $C conflict
|
||||
} msg] $msg
|
||||
} {0 {}}
|
||||
do_execsql_test 3.7 {
|
||||
SELECT * FROM p1;
|
||||
} {1 1 one}
|
||||
do_execsql_test 3.8 {
|
||||
SELECT * FROM c1;
|
||||
} {two}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -139,11 +139,13 @@ struct sqlite3_changeset_iter {
|
||||
struct SessionTable {
|
||||
SessionTable *pNext;
|
||||
char *zName; /* Local name of table */
|
||||
int nCol; /* Number of columns in table zName */
|
||||
int nCol; /* Number of non-hidden columns */
|
||||
int nTotalCol; /* Number of columns including hidden */
|
||||
int bStat1; /* True if this is sqlite_stat1 */
|
||||
int bRowid; /* True if this table uses rowid for PK */
|
||||
const char **azCol; /* Column names */
|
||||
const char **azDflt; /* Default value expressions */
|
||||
int *aiIdx; /* Index to pass to xNew/xOld */
|
||||
u8 *abPK; /* Array of primary key flags */
|
||||
int nEntry; /* Total number of entries in hash table */
|
||||
int nChange; /* Size of apChange[] array */
|
||||
@@ -546,22 +548,22 @@ static int sessionPreupdateHash(
|
||||
unsigned int h = 0; /* Hash value to return */
|
||||
int i; /* Used to iterate through columns */
|
||||
|
||||
assert( pTab->nTotalCol==pSession->hook.xCount(pSession->hook.pCtx) );
|
||||
if( pTab->bRowid ){
|
||||
assert( pTab->nCol-1==pSession->hook.xCount(pSession->hook.pCtx) );
|
||||
h = sessionHashAppendI64(h, iRowid);
|
||||
}else{
|
||||
assert( *pbNullPK==0 );
|
||||
assert( pTab->nCol==pSession->hook.xCount(pSession->hook.pCtx) );
|
||||
for(i=0; i<pTab->nCol; i++){
|
||||
if( pTab->abPK[i] ){
|
||||
int rc;
|
||||
int eType;
|
||||
sqlite3_value *pVal;
|
||||
int iIdx = pTab->aiIdx[i];
|
||||
|
||||
if( bNew ){
|
||||
rc = pSession->hook.xNew(pSession->hook.pCtx, i, &pVal);
|
||||
rc = pSession->hook.xNew(pSession->hook.pCtx, iIdx, &pVal);
|
||||
}else{
|
||||
rc = pSession->hook.xOld(pSession->hook.pCtx, i, &pVal);
|
||||
rc = pSession->hook.xOld(pSession->hook.pCtx, iIdx, &pVal);
|
||||
}
|
||||
if( rc!=SQLITE_OK ) return rc;
|
||||
|
||||
@@ -898,6 +900,7 @@ static int sessionPreupdateEqual(
|
||||
sqlite3_value *pVal; /* Value returned by preupdate_new/old */
|
||||
int rc; /* Error code from preupdate_new/old */
|
||||
int eType = *a++; /* Type of value from change record */
|
||||
int iIdx = pTab->aiIdx[iCol];
|
||||
|
||||
/* The following calls to preupdate_new() and preupdate_old() can not
|
||||
** fail. This is because they cache their return values, and by the
|
||||
@@ -906,10 +909,10 @@ static int sessionPreupdateEqual(
|
||||
** this (that the method has already been called). */
|
||||
if( op==SQLITE_INSERT ){
|
||||
/* assert( db->pPreUpdate->pNewUnpacked || db->pPreUpdate->aNew ); */
|
||||
rc = pSession->hook.xNew(pSession->hook.pCtx, iCol, &pVal);
|
||||
rc = pSession->hook.xNew(pSession->hook.pCtx, iIdx, &pVal);
|
||||
}else{
|
||||
/* assert( db->pPreUpdate->pUnpacked ); */
|
||||
rc = pSession->hook.xOld(pSession->hook.pCtx, iCol, &pVal);
|
||||
rc = pSession->hook.xOld(pSession->hook.pCtx, iIdx, &pVal);
|
||||
}
|
||||
assert( rc==SQLITE_OK );
|
||||
(void)rc; /* Suppress warning about unused variable */
|
||||
@@ -1034,9 +1037,11 @@ static int sessionTableInfo(
|
||||
const char *zDb, /* Name of attached database (e.g. "main") */
|
||||
const char *zThis, /* Table name */
|
||||
int *pnCol, /* OUT: number of columns */
|
||||
int *pnTotalCol, /* OUT: number of hidden columns */
|
||||
const char **pzTab, /* OUT: Copy of zThis */
|
||||
const char ***pazCol, /* OUT: Array of column names for table */
|
||||
const char ***pazDflt, /* OUT: Array of default value expressions */
|
||||
int **paiIdx, /* OUT: Array of xNew/xOld indexes */
|
||||
u8 **pabPK, /* OUT: Array of booleans - true for PK col */
|
||||
int *pbRowid /* OUT: True if only PK is a rowid */
|
||||
){
|
||||
@@ -1051,6 +1056,7 @@ static int sessionTableInfo(
|
||||
char **azCol = 0;
|
||||
char **azDflt = 0;
|
||||
u8 *abPK = 0;
|
||||
int *aiIdx = 0;
|
||||
int bRowid = 0; /* Set to true to use rowid as PK */
|
||||
|
||||
assert( pazCol && pabPK );
|
||||
@@ -1058,6 +1064,8 @@ static int sessionTableInfo(
|
||||
*pazCol = 0;
|
||||
*pabPK = 0;
|
||||
*pnCol = 0;
|
||||
if( pnTotalCol ) *pnTotalCol = 0;
|
||||
if( paiIdx ) *paiIdx = 0;
|
||||
if( pzTab ) *pzTab = 0;
|
||||
if( pazDflt ) *pazDflt = 0;
|
||||
|
||||
@@ -1067,9 +1075,9 @@ static int sessionTableInfo(
|
||||
if( rc==SQLITE_OK ){
|
||||
/* For sqlite_stat1, pretend that (tbl,idx) is the PRIMARY KEY. */
|
||||
zPragma = sqlite3_mprintf(
|
||||
"SELECT 0, 'tbl', '', 0, '', 1 UNION ALL "
|
||||
"SELECT 1, 'idx', '', 0, '', 2 UNION ALL "
|
||||
"SELECT 2, 'stat', '', 0, '', 0"
|
||||
"SELECT 0, 'tbl', '', 0, '', 1, 0 UNION ALL "
|
||||
"SELECT 1, 'idx', '', 0, '', 2, 0 UNION ALL "
|
||||
"SELECT 2, 'stat', '', 0, '', 0, 0"
|
||||
);
|
||||
}else if( rc==SQLITE_ERROR ){
|
||||
zPragma = sqlite3_mprintf("");
|
||||
@@ -1077,7 +1085,7 @@ static int sessionTableInfo(
|
||||
return rc;
|
||||
}
|
||||
}else{
|
||||
zPragma = sqlite3_mprintf("PRAGMA '%q'.table_info('%q')", zDb, zThis);
|
||||
zPragma = sqlite3_mprintf("PRAGMA '%q'.table_xinfo('%q')", zDb, zThis);
|
||||
}
|
||||
if( !zPragma ){
|
||||
return SQLITE_NOMEM;
|
||||
@@ -1094,7 +1102,9 @@ static int sessionTableInfo(
|
||||
while( SQLITE_ROW==sqlite3_step(pStmt) ){
|
||||
nByte += sqlite3_column_bytes(pStmt, 1); /* name */
|
||||
nByte += sqlite3_column_bytes(pStmt, 4); /* dflt_value */
|
||||
nDbCol++;
|
||||
if( sqlite3_column_int(pStmt, 6)==0 ){ /* !hidden */
|
||||
nDbCol++;
|
||||
}
|
||||
if( sqlite3_column_int(pStmt, 5) ) bRowid = 0; /* pk */
|
||||
}
|
||||
if( nDbCol==0 ) bRowid = 0;
|
||||
@@ -1103,7 +1113,7 @@ static int sessionTableInfo(
|
||||
rc = sqlite3_reset(pStmt);
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
nByte += nDbCol * (sizeof(const char *)*2 + sizeof(u8) + 1 + 1);
|
||||
nByte += nDbCol * (sizeof(const char *)*2 +sizeof(int)+sizeof(u8) + 1 + 1);
|
||||
pAlloc = sessionMalloc64(pSession, nByte);
|
||||
if( pAlloc==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
@@ -1114,8 +1124,8 @@ static int sessionTableInfo(
|
||||
if( rc==SQLITE_OK ){
|
||||
azCol = (char **)pAlloc;
|
||||
azDflt = (char**)&azCol[nDbCol];
|
||||
pAlloc = (u8 *)&azDflt[nDbCol];
|
||||
abPK = (u8 *)pAlloc;
|
||||
aiIdx = (int*)&azDflt[nDbCol];
|
||||
abPK = (u8 *)&aiIdx[nDbCol];
|
||||
pAlloc = &abPK[nDbCol];
|
||||
if( pzTab ){
|
||||
memcpy(pAlloc, zThis, nThis+1);
|
||||
@@ -1130,27 +1140,32 @@ static int sessionTableInfo(
|
||||
azCol[i] = (char*)pAlloc;
|
||||
pAlloc += nName+1;
|
||||
abPK[i] = 1;
|
||||
aiIdx[i] = -1;
|
||||
i++;
|
||||
}
|
||||
while( SQLITE_ROW==sqlite3_step(pStmt) ){
|
||||
int nName = sqlite3_column_bytes(pStmt, 1);
|
||||
int nDflt = sqlite3_column_bytes(pStmt, 4);
|
||||
const unsigned char *zName = sqlite3_column_text(pStmt, 1);
|
||||
const unsigned char *zDflt = sqlite3_column_text(pStmt, 4);
|
||||
if( sqlite3_column_int(pStmt, 6)==0 ){ /* !hidden */
|
||||
int nName = sqlite3_column_bytes(pStmt, 1);
|
||||
int nDflt = sqlite3_column_bytes(pStmt, 4);
|
||||
const unsigned char *zName = sqlite3_column_text(pStmt, 1);
|
||||
const unsigned char *zDflt = sqlite3_column_text(pStmt, 4);
|
||||
|
||||
if( zName==0 ) break;
|
||||
memcpy(pAlloc, zName, nName+1);
|
||||
azCol[i] = (char *)pAlloc;
|
||||
pAlloc += nName+1;
|
||||
if( zDflt ){
|
||||
memcpy(pAlloc, zDflt, nDflt+1);
|
||||
azDflt[i] = (char *)pAlloc;
|
||||
pAlloc += nDflt+1;
|
||||
}else{
|
||||
azDflt[i] = 0;
|
||||
if( zName==0 ) break;
|
||||
memcpy(pAlloc, zName, nName+1);
|
||||
azCol[i] = (char *)pAlloc;
|
||||
pAlloc += nName+1;
|
||||
if( zDflt ){
|
||||
memcpy(pAlloc, zDflt, nDflt+1);
|
||||
azDflt[i] = (char *)pAlloc;
|
||||
pAlloc += nDflt+1;
|
||||
}else{
|
||||
azDflt[i] = 0;
|
||||
}
|
||||
abPK[i] = sqlite3_column_int(pStmt, 5);
|
||||
aiIdx[i] = sqlite3_column_int(pStmt, 0);
|
||||
i++;
|
||||
}
|
||||
abPK[i] = sqlite3_column_int(pStmt, 5);
|
||||
i++;
|
||||
if( pnTotalCol ) (*pnTotalCol)++;
|
||||
}
|
||||
rc = sqlite3_reset(pStmt);
|
||||
}
|
||||
@@ -1163,6 +1178,7 @@ static int sessionTableInfo(
|
||||
if( pazDflt ) *pazDflt = (const char**)azDflt;
|
||||
*pabPK = abPK;
|
||||
*pnCol = nDbCol;
|
||||
if( paiIdx ) *paiIdx = aiIdx;
|
||||
}else{
|
||||
sessionFree(pSession, azCol);
|
||||
}
|
||||
@@ -1194,7 +1210,8 @@ static int sessionInitTable(
|
||||
u8 *abPK;
|
||||
assert( pTab->azCol==0 || pTab->abPK==0 );
|
||||
rc = sessionTableInfo(pSession, db, zDb,
|
||||
pTab->zName, &pTab->nCol, 0, &pTab->azCol, &pTab->azDflt, &abPK,
|
||||
pTab->zName, &pTab->nCol, &pTab->nTotalCol, 0, &pTab->azCol,
|
||||
&pTab->azDflt, &pTab->aiIdx, &abPK,
|
||||
((pSession==0 || pSession->bImplicitPK) ? &pTab->bRowid : 0)
|
||||
);
|
||||
if( rc==SQLITE_OK ){
|
||||
@@ -1229,15 +1246,17 @@ static int sessionInitTable(
|
||||
*/
|
||||
static int sessionReinitTable(sqlite3_session *pSession, SessionTable *pTab){
|
||||
int nCol = 0;
|
||||
int nTotalCol = 0;
|
||||
const char **azCol = 0;
|
||||
const char **azDflt = 0;
|
||||
int *aiIdx = 0;
|
||||
u8 *abPK = 0;
|
||||
int bRowid = 0;
|
||||
|
||||
assert( pSession->rc==SQLITE_OK );
|
||||
|
||||
pSession->rc = sessionTableInfo(pSession, pSession->db, pSession->zDb,
|
||||
pTab->zName, &nCol, 0, &azCol, &azDflt, &abPK,
|
||||
pTab->zName, &nCol, &nTotalCol, 0, &azCol, &azDflt, &aiIdx, &abPK,
|
||||
(pSession->bImplicitPK ? &bRowid : 0)
|
||||
);
|
||||
if( pSession->rc==SQLITE_OK ){
|
||||
@@ -1260,8 +1279,10 @@ static int sessionReinitTable(sqlite3_session *pSession, SessionTable *pTab){
|
||||
const char **a = pTab->azCol;
|
||||
pTab->azCol = azCol;
|
||||
pTab->nCol = nCol;
|
||||
pTab->nTotalCol = nTotalCol;
|
||||
pTab->azDflt = azDflt;
|
||||
pTab->abPK = abPK;
|
||||
pTab->aiIdx = aiIdx;
|
||||
azCol = a;
|
||||
}
|
||||
if( pSession->bEnableSize ){
|
||||
@@ -1579,7 +1600,7 @@ static int sessionUpdateMaxSize(
|
||||
int ii;
|
||||
for(ii=0; ii<pTab->nCol; ii++){
|
||||
sqlite3_value *p = 0;
|
||||
pSession->hook.xNew(pSession->hook.pCtx, ii, &p);
|
||||
pSession->hook.xNew(pSession->hook.pCtx, pTab->aiIdx[ii], &p);
|
||||
sessionSerializeValue(0, p, &nNew);
|
||||
}
|
||||
}
|
||||
@@ -1599,8 +1620,9 @@ static int sessionUpdateMaxSize(
|
||||
int bChanged = 1;
|
||||
int nOld = 0;
|
||||
int eType;
|
||||
int iIdx = pTab->aiIdx[ii];
|
||||
sqlite3_value *p = 0;
|
||||
pSession->hook.xNew(pSession->hook.pCtx, ii-pTab->bRowid, &p);
|
||||
pSession->hook.xNew(pSession->hook.pCtx, iIdx, &p);
|
||||
if( p==0 ){
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
@@ -1697,11 +1719,11 @@ static void sessionPreupdateOneChange(
|
||||
/* Check the number of columns in this xPreUpdate call matches the
|
||||
** number of columns in the table. */
|
||||
nExpect = pSession->hook.xCount(pSession->hook.pCtx);
|
||||
if( (pTab->nCol-pTab->bRowid)<nExpect ){
|
||||
if( pTab->nTotalCol<nExpect ){
|
||||
if( sessionReinitTable(pSession, pTab) ) return;
|
||||
if( sessionUpdateChanges(pSession, pTab) ) return;
|
||||
}
|
||||
if( (pTab->nCol-pTab->bRowid)!=nExpect ){
|
||||
if( pTab->nTotalCol!=nExpect ){
|
||||
pSession->rc = SQLITE_SCHEMA;
|
||||
return;
|
||||
}
|
||||
@@ -1758,14 +1780,15 @@ static void sessionPreupdateOneChange(
|
||||
|
||||
/* Figure out how large an allocation is required */
|
||||
nByte = sizeof(SessionChange);
|
||||
for(i=0; i<(pTab->nCol-pTab->bRowid); i++){
|
||||
for(i=pTab->bRowid; i<pTab->nCol; i++){
|
||||
int iIdx = pTab->aiIdx[i];
|
||||
sqlite3_value *p = 0;
|
||||
if( op!=SQLITE_INSERT ){
|
||||
/* This may fail if the column has a non-NULL default and was added
|
||||
** using ALTER TABLE ADD COLUMN after this record was created. */
|
||||
rc = pSession->hook.xOld(pSession->hook.pCtx, i, &p);
|
||||
rc = pSession->hook.xOld(pSession->hook.pCtx, iIdx, &p);
|
||||
}else if( pTab->abPK[i] ){
|
||||
TESTONLY(int trc = ) pSession->hook.xNew(pSession->hook.pCtx, i, &p);
|
||||
TESTONLY(int trc = ) pSession->hook.xNew(pSession->hook.pCtx,iIdx,&p);
|
||||
assert( trc==SQLITE_OK );
|
||||
}
|
||||
|
||||
@@ -1800,12 +1823,13 @@ static void sessionPreupdateOneChange(
|
||||
sessionPutI64(&pC->aRecord[1], iRowid);
|
||||
nByte = 9;
|
||||
}
|
||||
for(i=0; i<(pTab->nCol-pTab->bRowid); i++){
|
||||
for(i=pTab->bRowid; i<pTab->nCol; i++){
|
||||
sqlite3_value *p = 0;
|
||||
int iIdx = pTab->aiIdx[i];
|
||||
if( op!=SQLITE_INSERT ){
|
||||
pSession->hook.xOld(pSession->hook.pCtx, i, &p);
|
||||
pSession->hook.xOld(pSession->hook.pCtx, iIdx, &p);
|
||||
}else if( pTab->abPK[i] ){
|
||||
pSession->hook.xNew(pSession->hook.pCtx, i, &p);
|
||||
pSession->hook.xNew(pSession->hook.pCtx, iIdx, &p);
|
||||
}
|
||||
sessionSerializeValue(&pC->aRecord[nByte], p, &nByte);
|
||||
}
|
||||
@@ -2207,7 +2231,8 @@ int sqlite3session_diff(
|
||||
int bRowid = 0;
|
||||
u8 *abPK;
|
||||
const char **azCol = 0;
|
||||
rc = sessionTableInfo(0, db, zFrom, zTbl, &nCol, 0, &azCol, 0, &abPK,
|
||||
rc = sessionTableInfo(0, db, zFrom, zTbl,
|
||||
&nCol, 0, 0, &azCol, 0, 0, &abPK,
|
||||
pSession->bImplicitPK ? &bRowid : 0
|
||||
);
|
||||
if( rc==SQLITE_OK ){
|
||||
@@ -2531,9 +2556,11 @@ static void sessionAppendIdent(
|
||||
char *zOut = (char *)&p->aBuf[p->nBuf];
|
||||
const char *zIn = zStr;
|
||||
*zOut++ = '"';
|
||||
while( *zIn ){
|
||||
if( *zIn=='"' ) *zOut++ = '"';
|
||||
*zOut++ = *(zIn++);
|
||||
if( zIn!=0 ){
|
||||
while( *zIn ){
|
||||
if( *zIn=='"' ) *zOut++ = '"';
|
||||
*zOut++ = *(zIn++);
|
||||
}
|
||||
}
|
||||
*zOut++ = '"';
|
||||
p->nBuf = (int)((u8 *)zOut - p->aBuf);
|
||||
@@ -2784,10 +2811,10 @@ static int sessionSelectStmt(
|
||||
int rc = SQLITE_OK;
|
||||
char *zSql = 0;
|
||||
const char *zSep = "";
|
||||
const char *zCols = bRowid ? SESSIONS_ROWID ", *" : "*";
|
||||
int nSql = -1;
|
||||
int i;
|
||||
|
||||
SessionBuffer cols = {0, 0, 0};
|
||||
SessionBuffer nooptest = {0, 0, 0};
|
||||
SessionBuffer pkfield = {0, 0, 0};
|
||||
SessionBuffer pkvar = {0, 0, 0};
|
||||
@@ -2800,9 +2827,16 @@ static int sessionSelectStmt(
|
||||
sessionAppendStr(&pkvar,
|
||||
"?1, (CASE WHEN ?2=X'' THEN NULL ELSE ?2 END)", &rc
|
||||
);
|
||||
zCols = "tbl, ?2, stat";
|
||||
sessionAppendStr(&cols, "tbl, ?2, stat", &rc);
|
||||
}else{
|
||||
#if 0
|
||||
if( bRowid ){
|
||||
sessionAppendStr(&cols, SESSIONS_ROWID, &rc);
|
||||
}
|
||||
#endif
|
||||
for(i=0; i<nCol; i++){
|
||||
if( cols.nBuf ) sessionAppendStr(&cols, ", ", &rc);
|
||||
sessionAppendIdent(&cols, azCol[i], &rc);
|
||||
if( abPK[i] ){
|
||||
sessionAppendStr(&pkfield, zSep, &rc);
|
||||
sessionAppendStr(&pkvar, zSep, &rc);
|
||||
@@ -2820,7 +2854,7 @@ static int sessionSelectStmt(
|
||||
if( rc==SQLITE_OK ){
|
||||
zSql = sqlite3_mprintf(
|
||||
"SELECT %s%s FROM %Q.%Q WHERE (%s) IS (%s)",
|
||||
zCols, (bIgnoreNoop ? (char*)nooptest.aBuf : ""),
|
||||
(char*)cols.aBuf, (bIgnoreNoop ? (char*)nooptest.aBuf : ""),
|
||||
zDb, zTab, (char*)pkfield.aBuf, (char*)pkvar.aBuf
|
||||
);
|
||||
if( zSql==0 ) rc = SQLITE_NOMEM;
|
||||
@@ -2863,6 +2897,7 @@ static int sessionSelectStmt(
|
||||
sqlite3_free(nooptest.aBuf);
|
||||
sqlite3_free(pkfield.aBuf);
|
||||
sqlite3_free(pkvar.aBuf);
|
||||
sqlite3_free(cols.aBuf);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -5203,7 +5238,8 @@ static int sessionChangesetApply(
|
||||
|
||||
sqlite3changeset_pk(pIter, &abPK, 0);
|
||||
rc = sessionTableInfo(0, db, "main", zNew,
|
||||
&sApply.nCol, &zTab, &sApply.azCol, 0, &sApply.abPK, &sApply.bRowid
|
||||
&sApply.nCol, 0, &zTab, &sApply.azCol, 0, 0,
|
||||
&sApply.abPK, &sApply.bRowid
|
||||
);
|
||||
if( rc!=SQLITE_OK ) break;
|
||||
for(i=0; i<sApply.nCol; i++){
|
||||
@@ -5283,12 +5319,17 @@ static int sessionChangesetApply(
|
||||
}
|
||||
}
|
||||
}
|
||||
sqlite3_exec(db, "PRAGMA defer_foreign_keys = 0", 0, 0, 0);
|
||||
|
||||
{
|
||||
int rc2 = sqlite3_exec(db, "PRAGMA defer_foreign_keys = 0", 0, 0, 0);
|
||||
if( rc==SQLITE_OK ) rc = rc2;
|
||||
}
|
||||
|
||||
if( (flags & SQLITE_CHANGESETAPPLY_NOSAVEPOINT)==0 ){
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3_exec(db, "RELEASE changeset_apply", 0, 0, 0);
|
||||
}else{
|
||||
}
|
||||
if( rc!=SQLITE_OK ){
|
||||
sqlite3_exec(db, "ROLLBACK TO changeset_apply", 0, 0, 0);
|
||||
sqlite3_exec(db, "RELEASE changeset_apply", 0, 0, 0);
|
||||
}
|
||||
|
||||
@@ -719,7 +719,6 @@ static int replace_handler(
|
||||
const char *zTab; /* Name of table conflict is on */
|
||||
int nCol; /* Number of columns in table zTab */
|
||||
int i;
|
||||
int x = 0;
|
||||
|
||||
sqlite3changeset_op(pIter, &zTab, &nCol, &op, 0);
|
||||
|
||||
@@ -728,7 +727,6 @@ static int replace_handler(
|
||||
sqlite3_value *pVal;
|
||||
sqlite3changeset_old(pIter, i, &pVal);
|
||||
sqlite3_value_text16(pVal);
|
||||
x++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -737,7 +735,6 @@ static int replace_handler(
|
||||
sqlite3_value *pVal;
|
||||
sqlite3changeset_new(pIter, i, &pVal);
|
||||
sqlite3_value_text16(pVal);
|
||||
x++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,96 +0,0 @@
|
||||
/*
|
||||
** 2014-09-08
|
||||
**
|
||||
** The author disclaims copyright to this source code. In place of
|
||||
** a legal notice, here is a blessing:
|
||||
**
|
||||
** May you do good and not evil.
|
||||
** May you find forgiveness for yourself and forgive others.
|
||||
** May you share freely, never taking more than you give.
|
||||
**
|
||||
*************************************************************************
|
||||
**
|
||||
** This file contains the application interface definitions for the
|
||||
** user-authentication extension feature.
|
||||
**
|
||||
** To compile with the user-authentication feature, append this file to
|
||||
** end of an SQLite amalgamation header file ("sqlite3.h"), then add
|
||||
** the SQLITE_USER_AUTHENTICATION compile-time option. See the
|
||||
** user-auth.txt file in the same source directory as this file for
|
||||
** additional information.
|
||||
*/
|
||||
#ifdef SQLITE_USER_AUTHENTICATION
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
** If a database contains the SQLITE_USER table, then the
|
||||
** sqlite3_user_authenticate() interface must be invoked with an
|
||||
** appropriate username and password prior to enable read and write
|
||||
** access to the database.
|
||||
**
|
||||
** Return SQLITE_OK on success or SQLITE_ERROR if the username/password
|
||||
** combination is incorrect or unknown.
|
||||
**
|
||||
** If the SQLITE_USER table is not present in the database file, then
|
||||
** this interface is a harmless no-op returnning SQLITE_OK.
|
||||
*/
|
||||
int sqlite3_user_authenticate(
|
||||
sqlite3 *db, /* The database connection */
|
||||
const char *zUsername, /* Username */
|
||||
const char *aPW, /* Password or credentials */
|
||||
int nPW /* Number of bytes in aPW[] */
|
||||
);
|
||||
|
||||
/*
|
||||
** The sqlite3_user_add() interface can be used (by an admin user only)
|
||||
** to create a new user. When called on a no-authentication-required
|
||||
** database, this routine converts the database into an authentication-
|
||||
** required database, automatically makes the added user an
|
||||
** administrator, and logs in the current connection as that user.
|
||||
** The sqlite3_user_add() interface only works for the "main" database, not
|
||||
** for any ATTACH-ed databases. Any call to sqlite3_user_add() by a
|
||||
** non-admin user results in an error.
|
||||
*/
|
||||
int sqlite3_user_add(
|
||||
sqlite3 *db, /* Database connection */
|
||||
const char *zUsername, /* Username to be added */
|
||||
const char *aPW, /* Password or credentials */
|
||||
int nPW, /* Number of bytes in aPW[] */
|
||||
int isAdmin /* True to give new user admin privilege */
|
||||
);
|
||||
|
||||
/*
|
||||
** The sqlite3_user_change() interface can be used to change a users
|
||||
** login credentials or admin privilege. Any user can change their own
|
||||
** login credentials. Only an admin user can change another users login
|
||||
** credentials or admin privilege setting. No user may change their own
|
||||
** admin privilege setting.
|
||||
*/
|
||||
int sqlite3_user_change(
|
||||
sqlite3 *db, /* Database connection */
|
||||
const char *zUsername, /* Username to change */
|
||||
const char *aPW, /* New password or credentials */
|
||||
int nPW, /* Number of bytes in aPW[] */
|
||||
int isAdmin /* Modified admin privilege for the user */
|
||||
);
|
||||
|
||||
/*
|
||||
** The sqlite3_user_delete() interface can be used (by an admin user only)
|
||||
** to delete a user. The currently logged-in user cannot be deleted,
|
||||
** which guarantees that there is always an admin user and hence that
|
||||
** the database cannot be converted into a no-authentication-required
|
||||
** database.
|
||||
*/
|
||||
int sqlite3_user_delete(
|
||||
sqlite3 *db, /* Database connection */
|
||||
const char *zUsername /* Username to remove */
|
||||
);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end of the 'extern "C"' block */
|
||||
#endif
|
||||
|
||||
#endif /* SQLITE_USER_AUTHENTICATION */
|
||||
@@ -1,176 +0,0 @@
|
||||
*********************************** NOTICE ************************************
|
||||
* This extension is deprecated. The SQLite developers do not maintain this *
|
||||
* extension. At some point in the future, it might disappear from the source *
|
||||
* tree. *
|
||||
* *
|
||||
* If you are using this extension and think it should be supported moving *
|
||||
* forward, visit the SQLite Forum (https://sqlite.org/forum) and argue your *
|
||||
* case there. *
|
||||
* *
|
||||
* This deprecation notice was added on 2024-01-22. *
|
||||
*******************************************************************************
|
||||
|
||||
Activate the user authentication logic by including the
|
||||
ext/userauth/userauth.c source code file in the build and
|
||||
adding the -DSQLITE_USER_AUTHENTICATION compile-time option.
|
||||
The ext/userauth/sqlite3userauth.h header file is available to
|
||||
applications to define the interface.
|
||||
|
||||
When using the SQLite amalgamation, it is sufficient to append
|
||||
the ext/userauth/userauth.c source file onto the end of the
|
||||
amalgamation.
|
||||
|
||||
The following new APIs are available when user authentication is
|
||||
activated:
|
||||
|
||||
int sqlite3_user_authenticate(
|
||||
sqlite3 *db, /* The database connection */
|
||||
const char *zUsername, /* Username */
|
||||
const char *aPW, /* Password or credentials */
|
||||
int nPW /* Number of bytes in aPW[] */
|
||||
);
|
||||
|
||||
int sqlite3_user_add(
|
||||
sqlite3 *db, /* Database connection */
|
||||
const char *zUsername, /* Username to be added */
|
||||
const char *aPW, /* Password or credentials */
|
||||
int nPW, /* Number of bytes in aPW[] */
|
||||
int isAdmin /* True to give new user admin privilege */
|
||||
);
|
||||
|
||||
int sqlite3_user_change(
|
||||
sqlite3 *db, /* Database connection */
|
||||
const char *zUsername, /* Username to change */
|
||||
const void *aPW, /* Modified password or credentials */
|
||||
int nPW, /* Number of bytes in aPW[] */
|
||||
int isAdmin /* Modified admin privilege for the user */
|
||||
);
|
||||
|
||||
int sqlite3_user_delete(
|
||||
sqlite3 *db, /* Database connection */
|
||||
const char *zUsername /* Username to remove */
|
||||
);
|
||||
|
||||
With this extension, a database can be marked as requiring authentication.
|
||||
By default a database does not require authentication.
|
||||
|
||||
The sqlite3_open(), sqlite3_open16(), and sqlite3_open_v2() interfaces
|
||||
work as before: they open a new database connection. However, if the
|
||||
database being opened requires authentication, then attempts to read
|
||||
or write from the database will fail with an SQLITE_AUTH error until
|
||||
after sqlite3_user_authenticate() has been called successfully. The
|
||||
sqlite3_user_authenticate() call will return SQLITE_OK if the
|
||||
authentication credentials are accepted and SQLITE_ERROR if not.
|
||||
|
||||
Calling sqlite3_user_authenticate() on a no-authentication-required
|
||||
database connection is a harmless no-op.
|
||||
|
||||
If the database is encrypted, then sqlite3_key_v2() must be called first,
|
||||
with the correct decryption key, prior to invoking sqlite3_user_authenticate().
|
||||
|
||||
To recapitulate: When opening an existing unencrypted authentication-
|
||||
required database, the call sequence is:
|
||||
|
||||
sqlite3_open_v2()
|
||||
sqlite3_user_authenticate();
|
||||
/* Database is now usable */
|
||||
|
||||
To open an existing, encrypted, authentication-required database, the
|
||||
call sequence is:
|
||||
|
||||
sqlite3_open_v2();
|
||||
sqlite3_key_v2();
|
||||
sqlite3_user_authenticate();
|
||||
/* Database is now usable */
|
||||
|
||||
When opening a no-authentication-required database, the database
|
||||
connection is treated as if it was authenticated as an admin user.
|
||||
|
||||
When ATTACH-ing new database files to a connection, each newly attached
|
||||
database that is an authentication-required database is checked using
|
||||
the same username and password as supplied to the main database. If that
|
||||
check fails, then the ATTACH command fails with an SQLITE_AUTH error.
|
||||
|
||||
The sqlite3_user_add() interface can be used (by an admin user only)
|
||||
to create a new user. When called on a no-authentication-required
|
||||
database and when A is true, the sqlite3_user_add(D,U,P,N,A) routine
|
||||
converts the database into an authentication-required database and
|
||||
logs in the database connection D as user U with password P,N.
|
||||
To convert a no-authentication-required database into an authentication-
|
||||
required database, the isAdmin parameter must be true. If
|
||||
sqlite3_user_add(D,U,P,N,A) is called on a no-authentication-required
|
||||
database and A is false, then the call fails with an SQLITE_AUTH error.
|
||||
|
||||
Any call to sqlite3_user_add() by a non-admin user results in an error.
|
||||
|
||||
Hence, to create a new, unencrypted, authentication-required database,
|
||||
the call sequence is:
|
||||
|
||||
sqlite3_open_v2();
|
||||
sqlite3_user_add();
|
||||
|
||||
And to create a new, encrypted, authentication-required database, the call
|
||||
sequence is:
|
||||
|
||||
sqlite3_open_v2();
|
||||
sqlite3_key_v2();
|
||||
sqlite3_user_add();
|
||||
|
||||
The sqlite3_user_delete() interface can be used (by an admin user only)
|
||||
to delete a user. The currently logged-in user cannot be deleted,
|
||||
which guarantees that there is always an admin user and hence that
|
||||
the database cannot be converted into a no-authentication-required
|
||||
database.
|
||||
|
||||
The sqlite3_user_change() interface can be used to change a users
|
||||
login credentials or admin privilege. Any user can change their own
|
||||
password. Only an admin user can change another users login
|
||||
credentials or admin privilege setting. No user may change their own
|
||||
admin privilege setting.
|
||||
|
||||
The sqlite3_set_authorizer() callback is modified to take a 7th parameter
|
||||
which is the username of the currently logged in user, or NULL for a
|
||||
no-authentication-required database.
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
Implementation notes:
|
||||
|
||||
An authentication-required database is identified by the presence of a
|
||||
new table:
|
||||
|
||||
CREATE TABLE sqlite_user(
|
||||
uname TEXT PRIMARY KEY,
|
||||
isAdmin BOOLEAN,
|
||||
pw BLOB
|
||||
) WITHOUT ROWID;
|
||||
|
||||
The sqlite_user table is inaccessible (unreadable and unwriteable) to
|
||||
non-admin users and is read-only for admin users. However, if the same
|
||||
database file is opened by a version of SQLite that omits
|
||||
the -DSQLITE_USER_AUTHENTICATION compile-time option, then the sqlite_user
|
||||
table will be readable by anybody and writeable by anybody if
|
||||
the "PRAGMA writable_schema=ON" statement is run first.
|
||||
|
||||
The sqlite_user.pw field is encoded by a built-in SQL function
|
||||
"sqlite_crypt(X,Y)". The two arguments are both BLOBs. The first argument
|
||||
is the plaintext password supplied to the sqlite3_user_authenticate()
|
||||
interface. The second argument is the sqlite_user.pw value and is supplied
|
||||
so that the function can extract the "salt" used by the password encoder.
|
||||
The result of sqlite_crypt(X,Y) is another blob which is the value that
|
||||
ends up being stored in sqlite_user.pw. To verify credentials X supplied
|
||||
by the sqlite3_user_authenticate() routine, SQLite runs:
|
||||
|
||||
sqlite_user.pw == sqlite_crypt(X, sqlite_user.pw)
|
||||
|
||||
To compute an appropriate sqlite_user.pw value from a new or modified
|
||||
password X, sqlite_crypt(X,NULL) is run. A new random salt is selected
|
||||
when the second argument is NULL.
|
||||
|
||||
The built-in version of of sqlite_crypt() uses a simple Ceasar-cypher
|
||||
which prevents passwords from being revealed by searching the raw database
|
||||
for ASCII text, but is otherwise trivally broken. For better password
|
||||
security, the database should be encrypted using the SQLite Encryption
|
||||
Extension or similar technology. Or, the application can use the
|
||||
sqlite3_create_function() interface to provide an alternative
|
||||
implementation of sqlite_crypt() that computes a stronger password hash,
|
||||
perhaps using a cryptographic hash function like SHA1.
|
||||
@@ -1,355 +0,0 @@
|
||||
/*
|
||||
** 2014-09-08
|
||||
**
|
||||
** The author disclaims copyright to this source code. In place of
|
||||
** a legal notice, here is a blessing:
|
||||
**
|
||||
** May you do good and not evil.
|
||||
** May you find forgiveness for yourself and forgive others.
|
||||
** May you share freely, never taking more than you give.
|
||||
**
|
||||
*************************************************************************
|
||||
**
|
||||
** This file contains the bulk of the implementation of the
|
||||
** user-authentication extension feature. Some parts of the user-
|
||||
** authentication code are contained within the SQLite core (in the
|
||||
** src/ subdirectory of the main source code tree) but those parts
|
||||
** that could reasonable be separated out are moved into this file.
|
||||
**
|
||||
** To compile with the user-authentication feature, append this file to
|
||||
** end of an SQLite amalgamation, then add the SQLITE_USER_AUTHENTICATION
|
||||
** compile-time option. See the user-auth.txt file in the same source
|
||||
** directory as this file for additional information.
|
||||
*/
|
||||
#ifdef SQLITE_USER_AUTHENTICATION
|
||||
#ifndef SQLITEINT_H
|
||||
# include "sqliteInt.h"
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Prepare an SQL statement for use by the user authentication logic.
|
||||
** Return a pointer to the prepared statement on success. Return a
|
||||
** NULL pointer if there is an error of any kind.
|
||||
*/
|
||||
static sqlite3_stmt *sqlite3UserAuthPrepare(
|
||||
sqlite3 *db,
|
||||
const char *zFormat,
|
||||
...
|
||||
){
|
||||
sqlite3_stmt *pStmt;
|
||||
char *zSql;
|
||||
int rc;
|
||||
va_list ap;
|
||||
u64 savedFlags = db->flags;
|
||||
|
||||
va_start(ap, zFormat);
|
||||
zSql = sqlite3_vmprintf(zFormat, ap);
|
||||
va_end(ap);
|
||||
if( zSql==0 ) return 0;
|
||||
db->flags |= SQLITE_WriteSchema;
|
||||
rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
|
||||
db->flags = savedFlags;
|
||||
sqlite3_free(zSql);
|
||||
if( rc ){
|
||||
sqlite3_finalize(pStmt);
|
||||
pStmt = 0;
|
||||
}
|
||||
return pStmt;
|
||||
}
|
||||
|
||||
/*
|
||||
** Check to see if the sqlite_user table exists in database zDb.
|
||||
*/
|
||||
static int userTableExists(sqlite3 *db, const char *zDb){
|
||||
int rc;
|
||||
sqlite3_mutex_enter(db->mutex);
|
||||
sqlite3BtreeEnterAll(db);
|
||||
if( db->init.busy==0 ){
|
||||
char *zErr = 0;
|
||||
sqlite3Init(db, &zErr);
|
||||
sqlite3DbFree(db, zErr);
|
||||
}
|
||||
rc = sqlite3FindTable(db, "sqlite_user", zDb)!=0;
|
||||
sqlite3BtreeLeaveAll(db);
|
||||
sqlite3_mutex_leave(db->mutex);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Check to see if database zDb has a "sqlite_user" table and if it does
|
||||
** whether that table can authenticate zUser with nPw,zPw. Write one of
|
||||
** the UAUTH_* user authorization level codes into *peAuth and return a
|
||||
** result code.
|
||||
*/
|
||||
static int userAuthCheckLogin(
|
||||
sqlite3 *db, /* The database connection to check */
|
||||
const char *zDb, /* Name of specific database to check */
|
||||
u8 *peAuth /* OUT: One of UAUTH_* constants */
|
||||
){
|
||||
sqlite3_stmt *pStmt;
|
||||
int rc;
|
||||
|
||||
*peAuth = UAUTH_Unknown;
|
||||
if( !userTableExists(db, "main") ){
|
||||
*peAuth = UAUTH_Admin; /* No sqlite_user table. Everybody is admin. */
|
||||
return SQLITE_OK;
|
||||
}
|
||||
if( db->auth.zAuthUser==0 ){
|
||||
*peAuth = UAUTH_Fail;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
pStmt = sqlite3UserAuthPrepare(db,
|
||||
"SELECT pw=sqlite_crypt(?1,pw), isAdmin FROM \"%w\".sqlite_user"
|
||||
" WHERE uname=?2", zDb);
|
||||
if( pStmt==0 ) return SQLITE_NOMEM;
|
||||
sqlite3_bind_blob(pStmt, 1, db->auth.zAuthPW, db->auth.nAuthPW,SQLITE_STATIC);
|
||||
sqlite3_bind_text(pStmt, 2, db->auth.zAuthUser, -1, SQLITE_STATIC);
|
||||
rc = sqlite3_step(pStmt);
|
||||
if( rc==SQLITE_ROW && sqlite3_column_int(pStmt,0) ){
|
||||
*peAuth = sqlite3_column_int(pStmt, 1) + UAUTH_User;
|
||||
}else{
|
||||
*peAuth = UAUTH_Fail;
|
||||
}
|
||||
return sqlite3_finalize(pStmt);
|
||||
}
|
||||
int sqlite3UserAuthCheckLogin(
|
||||
sqlite3 *db, /* The database connection to check */
|
||||
const char *zDb, /* Name of specific database to check */
|
||||
u8 *peAuth /* OUT: One of UAUTH_* constants */
|
||||
){
|
||||
int rc;
|
||||
u8 savedAuthLevel;
|
||||
assert( zDb!=0 );
|
||||
assert( peAuth!=0 );
|
||||
savedAuthLevel = db->auth.authLevel;
|
||||
db->auth.authLevel = UAUTH_Admin;
|
||||
rc = userAuthCheckLogin(db, zDb, peAuth);
|
||||
db->auth.authLevel = savedAuthLevel;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** If the current authLevel is UAUTH_Unknown, the take actions to figure
|
||||
** out what authLevel should be
|
||||
*/
|
||||
void sqlite3UserAuthInit(sqlite3 *db){
|
||||
if( db->auth.authLevel==UAUTH_Unknown ){
|
||||
u8 authLevel = UAUTH_Fail;
|
||||
sqlite3UserAuthCheckLogin(db, "main", &authLevel);
|
||||
db->auth.authLevel = authLevel;
|
||||
if( authLevel<UAUTH_Admin ) db->flags &= ~SQLITE_WriteSchema;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Implementation of the sqlite_crypt(X,Y) function.
|
||||
**
|
||||
** If Y is NULL then generate a new hash for password X and return that
|
||||
** hash. If Y is not null, then generate a hash for password X using the
|
||||
** same salt as the previous hash Y and return the new hash.
|
||||
*/
|
||||
void sqlite3CryptFunc(
|
||||
sqlite3_context *context,
|
||||
int NotUsed,
|
||||
sqlite3_value **argv
|
||||
){
|
||||
const char *zIn;
|
||||
int nIn, ii;
|
||||
u8 *zOut;
|
||||
char zSalt[8];
|
||||
zIn = sqlite3_value_blob(argv[0]);
|
||||
nIn = sqlite3_value_bytes(argv[0]);
|
||||
if( sqlite3_value_type(argv[1])==SQLITE_BLOB
|
||||
&& sqlite3_value_bytes(argv[1])==nIn+sizeof(zSalt)
|
||||
){
|
||||
memcpy(zSalt, sqlite3_value_blob(argv[1]), sizeof(zSalt));
|
||||
}else{
|
||||
sqlite3_randomness(sizeof(zSalt), zSalt);
|
||||
}
|
||||
zOut = sqlite3_malloc( nIn+sizeof(zSalt) );
|
||||
if( zOut==0 ){
|
||||
sqlite3_result_error_nomem(context);
|
||||
}else{
|
||||
memcpy(zOut, zSalt, sizeof(zSalt));
|
||||
for(ii=0; ii<nIn; ii++){
|
||||
zOut[ii+sizeof(zSalt)] = zIn[ii]^zSalt[ii&0x7];
|
||||
}
|
||||
sqlite3_result_blob(context, zOut, nIn+sizeof(zSalt), sqlite3_free);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** If a database contains the SQLITE_USER table, then the
|
||||
** sqlite3_user_authenticate() interface must be invoked with an
|
||||
** appropriate username and password prior to enable read and write
|
||||
** access to the database.
|
||||
**
|
||||
** Return SQLITE_OK on success or SQLITE_ERROR if the username/password
|
||||
** combination is incorrect or unknown.
|
||||
**
|
||||
** If the SQLITE_USER table is not present in the database file, then
|
||||
** this interface is a harmless no-op returnning SQLITE_OK.
|
||||
*/
|
||||
int sqlite3_user_authenticate(
|
||||
sqlite3 *db, /* The database connection */
|
||||
const char *zUsername, /* Username */
|
||||
const char *zPW, /* Password or credentials */
|
||||
int nPW /* Number of bytes in aPW[] */
|
||||
){
|
||||
int rc;
|
||||
u8 authLevel = UAUTH_Fail;
|
||||
db->auth.authLevel = UAUTH_Unknown;
|
||||
sqlite3_free(db->auth.zAuthUser);
|
||||
sqlite3_free(db->auth.zAuthPW);
|
||||
memset(&db->auth, 0, sizeof(db->auth));
|
||||
db->auth.zAuthUser = sqlite3_mprintf("%s", zUsername);
|
||||
if( db->auth.zAuthUser==0 ) return SQLITE_NOMEM;
|
||||
db->auth.zAuthPW = sqlite3_malloc( nPW+1 );
|
||||
if( db->auth.zAuthPW==0 ) return SQLITE_NOMEM;
|
||||
memcpy(db->auth.zAuthPW,zPW,nPW);
|
||||
db->auth.nAuthPW = nPW;
|
||||
rc = sqlite3UserAuthCheckLogin(db, "main", &authLevel);
|
||||
db->auth.authLevel = authLevel;
|
||||
sqlite3ExpirePreparedStatements(db, 0);
|
||||
if( rc ){
|
||||
return rc; /* OOM error, I/O error, etc. */
|
||||
}
|
||||
if( authLevel<UAUTH_User ){
|
||||
return SQLITE_AUTH; /* Incorrect username and/or password */
|
||||
}
|
||||
return SQLITE_OK; /* Successful login */
|
||||
}
|
||||
|
||||
/*
|
||||
** The sqlite3_user_add() interface can be used (by an admin user only)
|
||||
** to create a new user. When called on a no-authentication-required
|
||||
** database, this routine converts the database into an authentication-
|
||||
** required database, automatically makes the added user an
|
||||
** administrator, and logs in the current connection as that user.
|
||||
** The sqlite3_user_add() interface only works for the "main" database, not
|
||||
** for any ATTACH-ed databases. Any call to sqlite3_user_add() by a
|
||||
** non-admin user results in an error.
|
||||
*/
|
||||
int sqlite3_user_add(
|
||||
sqlite3 *db, /* Database connection */
|
||||
const char *zUsername, /* Username to be added */
|
||||
const char *aPW, /* Password or credentials */
|
||||
int nPW, /* Number of bytes in aPW[] */
|
||||
int isAdmin /* True to give new user admin privilege */
|
||||
){
|
||||
sqlite3_stmt *pStmt;
|
||||
int rc;
|
||||
sqlite3UserAuthInit(db);
|
||||
if( db->auth.authLevel<UAUTH_Admin ) return SQLITE_AUTH;
|
||||
if( !userTableExists(db, "main") ){
|
||||
if( !isAdmin ) return SQLITE_AUTH;
|
||||
pStmt = sqlite3UserAuthPrepare(db,
|
||||
"CREATE TABLE sqlite_user(\n"
|
||||
" uname TEXT PRIMARY KEY,\n"
|
||||
" isAdmin BOOLEAN,\n"
|
||||
" pw BLOB\n"
|
||||
") WITHOUT ROWID;");
|
||||
if( pStmt==0 ) return SQLITE_NOMEM;
|
||||
sqlite3_step(pStmt);
|
||||
rc = sqlite3_finalize(pStmt);
|
||||
if( rc ) return rc;
|
||||
}
|
||||
pStmt = sqlite3UserAuthPrepare(db,
|
||||
"INSERT INTO sqlite_user(uname,isAdmin,pw)"
|
||||
" VALUES(%Q,%d,sqlite_crypt(?1,NULL))",
|
||||
zUsername, isAdmin!=0);
|
||||
if( pStmt==0 ) return SQLITE_NOMEM;
|
||||
sqlite3_bind_blob(pStmt, 1, aPW, nPW, SQLITE_STATIC);
|
||||
sqlite3_step(pStmt);
|
||||
rc = sqlite3_finalize(pStmt);
|
||||
if( rc ) return rc;
|
||||
if( db->auth.zAuthUser==0 ){
|
||||
assert( isAdmin!=0 );
|
||||
sqlite3_user_authenticate(db, zUsername, aPW, nPW);
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** The sqlite3_user_change() interface can be used to change a users
|
||||
** login credentials or admin privilege. Any user can change their own
|
||||
** login credentials. Only an admin user can change another users login
|
||||
** credentials or admin privilege setting. No user may change their own
|
||||
** admin privilege setting.
|
||||
*/
|
||||
int sqlite3_user_change(
|
||||
sqlite3 *db, /* Database connection */
|
||||
const char *zUsername, /* Username to change */
|
||||
const char *aPW, /* Modified password or credentials */
|
||||
int nPW, /* Number of bytes in aPW[] */
|
||||
int isAdmin /* Modified admin privilege for the user */
|
||||
){
|
||||
sqlite3_stmt *pStmt;
|
||||
int rc;
|
||||
u8 authLevel;
|
||||
|
||||
authLevel = db->auth.authLevel;
|
||||
if( authLevel<UAUTH_User ){
|
||||
/* Must be logged in to make a change */
|
||||
return SQLITE_AUTH;
|
||||
}
|
||||
if( strcmp(db->auth.zAuthUser, zUsername)!=0 ){
|
||||
if( db->auth.authLevel<UAUTH_Admin ){
|
||||
/* Must be an administrator to change a different user */
|
||||
return SQLITE_AUTH;
|
||||
}
|
||||
}else if( isAdmin!=(authLevel==UAUTH_Admin) ){
|
||||
/* Cannot change the isAdmin setting for self */
|
||||
return SQLITE_AUTH;
|
||||
}
|
||||
db->auth.authLevel = UAUTH_Admin;
|
||||
if( !userTableExists(db, "main") ){
|
||||
/* This routine is a no-op if the user to be modified does not exist */
|
||||
}else{
|
||||
pStmt = sqlite3UserAuthPrepare(db,
|
||||
"UPDATE sqlite_user SET isAdmin=%d, pw=sqlite_crypt(?1,NULL)"
|
||||
" WHERE uname=%Q", isAdmin, zUsername);
|
||||
if( pStmt==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
sqlite3_bind_blob(pStmt, 1, aPW, nPW, SQLITE_STATIC);
|
||||
sqlite3_step(pStmt);
|
||||
rc = sqlite3_finalize(pStmt);
|
||||
}
|
||||
}
|
||||
db->auth.authLevel = authLevel;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** The sqlite3_user_delete() interface can be used (by an admin user only)
|
||||
** to delete a user. The currently logged-in user cannot be deleted,
|
||||
** which guarantees that there is always an admin user and hence that
|
||||
** the database cannot be converted into a no-authentication-required
|
||||
** database.
|
||||
*/
|
||||
int sqlite3_user_delete(
|
||||
sqlite3 *db, /* Database connection */
|
||||
const char *zUsername /* Username to remove */
|
||||
){
|
||||
sqlite3_stmt *pStmt;
|
||||
if( db->auth.authLevel<UAUTH_Admin ){
|
||||
/* Must be an administrator to delete a user */
|
||||
return SQLITE_AUTH;
|
||||
}
|
||||
if( strcmp(db->auth.zAuthUser, zUsername)==0 ){
|
||||
/* Cannot delete self */
|
||||
return SQLITE_AUTH;
|
||||
}
|
||||
if( !userTableExists(db, "main") ){
|
||||
/* This routine is a no-op if the user to be deleted does not exist */
|
||||
return SQLITE_OK;
|
||||
}
|
||||
pStmt = sqlite3UserAuthPrepare(db,
|
||||
"DELETE FROM sqlite_user WHERE uname=%Q", zUsername);
|
||||
if( pStmt==0 ) return SQLITE_NOMEM;
|
||||
sqlite3_step(pStmt);
|
||||
return sqlite3_finalize(pStmt);
|
||||
}
|
||||
|
||||
#endif /* SQLITE_USER_AUTHENTICATION */
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user