diff --git a/manifest b/manifest index 50ec5c7beb..bbe26c7268 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\strunk\senhancements\sinto\sthe\sbegin-concurrent\sbranch. -D 2022-02-04T17:40:59.906 +C Merge\sthe\slatest\strunk\schanges\sinto\sthe\sbegin-concurrent\sbranch. +D 2022-02-15T20:18:11.423 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -490,29 +490,29 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786 F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a -F src/alter.c e8ac1df663bf4ec74920edd1299435f2a616d2404de0ac4013c151ea4e7a11f2 +F src/alter.c e31cae888bc3077e34f9a82c6b4a96e4e44d37861eeb6472d68a378f1e8e46ba F src/analyze.c 7518b99e07c5494111fe3bd867f28f804b6c5c1ad0703ec3d116de9bab3fa516 F src/attach.c f26d400f3ffe2cdca01406bca70e5f58c5488bf165b4fc37c228136dfcf1b583 F src/auth.c f4fa91b6a90bbc8e0d0f738aa284551739c9543a367071f55574681e0f24f8cf F src/backup.c a2891172438e385fdbe97c11c9745676bec54f518d4447090af97189fd8e52d7 F src/bitvec.c 3907fcbe8a0c8c2db58d97087d15cdabbf2842adb9125df9ab9ff87d3db16775 F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6 -F src/btree.c bdcf1b01f61807ea66e40c8259235ba6d865f23daea05b9e6eeb22343befe941 +F src/btree.c 701beb1950402930d304de7dd96ea62e5682f15a88453c695121c4984cac45b6 F src/btree.h 900067641b64d619e6e2a93bd115c952a52f41d3bee32e551e2a4ceee05fc431 F src/btreeInt.h 3f19f0be5af0b68cff55e58df4b11e7a0692d9e8a820ceaeba4084659a86cf28 -F src/build.c d62a68c0bcefc4a1154e3f44424b3c3c74699c6a30fb9535e2cbedb9c376a9ff +F src/build.c e654e5dacff941bb88177bbb3c69d9dfbe6efd302cea018b5ebf1f7b224be9aa F src/callback.c 4c19af69835787bfe790ac560f3071a824eb629f34e41f97b52ce5235c77de1c F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e F src/ctime.c 2cce39df1a13e05b7633e6d21b651f21492471f991dd7b323a4ee4e7b7f0b7f1 -F src/date.c 41627dec396f3d33e2c317a065f9d59bb535982b2ea3a561c96e4d4cf1137b65 +F src/date.c 1fcc64294b0e81cc9fa05cf8f773e862dd004f74d023544d43edeeacbcfde7e5 F src/dbpage.c 8a01e865bf8bc6d7b1844b4314443a6436c07c3efe1d488ed89e81719047833a F src/dbstat.c 861e08690fcb0f2ee1165eff0060ea8d4f3e2ea10f80dab7d32ad70443a6ff2d F src/delete.c b5f1716b4d723db48254ee0f896e362cd029e865e05414139ea7f539f3884e1d -F src/expr.c 31d23e6b57827b4cb8f0054f44e2ed86feb1dfcaa9b0c4d6c960b42536a17ca0 +F src/expr.c b90a029105a93a93a0ed5e5f8c5eaed8f19043a3b62e4c4d235a4611d9ada178 F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 F src/fkey.c 06e4ac33031b02dde7130c12e79cddf4dc5cfa72b23d8e63a3c26878fc9c1d3c -F src/func.c 1c25ea71ccfa323e713306755d8d757404c93b8291867ec3a93550fcae23aa51 -F src/global.c 1f56aead86e8a18c4415638f5e6c4d0a0550427f4b3f5d065ba5164cc09c22e8 +F src/func.c 64e37fded60afe8af2ccea05ab7217dfee55100c0b0a9d777ba34111c0c5b6eb +F src/global.c a3daa18a1696aadd94f18d37cbbdebf0bbdb827b8397a534f021cd56c15cd0f9 F src/hash.c 8d7dda241d0ebdafb6ffdeda3149a412d7df75102cecfc1021c98d6219823b19 F src/hash.h 3340ab6e1d13e725571d7cee6d3e3135f0779a7d8e76a9ce0a85971fa3953c51 F src/hwtime.h cb1d7e3e1ed94b7aa6fde95ae2c2daccc3df826be26fc9ed7fd90d1750ae6144 @@ -521,7 +521,7 @@ F src/insert.c 1eea44389de3768ac98588c1410171cd53e7c6ad1af74049983dcbac82093de0 F src/json.c 225b00422112ecd7094a555f3ace16b25d7d5894062b823269ed03899907c2a2 F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa F src/loadext.c aa919a6a7884f8b34d7b791841b24d14b1b0ab43f45b3940f4851043b2855c0c -F src/main.c 4806307e415189bbf91df6467d6ff923643fdeb84e782ef0d5451a14465db935 +F src/main.c 4fa5379ff5981bc1e35bc988dc908e5bb9b84f820cd7eebae88ce6ae8617b624 F src/malloc.c fec841aa0a0400a6f7d20706178a5d8e8219a6bf562b6fe712c17f6c26813266 F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de @@ -529,7 +529,7 @@ F src/mem2.c c8bfc9446fd0798bddd495eb5d9dbafa7d4b7287d8c22d50a83ac9daa26d8a75 F src/mem3.c 30301196cace2a085cbedee1326a49f4b26deff0af68774ca82c1f7c06fda4f6 F src/mem5.c 9bf955937b07f8c32541c8a9991f33ce3173d944 F src/memdb.c c2dc88f97c410eb68a24468344b65526685e18354ddfd15906750c1eaf9dc2dd -F src/memjournal.c ff4336a98b05ede2adee7595f22d6f7d1cdc6bf0f0a5c3d77b0acdf017b2e8b2 +F src/memjournal.c 8bd50ae6d9c6d34b3a96cc3b4f567f9935dc358444d872ab48901a8c11ad82a6 F src/msvc.h 3a15918220367a8876be3fa4f2abe423a861491e84b864fb2b7426bf022a28f8 F src/mutex.c 5e3409715552348732e97b9194abe92fdfcd934cfb681df4ba0ab87ac6c18d25 F src/mutex.h a7b2293c48db5f27007c3bdb21d438873637d12658f5a0bf8ad025bb96803c4a @@ -544,30 +544,30 @@ F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586 F src/os_unix.c d6815223d2a91a63b34d240a98f51341e74f8aabd3f8391fb3131c0ab1bd4b1e F src/os_win.c 77d39873836f1831a9b0b91894fec45ab0e9ca8e067dc8c549e1d1eca1566fe9 F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a -F src/pager.c 40b9f9525ba45151d508569ef339eab70929250712d449fb93d3ac0a575d7748 +F src/pager.c 99a8603017943185b2e01557e25aca8ce831e7ff7c84c9761b93f4ea2985eb52 F src/pager.h fdc30693c403aa9b4293d0b126346db7e450f8f0e5d2c1bb8355acb1cb8da6fd -F src/parse.y c7c307018e6d328523833cf7ee7738cf95e81c2b272e97076665caf9221fc9a2 +F src/parse.y 34748e63f17252faa9b0176a912bf83bac2f02f1f18b027480cc1caaa4c88222 F src/pcache.c 084e638432c610f95aea72b8509f0845d2791293f39d1b82f0c0a7e089c3bb6b F src/pcache.h 4f87acd914cef5016fae3030343540d75f5b85a1877eed1a2a19b9f284248586 F src/pcache1.c 54881292a9a5db202b2c0ac541c5e3ef9a5e8c4f1c1383adb2601d5499a60e65 F src/pragma.c 7c024d690a3dc93f61830f11f900e4af2357f31d081b0c79099ca5e28919cba7 F src/pragma.h f98354c48571c490927029510566839bf9e7242569bfbb48032dafeb008481d2 F src/prepare.c a187dade741c1f09ae118fcbbf0302511807bfc0355880927d7152eb75b8260d -F src/printf.c 975f1f5417f2526365b6e6d7f22332e3e11806dad844701d92846292b654ba9a +F src/printf.c 05d8dfd2018bc4fc3ddb8b37eb97ccef7abf985643fa1caebdcf2916ca90fa32 F src/random.c d4127b3d8ba155e293cc1abb19f70992c147abd5cc911df25582cb481b705974 -F src/resolve.c 0dd8e23fda88411d63b2e6650f2380fdb08e88112e9a095fc23d5a08de4b2641 +F src/resolve.c ea935b87d6fb36c78b70cdc7b28561dc8f33f2ef37048389549c7b5ef9b0ba5e F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92 -F src/select.c 23af49702cfb73e604f5befcebddb089d285a9a7ddf786e0a04920ff6a0fce21 -F src/shell.c.in 5d1b61ed8641cf470534d360b91ebcf7487559121be04ed330a7bd3ece42dc40 -F src/sqlite.h.in 3b3ce1eac1cab6298530e38b03d7b9cbc28918e865ff64c3e1c70781e43f197b +F src/select.c 9f660188fffb63b7fa5db8fcee791277a6307e43922d7765c26e8a0754b6423e +F src/shell.c.in 125b2c6d7c91716e2d79d132428549f371bd294a810dc5c0213fad4878f34ccb +F src/sqlite.h.in 0ac519ae7771eff5d093b9b39d8bb5e8281ddd1bdc6424c792dbb9763c4607cf F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h a95cb9ed106e3d39e2118e4dcc15a14faec3fa50d0093425083d340d9dfd96e6 -F src/sqliteInt.h 21f4ad9b41ce7c5decd5398ada43468d4c07de8dd3cdcee02a06e937231fcc4f +F src/sqliteInt.h 16215a0d9366ee72a158454360e74e5d28ddc987e0e3b28ca0f36251092d8ee4 F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a31657 F src/status.c 4b8bc2a6905163a38b739854a35b826c737333fab5b1f8e03fa7eb9a4799c4c1 F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1 F src/tclsqlite.c 48f291e1a7e672a7204884d4c164a8ed3a522ff087c361ada2991f5d54e987f6 -F src/test1.c 5d39b01f7ce4c0d50e1e83c574e1693de2e88036aa298bc156a03b7d388f6ca1 +F src/test1.c 85b55c1154f0568856f7c8a93c8549613595b7d861803a7dca7b056383ba2ace F src/test2.c 3efb99ab7f1fc8d154933e02ae1378bac9637da5 F src/test3.c 61798bb0d38b915067a8c8e03f5a534b431181f802659a6616f9b4ff7d872644 F src/test4.c 7c4420e01c577b5c4add2cb03119743b1a357543d347773b9e717195ea967159 @@ -621,9 +621,9 @@ F src/test_windirent.h 90dfbe95442c9762357fe128dc7ae3dc199d006de93eb33ba3972e0a9 F src/test_window.c cdae419fdcea5bad6dcd9368c685abdad6deb59e9fc8b84b153de513d394ba3f F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9 F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c -F src/tokenize.c b74d878aa7c82ec8460779468061a96185e22257f68ab785b69abce354b70446 -F src/treeview.c 9dfdb7ff7f6645d0a6458dbdf4ffac041c071c4533a6db8bb6e502b979ac67bc -F src/trigger.c 692972e4393dfc8017a1a527c1ea1b96ce3d101e84584cd832fcfb83d22b50b2 +F src/tokenize.c 6661a9fa660ecbd3ac0df1acd2ec788b3a8122b4316022bcdaf476ea6754a8de +F src/treeview.c a84b57d15e46007d8b1ae249344b3f0b7f3c62def908b98baaa54935a57c8476 +F src/trigger.c 19fc6fe696a2409b04496df1ff044e6a942dad6ed3b6e897b1c9093b88cc2c62 F src/update.c ee9b4f2a29d93af457b098a80ef34d2228dc38e951910430ea04eb3e81de2b68 F src/upsert.c 8789047a8f0a601ea42fa0256d1ba3190c13746b6ba940fe2d25643a7e991937 F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0 @@ -632,8 +632,8 @@ F src/vacuum.c 72867c740476d13f1c397015e4d3168b4e96a237a80b9afa67e1bb8500bfeeab F src/vdbe.c c3f0c0e71d08b37ec11757f3f3a055b064c7c9ada24774eb1f70ffc1214562a0 F src/vdbe.h 25dabb25c7e157b84e59260cfb5b466c3ac103ede9f36f4db371332c47601abe F src/vdbeInt.h b45599a2b59f1ce042512ab6786b0b82a8cf3002f6b0fa60b4834e2cd3ac61d8 -F src/vdbeapi.c 06bff35393ca5daa3e02e38fb516df320bd52720a2781eb70c2db23ea1c746dd -F src/vdbeaux.c 312d57e71e6e152243867390308aec667e05a4e7e676a674114a33f6687d3702 +F src/vdbeapi.c 8863ffb5a7bac42fe9a68aaa3526ee29fc18fb02a9b27188b756de41e33856e9 +F src/vdbeaux.c d0fed930f5c63fd49c0e0f4e576e3fa03078614497154ebeb2e7aa2cdd144802 F src/vdbeblob.c 5e61ce31aca17db8fb60395407457a8c1c7fb471dde405e0cd675974611dcfcd F src/vdbemem.c eb6042667c02c3ef1f968235b4a170e31b23a4b6a57f65a8454eab4d36f14b7f F src/vdbesort.c 43756031ca7430f7aec3ef904824a7883c4ede783e51f280d99b9b65c0796e35 @@ -644,10 +644,10 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c 419c0a98dd65b9419fd07bdd4f9facc61143c33d57b0dbeffd83cf38a2e0e33e F src/wal.h 7ffe787437f20a098af347011967a6d3bb8e5c3dc645e6be59eff44d2b2c5297 F src/walker.c f890a3298418d7cba3b69b8803594fdc484ea241206a8dfa99db6dd36f8cbb3b -F src/where.c 31bc1f43b0bf679e93c3e7a7d67cbcaddc7ae746694b149b282427d337b06caa +F src/where.c 0d75d7514764726409ea945520fe9fb515e7d9ae52a5a3c0a136142cfaa19087 F src/whereInt.h 15d2975c3b4c193c78c26674400a840da8647fe1777ae3b026e2d15937b38a03 -F src/wherecode.c 4a0dd0403e1c9b628a420eefbe1d60da0003356de6ee18e6707480c9b995bae7 -F src/whereexpr.c 2da56404a024dc8dc41a31d8b498eed2c7c6b0bb412150d88cb3327516aa3b9f +F src/wherecode.c 6150f51c0368be941fad90a736ce37cc1e2a719876750a3183a516ed256a4cbb +F src/whereexpr.c 2a71f5491798460c9590317329234d332d9eb1717cba4f3403122189a75c465e F src/window.c dfaec4abc6012cbc18e4a202ca3a5d5a0efcc4011d86a06d882ddaab8aedee4d F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/affinity2.test ce1aafc86e110685b324e9a763eab4f2a73f737842ec3b687bd965867de90627 @@ -662,18 +662,18 @@ F test/alter3.test ffc4ab29ce78a3517a66afd69b2730667e3471622509c283b2bd4c46f680f F test/alter4.test 716caa071dd8a3c6d57225778d15d3c3cbf5e34b2e84ae44199aeb2bbf50a707 F test/alterauth.test 63442ba61ceb0c1eeb63aac1f4f5cebfa509d352276059d27106ae256bafc959 F test/alterauth2.test 48967abae0494d9a300d1c92473d99fcb66edfcc23579c89322f033f49410adc -F test/altercol.test 9471187fe155d9c4211ae185e104ff48ce8f114262ee1256cf1e110b339c725f +F test/altercol.test 8465ca659c2c55a359cf16cc261df4fcb5c45a5f104a50827c337ae66c09dc15 F test/altercorrupt.test 2e1d705342cf9d7de884518ddbb053fd52d7e60d2b8869b7b63b2fda68435c12 F test/alterdropcol.test a653a3945f964d26845ec0cd0a8e74189f46de3119a984c5bc45457da392612e F test/alterdropcol2.test 527fce683b200d620f560f666c44ae33e22728e990a10a48a543280dfd4b4d41 F test/alterfault.test 289067108947bedca27534edd4ff251bcd298cf84402d7b24eaa3749305418c6 F test/alterlegacy.test f38c6d06cda39e1f7b955bbce57f2e3ef5b7cb566d3d1234502093e228c15811 F test/altermalloc.test 167a47de41b5c638f5f5c6efb59784002b196fff70f98d9b4ed3cd74a3fb80c9 -F test/altermalloc2.test ca3ebc01670d9313953a2b7628d8cc00dc5ea9988f229b3cbbbe1cca506dae45 -F test/altermalloc3.test 4660ac6240a8c82ba3947b927612dcc7c05a8eec3fe3c9f38e047ca69a789a33 +F test/altermalloc2.test 17fb3724c4b004c469c27dc4ef181608aa644555fbd3f3236767584f73747c81 +F test/altermalloc3.test 55e606edf4b0acfbbd851ddfe93cfdddfae43d103644dcfd6008ae4ab3c44adf F test/alterqf.test 3008318ba9e16b4ac0b5f83cf7683caa4b0a3154aafe3b4099838a250d4ba74a F test/altertab.test 7273b8506eab46342be016af78028df49f3bd99037412f997a8f1011b37a6912 -F test/altertab2.test b0d62f323ca5dab42b0bc028c52e310ebdd13e655e8fac070fe622bad7852c2b +F test/altertab2.test 62597b6fd08feaba1b6bfe7d31dac6117c67e06dc9ce9c478a3abe75b5926de0 F test/altertab3.test 5929f522fd6fd708396ad9f317d4af9ff1a93e460df85bb1d54d4499eeb94960 F test/amatch1.test b5ae7065f042b7f4c1c922933f4700add50cdb9f F test/analyze.test 547bb700f903107b38611b014ca645d6b5bb819f5210d7bf39c40802aafeb7d7 @@ -745,6 +745,7 @@ F test/bigmmap.test b820c234daa56d24bc3bf006e3ac7aa9d9623c8ac656a38f59063b444a2d F test/bigrow.test f0aeb7573dcb8caaafea76454be3ade29b7fc747 F test/bigsort.test 8299fa9298f4f1e02fc7d2712e8b77d6cd60e5a2 F test/bind.test 1e136709b306f7ed3192d349c2930d89df6ab621654ad6f1a72381d3fe76f483 +F test/bind2.test 918bc35135f4141809ead7585909cde57d44db90a7a62aef540127148f91aab7 F test/bindxfer.test efecd12c580c14df5f4ad3b3e83c667744a4f7e0 F test/bitvec.test 75894a880520164d73b1305c1c3f96882615e142 F test/blob.test e7ac6c7d3a985cc4678c64f325292529a69ae252 @@ -851,7 +852,7 @@ F test/ctime.test 340f362f41f92972bbd71f44e10569a5cc694062b692231bd08aa6fe6c1c47 F test/cursorhint.test 0175e4404181ace3ceca8b114eb0a98eae600d565aa4e2705abbe6614c7fe201 F test/cursorhint2.test 6f3aa9cb19e7418967a10ec6905209bcbb5968054da855fc36c8beee9ae9c42f F test/dataversion1.test 6e5e86ac681f0782e766ebcb56c019ae001522d114e0e111e5ebf68ccf2a7bb8 -F test/date.test 9b73bbeb1b82d9c1f44dec5cf563bf7da58d2373 +F test/date.test 50d5b1eeec57041c000d2be5e9ab995026ded4255507f0206c81c1ca3b34b840 F test/date2.test 7e12ec14aaf4d5e6294b4ba140445b0eca06ea50062a9c3a69c4ee13d0b6f8b1 F test/date3.test a1b77abf05c6772fe5ca2337cac1398892f2a41e62bce7e6be0f4a08a0e64ae5 F test/dbdata.test 042f49acff3438f940eeba5868d3af080ae64ddf26ae78f80c92bec3ca7d8603 @@ -881,7 +882,7 @@ F test/e_blobclose.test 692fc02a058476c2222a63d97e3f3b2b809c1842e5525ded7f854d54 F test/e_blobopen.test 29f6055ee453b8e679fe9570c4d3acfedbef821622c5dad16875148c5952ef50 F test/e_blobwrite.test 3075ff539827576d9a34cbb5a2ac75eb65fb49cd5aadc27686b0719fbf99c156 F test/e_changes.test 0f8c3e6aab7335cb772d5a3ea34ca4c82f98d0eb896e2eb3add971c16984b405 -F test/e_createtable.test 04c50b7fe41c12ed9cd88fbbc09b4900bcfc66f98ad198874fc993a2771f3913 +F test/e_createtable.test e3b9782e80c0cf2898ac0eb1d9cd058412955ff53a8e47307a60c8289d62ff9c F test/e_delete.test ab39084f26ae1f033c940b70ebdbbd523dc4962e F test/e_droptrigger.test 235c610f8bf8ec44513e222b9085c7e49fad65ad0c1975ac2577109dd06fd8fa F test/e_dropview.test 74e405df7fa0f762e0c9445b166fe03955856532e2bb234c372f7c51228d75e7 @@ -1072,13 +1073,13 @@ F test/func5.test 863e6d1bd0013d09c17236f8a13ea34008dd857d87d85a13a673960e4c25d8 F test/func6.test 90e42b64c4f9fb6f04f44cb8a1da586c8542502e926b19c76504fe74ff2a9b7c F test/func7.test b9e2a1a30a8562b00841b4a21a5d2d81754fa3ab99275fd71fd5279287b44b1c F test/fuzz-oss1.test 514dcabb24687818ea949fa6760229eaacad74ca70157743ef36d35bbe01ffb0 -F test/fuzz.test 96083052bf5765e4518c1ba686ce2bab785670d1 +F test/fuzz.test 4608c1310cff4c3014a84bcced6278139743e080046e5f6784b0de7b069371d8 F test/fuzz2.test 76dc35b32b6d6f965259508508abce75a6c4d7e1 F test/fuzz3.test 9c813e6613b837cb7a277b0383cd66bfa07042b4cf0317157c35852f30043c31 F test/fuzz4.test c229bcdb45518a89e1d208a21343e061503460ac69fae1539320a89f572eb634 F test/fuzz_common.tcl b7197de6ed1ee8250a4f82d67876f4561b42ee8cbbfc6160dcb66331bad3f830 F test/fuzz_malloc.test f348276e732e814802e39f042b1f6da6362a610af73a528d8f76898fde6b22f2 -F test/fuzzcheck.c bdb852815048a0beebbe5768bca61e75295324a811a8d7216f97b96501befd1e +F test/fuzzcheck.c e34696a5db46738118b2efd14fb71f8458ecf0f482df8bbae18fa1d64db9ab7b F test/fuzzdata1.db d36e88741b4f23bcbaaf55b006290669d03c6c891cf13c7b3a53bc1b097b693f F test/fuzzdata2.db 128b3feeb78918d075c9b14b48610145a0dd4c8d6f1ca7c2870c7e425f5bf31f F test/fuzzdata3.db c6586d3e3cef0fbc18108f9bb649aa77bfc38aba @@ -1086,7 +1087,7 @@ F test/fuzzdata4.db b502c7d5498261715812dd8b3c2005bad08b3a26e6489414bd13926cd3e4 F test/fuzzdata5.db e35f64af17ec48926481cfaf3b3855e436bd40d1cfe2d59a9474cb4b748a52a5 F test/fuzzdata6.db 92a80e4afc172c24f662a10a612d188fb272de4a9bd19e017927c95f737de6d7 F test/fuzzdata7.db 0166b56fd7a6b9636a1d60ef0a060f86ddaecf99400a666bb6e5bbd7199ad1f2 -F test/fuzzdata8.db 738ed275638f2423cdef240a44eba3b9bc272eec619e68b00429d4575a15e50b +F test/fuzzdata8.db ca9a97f401b06b0d5376139ec7e1f9e773e13345a9a2d9ccc0032cdbfedea230 F test/fuzzer1.test 3d4c4b7e547aba5e5511a2991e3e3d07166cfbb8 F test/fuzzer2.test a85ef814ce071293bce1ad8dffa217cbbaad4c14 F test/fuzzerfault.test f64c4aef4c9e9edf1d6dc0d3f1e65dcc81e67c996403c88d14f09b74807a42bc @@ -1226,7 +1227,7 @@ F test/memjournal2.test 89a4e0d1084170a281efa4d54c2677599f986f44227f98f7dfae2828 F test/memleak.test 10b9c6c57e19fc68c32941495e9ba1c50123f6e2 F test/memsubsys1.test 9e7555a22173b8f1c96c281ce289b338fcba2abe8b157f8798ca195bbf1d347e F test/memsubsys2.test 3e4a8d0c05fd3e5fa92017c64666730a520c7e08 -F test/merge1.test c5abf7d4eca25b3d5ee96927efff18efc3cee5a8af54b8415cbddd6d4471fd70 +F test/merge1.test 0ade470d77b689c4a64dc7f736527fcd893140bcafa70af8f7b98523cfb83f16 F test/minmax.test fe638b55d77d2375531a8f549b338eafcd9adfbd2f72df37ed77d9b26ca0a71a F test/minmax2.test cf9311babb6f0518d04e42fd6a42c619531c4309a9dd790a2c4e9b3bc595e0de F test/minmax3.test cc1e8b010136db0d01a6f2a29ba5a9f321034354 @@ -1402,11 +1403,11 @@ F test/sharedA.test 49d87ec54ab640fbbc3786ee3c01de94aaa482a3a9f834ad3fe92770eb69 F test/sharedB.test 16cc7178e20965d75278f410943109b77b2e645e F test/shared_err.test 32634e404a3317eeb94abc7a099c556a346fdb8fb3858dbe222a4cbb8926a939 F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304 -F test/shell1.test ce2f370886645f38fabdde44976c14a004400f166edea8fdd9741079b645fef6 -F test/shell2.test f00a0501c00583cbc46f7510e1d713366326b2b3e63d06d15937284171a8787c -F test/shell3.test cb4b835a901742c9719437a89171172ecc4a8823ad97349af8e4e841e6f82566 +F test/shell1.test b224e0793c5f48aa3749e65d8c64b93a30731bd206f2e41e6c5f1bee1bdb16c6 +F test/shell2.test 89e4b2db062d52baed75022227b462d085cff495809de1699652779d8e0257d6 +F test/shell3.test a50628ab1d78d90889d9d3f32fb2c084ee15674771e96afe954aaa0accd1de3c F test/shell4.test 8f6c0fce4abed19a8a7f7262517149812a04caa905d01bdc8f5e92573504b759 -F test/shell5.test b85069bfcf3159b225228629ab2c3e69aa923d098fea8ea074b5dcd743522e2c +F test/shell5.test 3be444397eb1e91619ce289a6216a8df9ac690cc45d5e9595f60e750a944161f F test/shell6.test 1ceb51b2678c472ba6cf1e5da96679ce8347889fe2c3bf93a0e0fa73f00b00d3 F test/shell7.test 115132f66d0463417f408562cc2cf534f6bbc6d83a6d50f0072a9eb171bae97f F test/shell8.test 388471d16e4de767333107e30653983f186232c0e863f4490bb230419e830aae @@ -1744,7 +1745,7 @@ F test/vtab_err.test dcc8b7b9cb67522b3fe7a272c73856829dae4ab7fdb30399aea1b6981bd F test/vtab_shared.test 5253bff2355a9a3f014c15337da7e177ab0ef8ad F test/vtabdistinct.test 7688f0889358f849fd60bbfde1ded38b014b18066076d4bfbb75395804dfe072 F test/vtabdrop.test 65d4cf6722972e5499bdaf0c0d70ee3b8133944a4e4bc31862563f32a7edca12 -F test/vtabrhs1.test c138346be341916ecc9d918dcfc2657d27bce211a350a82b01d62d224b167b56 +F test/vtabrhs1.test 9b5ecbc74a689500c33a4b2b36761f9bcc22fcc4e3f9d21066ee0c9c74cf5f6c F test/wal.test b7cc6984709f54afbf8441747ced1f646af120bf0c1b1d847bfa39306fbea089 F test/wal2.test 88d34cc62bf5460ad6b1f837cd56ab55731bb0637ff99e113b790873d9b60b14 F test/wal3.test 2a93004bc0fb2b5c29888964024695bade278ab2 @@ -1841,7 +1842,7 @@ F test/with4.test 257be66c0c67fee1defbbac0f685c3465e2cad037f21ce65f23f86084f1982 F test/with5.test 6248213c41fab36290b5b73aa3f937309dfba337004d9d8434c3fabc8c7d4be8 F test/with6.test 661d7e416bef6c0a2556b2c9f0c8178a5b15932bed65246abed99723a8d4e7c0 F test/withM.test 693b61765f2b387b5e3e24a4536e2e82de15ff64 -F test/without_rowid1.test 78fd9b437f4cdb46f76e6a510d545334e4f58e3e4ce37aaf19384eda5b27de8c +F test/without_rowid1.test a5210b8770dc4736bca4e74bc96588f43025ad03ad6a80f885afd36d9890e217 F test/without_rowid2.test af260339f79d13cb220288b67cd287fbcf81ad99 F test/without_rowid3.test 39ab0dd773eaa62e59b17093f875327630f54c4145458f6d2b053d68d4b2f67b F test/without_rowid4.test 4e08bcbaee0399f35d58b5581881e7a6243d458a @@ -1959,8 +1960,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P dae81f45d2bee8e5bced2564a6a85ffb23dc93fce6547760cd811acddbc09e25 70049342d5ad57ea3e863bba19253934b868bacdd1c26c9371bac024a829badf -R b23502faac945ebd993a7d5170df0824 +P 85054a8691cec593b0490b78715a506f25a8cbe04cbf673129c0e17f7f5fa912 9edaeed56f2282fd4da935454178c38ab49d259aed96d4e720aae09050a53006 +R 69285a48e91fd1af8824a47bd6a895ac U drh -Z 512010d85591fc13397cb5074c1b9277 +Z 3ed8b82579a35a4ac36eb787743744b8 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 5881063d01..b69738c320 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -85054a8691cec593b0490b78715a506f25a8cbe04cbf673129c0e17f7f5fa912 \ No newline at end of file +94838f16baf810054926196f277be4688359c502cb7e6872e3e3273a9c67e56d \ No newline at end of file diff --git a/src/alter.c b/src/alter.c index 4de7cc51d3..59b3bf0303 100644 --- a/src/alter.c +++ b/src/alter.c @@ -631,7 +631,7 @@ void sqlite3AlterRenameColumn( if( 0==sqlite3StrICmp(pTab->aCol[iCol].zCnName, zOld) ) break; } if( iCol==pTab->nCol ){ - sqlite3ErrorMsg(pParse, "no such column: \"%s\"", zOld); + sqlite3ErrorMsg(pParse, "no such column: \"%T\"", pOld); goto exit_rename_column; } @@ -1061,12 +1061,12 @@ static void renameColumnParseError( const char *zN = (const char*)sqlite3_value_text(pObject); char *zErr; - zErr = sqlite3_mprintf("error in %s %s%s%s: %s", + zErr = sqlite3MPrintf(pParse->db, "error in %s %s%s%s: %s", zT, zN, (zWhen[0] ? " " : ""), zWhen, pParse->zErrMsg ); sqlite3_result_error(pCtx, zErr, -1); - sqlite3_free(zErr); + sqlite3DbFree(pParse->db, zErr); } /* @@ -1427,7 +1427,7 @@ static void renameParseCleanup(Parse *pParse){ /* ** SQL function: ** -** sqlite_rename_column(zSql, iCol, bQuote, zNew, zTable, zOld) +** sqlite_rename_column(SQL,TYPE,OBJ,DB,TABLE,COL,NEWNAME,QUOTE,TEMP) ** ** 0. zSql: SQL statement to rewrite ** 1. type: Type of object ("table", "view" etc.) @@ -1445,7 +1445,8 @@ static void renameParseCleanup(Parse *pParse){ ** ** This function is used internally by the ALTER TABLE RENAME COLUMN command. ** It is only accessible to SQL created using sqlite3NestedParse(). It is -** not reachable from ordinary SQL passed into sqlite3_prepare(). +** not reachable from ordinary SQL passed into sqlite3_prepare() unless the +** SQLITE_TESTCTRL_INTERNAL_FUNCTIONS test setting is enabled. */ static void renameColumnFunc( sqlite3_context *context, @@ -1594,7 +1595,9 @@ static void renameColumnFunc( renameColumnFunc_done: if( rc!=SQLITE_OK ){ - if( sParse.zErrMsg ){ + if( rc==SQLITE_ERROR && sqlite3WritableSchema(db) ){ + sqlite3_result_value(context, argv[0]); + }else if( sParse.zErrMsg ){ renameColumnParseError(context, "", argv[1], argv[2], &sParse); }else{ sqlite3_result_error_code(context, rc); @@ -1793,7 +1796,9 @@ static void renameTableFunc( rc = renameEditSql(context, &sCtx, zInput, zNew, bQuote); } if( rc!=SQLITE_OK ){ - if( sParse.zErrMsg ){ + if( rc==SQLITE_ERROR && sqlite3WritableSchema(db) ){ + sqlite3_result_value(context, argv[3]); + }else if( sParse.zErrMsg ){ renameColumnParseError(context, "", argv[1], argv[2], &sParse); }else{ sqlite3_result_error_code(context, rc); @@ -1818,10 +1823,10 @@ static int renameQuotefixExprCb(Walker *pWalker, Expr *pExpr){ return WRC_Continue; } -/* -** The implementation of an SQL scalar function that rewrites DDL statements -** so that any string literals that use double-quotes are modified so that -** they use single quotes. +/* SQL function: sqlite_rename_quotefix(DB,SQL) +** +** Rewrite the DDL statement "SQL" so that any string literals that use +** double-quotes use single quotes instead. ** ** Two arguments must be passed: ** @@ -1840,6 +1845,10 @@ static int renameQuotefixExprCb(Walker *pWalker, Expr *pExpr){ ** returns the string: ** ** CREATE VIEW v1 AS SELECT "a", 'string' FROM t1 +** +** If there is a error in the input SQL, then raise an error, except +** if PRAGMA writable_schema=ON, then just return the input string +** unmodified following an error. */ static void renameQuotefixFunc( sqlite3_context *context, @@ -1914,7 +1923,11 @@ static void renameQuotefixFunc( renameTokenFree(db, sCtx.pList); } if( rc!=SQLITE_OK ){ - sqlite3_result_error_code(context, rc); + if( sqlite3WritableSchema(db) && rc==SQLITE_ERROR ){ + sqlite3_result_value(context, argv[1]); + }else{ + sqlite3_result_error_code(context, rc); + } } renameParseCleanup(&sParse); } @@ -1926,7 +1939,8 @@ static void renameQuotefixFunc( sqlite3BtreeLeaveAll(db); } -/* +/* Function: sqlite_rename_test(DB,SQL,TYPE,NAME,ISTEMP,WHEN,DQS) +** ** An SQL user function that checks that there are no parse or symbol ** resolution problems in a CREATE TRIGGER|TABLE|VIEW|INDEX statement. ** After an ALTER TABLE .. RENAME operation is performed and the schema @@ -1941,11 +1955,13 @@ static void renameQuotefixFunc( ** 5: "when" part of error message. ** 6: True to disable the DQS quirk when parsing SQL. ** -** Unless it finds an error, this function normally returns NULL. However, it -** returns integer value 1 if: +** The return value is computed as follows: ** -** * the SQL argument creates a trigger, and -** * the table that the trigger is attached to is in database zDb. +** A. If an error is seen and not in PRAGMA writable_schema=ON mode, +** then raise the error. +** B. Else if a trigger is created and the the table that the trigger is +** attached to is in database zDb, then return 1. +** C. Otherwise return NULL. */ static void renameTableTest( sqlite3_context *context, @@ -1990,12 +2006,16 @@ static void renameTableTest( if( rc==SQLITE_OK ){ int i1 = sqlite3SchemaToIndex(db, sParse.pNewTrigger->pTabSchema); int i2 = sqlite3FindDbName(db, zDb); - if( i1==i2 ) sqlite3_result_int(context, 1); + if( i1==i2 ){ + /* Handle output case B */ + sqlite3_result_int(context, 1); + } } } } - if( rc!=SQLITE_OK && zWhen ){ + if( rc!=SQLITE_OK && zWhen && !sqlite3WritableSchema(db) ){ + /* Output case A */ renameColumnParseError(context, zWhen, argv[2], argv[3],&sParse); } renameParseCleanup(&sParse); @@ -2111,7 +2131,7 @@ void sqlite3AlterDropColumn(Parse *pParse, SrcList *pSrc, const Token *pName){ } iCol = sqlite3ColumnIndex(pTab, zCol); if( iCol<0 ){ - sqlite3ErrorMsg(pParse, "no such column: \"%s\"", zCol); + sqlite3ErrorMsg(pParse, "no such column: \"%T\"", pName); goto exit_drop_column; } diff --git a/src/btree.c b/src/btree.c index 3c38e0f453..87c180b18b 100644 --- a/src/btree.c +++ b/src/btree.c @@ -2022,7 +2022,7 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){ if( iFreeBlk>pPage->pBt->usableSize-4 ){ /* TH3: corrupt081.100 */ return SQLITE_CORRUPT_PAGE(pPage); } - assert( iFreeBlk>iPtr || iFreeBlk==0 ); + assert( iFreeBlk>iPtr || iFreeBlk==0 || CORRUPT_DB ); /* At this point: ** iFreeBlk: First freeblock after iStart, or zero if none @@ -6879,7 +6879,7 @@ static int freePage2(BtShared *pBt, MemPage *pMemPage, Pgno iPage){ assert( CORRUPT_DB || iPage>1 ); assert( !pMemPage || pMemPage->pgno==iPage ); - if( NEVER(iPage<2) || iPage>pBt->nPage ){ + if( iPage<2 || iPage>pBt->nPage ){ return SQLITE_CORRUPT_BKPT; } if( pMemPage ){ @@ -7313,6 +7313,12 @@ static void dropCell(MemPage *pPage, int idx, int sz, int *pRC){ assert( pPage->pBt->usableSize > (u32)(ptr-data) ); pc = get2byte(ptr); hdr = pPage->hdrOffset; +#if 0 /* Not required. Omit for efficiency */ + if( pcnCell*2 ){ + *pRC = SQLITE_CORRUPT_BKPT; + return; + } +#endif testcase( pc==(u32)get2byte(&data[hdr+5]) ); testcase( pc+sz==pPage->pBt->usableSize ); if( pc+sz > pPage->pBt->usableSize ){ @@ -10086,7 +10092,7 @@ static int clearDatabasePage( if( rc ) return rc; setMempageRoot(pPage, pgnoRoot); if( (pBt->openFlags & BTREE_SINGLE)==0 - && sqlite3PagerPageRefcount(pPage->pDbPage)!=1 + && sqlite3PagerPageRefcount(pPage->pDbPage) != (1 + (pgno==1)) ){ rc = SQLITE_CORRUPT_BKPT; goto cleardatabasepage_out; diff --git a/src/build.c b/src/build.c index c8587f9d59..d91b86fda2 100644 --- a/src/build.c +++ b/src/build.c @@ -1295,7 +1295,8 @@ void sqlite3StartTable( pTable = sqlite3FindTable(db, zName, zDb); if( pTable ){ if( !noErr ){ - sqlite3ErrorMsg(pParse, "table %T already exists", pName); + sqlite3ErrorMsg(pParse, "%s %T already exists", + (IsView(pTable)? "view" : "table"), pName); }else{ assert( !db->init.busy || CORRUPT_DB ); sqlite3CodeVerifySchema(pParse, iDb); diff --git a/src/date.c b/src/date.c index ef4442aad5..a510d62750 100644 --- a/src/date.c +++ b/src/date.c @@ -503,8 +503,10 @@ static void clearYMD_HMS_TZ(DateTime *p){ ** is available. This routine returns 0 on success and ** non-zero on any kind of error. ** -** If the sqlite3GlobalConfig.bLocaltimeFault variable is true then this -** routine will always fail. +** If the sqlite3GlobalConfig.bLocaltimeFault variable is non-zero then this +** routine will always fail. If bLocaltimeFault is nonzero and +** sqlite3GlobalConfig.xAltLocaltime is not NULL, then xAltLocaltime() is +** invoked in place of the OS-defined localtime() function. ** ** EVIDENCE-OF: R-62172-00036 In this implementation, the standard C ** library function localtime_r() is used to assist in the calculation of @@ -520,7 +522,15 @@ static int osLocaltime(time_t *t, struct tm *pTm){ sqlite3_mutex_enter(mutex); pX = localtime(t); #ifndef SQLITE_UNTESTABLE - if( sqlite3GlobalConfig.bLocaltimeFault ) pX = 0; + if( sqlite3GlobalConfig.bLocaltimeFault ){ + if( sqlite3GlobalConfig.xAltLocaltime!=0 + && 0==sqlite3GlobalConfig.xAltLocaltime((const void*)t,(void*)pTm) + ){ + pX = pTm; + }else{ + pX = 0; + } + } #endif if( pX ) *pTm = *pX; #if SQLITE_THREADSAFE>0 @@ -529,7 +539,13 @@ static int osLocaltime(time_t *t, struct tm *pTm){ rc = pX==0; #else #ifndef SQLITE_UNTESTABLE - if( sqlite3GlobalConfig.bLocaltimeFault ) return 1; + if( sqlite3GlobalConfig.bLocaltimeFault ){ + if( sqlite3GlobalConfig.xAltLocaltime!=0 ){ + return sqlite3GlobalConfig.xAltLocaltime((const void*)t,(void*)pTm); + }else{ + return 1; + } + } #endif #if HAVE_LOCALTIME_R rc = localtime_r(t, pTm)==0; @@ -544,67 +560,56 @@ static int osLocaltime(time_t *t, struct tm *pTm){ #ifndef SQLITE_OMIT_LOCALTIME /* -** Compute the difference (in milliseconds) between localtime and UTC -** (a.k.a. GMT) for the time value p where p is in UTC. If no error occurs, -** return this value and set *pRc to SQLITE_OK. -** -** Or, if an error does occur, set *pRc to SQLITE_ERROR. The returned value -** is undefined in this case. +** Assuming the input DateTime is UTC, move it to its localtime equivalent. */ -static sqlite3_int64 localtimeOffset( - DateTime *p, /* Date at which to calculate offset */ - sqlite3_context *pCtx, /* Write error here if one occurs */ - int *pRc /* OUT: Error code. SQLITE_OK or ERROR */ +static int toLocaltime( + DateTime *p, /* Date at which to calculate offset */ + sqlite3_context *pCtx /* Write error here if one occurs */ ){ - DateTime x, y; time_t t; struct tm sLocal; + int iYearDiff; /* Initialize the contents of sLocal to avoid a compiler warning. */ memset(&sLocal, 0, sizeof(sLocal)); - x = *p; - computeYMD_HMS(&x); - if( x.Y<1971 || x.Y>=2038 ){ + computeJD(p); + if( p->iJD<21086676000*(i64)10000 /* 1970-01-01 */ + || p->iJD>21301414560*(i64)10000 /* 2038-01-18 */ + ){ /* EVIDENCE-OF: R-55269-29598 The localtime_r() C function normally only ** works for years between 1970 and 2037. For dates outside this range, ** SQLite attempts to map the year into an equivalent year within this ** range, do the calculation, then map the year back. */ - x.Y = 2000; - x.M = 1; - x.D = 1; - x.h = 0; - x.m = 0; - x.s = 0.0; - } else { - int s = (int)(x.s + 0.5); - x.s = s; + DateTime x = *p; + computeYMD_HMS(&x); + iYearDiff = (2000 + x.Y%4) - x.Y; + x.Y += iYearDiff; + x.validJD = 0; + computeJD(&x); + t = (time_t)(x.iJD/1000 - 21086676*(i64)10000); + }else{ + iYearDiff = 0; + t = (time_t)(p->iJD/1000 - 21086676*(i64)10000); } - x.tz = 0; - x.validJD = 0; - computeJD(&x); - t = (time_t)(x.iJD/1000 - 21086676*(i64)10000); if( osLocaltime(&t, &sLocal) ){ sqlite3_result_error(pCtx, "local time unavailable", -1); - *pRc = SQLITE_ERROR; - return 0; + return SQLITE_ERROR; } - y.Y = sLocal.tm_year + 1900; - y.M = sLocal.tm_mon + 1; - y.D = sLocal.tm_mday; - y.h = sLocal.tm_hour; - y.m = sLocal.tm_min; - y.s = sLocal.tm_sec; - y.validYMD = 1; - y.validHMS = 1; - y.validJD = 0; - y.rawS = 0; - y.validTZ = 0; - y.isError = 0; - computeJD(&y); - *pRc = SQLITE_OK; - return y.iJD - x.iJD; + p->Y = sLocal.tm_year + 1900 - iYearDiff; + p->M = sLocal.tm_mon + 1; + p->D = sLocal.tm_mday; + p->h = sLocal.tm_hour; + p->m = sLocal.tm_min; + p->s = sLocal.tm_sec; + p->validYMD = 1; + p->validHMS = 1; + p->validJD = 0; + p->rawS = 0; + p->validTZ = 0; + p->isError = 0; + return SQLITE_OK; } #endif /* SQLITE_OMIT_LOCALTIME */ @@ -713,9 +718,7 @@ static int parseModifier( ** show local time. */ if( sqlite3_stricmp(z, "localtime")==0 && sqlite3NotPureFunc(pCtx) ){ - computeJD(p); - p->iJD += localtimeOffset(p, pCtx, &rc); - clearYMD_HMS_TZ(p); + rc = toLocaltime(p, pCtx); } break; } @@ -741,18 +744,31 @@ static int parseModifier( #ifndef SQLITE_OMIT_LOCALTIME else if( sqlite3_stricmp(z, "utc")==0 && sqlite3NotPureFunc(pCtx) ){ if( p->tzSet==0 ){ - sqlite3_int64 c1; + i64 iOrigJD; /* Original localtime */ + i64 iGuess; /* Guess at the corresponding utc time */ + int cnt = 0; /* Safety to prevent infinite loop */ + int iErr; /* Guess is off by this much */ + computeJD(p); - c1 = localtimeOffset(p, pCtx, &rc); - if( rc==SQLITE_OK ){ - p->iJD -= c1; - clearYMD_HMS_TZ(p); - p->iJD += c1 - localtimeOffset(p, pCtx, &rc); - } + iGuess = iOrigJD = p->iJD; + iErr = 0; + do{ + DateTime new; + memset(&new, 0, sizeof(new)); + iGuess -= iErr; + new.iJD = iGuess; + new.validJD = 1; + rc = toLocaltime(&new, pCtx); + if( rc ) return rc; + computeJD(&new); + iErr = new.iJD - iOrigJD; + }while( iErr && cnt++<3 ); + memset(p, 0, sizeof(*p)); + p->iJD = iGuess; + p->validJD = 1; p->tzSet = 1; - }else{ - rc = SQLITE_OK; } + rc = SQLITE_OK; } #endif break; @@ -1002,11 +1018,38 @@ static void datetimeFunc( ){ DateTime x; if( isDate(context, argc, argv, &x)==0 ){ - char zBuf[100]; + int Y, s; + char zBuf[24]; computeYMD_HMS(&x); - sqlite3_snprintf(sizeof(zBuf), zBuf, "%04d-%02d-%02d %02d:%02d:%02d", - x.Y, x.M, x.D, x.h, x.m, (int)(x.s)); - sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT); + Y = x.Y; + if( Y<0 ) Y = -Y; + zBuf[1] = '0' + (Y/1000)%10; + zBuf[2] = '0' + (Y/100)%10; + zBuf[3] = '0' + (Y/10)%10; + zBuf[4] = '0' + (Y)%10; + zBuf[5] = '-'; + zBuf[6] = '0' + (x.M/10)%10; + zBuf[7] = '0' + (x.M)%10; + zBuf[8] = '-'; + zBuf[9] = '0' + (x.D/10)%10; + zBuf[10] = '0' + (x.D)%10; + zBuf[11] = ' '; + zBuf[12] = '0' + (x.h/10)%10; + zBuf[13] = '0' + (x.h)%10; + zBuf[14] = ':'; + zBuf[15] = '0' + (x.m/10)%10; + zBuf[16] = '0' + (x.m)%10; + zBuf[17] = ':'; + s = (int)x.s; + zBuf[18] = '0' + (s/10)%10; + zBuf[19] = '0' + (s)%10; + zBuf[20] = 0; + if( x.Y<0 ){ + zBuf[0] = '-'; + sqlite3_result_text(context, zBuf, 20, SQLITE_TRANSIENT); + }else{ + sqlite3_result_text(context, &zBuf[1], 19, SQLITE_TRANSIENT); + } } } @@ -1022,10 +1065,20 @@ static void timeFunc( ){ DateTime x; if( isDate(context, argc, argv, &x)==0 ){ - char zBuf[100]; + int s; + char zBuf[16]; computeHMS(&x); - sqlite3_snprintf(sizeof(zBuf), zBuf, "%02d:%02d:%02d", x.h, x.m, (int)x.s); - sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT); + zBuf[0] = '0' + (x.h/10)%10; + zBuf[1] = '0' + (x.h)%10; + zBuf[2] = ':'; + zBuf[3] = '0' + (x.m/10)%10; + zBuf[4] = '0' + (x.m)%10; + zBuf[5] = ':'; + s = (int)x.s; + zBuf[6] = '0' + (s/10)%10; + zBuf[7] = '0' + (s)%10; + zBuf[8] = 0; + sqlite3_result_text(context, zBuf, 8, SQLITE_TRANSIENT); } } @@ -1041,10 +1094,28 @@ static void dateFunc( ){ DateTime x; if( isDate(context, argc, argv, &x)==0 ){ - char zBuf[100]; + int Y; + char zBuf[16]; computeYMD(&x); - sqlite3_snprintf(sizeof(zBuf), zBuf, "%04d-%02d-%02d", x.Y, x.M, x.D); - sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT); + Y = x.Y; + if( Y<0 ) Y = -Y; + zBuf[1] = '0' + (Y/1000)%10; + zBuf[2] = '0' + (Y/100)%10; + zBuf[3] = '0' + (Y/10)%10; + zBuf[4] = '0' + (Y)%10; + zBuf[5] = '-'; + zBuf[6] = '0' + (x.M/10)%10; + zBuf[7] = '0' + (x.M)%10; + zBuf[8] = '-'; + zBuf[9] = '0' + (x.D/10)%10; + zBuf[10] = '0' + (x.D)%10; + zBuf[11] = 0; + if( x.Y<0 ){ + zBuf[0] = '-'; + sqlite3_result_text(context, zBuf, 11, SQLITE_TRANSIENT); + }else{ + sqlite3_result_text(context, &zBuf[1], 10, SQLITE_TRANSIENT); + } } } diff --git a/src/expr.c b/src/expr.c index af28fd6d29..271f06bc6a 100644 --- a/src/expr.c +++ b/src/expr.c @@ -769,9 +769,8 @@ static void heightOfSelect(const Select *pSelect, int *pnHeight){ ** if appropriate. */ static void exprSetHeight(Expr *p){ - int nHeight = 0; - heightOfExpr(p->pLeft, &nHeight); - heightOfExpr(p->pRight, &nHeight); + int nHeight = p->pLeft ? p->pLeft->nHeight : 0; + if( p->pRight && p->pRight->nHeight>nHeight ) nHeight = p->pRight->nHeight; if( ExprUseXSelect(p) ){ heightOfSelect(p->x.pSelect, &nHeight); }else if( p->x.pList ){ @@ -1070,6 +1069,7 @@ Expr *sqlite3ExprFunction( sqlite3ExprListDelete(db, pList); /* Avoid memory leak when malloc fails */ return 0; } + pNew->w.iOfst = (int)(pToken->z - pParse->zTail); if( pList && pList->nExpr > pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG] && !pParse->nested @@ -1113,7 +1113,7 @@ void sqlite3ExprFunctionUsable( ** SQLITE_DBCONFIG_TRUSTED_SCHEMA is off (meaning ** that the schema is possibly tainted). */ - sqlite3ErrorMsg(pParse, "unsafe use of %s()", pDef->zName); + sqlite3ErrorMsg(pParse, "unsafe use of %#T()", pExpr); } } } @@ -1169,6 +1169,7 @@ void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr, u32 n){ if( bOk==0 || i<1 || i>db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ){ sqlite3ErrorMsg(pParse, "variable number must be between ?1 and ?%d", db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]); + sqlite3RecordErrorOffsetOfExpr(pParse->db, pExpr); return; } x = (ynVar)i; @@ -1196,6 +1197,7 @@ void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr, u32 n){ pExpr->iColumn = x; if( x>db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ){ sqlite3ErrorMsg(pParse, "too many SQL variables"); + sqlite3RecordErrorOffsetOfExpr(pParse->db, pExpr); } } @@ -3637,11 +3639,12 @@ static void codeInteger(Parse *pParse, Expr *pExpr, int negFlag, int iMem){ c = sqlite3DecOrHexToI64(z, &value); if( (c==3 && !negFlag) || (c==2) || (negFlag && value==SMALLEST_INT64)){ #ifdef SQLITE_OMIT_FLOATING_POINT - sqlite3ErrorMsg(pParse, "oversized integer: %s%s", negFlag ? "-" : "", z); + sqlite3ErrorMsg(pParse, "oversized integer: %s%#T", negFlag?"-":"",pExpr); #else #ifndef SQLITE_OMIT_HEX_INTEGER if( sqlite3_strnicmp(z,"0x",2)==0 ){ - sqlite3ErrorMsg(pParse, "hex literal too big: %s%s", negFlag?"-":"",z); + sqlite3ErrorMsg(pParse, "hex literal too big: %s%#T", + negFlag?"-":"",pExpr); }else #endif { @@ -4317,7 +4320,7 @@ expr_code_doover: || NEVER(pExpr->iAgg>=pInfo->nFunc) ){ assert( !ExprHasProperty(pExpr, EP_IntValue) ); - sqlite3ErrorMsg(pParse, "misuse of aggregate: %s()", pExpr->u.zToken); + sqlite3ErrorMsg(pParse, "misuse of aggregate: %#T()", pExpr); }else{ return pInfo->aFunc[pExpr->iAgg].iMem; } @@ -4358,7 +4361,7 @@ expr_code_doover: } #endif if( pDef==0 || pDef->xFinalize!=0 ){ - sqlite3ErrorMsg(pParse, "unknown function: %s()", zId); + sqlite3ErrorMsg(pParse, "unknown function: %#T()", pExpr); break; } if( pDef->funcFlags & SQLITE_FUNC_INLINE ){ diff --git a/src/func.c b/src/func.c index f0026a16a9..a93f91e21f 100644 --- a/src/func.c +++ b/src/func.c @@ -1122,8 +1122,9 @@ static void quoteFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ sqlite3QuoteValue(&str,argv[0]); sqlite3_result_text(context, sqlite3StrAccumFinish(&str), str.nChar, SQLITE_DYNAMIC); - if( str.accError==SQLITE_NOMEM ){ - sqlite3_result_error_nomem(context); + if( str.accError!=SQLITE_OK ){ + sqlite3_result_null(context); + sqlite3_result_error_code(context, str.accError); } } diff --git a/src/global.c b/src/global.c index 34b7d9583b..6ad3bb4654 100644 --- a/src/global.c +++ b/src/global.c @@ -286,6 +286,7 @@ SQLITE_WSD struct Sqlite3Config sqlite3Config = { 0, /* xTestCallback */ #endif 0, /* bLocaltimeFault */ + 0, /* xAltLocaltime */ 0x7ffffffe, /* iOnceResetThreshold */ SQLITE_DEFAULT_SORTERREF_SIZE, /* szSorterRef */ 0, /* iPrngSeed */ diff --git a/src/main.c b/src/main.c index 1b5d9aa61f..a4dfe8baf3 100644 --- a/src/main.c +++ b/src/main.c @@ -4029,12 +4029,16 @@ int sqlite3_test_control(int op, ...){ ** sqlite3_test_control(). */ case SQLITE_TESTCTRL_FAULT_INSTALL: { - /* MSVC is picky about pulling func ptrs from va lists. - ** http://support.microsoft.com/kb/47961 + /* A bug in MSVC prevents it from understanding pointers to functions + ** types in the second argument to va_arg(). Work around the problem + ** using a typedef. + ** http://support.microsoft.com/kb/47961 <-- dead hyperlink + ** Search at http://web.archive.org/ to find the 2015-03-16 archive + ** of the link above to see the original text. ** sqlite3GlobalConfig.xTestCallback = va_arg(ap, int(*)(int)); */ - typedef int(*TESTCALLBACKFUNC_t)(int); - sqlite3GlobalConfig.xTestCallback = va_arg(ap, TESTCALLBACKFUNC_t); + typedef int(*sqlite3FaultFuncType)(int); + sqlite3GlobalConfig.xTestCallback = va_arg(ap, sqlite3FaultFuncType); rc = sqlite3FaultSim(0); break; } @@ -4161,13 +4165,27 @@ int sqlite3_test_control(int op, ...){ break; } - /* sqlite3_test_control(SQLITE_TESTCTRL_LOCALTIME_FAULT, int onoff); + /* sqlite3_test_control(SQLITE_TESTCTRL_LOCALTIME_FAULT, onoff, xAlt); ** - ** If parameter onoff is non-zero, subsequent calls to localtime() - ** and its variants fail. If onoff is zero, undo this setting. + ** If parameter onoff is 1, subsequent calls to localtime() fail. + ** If 2, then invoke xAlt() instead of localtime(). If 0, normal + ** processing. + ** + ** xAlt arguments are void pointers, but they really want to be: + ** + ** int xAlt(const time_t*, struct tm*); + ** + ** xAlt should write results in to struct tm object of its 2nd argument + ** and return zero on success, or return non-zero on failure. */ case SQLITE_TESTCTRL_LOCALTIME_FAULT: { sqlite3GlobalConfig.bLocaltimeFault = va_arg(ap, int); + if( sqlite3GlobalConfig.bLocaltimeFault==2 ){ + typedef int(*sqlite3LocaltimeType)(const void*,void*); + sqlite3GlobalConfig.xAltLocaltime = va_arg(ap, sqlite3LocaltimeType); + }else{ + sqlite3GlobalConfig.xAltLocaltime = 0; + } break; } diff --git a/src/memjournal.c b/src/memjournal.c index 63ef2ad7b9..a4c17eedd4 100644 --- a/src/memjournal.c +++ b/src/memjournal.c @@ -178,6 +178,9 @@ static int memjrnlCreateFile(MemJournal *p){ } +/* Forward reference */ +static int memjrnlTruncate(sqlite3_file *pJfd, sqlite_int64 size); + /* ** Write data to the file. */ @@ -207,23 +210,21 @@ static int memjrnlWrite( ** access writes are not required. The only exception to this is when ** the in-memory journal is being used by a connection using the ** atomic-write optimization. In this case the first 28 bytes of the - ** journal file may be written as part of committing the transaction. */ - assert( iOfst==p->endpoint.iOffset || iOfst==0 ); -#if defined(SQLITE_ENABLE_ATOMIC_WRITE) \ - || defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE) + ** journal file may be written as part of committing the transaction. */ + assert( iOfst<=p->endpoint.iOffset ); + if( iOfst>0 && iOfst!=p->endpoint.iOffset ){ + memjrnlTruncate(pJfd, iOfst); + } if( iOfst==0 && p->pFirst ){ assert( p->nChunkSize>iAmt ); memcpy((u8*)p->pFirst->zChunk, zBuf, iAmt); - }else -#else - assert( iOfst>0 || p->pFirst==0 ); -#endif - { + }else{ while( nWrite>0 ){ FileChunk *pChunk = p->endpoint.pChunk; int iChunkOffset = (int)(p->endpoint.iOffset%p->nChunkSize); int iSpace = MIN(nWrite, p->nChunkSize - iChunkOffset); + assert( pChunk!=0 || iChunkOffset==0 ); if( iChunkOffset==0 ){ /* New chunk is required to extend the file. */ FileChunk *pNew = sqlite3_malloc(fileChunkSize(p->nChunkSize)); @@ -238,10 +239,11 @@ static int memjrnlWrite( assert( !p->pFirst ); p->pFirst = pNew; } - p->endpoint.pChunk = pNew; + pChunk = p->endpoint.pChunk = pNew; } - memcpy((u8*)p->endpoint.pChunk->zChunk + iChunkOffset, zWrite, iSpace); + assert( pChunk!=0 ); + memcpy((u8*)pChunk->zChunk + iChunkOffset, zWrite, iSpace); zWrite += iSpace; nWrite -= iSpace; p->endpoint.iOffset += iSpace; diff --git a/src/pager.c b/src/pager.c index d981df567f..c600f713e6 100644 --- a/src/pager.c +++ b/src/pager.c @@ -4013,7 +4013,7 @@ static void assertTruncateConstraint(Pager *pPager){ ** then continue writing to the database. */ void sqlite3PagerTruncateImage(Pager *pPager, Pgno nPage){ - assert( pPager->dbSize>=nPage ); + assert( pPager->dbSize>=nPage || CORRUPT_DB ); assert( pPager->eState>=PAGER_WRITER_CACHEMOD ); pPager->dbSize = nPage; @@ -7586,6 +7586,18 @@ int sqlite3PagerCheckpoint( int *pnCkpt /* OUT: Final number of checkpointed frames */ ){ int rc = SQLITE_OK; + if( pPager->pWal==0 && pPager->journalMode==PAGER_JOURNALMODE_WAL ){ + /* This only happens when a database file is zero bytes in size opened and + ** then "PRAGMA journal_mode=WAL" is run and then sqlite3_wal_checkpoint() + ** is invoked without any intervening transactions. We need to start + ** a transaction to initialize pWal. The PRAGMA table_list statement is + ** used for this since it starts transactions on every database file, + ** including all ATTACHed databases. This seems expensive for a single + ** sqlite3_wal_checkpoint() call, but it happens very rarely. + ** https://sqlite.org/forum/forumpost/fd0f19d229156939 + */ + sqlite3_exec(db, "PRAGMA table_list",0,0,0); + } if( pPager->pWal ){ rc = sqlite3WalCheckpoint(pPager->pWal, db, eMode, (eMode==SQLITE_CHECKPOINT_PASSIVE ? 0 : pPager->xBusyHandler), diff --git a/src/parse.y b/src/parse.y index 9ef2a2fec6..da6b2173e6 100644 --- a/src/parse.y +++ b/src/parse.y @@ -674,7 +674,7 @@ selcollist(A) ::= sclp(A) scanpt STAR. { } selcollist(A) ::= sclp(A) scanpt nm(X) DOT STAR. { Expr *pRight = sqlite3PExpr(pParse, TK_ASTERISK, 0, 0); - Expr *pLeft = sqlite3ExprAlloc(pParse->db, TK_ID, &X, 1); + Expr *pLeft = tokenExpr(pParse, TK_ID, X); Expr *pDot = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight); A = sqlite3ExprListAppend(pParse,A, pDot); } @@ -1040,10 +1040,7 @@ idlist(A) ::= nm(Y). %include { - /* Construct a new Expr object from a single identifier. Use the - ** new Expr to populate pOut. Set the span of pOut to be the identifier - ** that created the expression. - */ + /* Construct a new Expr object from a single token */ static Expr *tokenExpr(Parse *pParse, int op, Token t){ Expr *p = sqlite3DbMallocRawNN(pParse->db, sizeof(Expr)+t.n+1); if( p ){ @@ -1063,6 +1060,7 @@ idlist(A) ::= nm(Y). p->u.zToken = (char*)&p[1]; memcpy(p->u.zToken, t.z, t.n); p->u.zToken[t.n] = 0; + p->w.iOfst = (int)(t.z - pParse->zTail); if( sqlite3Isquote(p->u.zToken[0]) ){ sqlite3DequoteExpr(p); } @@ -1083,22 +1081,17 @@ expr(A) ::= LP expr(X) RP. {A = X;} expr(A) ::= id(X). {A=tokenExpr(pParse,TK_ID,X); /*A-overwrites-X*/} expr(A) ::= JOIN_KW(X). {A=tokenExpr(pParse,TK_ID,X); /*A-overwrites-X*/} expr(A) ::= nm(X) DOT nm(Y). { - Expr *temp1 = sqlite3ExprAlloc(pParse->db, TK_ID, &X, 1); - Expr *temp2 = sqlite3ExprAlloc(pParse->db, TK_ID, &Y, 1); - if( IN_RENAME_OBJECT ){ - sqlite3RenameTokenMap(pParse, (void*)temp2, &Y); - sqlite3RenameTokenMap(pParse, (void*)temp1, &X); - } + Expr *temp1 = tokenExpr(pParse,TK_ID,X); + Expr *temp2 = tokenExpr(pParse,TK_ID,Y); A = sqlite3PExpr(pParse, TK_DOT, temp1, temp2); } expr(A) ::= nm(X) DOT nm(Y) DOT nm(Z). { - Expr *temp1 = sqlite3ExprAlloc(pParse->db, TK_ID, &X, 1); - Expr *temp2 = sqlite3ExprAlloc(pParse->db, TK_ID, &Y, 1); - Expr *temp3 = sqlite3ExprAlloc(pParse->db, TK_ID, &Z, 1); + Expr *temp1 = tokenExpr(pParse,TK_ID,X); + Expr *temp2 = tokenExpr(pParse,TK_ID,Y); + Expr *temp3 = tokenExpr(pParse,TK_ID,Z); Expr *temp4 = sqlite3PExpr(pParse, TK_DOT, temp2, temp3); if( IN_RENAME_OBJECT ){ - sqlite3RenameTokenMap(pParse, (void*)temp3, &Z); - sqlite3RenameTokenMap(pParse, (void*)temp2, &Y); + sqlite3RenameTokenRemap(pParse, 0, temp1); } A = sqlite3PExpr(pParse, TK_DOT, temp1, temp4); } @@ -1106,6 +1099,7 @@ term(A) ::= NULL|FLOAT|BLOB(X). {A=tokenExpr(pParse,@X,X); /*A-overwrites-X*/} term(A) ::= STRING(X). {A=tokenExpr(pParse,@X,X); /*A-overwrites-X*/} term(A) ::= INTEGER(X). { A = sqlite3ExprAlloc(pParse->db, TK_INTEGER, &X, 1); + if( A ) A->w.iOfst = (int)(X.z - pParse->zTail); } expr(A) ::= VARIABLE(X). { if( !(X.z[0]=='#' && sqlite3Isdigit(X.z[1])) ){ @@ -1608,7 +1602,7 @@ expr(A) ::= RAISE LP IGNORE RP. { } } expr(A) ::= RAISE LP raisetype(T) COMMA nm(Z) RP. { - A = sqlite3ExprAlloc(pParse->db, TK_RAISE, &Z, 1); + A = sqlite3ExprAlloc(pParse->db, TK_RAISE, &Z, 1); if( A ) { A->affExpr = (char)T; } diff --git a/src/printf.c b/src/printf.c index 9fea2d6ef0..7bf6f2aebb 100644 --- a/src/printf.c +++ b/src/printf.c @@ -849,13 +849,22 @@ void sqlite3_str_vappendf( goto adjust_width_for_utf8; } case etTOKEN: { - Token *pToken; if( (pAccum->printfFlags & SQLITE_PRINTF_INTERNAL)==0 ) return; - pToken = va_arg(ap, Token*); - assert( bArgList==0 ); - if( pToken && pToken->n ){ - sqlite3_str_append(pAccum, (const char*)pToken->z, pToken->n); - sqlite3RecordErrorByteOffset(pAccum->db, pToken->z); + if( flag_alternateform ){ + /* %#T means an Expr pointer that uses Expr.u.zToken */ + Expr *pExpr = va_arg(ap,Expr*); + if( ALWAYS(pExpr) && ALWAYS(!ExprHasProperty(pExpr,EP_IntValue)) ){ + sqlite3_str_appendall(pAccum, (const char*)pExpr->u.zToken); + sqlite3RecordErrorOffsetOfExpr(pAccum->db, pExpr); + } + }else{ + /* %T means a Token pointer */ + Token *pToken = va_arg(ap, Token*); + assert( bArgList==0 ); + if( pToken && pToken->n ){ + sqlite3_str_append(pAccum, (const char*)pToken->z, pToken->n); + sqlite3RecordErrorByteOffset(pAccum->db, pToken->z); + } } length = width = 0; break; @@ -934,6 +943,18 @@ void sqlite3RecordErrorByteOffset(sqlite3 *db, const char *z){ } } +/* +** If pExpr has a byte offset for the start of a token, record that as +** as the error offset. +*/ +void sqlite3RecordErrorOffsetOfExpr(sqlite3 *db, const Expr *pExpr){ + while( pExpr && (ExprHasProperty(pExpr,EP_FromJoin) || pExpr->w.iOfst<=0) ){ + pExpr = pExpr->pLeft; + } + if( pExpr==0 ) return; + db->errByteOffset = pExpr->w.iOfst; +} + /* ** Enlarge the memory allocation on a StrAccum object so that it is ** able to accept at least N more bytes of text. diff --git a/src/resolve.c b/src/resolve.c index 78135cf3b4..480694f6f5 100644 --- a/src/resolve.c +++ b/src/resolve.c @@ -620,6 +620,7 @@ static int lookupName( }else{ sqlite3ErrorMsg(pParse, "%s: %s", zErr, zCol); } + sqlite3RecordErrorOffsetOfExpr(pParse->db, pExpr); pParse->checkSchema = 1; pTopNC->nNcErr++; } @@ -728,7 +729,8 @@ static void notValidImpl( Parse *pParse, /* Leave error message here */ NameContext *pNC, /* The name context */ const char *zMsg, /* Type of error */ - Expr *pExpr /* Invalidate this expression on error */ + Expr *pExpr, /* Invalidate this expression on error */ + Expr *pError /* Associate error with this expression */ ){ const char *zIn = "partial index WHERE clauses"; if( pNC->ncFlags & NC_IdxExpr ) zIn = "index expressions"; @@ -740,10 +742,11 @@ static void notValidImpl( #endif sqlite3ErrorMsg(pParse, "%s prohibited in %s", zMsg, zIn); if( pExpr ) pExpr->op = TK_NULL; + sqlite3RecordErrorOffsetOfExpr(pParse->db, pError); } -#define sqlite3ResolveNotValid(P,N,M,X,E) \ +#define sqlite3ResolveNotValid(P,N,M,X,E,R) \ assert( ((X)&~(NC_IsCheck|NC_PartIdx|NC_IdxExpr|NC_GenCol))==0 ); \ - if( ((N)->ncFlags & (X))!=0 ) notValidImpl(P,N,M,E); + if( ((N)->ncFlags & (X))!=0 ) notValidImpl(P,N,M,E,R); /* ** Expression p should encode a floating point value between 1.0 and 0.0. @@ -878,7 +881,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ testcase( pNC->ncFlags & NC_IdxExpr ); testcase( pNC->ncFlags & NC_GenCol ); sqlite3ResolveNotValid(pParse, pNC, "the \".\" operator", - NC_IdxExpr|NC_GenCol, 0); + NC_IdxExpr|NC_GenCol, 0, pExpr); pRight = pExpr->pRight; if( pRight->op==TK_ID ){ zDb = 0; @@ -909,7 +912,6 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ int no_such_func = 0; /* True if no such function exists */ int wrong_num_args = 0; /* True if wrong number of arguments */ int is_agg = 0; /* True if is an aggregate function */ - int nId; /* Number of characters in function name */ const char *zId; /* The function name. */ FuncDef *pDef; /* Information about the function */ u8 enc = ENC(pParse->db); /* The database encoding */ @@ -919,7 +921,6 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ #endif assert( !ExprHasProperty(pExpr, EP_xIsSelect|EP_IntValue) ); zId = pExpr->u.zToken; - nId = sqlite3Strlen30(zId); pDef = sqlite3FindFunction(pParse->db, zId, n, enc, 0); if( pDef==0 ){ pDef = sqlite3FindFunction(pParse->db, zId, -2, enc, 0); @@ -936,8 +937,8 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ pExpr->iTable = exprProbability(pList->a[1].pExpr); if( pExpr->iTable<0 ){ sqlite3ErrorMsg(pParse, - "second argument to likelihood() must be a " - "constant between 0.0 and 1.0"); + "second argument to %#T() must be a " + "constant between 0.0 and 1.0", pExpr); pNC->nNcErr++; } }else{ @@ -958,8 +959,8 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ int auth = sqlite3AuthCheck(pParse, SQLITE_FUNCTION, 0,pDef->zName,0); if( auth!=SQLITE_OK ){ if( auth==SQLITE_DENY ){ - sqlite3ErrorMsg(pParse, "not authorized to use function: %s", - pDef->zName); + sqlite3ErrorMsg(pParse, "not authorized to use function: %#T", + pExpr); pNC->nNcErr++; } pExpr->op = TK_NULL; @@ -982,7 +983,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ ** in a CHECK constraint. SQLServer, MySQL, and PostgreSQL all ** all this. */ sqlite3ResolveNotValid(pParse, pNC, "non-deterministic functions", - NC_IdxExpr|NC_PartIdx|NC_GenCol, 0); + NC_IdxExpr|NC_PartIdx|NC_GenCol, 0, pExpr); }else{ assert( (NC_SelfRef & 0xff)==NC_SelfRef ); /* Must fit in 8 bits */ pExpr->op2 = pNC->ncFlags & NC_SelfRef; @@ -1014,7 +1015,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ ); if( pDef && pDef->xValue==0 && pWin ){ sqlite3ErrorMsg(pParse, - "%.*s() may not be used as a window function", nId, zId + "%#T() may not be used as a window function", pExpr ); pNC->nNcErr++; }else if( @@ -1028,13 +1029,13 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ }else{ zType = "aggregate"; } - sqlite3ErrorMsg(pParse, "misuse of %s function %.*s()",zType,nId,zId); + sqlite3ErrorMsg(pParse, "misuse of %s function %#T()",zType,pExpr); pNC->nNcErr++; is_agg = 0; } #else if( (is_agg && (pNC->ncFlags & NC_AllowAgg)==0) ){ - sqlite3ErrorMsg(pParse,"misuse of aggregate function %.*s()",nId,zId); + sqlite3ErrorMsg(pParse,"misuse of aggregate function %#T()",pExpr); pNC->nNcErr++; is_agg = 0; } @@ -1044,18 +1045,18 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ && pParse->explain==0 #endif ){ - sqlite3ErrorMsg(pParse, "no such function: %.*s", nId, zId); + sqlite3ErrorMsg(pParse, "no such function: %#T", pExpr); pNC->nNcErr++; }else if( wrong_num_args ){ - sqlite3ErrorMsg(pParse,"wrong number of arguments to function %.*s()", - nId, zId); + sqlite3ErrorMsg(pParse,"wrong number of arguments to function %#T()", + pExpr); pNC->nNcErr++; } #ifndef SQLITE_OMIT_WINDOWFUNC else if( is_agg==0 && ExprHasProperty(pExpr, EP_WinFunc) ){ sqlite3ErrorMsg(pParse, - "FILTER may not be used with non-aggregate %.*s()", - nId, zId + "FILTER may not be used with non-aggregate %#T()", + pExpr ); pNC->nNcErr++; } @@ -1140,7 +1141,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ testcase( pNC->ncFlags & NC_IdxExpr ); testcase( pNC->ncFlags & NC_GenCol ); if( pNC->ncFlags & NC_SelfRef ){ - notValidImpl(pParse, pNC, "subqueries", pExpr); + notValidImpl(pParse, pNC, "subqueries", pExpr, pExpr); }else{ sqlite3WalkSelect(pWalker, pExpr->x.pSelect); } @@ -1158,7 +1159,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ testcase( pNC->ncFlags & NC_IdxExpr ); testcase( pNC->ncFlags & NC_GenCol ); sqlite3ResolveNotValid(pParse, pNC, "parameters", - NC_IsCheck|NC_PartIdx|NC_IdxExpr|NC_GenCol, pExpr); + NC_IsCheck|NC_PartIdx|NC_IdxExpr|NC_GenCol, pExpr, pExpr); break; } case TK_IS: @@ -1210,6 +1211,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ testcase( pExpr->op==TK_ISNOT ); testcase( pExpr->op==TK_BETWEEN ); sqlite3ErrorMsg(pParse, "row value misused"); + sqlite3RecordErrorOffsetOfExpr(pParse->db, pExpr); } break; } @@ -1323,11 +1325,13 @@ static void resolveOutOfRangeError( Parse *pParse, /* The error context into which to write the error */ const char *zType, /* "ORDER" or "GROUP" */ int i, /* The index (1-based) of the term out of range */ - int mx /* Largest permissible value of i */ + int mx, /* Largest permissible value of i */ + Expr *pError /* Associate the error with the expression */ ){ sqlite3ErrorMsg(pParse, "%r %s BY term out of range - should be " "between 1 and %d", i, zType, mx); + sqlite3RecordErrorOffsetOfExpr(pParse->db, pError); } /* @@ -1383,7 +1387,7 @@ static int resolveCompoundOrderBy( if( NEVER(pE==0) ) continue; if( sqlite3ExprIsInteger(pE, &iCol) ){ if( iCol<=0 || iCol>pEList->nExpr ){ - resolveOutOfRangeError(pParse, "ORDER", i+1, pEList->nExpr); + resolveOutOfRangeError(pParse, "ORDER", i+1, pEList->nExpr, pE); return 1; } }else{ @@ -1479,7 +1483,7 @@ int sqlite3ResolveOrderGroupBy( for(i=0, pItem=pOrderBy->a; inExpr; i++, pItem++){ if( pItem->u.x.iOrderByCol ){ if( pItem->u.x.iOrderByCol>pEList->nExpr ){ - resolveOutOfRangeError(pParse, zType, i+1, pEList->nExpr); + resolveOutOfRangeError(pParse, zType, i+1, pEList->nExpr, 0); return 1; } resolveAlias(pParse, pEList, pItem->u.x.iOrderByCol-1, pItem->pExpr,0); @@ -1571,7 +1575,7 @@ static int resolveOrderGroupBy( ** number so that sqlite3ResolveOrderGroupBy() will convert the ** order-by term to a copy of the result-set expression */ if( iCol<1 || iCol>0xffff ){ - resolveOutOfRangeError(pParse, zType, i+1, nResult); + resolveOutOfRangeError(pParse, zType, i+1, nResult, pE2); return 1; } pItem->u.x.iOrderByCol = (u16)iCol; diff --git a/src/select.c b/src/select.c index 3f6bb1952e..5b8d994994 100644 --- a/src/select.c +++ b/src/select.c @@ -354,14 +354,14 @@ static void addWhereTerm( ExprSetProperty(pEq, EP_FromJoin); assert( !ExprHasProperty(pEq, EP_TokenOnly|EP_Reduced) ); ExprSetVVAProperty(pEq, EP_NoReduce); - pEq->iRightJoinTable = pE2->iTable; + pEq->w.iRightJoinTable = pE2->iTable; } *ppWhere = sqlite3ExprAnd(pParse, *ppWhere, pEq); } /* ** Set the EP_FromJoin property on all terms of the given expression. -** And set the Expr.iRightJoinTable to iTable for every term in the +** And set the Expr.w.iRightJoinTable to iTable for every term in the ** expression. ** ** The EP_FromJoin property is used on terms of an expression to tell @@ -371,8 +371,8 @@ static void addWhereTerm( ** WHERE clause during join processing but we need to remember that they ** originated in the ON or USING clause. ** -** The Expr.iRightJoinTable tells the WHERE clause processing that the -** expression depends on table iRightJoinTable even if that table is not +** The Expr.w.iRightJoinTable tells the WHERE clause processing that the +** expression depends on table w.iRightJoinTable even if that table is not ** explicitly mentioned in the expression. That information is needed ** for cases like this: ** @@ -390,7 +390,7 @@ void sqlite3SetJoinExpr(Expr *p, int iTable){ ExprSetProperty(p, EP_FromJoin); assert( !ExprHasProperty(p, EP_TokenOnly|EP_Reduced) ); ExprSetVVAProperty(p, EP_NoReduce); - p->iRightJoinTable = iTable; + p->w.iRightJoinTable = iTable; if( p->op==TK_FUNCTION ){ assert( ExprUseXList(p) ); if( p->x.pList ){ @@ -406,7 +406,7 @@ void sqlite3SetJoinExpr(Expr *p, int iTable){ } /* Undo the work of sqlite3SetJoinExpr(). In the expression p, convert every -** term that is marked with EP_FromJoin and iRightJoinTable==iTable into +** term that is marked with EP_FromJoin and w.iRightJoinTable==iTable into ** an ordinary term that omits the EP_FromJoin mark. ** ** This happens when a LEFT JOIN is simplified into an ordinary JOIN. @@ -414,7 +414,7 @@ void sqlite3SetJoinExpr(Expr *p, int iTable){ static void unsetJoinExpr(Expr *p, int iTable){ while( p ){ if( ExprHasProperty(p, EP_FromJoin) - && (iTable<0 || p->iRightJoinTable==iTable) ){ + && (iTable<0 || p->w.iRightJoinTable==iTable) ){ ExprClearProperty(p, EP_FromJoin); } if( p->op==TK_COLUMN && p->iTable==iTable ){ @@ -3648,9 +3648,9 @@ static Expr *substExpr( ){ if( pExpr==0 ) return 0; if( ExprHasProperty(pExpr, EP_FromJoin) - && pExpr->iRightJoinTable==pSubst->iTable + && pExpr->w.iRightJoinTable==pSubst->iTable ){ - pExpr->iRightJoinTable = pSubst->iNewTable; + pExpr->w.iRightJoinTable = pSubst->iNewTable; } if( pExpr->op==TK_COLUMN && pExpr->iTable==pSubst->iTable @@ -3689,7 +3689,7 @@ static Expr *substExpr( ExprSetProperty(pNew, EP_CanBeNull); } if( ExprHasProperty(pExpr,EP_FromJoin) ){ - sqlite3SetJoinExpr(pNew, pExpr->iRightJoinTable); + sqlite3SetJoinExpr(pNew, pExpr->w.iRightJoinTable); } sqlite3ExprDelete(db, pExpr); pExpr = pNew; @@ -3854,7 +3854,7 @@ static int renumberCursorsCb(Walker *pWalker, Expr *pExpr){ renumberCursorDoMapping(pWalker, &pExpr->iTable); } if( ExprHasProperty(pExpr, EP_FromJoin) ){ - renumberCursorDoMapping(pWalker, &pExpr->iRightJoinTable); + renumberCursorDoMapping(pWalker, &pExpr->w.iRightJoinTable); } return WRC_Continue; } @@ -4864,11 +4864,13 @@ static int pushDownWhereTerms( } if( isLeftJoin && (ExprHasProperty(pWhere,EP_FromJoin)==0 - || pWhere->iRightJoinTable!=iCursor) + || pWhere->w.iRightJoinTable!=iCursor) ){ return 0; /* restriction (4) */ } - if( ExprHasProperty(pWhere,EP_FromJoin) && pWhere->iRightJoinTable!=iCursor ){ + if( ExprHasProperty(pWhere,EP_FromJoin) + && pWhere->w.iRightJoinTable!=iCursor + ){ return 0; /* restriction (5) */ } if( sqlite3ExprIsTableConstant(pWhere, iCursor) ){ diff --git a/src/shell.c.in b/src/shell.c.in index 70f5b51c6f..a3b3918402 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -23,10 +23,10 @@ ** If SQLITE_CUSTOM_INCLUDE=? is defined, its value names the #include ** file. Note that this macro has a like effect on sqlite3.c compilation. */ +# define SHELL_STRINGIFY_(f) #f +# define SHELL_STRINGIFY(f) SHELL_STRINGIFY_(f) #ifdef SQLITE_CUSTOM_INCLUDE -# define INC_STRINGIFY_(f) #f -# define INC_STRINGIFY(f) INC_STRINGIFY_(f) -# include INC_STRINGIFY(SQLITE_CUSTOM_INCLUDE) +# include SHELL_STRINGIFY(SQLITE_CUSTOM_INCLUDE) #endif /* @@ -2311,7 +2311,12 @@ static int shell_callback( }else if( ur==0xfff0000000000000LL ){ raw_printf(p->out, "-1e999"); }else{ - sqlite3_snprintf(50,z,"%!.20g", r); + sqlite3_int64 ir = (sqlite3_int64)r; + if( r==(double)ir ){ + sqlite3_snprintf(50,z,"%lld.0", ir); + }else{ + sqlite3_snprintf(50,z,"%!.20g", r); + } raw_printf(p->out, "%s", z); } }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){ @@ -2637,17 +2642,24 @@ static int run_table_dump_query( */ static char *save_err_msg( sqlite3 *db, /* Database to query */ - const char *zWhen, /* Qualifier (format) wrapper */ + const char *zPhase, /* When the error occcurs */ int rc, /* Error code returned from API */ const char *zSql /* SQL string, or NULL */ ){ char *zErr; char *zContext; - if( zWhen==0 ) zWhen = "%s (%d)%s"; + sqlite3_str *pStr = sqlite3_str_new(0); + sqlite3_str_appendf(pStr, "%s, %s", zPhase, sqlite3_errmsg(db)); + if( rc>1 ){ + sqlite3_str_appendf(pStr, " (%d)", rc); + } zContext = shell_error_context(zSql, db); - zErr = sqlite3_mprintf(zWhen, sqlite3_errmsg(db), rc, zContext); + if( zContext ){ + sqlite3_str_appendall(pStr, zContext); + sqlite3_free(zContext); + } + zErr = sqlite3_str_finish(pStr); shell_check_oom(zErr); - sqlite3_free(zContext); return zErr; } @@ -3778,7 +3790,7 @@ static int shell_exec( rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zLeftover); if( SQLITE_OK != rc ){ if( pzErrMsg ){ - *pzErrMsg = save_err_msg(db, "in prepare, %s (%d)%s", rc, zSql); + *pzErrMsg = save_err_msg(db, "in prepare", rc, zSql); } }else{ if( !pStmt ){ @@ -3894,7 +3906,7 @@ static int shell_exec( zSql = zLeftover; while( IsSpace(zSql[0]) ) zSql++; }else if( pzErrMsg ){ - *pzErrMsg = save_err_msg(db, "stepping, %s (%d)", rc, 0); + *pzErrMsg = save_err_msg(db, "stepping", rc, 0); } /* clear saved stmt handle */ @@ -5744,10 +5756,10 @@ static void output_reset(ShellState *p){ /* ** Run an SQL command and return the single integer result. */ -static int db_int(ShellState *p, const char *zSql){ +static int db_int(sqlite3 *db, const char *zSql){ sqlite3_stmt *pStmt; int res = 0; - sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); + sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); if( pStmt && sqlite3_step(pStmt)==SQLITE_ROW ){ res = sqlite3_column_int(pStmt,0); } @@ -5852,7 +5864,7 @@ static int shell_dbinfo_command(ShellState *p, int nArg, char **azArg){ } for(i=0; idb, zSql); sqlite3_free(zSql); utf8_printf(p->out, "%-20s %d\n", aQuery[i].zName, val); } @@ -7216,6 +7228,7 @@ static char *shellMPrintf(int *pRc, const char *zFmt, ...){ return z; } + /* ** When running the ".recover" command, each output table, and the special ** orphaned row table if it is required, is represented by an instance @@ -7812,6 +7825,221 @@ static int recoverDatabaseCmd(ShellState *pState, int nArg, char **azArg){ } #endif /* !(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB) */ + +/* + * zAutoColumn(zCol, &db, ?) => Maybe init db, add column zCol to it. + * zAutoColumn(0, &db, ?) => (db!=0) Form columns spec for CREATE TABLE, + * close db and set it to 0, and return the columns spec, to later + * be sqlite3_free()'ed by the caller. + * The return is 0 when either: + * (a) The db was not initialized and zCol==0 (There are no columns.) + * (b) zCol!=0 (Column was added, db initialized as needed.) + * The 3rd argument, pRenamed, references an out parameter. If the + * pointer is non-zero, its referent will be set to a summary of renames + * done if renaming was necessary, or set to 0 if none was done. The out + * string (if any) must be sqlite3_free()'ed by the caller. + */ +#ifdef SHELL_DEBUG +#define rc_err_oom_die(rc) \ + if( rc==SQLITE_NOMEM ) shell_check_oom(0); \ + else if(!(rc==SQLITE_OK||rc==SQLITE_DONE)) \ + fprintf(stderr,"E:%d\n",rc), assert(0) +#else +static void rc_err_oom_die(int rc){ + if( rc==SQLITE_NOMEM ) shell_check_oom(0); + assert(rc==SQLITE_OK||rc==SQLITE_DONE); +} +#endif + +#ifdef SHELL_COLFIX_DB /* If this is set, the DB can be in a file. */ +static char zCOL_DB[] = SHELL_STRINGIFY(SHELL_COLFIX_DB); +#else /* Otherwise, memory is faster/better for the transient DB. */ +static const char *zCOL_DB = ":memory:"; +#endif + +/* Define character (as C string) to separate generated column ordinal + * from protected part of incoming column names. This defaults to "_" + * so that incoming column identifiers that did not need not be quoted + * remain usable without being quoted. It must be one character. + */ +#ifndef SHELL_AUTOCOLUMN_SEP +# define AUTOCOLUMN_SEP "_" +#else +# define AUTOCOLUMN_SEP SHELL_STRINGIFY(SHELL_AUTOCOLUMN_SEP) +#endif + +static char *zAutoColumn(const char *zColNew, sqlite3 **pDb, char **pzRenamed){ + /* Queries and D{D,M}L used here */ + static const char * const zTabMake = "\ +CREATE TABLE ColNames(\ + cpos INTEGER PRIMARY KEY,\ + name TEXT, nlen INT, chop INT, reps INT, suff TEXT);\ +CREATE VIEW RepeatedNames AS \ +SELECT DISTINCT t.name FROM ColNames t \ +WHERE t.name COLLATE NOCASE IN (\ + SELECT o.name FROM ColNames o WHERE o.cpos<>t.cpos\ +);\ +"; + static const char * const zTabFill = "\ +INSERT INTO ColNames(name,nlen,chop,reps,suff)\ + VALUES(iif(length(?1)>0,?1,'?'),max(length(?1),1),0,0,'')\ +"; + static const char * const zHasDupes = "\ +SELECT count(DISTINCT (substring(name,1,nlen-chop)||suff) COLLATE NOCASE)\ + 1, printf('%c%0*d', '"AUTOCOLUMN_SEP"', $1, cpos), '')" +#else /* ...RENAME_MINIMAL_ONE_PASS */ +"WITH Lzn(nlz) AS (" /* Find minimum extraneous leading 0's for uniqueness */ +" SELECT 0 AS nlz" +" UNION" +" SELECT nlz+1 AS nlz FROM Lzn" +" WHERE EXISTS(" +" SELECT 1" +" FROM ColNames t, ColNames o" +" WHERE" +" iif(t.name IN (SELECT * FROM RepeatedNames)," +" printf('%s"AUTOCOLUMN_SEP"%s'," +" t.name, substring(printf('%.*c%0.*d',nlz+1,'0',$1,t.cpos),2))," +" t.name" +" )" +" =" +" iif(o.name IN (SELECT * FROM RepeatedNames)," +" printf('%s"AUTOCOLUMN_SEP"%s'," +" o.name, substring(printf('%.*c%0.*d',nlz+1,'0',$1,o.cpos),2))," +" o.name" +" )" +" COLLATE NOCASE" +" AND o.cpos<>t.cpos" +" GROUP BY t.cpos" +" )" +") UPDATE Colnames AS t SET" +" chop = 0," /* No chopping, never touch incoming names. */ +" suff = iif(name IN (SELECT * FROM RepeatedNames)," +" printf('"AUTOCOLUMN_SEP"%s', substring(" +" printf('%.*c%0.*d',(SELECT max(nlz) FROM Lzn)+1,'0',1,t.cpos),2))," +" ''" +" )" +#endif + ; + static const char * const zCollectVar = "\ +SELECT\ + '('||x'0a'\ + || group_concat(\ + cname||' TEXT',\ + ','||iif((cpos-1)%4>0, ' ', x'0a'||' '))\ + ||')' AS ColsSpec \ +FROM (\ + SELECT cpos, printf('\"%w\"',printf('%.*s%s', nlen-chop,name,suff)) AS cname \ + FROM ColNames ORDER BY cpos\ +)"; + static const char * const zRenamesDone = + "SELECT group_concat(" + " printf('\"%w\" to \"%w\"',name,printf('%.*s%s', nlen-chop, name, suff))," + " ','||x'0a')" + "FROM ColNames WHERE suff<>'' OR chop!=0" + ; + int rc; + sqlite3_stmt *pStmt = 0; + assert(pDb!=0); + if( zColNew ){ + /* Add initial or additional column. Init db if necessary. */ + if( *pDb==0 ){ + if( SQLITE_OK!=sqlite3_open(zCOL_DB, pDb) ) return 0; +#ifdef SHELL_COLFIX_DB + if(*zCOL_DB!=':') + sqlite3_exec(*pDb,"drop table if exists ColNames;" + "drop view if exists RepeatedNames;",0,0,0); +#endif + rc = sqlite3_exec(*pDb, zTabMake, 0, 0, 0); + rc_err_oom_die(rc); + } + assert(*pDb!=0); + rc = sqlite3_prepare_v2(*pDb, zTabFill, -1, &pStmt, 0); + rc_err_oom_die(rc); + rc = sqlite3_bind_text(pStmt, 1, zColNew, -1, 0); + rc_err_oom_die(rc); + rc = sqlite3_step(pStmt); + rc_err_oom_die(rc); + sqlite3_finalize(pStmt); + return 0; + }else if( *pDb==0 ){ + return 0; + }else{ + /* Formulate the columns spec, close the DB, zero *pDb. */ + char *zColsSpec = 0; + int hasDupes = db_int(*pDb, zHasDupes); +#ifdef SQLITE_ENABLE_MATH_FUNCTIONS + int nDigits = (hasDupes)? db_int(*pDb, zColDigits) : 0; +#else +# define nDigits 2 +#endif + if( hasDupes ){ +#ifdef SHELL_COLUMN_RENAME_CLEAN + rc = sqlite3_exec(*pDb, zDedoctor, 0, 0, 0); + rc_err_oom_die(rc); +#endif + rc = sqlite3_exec(*pDb, zSetReps, 0, 0, 0); + rc_err_oom_die(rc); + rc = sqlite3_prepare_v2(*pDb, zRenameRank, -1, &pStmt, 0); + rc_err_oom_die(rc); + sqlite3_bind_int(pStmt, 1, nDigits); + rc = sqlite3_step(pStmt); + sqlite3_finalize(pStmt); + assert(rc==SQLITE_DONE); + } + assert(db_int(*pDb, zHasDupes)==0); /* Consider: remove this */ + rc = sqlite3_prepare_v2(*pDb, zCollectVar, -1, &pStmt, 0); + rc_err_oom_die(rc); + rc = sqlite3_step(pStmt); + if( rc==SQLITE_ROW ){ + zColsSpec = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 0)); + }else{ + zColsSpec = 0; + } + if( pzRenamed!=0 ){ + if( !hasDupes ) *pzRenamed = 0; + else{ + sqlite3_finalize(pStmt); + if( SQLITE_OK==sqlite3_prepare_v2(*pDb, zRenamesDone, -1, &pStmt, 0) + && SQLITE_ROW==sqlite3_step(pStmt) ){ + *pzRenamed = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 0)); + }else + *pzRenamed = 0; + } + } + sqlite3_finalize(pStmt); + sqlite3_close(*pDb); + *pDb = 0; + return zColsSpec; + } +} + /* ** If an input line begins with "." then invoke this routine to ** process that line. @@ -8760,20 +8988,29 @@ static int do_meta_command(char *zLine, ShellState *p){ if( rc && sqlite3_strglob("no such table: *", sqlite3_errmsg(p->db))==0 ){ char *zCreate = sqlite3_mprintf("CREATE TABLE \"%w\".\"%w\"", zSchema, zTable); - char cSep = '('; + sqlite3 *dbCols = 0; + char *zRenames = 0; + char *zColDefs; while( xRead(&sCtx) ){ - zCreate = sqlite3_mprintf("%z%c\n \"%w\" TEXT", zCreate, cSep, sCtx.z); - cSep = ','; + zAutoColumn(sCtx.z, &dbCols, 0); if( sCtx.cTerm!=sCtx.cColSep ) break; } - if( cSep=='(' ){ + zColDefs = zAutoColumn(0, &dbCols, &zRenames); + if( zRenames!=0 ){ + utf8_printf((stdin_is_interactive && p->in==stdin)? p->out : stderr, + "Columns renamed during .import %s due to duplicates:\n" + "%s\n", sCtx.zFile, zRenames); + sqlite3_free(zRenames); + } + assert(dbCols==0); + if( zColDefs==0 ){ sqlite3_free(zCreate); import_cleanup(&sCtx); utf8_printf(stderr,"%s: empty file\n", sCtx.zFile); rc = 1; goto meta_command_exit; } - zCreate = sqlite3_mprintf("%z\n)", zCreate); + zCreate = sqlite3_mprintf("%z%z\n", zCreate, zColDefs); if( eVerbose>=1 ){ utf8_printf(p->out, "%s\n", zCreate); } @@ -11179,19 +11416,30 @@ static int runOneSqlLine(ShellState *p, char *zSql, FILE *in, int startline){ END_TIMER; if( rc || zErrMsg ){ char zPrefix[100]; + const char *zErrorTail; + const char *zErrorType; + if( zErrMsg==0 ){ + zErrorType = "Error"; + zErrorTail = sqlite3_errmsg(p->db); + }else if( strncmp(zErrMsg, "in prepare, ",12)==0 ){ + zErrorType = "Parse error"; + zErrorTail = &zErrMsg[12]; + }else if( strncmp(zErrMsg, "stepping, ", 10)==0 ){ + zErrorType = "Runtime error"; + zErrorTail = &zErrMsg[10]; + }else{ + zErrorType = "Error"; + zErrorTail = zErrMsg; + } if( in!=0 || !stdin_is_interactive ){ sqlite3_snprintf(sizeof(zPrefix), zPrefix, - "Error: near line %d:", startline); + "%s near line %d:", zErrorType, startline); }else{ - sqlite3_snprintf(sizeof(zPrefix), zPrefix, "Error:"); - } - if( zErrMsg!=0 ){ - utf8_printf(stderr, "%s %s\n", zPrefix, zErrMsg); - sqlite3_free(zErrMsg); - zErrMsg = 0; - }else{ - utf8_printf(stderr, "%s %s\n", zPrefix, sqlite3_errmsg(p->db)); + sqlite3_snprintf(sizeof(zPrefix), zPrefix, "%s:", zErrorType); } + utf8_printf(stderr, "%s %s\n", zPrefix, zErrorTail); + sqlite3_free(zErrMsg); + zErrMsg = 0; return 1; }else if( ShellHasFlag(p, SHFLG_CountChanges) ){ char zLineBuf[2000]; diff --git a/src/sqlite.h.in b/src/sqlite.h.in index d293cc46c6..ecbfa37d05 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -566,7 +566,7 @@ int sqlite3_exec( #define SQLITE_WARNING_AUTOINDEX (SQLITE_WARNING | (1<<8)) #define SQLITE_AUTH_USER (SQLITE_AUTH | (1<<8)) #define SQLITE_OK_LOAD_PERMANENTLY (SQLITE_OK | (1<<8)) -#define SQLITE_OK_SYMLINK (SQLITE_OK | (2<<8)) +#define SQLITE_OK_SYMLINK (SQLITE_OK | (2<<8)) /* internal use only */ /* ** CAPI3REF: Flags For File Open Operations @@ -3850,7 +3850,7 @@ void sqlite3_free_filename(char*); ** SQL, the sqlite3_error_offset() interface returns the byte offset ** of the start of that token. ^The byte offset returned by ** sqlite3_error_offset() assumes that the input SQL is UTF8. -** ^If the most error does not reference a specific token in the input +** ^If the most recent error does not reference a specific token in the input ** SQL, then the sqlite3_error_offset() function returns -1. ** ** When the serialized [threading mode] is in use, it might be the @@ -7211,7 +7211,7 @@ struct sqlite3_index_info { ** destructor. ** ** ^If the third parameter (the pointer to the sqlite3_module object) is -** NULL then no new module is create and any existing modules with the +** NULL then no new module is created and any existing modules with the ** same name are dropped. ** ** See also: [sqlite3_drop_modules()] @@ -9642,7 +9642,7 @@ int sqlite3_vtab_distinct(sqlite3_index_info*); ** to SQLite that the virtual table does or does not want to process ** the IN operator all-at-once, respectively. ^Thus when the third ** parameter (F) is non-negative, this interface is the mechanism by -** which the virtual table tells SQLite how it wants to process in +** which the virtual table tells SQLite how it wants to process the ** IN operator. ** ** @@ -9668,7 +9668,7 @@ int sqlite3_vtab_distinct(sqlite3_index_info*); ** )^ ** ** ^If either or both of the conditions above are false, then SQLite uses -** the traditional one-at-a-time processing strategy for IN constraint. +** the traditional one-at-a-time processing strategy for the IN constraint. ** ^If both conditions are true, then the argvIndex-th parameter to the ** xFilter method will be an [sqlite3_value] that appears to be NULL, ** but which can be passed to [sqlite3_vtab_in_first()] and diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 50d902f34e..9acb787514 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -2845,7 +2845,10 @@ struct Expr { ** TK_VARIABLE: variable number (always >= 1). ** TK_SELECT_COLUMN: column of the result vector */ i16 iAgg; /* Which entry in pAggInfo->aCol[] or ->aFunc[] */ - int iRightJoinTable; /* If EP_FromJoin, the right table of the join */ + union { + int iRightJoinTable; /* If EP_FromJoin, the right table of the join */ + int iOfst; /* else: start of token from start of statement */ + } w; AggInfo *pAggInfo; /* Used by TK_AGG_COLUMN and TK_AGG_FUNCTION */ union { Table *pTab; /* TK_COLUMN: Table containing column. Can be NULL @@ -3954,6 +3957,7 @@ struct Sqlite3Config { int (*xTestCallback)(int); /* Invoked by sqlite3FaultSim() */ #endif int bLocaltimeFault; /* True to fail localtime() calls */ + int (*xAltLocaltime)(const void*,void*); /* Alternative localtime() routine */ int iOnceResetThreshold; /* When to reset OP_Once counters */ u32 szSorterRef; /* Min size in bytes to use sorter-refs */ unsigned int iPrngSeed; /* Alternative fixed seed for the PRNG */ @@ -5015,6 +5019,7 @@ void sqlite3ResultStrAccum(sqlite3_context*,StrAccum*); void sqlite3SelectDestInit(SelectDest*,int,int); Expr *sqlite3CreateColumnExpr(sqlite3 *, SrcList *, int, int); void sqlite3RecordErrorByteOffset(sqlite3*,const char*); +void sqlite3RecordErrorOffsetOfExpr(sqlite3*,const Expr*); void sqlite3BackupRestart(sqlite3_backup *); void sqlite3BackupUpdate(sqlite3_backup *, Pgno, const u8 *); diff --git a/src/test1.c b/src/test1.c index c6c2cb2f47..bf2bd68dcf 100644 --- a/src/test1.c +++ b/src/test1.c @@ -3977,6 +3977,102 @@ static int SQLITE_TCLAPI test_bind_blob( return TCL_OK; } +/* +** Usage: sqlite3_bind_value_from_preupdate STMT N NEW|OLD IDX +** +** Test the sqlite3_bind_value interface using sqlite3_value objects +** obtained from either sqlite3_preupdate_new() (if arg[3]=="new") or +** sqlite3_preupdate_old() if (arg[3]=="old"). IDX is the index to +** pass to the sqlite3_preupdate_xxx() function. +*/ +static int SQLITE_TCLAPI test_bind_value_from_preupdate( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + sqlite3_stmt *pStmt; + int idx; + int bidx; + const char *z3 = 0; + sqlite3 *db = 0; + sqlite3_value *pVal = 0; + + if( objc!=5 ){ + Tcl_WrongNumArgs(interp, 1, objv, "STMT N NEW|OLD IDX"); + return TCL_ERROR; + } + + if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; + if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; + z3 = Tcl_GetString(objv[3]); + if( Tcl_GetIntFromObj(interp, objv[4], &bidx) ) return TCL_ERROR; + db = sqlite3_db_handle(pStmt); + +#ifdef SQLITE_ENABLE_PREUPDATE_HOOK + if( z3[0]=='n' ){ + sqlite3_preupdate_new(db, bidx, &pVal); + }else if( z3[0]=='o' ){ + sqlite3_preupdate_old(db, bidx, &pVal); + }else{ + Tcl_AppendResult(interp, "expected new or old, got: ", z3, (char*)0); + return TCL_ERROR; + } + sqlite3_bind_value(pStmt, idx, pVal); +#endif + + return TCL_OK; +} + +/* +** Usage: sqlite3_bind_value_from_select STMT N SELECT +** +** Test the sqlite3_bind_value interface. STMT is a prepared statement. +** N is the index of a wildcard in the prepared statement. +*/ +static int SQLITE_TCLAPI test_bind_value_from_select( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + sqlite3_stmt *pStmt; + sqlite3_stmt *pStmt2; + int idx; + const char *zSql = 0; + sqlite3 *db = 0; + int rc = SQLITE_OK; + + if( objc!=4 ){ + Tcl_WrongNumArgs(interp, 1, objv, "STMT N SELECT"); + return TCL_ERROR; + } + + if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; + if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; + zSql = Tcl_GetString(objv[3]); + db = sqlite3_db_handle(pStmt); + + rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt2, 0); + if( rc!=SQLITE_OK ){ + Tcl_AppendResult(interp, "error in SQL: ", sqlite3_errmsg(db), (char*)0); + return TCL_ERROR; + } + if( sqlite3_step(pStmt2)==SQLITE_ROW ){ + sqlite3_value *pVal = sqlite3_column_value(pStmt2, 0); + sqlite3_bind_value(pStmt, idx, pVal); + } + rc = sqlite3_finalize(pStmt2); + if( rc!=SQLITE_OK ){ + Tcl_AppendResult(interp, + "error runnning SQL: ", sqlite3_errmsg(db), (char*)0 + ); + return TCL_ERROR; + } + + return TCL_OK; +} + #ifndef SQLITE_OMIT_VIRTUALTABLE /* @@ -7111,6 +7207,55 @@ static int SQLITE_TCLAPI test_print_eqp( } #endif /* SQLITE_OMIT_EXPLAIN */ +#include +/* +** This is an alternative localtime_r() implementation used for testing +** the 'localtime' and 'utc' modifiers of date-time functions. Because +** the OS-supplied localtime_r() is locale-dependent, this alternative is +** provided as a stable test platform. +** +** Operation: +** +** (1) Localtime is 30 minutes earlier than (west of) UTC on +** even days (counting from 1970-01-01) +** +** (2) Localtime is 30 minutes later than (east of) UTC on odd days. +** +** (3) The function fails for the specific date/time value +** of 2000-05-29 14:16:00 in order to test the ability of +** SQLite to deal with localtime_r() failures. +*/ +static int testLocaltime(const void *aliasT, void *aliasTM){ + const time_t t = *(const time_t*)aliasT; + struct tm *pTm = (struct tm *)aliasTM; + time_t altT; + sqlite3_int64 iJD; + int Z, A, B, C, D, E, X1, S; + + if( (t/86400) & 1 ){ + altT = t + 1800; /* 30 minutes later on odd days */ + }else{ + altT = t - 1800; /* 30 minutes earlier on even days */ + } + iJD = (sqlite3_int64)(altT + 210866760000); + Z = (int)((iJD + 43200)/86400); + A = (int)((Z - 1867216.25)/36524.25); + A = Z + 1 + A - (A/4); + B = A + 1524; + C = (int)((B - 122.1)/365.25); + D = (36525*(C&32767))/100; + E = (int)((B-D)/30.6001); + X1 = (int)(30.6001*E); + pTm->tm_mday = B - D - X1; + pTm->tm_mon = E<14 ? E-2 : E-14; + pTm->tm_year = (pTm->tm_mon>1 ? C - 4716 : C - 4715) - 1900; + S = (int)((iJD + 43200)%86400); + pTm->tm_hour = S/3600; + pTm->tm_min = (S/60)%60; + pTm->tm_sec = S % 60; + return t==959609760; /* Special case: 2000-05-29 14:16:00 fails */ +} + /* ** sqlite3_test_control VERB ARGS... */ @@ -7158,11 +7303,11 @@ static int SQLITE_TCLAPI test_test_control( case SQLITE_TESTCTRL_LOCALTIME_FAULT: { int val; if( objc!=3 ){ - Tcl_WrongNumArgs(interp, 2, objv, "ONOFF"); + Tcl_WrongNumArgs(interp, 2, objv, "0|1|2"); return TCL_ERROR; } - if( Tcl_GetBooleanFromObj(interp, objv[2], &val) ) return TCL_ERROR; - sqlite3_test_control(iFlag, val); + if( Tcl_GetIntFromObj(interp, objv[2], &val) ) return TCL_ERROR; + sqlite3_test_control(iFlag, val, testLocaltime); break; } @@ -8477,6 +8622,8 @@ int Sqlitetest1_Init(Tcl_Interp *interp){ { "sqlite3_bind_text", test_bind_text ,0 }, { "sqlite3_bind_text16", test_bind_text16 ,0 }, { "sqlite3_bind_blob", test_bind_blob ,0 }, + { "sqlite3_bind_value_from_select",test_bind_value_from_select ,0 }, + { "sqlite3_bind_value_from_preupdate",test_bind_value_from_preupdate ,0 }, #ifndef SQLITE_OMIT_VIRTUALTABLE { "sqlite3_carray_bind", test_carray_bind ,0 }, #endif diff --git a/src/tokenize.c b/src/tokenize.c index 347fd57323..a727078ba7 100644 --- a/src/tokenize.c +++ b/src/tokenize.c @@ -657,7 +657,10 @@ int sqlite3RunParser(Parse *pParse, const char *zSql){ tokenType = analyzeFilterKeyword((const u8*)&zSql[6], lastTokenParsed); #endif /* SQLITE_OMIT_WINDOWFUNC */ }else{ - sqlite3ErrorMsg(pParse, "unrecognized token: \"%.*s\"", n, zSql); + Token x; + x.z = zSql; + x.n = n; + sqlite3ErrorMsg(pParse, "unrecognized token: \"%T\"", &x); break; } } diff --git a/src/treeview.c b/src/treeview.c index 1b19ea6797..86f06e8323 100644 --- a/src/treeview.c +++ b/src/treeview.c @@ -412,7 +412,7 @@ void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){ sqlite3_str_appendf(&x, " fg.af=%x.%c", pExpr->flags, pExpr->affExpr ? pExpr->affExpr : 'n'); if( ExprHasProperty(pExpr, EP_FromJoin) ){ - sqlite3_str_appendf(&x, " iRJT=%d", pExpr->iRightJoinTable); + sqlite3_str_appendf(&x, " iRJT=%d", pExpr->w.iRightJoinTable); } if( ExprHasProperty(pExpr, EP_FromDDL) ){ sqlite3_str_appendf(&x, " DDL"); diff --git a/src/trigger.c b/src/trigger.c index 420ef7061c..8f096a05c6 100644 --- a/src/trigger.c +++ b/src/trigger.c @@ -1236,6 +1236,7 @@ static TriggerPrg *getRowTrigger( /* If an existing TriggerPrg could not be located, create a new one. */ if( !pPrg ){ pPrg = codeRowTrigger(pParse, pTrigger, pTab, orconf); + pParse->db->errByteOffset = -1; } return pPrg; diff --git a/src/vdbeapi.c b/src/vdbeapi.c index 9cc200298e..6939813a27 100644 --- a/src/vdbeapi.c +++ b/src/vdbeapi.c @@ -1594,7 +1594,10 @@ int sqlite3_bind_value(sqlite3_stmt *pStmt, int i, const sqlite3_value *pValue){ break; } case SQLITE_FLOAT: { - rc = sqlite3_bind_double(pStmt, i, pValue->u.r); + assert( pValue->flags & (MEM_Real|MEM_IntReal) ); + rc = sqlite3_bind_double(pStmt, i, + (pValue->flags & MEM_Real) ? pValue->u.r : (double)pValue->u.i + ); break; } case SQLITE_BLOB: { diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 5e042a6b32..434d9700d4 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -3269,6 +3269,7 @@ int sqlite3VdbeTransferError(Vdbe *p){ sqlite3ValueSetNull(db->pErr); } db->errCode = rc; + db->errByteOffset = -1; return rc; } diff --git a/src/where.c b/src/where.c index bd42789770..c1a2f0595e 100644 --- a/src/where.c +++ b/src/where.c @@ -1243,7 +1243,9 @@ static sqlite3_index_info *allocateIndexInfo( pIdxCons[j].iTermOffset = i; op = pTerm->eOperator & WO_ALL; if( op==WO_IN ){ - pHidden->mIn |= SMASKBIT32(j); + if( (pTerm->wtFlags & TERM_SLICE)==0 ){ + pHidden->mIn |= SMASKBIT32(j); + } op = WO_EQ; } if( op==WO_AUX ){ @@ -3166,7 +3168,7 @@ static int whereUsablePartialIndex( for(i=0, pTerm=pWC->a; inTerm; i++, pTerm++){ Expr *pExpr; pExpr = pTerm->pExpr; - if( (!ExprHasProperty(pExpr, EP_FromJoin) || pExpr->iRightJoinTable==iTab) + if( (!ExprHasProperty(pExpr, EP_FromJoin) || pExpr->w.iRightJoinTable==iTab) && (isLeft==0 || ExprHasProperty(pExpr, EP_FromJoin)) && sqlite3ExprImpliesExpr(pParse, pExpr, pWhere, iTab) && (pTerm->wtFlags & TERM_VNULL)==0 @@ -5146,7 +5148,7 @@ static SQLITE_NOINLINE Bitmask whereOmitNoopJoin( for(pTerm=pWInfo->sWC.a; pTermprereqAll & pLoop->maskSelf)!=0 ){ if( !ExprHasProperty(pTerm->pExpr, EP_FromJoin) - || pTerm->pExpr->iRightJoinTable!=pItem->iCursor + || pTerm->pExpr->w.iRightJoinTable!=pItem->iCursor ){ break; } diff --git a/src/wherecode.c b/src/wherecode.c index 603fcdfd76..79504159a6 100644 --- a/src/wherecode.c +++ b/src/wherecode.c @@ -1062,7 +1062,7 @@ static void codeCursorHint( if( pTabItem->fg.jointype & JT_LEFT ){ Expr *pExpr = pTerm->pExpr; if( !ExprHasProperty(pExpr, EP_FromJoin) - || pExpr->iRightJoinTable!=pTabItem->iCursor + || pExpr->w.iRightJoinTable!=pTabItem->iCursor ){ sWalker.eCode = 0; sWalker.xExprCallback = codeCursorHintIsOrFunction; diff --git a/src/whereexpr.c b/src/whereexpr.c index ac4f2e1fbe..19dd886de5 100644 --- a/src/whereexpr.c +++ b/src/whereexpr.c @@ -466,7 +466,7 @@ static int isAuxiliaryVtabOperator( static void transferJoinMarkings(Expr *pDerived, Expr *pBase){ if( pDerived ){ pDerived->flags |= pBase->flags & EP_FromJoin; - pDerived->iRightJoinTable = pBase->iRightJoinTable; + pDerived->w.iRightJoinTable = pBase->w.iRightJoinTable; } } @@ -1111,7 +1111,7 @@ static void exprAnalyze( #endif if( ExprHasProperty(pExpr, EP_FromJoin) ){ - Bitmask x = sqlite3WhereGetMask(pMaskSet, pExpr->iRightJoinTable); + Bitmask x = sqlite3WhereGetMask(pMaskSet, pExpr->w.iRightJoinTable); prereqAll |= x; extraRight = x-1; /* ON clause terms may not be used with an index ** on left table of a LEFT JOIN. Ticket #3015 */ @@ -1429,7 +1429,7 @@ static void exprAnalyze( int i; for(i=0; ipLeft); i++){ int idxNew; - idxNew = whereClauseInsert(pWC, pExpr, TERM_VIRTUAL); + idxNew = whereClauseInsert(pWC, pExpr, TERM_VIRTUAL|TERM_SLICE); pWC->a[idxNew].u.x.iField = i+1; exprAnalyze(pSrc, pWC, idxNew); markTermAsChild(pWC, idxNew, idxTerm); @@ -1462,7 +1462,7 @@ static void exprAnalyze( 0, sqlite3ExprDup(db, pRight, 0)); if( ExprHasProperty(pExpr, EP_FromJoin) && pNewExpr ){ ExprSetProperty(pNewExpr, EP_FromJoin); - pNewExpr->iRightJoinTable = pExpr->iRightJoinTable; + pNewExpr->w.iRightJoinTable = pExpr->w.iRightJoinTable; } idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC); testcase( idxNew==0 ); @@ -1536,7 +1536,7 @@ void sqlite3WhereSplit(WhereClause *pWC, Expr *pExpr, u8 op){ ** TK_INTEGER so that it will be available to sqlite3_vtab_rhs_value(). ** If not, then it codes as a TK_REGISTER expression. */ -void whereAddLimitExpr( +static void whereAddLimitExpr( WhereClause *pWC, /* Add the constraint to this WHERE clause */ int iReg, /* Register that will hold value of the limit/offset */ Expr *pExpr, /* Expression that defines the limit/offset */ diff --git a/test/altercol.test b/test/altercol.test index 10ff9e773f..e39793aa9f 100644 --- a/test/altercol.test +++ b/test/altercol.test @@ -553,8 +553,9 @@ do_execsql_test 13.1.3 { sqlite3_db_config db DEFENSIVE 0 do_execsql_test 13.1.4 { - PRAGMA writable_schema = 1; + PRAGMA writable_schema = ON; UPDATE sqlite_master SET sql = 'CREATE INDEX x1i ON x1(j)' WHERE name='x1i'; + PRAGMA writable_schema = OFF; } {} do_catchsql_test 13.1.5 { @@ -562,7 +563,9 @@ do_catchsql_test 13.1.5 { } {1 {error in index x1i: no such column: j}} do_execsql_test 13.1.6 { + PRAGMA writable_schema = ON; UPDATE sqlite_master SET sql = '' WHERE name='x1i'; + PRAGMA writable_schema = OFF; } {} do_catchsql_test 13.1.7 { @@ -570,7 +573,9 @@ do_catchsql_test 13.1.7 { } {1 {error in index x1i: }} do_execsql_test 13.1.8 { + PRAGMA writable_schema = ON; DELETE FROM sqlite_master WHERE name = 'x1i'; + PRAGMA writable_schema = OFF; } do_execsql_test 13.2.0 { @@ -861,5 +866,69 @@ do_execsql_test 23.0 { } {ok {CREATE TABLE t1("x" "b",c)}} +# 2022-02-04 +# Do not complain about syntax errors in the schema if +# in PRAGMA writable_schema=ON mode. +# +reset_db +do_execsql_test 23.0 { + CREATE TABLE t1(a INT, b REAL, c TEXT, d BLOB, e ANY); + CREATE INDEX t1abx ON t1(a, b, a+b) WHERE c IS NOT NULL; + CREATE VIEW t2 AS SELECT a+10, b*5.0, xyz FROM t1; -- unknown column "xyz" + CREATE TABLE schema_copy(name TEXT, sql TEXT); + INSERT INTO schema_copy(name,sql) SELECT name, sql FROM sqlite_schema WHERE sql IS NOT NULL; +} {} +do_catchsql_test 23.1 { + ALTER TABLE t1 RENAME COLUMN e TO eeee; +} {1 {error in view t2: no such column: xyz}} +do_execsql_test 23.2 { + SELECT name, sql FROM sqlite_master + EXCEPT SELECT name, sql FROM schema_copy; +} {} +do_execsql_test 23.3 { + BEGIN; + PRAGMA writable_schema=ON; + ALTER TABLE t1 RENAME COLUMN e TO eeee; + PRAGMA writable_schema=OFF; + SELECT name FROM sqlite_master + WHERE (name, sql) NOT IN (SELECT name, sql FROM schema_copy); + ROLLBACK; +} {t1} +do_execsql_test 23.10 { + DROP VIEW t2; + CREATE TRIGGER r3 AFTER INSERT ON t1 BEGIN + INSERT INTO t3(x,y) VALUES(new.a, new.b); + INSERT INTO t4(p) VALUES(new.c); -- no such table "t4" + END; + DELETE FROM schema_copy; + INSERT INTO schema_copy(name,sql) SELECT name, sql FROM sqlite_schema WHERE sql IS NOT NULL; +} {} +do_catchsql_test 23.11 { + ALTER TABLE t1 RENAME COLUMN e TO eeee; +} {1 {error in trigger r3: no such table: main.t3}} +do_execsql_test 23.12 { + SELECT name, sql FROM sqlite_master + EXCEPT SELECT name, sql FROM schema_copy; +} {} +do_execsql_test 23.13 { + BEGIN; + PRAGMA writable_schema=ON; + ALTER TABLE t1 RENAME COLUMN e TO eeee; + PRAGMA writable_schema=OFF; + SELECT name FROM sqlite_master + WHERE (name, sql) NOT IN (SELECT name, sql FROM schema_copy); + ROLLBACK; +} {t1} +do_execsql_test 23.20 { + CREATE TABLE t4(id INTEGER PRIMARY KEY, c1 INT, c2 INT); + CREATE VIEW t4v1 AS SELECT id, c1, c99 FROM t4; + DELETE FROM schema_copy; + INSERT INTO schema_copy SELECT name, sql FROM sqlite_schema; + BEGIN; + PRAGMA writable_schema=ON; + ALTER TABLE t4 RENAME to t4new; + SELECT name FROM sqlite_schema WHERE (name,sql) NOT IN (SELECT * FROM schema_copy); + ROLLBACK; +} {t4new} finish_test diff --git a/test/altermalloc2.test b/test/altermalloc2.test index 3d22ad9453..a90be88cf5 100644 --- a/test/altermalloc2.test +++ b/test/altermalloc2.test @@ -26,6 +26,11 @@ do_execsql_test 1.0 { } faultsim_save_and_close +set ::TMPDBERROR [list 1 \ + {unable to open a temporary database file for storing temporary tables} +] + + do_faultsim_test 1 -prep { faultsim_restore_and_reopen } -body { @@ -33,7 +38,7 @@ do_faultsim_test 1 -prep { ALTER TABLE t1 RENAME abcd TO dcba } } -test { - faultsim_test_result {0 {}} + faultsim_test_result {0 {}} $::TMPDBERROR } catch {db close} @@ -52,7 +57,7 @@ do_faultsim_test 2 -prep { ALTER TABLE t1 RENAME abcd TO dcba } } -test { - faultsim_test_result {0 {}} + faultsim_test_result {0 {}} $::TMPDBERROR } @@ -70,7 +75,7 @@ do_faultsim_test 3 -prep { ALTER TABLE t1 RENAME abcd TO dcba } } -test { - faultsim_test_result {0 {}} + faultsim_test_result {0 {}} $::TMPDBERROR } reset_db @@ -95,7 +100,7 @@ do_faultsim_test 4 -faults oom-* -prep { ALTER TABLE rr RENAME a TO c; } } -test { - faultsim_test_result {0 {}} + faultsim_test_result {0 {}} $::TMPDBERROR } reset_db @@ -116,7 +121,7 @@ do_faultsim_test 5 -faults oom-* -prep { ALTER TABLE rr RENAME TO c; } } -test { - faultsim_test_result {0 {}} + faultsim_test_result {0 {}} $::TMPDBERROR } finish_test diff --git a/test/altermalloc3.test b/test/altermalloc3.test index 4c10f48fed..7023b1c0f6 100644 --- a/test/altermalloc3.test +++ b/test/altermalloc3.test @@ -21,6 +21,10 @@ ifcapable !altertable { return } +set ::TMPDBERROR [list 1 \ + {unable to open a temporary database file for storing temporary tables} +] + do_execsql_test 1.0 { CREATE TABLE x1( one, two, three, PRIMARY KEY(one), @@ -40,7 +44,7 @@ do_faultsim_test 1 -prep { } -body { execsql { ALTER TABLE t1 DROP COLUMN c } } -test { - faultsim_test_result {0 {}} + faultsim_test_result {0 {}} $::TMPDBERROR } #------------------------------------------------------------------------- @@ -72,7 +76,7 @@ do_faultsim_test 2.2 -prep { ALTER TABLE t2 RENAME TO t2x; } } -test { - faultsim_test_result {0 {}} + faultsim_test_result {0 {}} $::TMPDBERROR } finish_test diff --git a/test/altertab2.test b/test/altertab2.test index 9c1ad58134..def9e56686 100644 --- a/test/altertab2.test +++ b/test/altertab2.test @@ -355,7 +355,7 @@ do_execsql_test 8.5 { reset_db do_catchsql_test 8.6 { CREATE TABLE t0(c0); - CREATE INDEX i0 ON t0(LIKELIHOOD(1,2) AND 0); + CREATE INDEX i0 ON t0(likelihood(1,2) AND 0); ALTER TABLE t0 RENAME TO t1; SELECT sql FROM sqlite_master WHERE name='i0'; } {1 {error in index i0: second argument to likelihood() must be a constant between 0.0 and 1.0}} diff --git a/test/bind2.test b/test/bind2.test new file mode 100644 index 0000000000..1ebf35c2e0 --- /dev/null +++ b/test/bind2.test @@ -0,0 +1,63 @@ +# 2022 Feb 10 +# +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. +# +#*********************************************************************** +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl +set testprefix bind2 + + +# Test that using bind_value() on a REAL sqlite3_value that was stored +# as an INTEGER works properly. +# +# 1.1: An IntReal value read from a table, +# 1.2: IntReal values obtained via the sqlite3_preupdate_old|new() +# interfaces. +# +do_execsql_test 1.0 { + CREATE TABLE t1(a REAL); + INSERT INTO t1 VALUES(42.0); + SELECT * FROM t1; +} {42.0} + +do_test 1.1 { + set stmt [sqlite3_prepare db "SELECT ?" -1 tail] + sqlite3_bind_value_from_select $stmt 1 "SELECT a FROM t1" + sqlite3_step $stmt + sqlite3_column_text $stmt 0 +} {42.0} +sqlite3_finalize $stmt + +ifcapable !preupdate { + finish_test + return +} + +proc preup {args} { + set stmt [sqlite3_prepare db "SELECT ?" -1 tail] + sqlite3_bind_value_from_preupdate $stmt 1 old 0 + sqlite3_step $stmt + lappend ::reslist [sqlite3_column_text $stmt 0] + sqlite3_reset $stmt + sqlite3_bind_value_from_preupdate $stmt 1 new 0 + sqlite3_step $stmt + lappend ::reslist [sqlite3_column_text $stmt 0] + sqlite3_finalize $stmt +} +db preupdate hook preup + +do_test 1.2 { + set ::reslist [list] + execsql { UPDATE t1 SET a=43; } + set ::reslist +} {42.0 43.0} + +finish_test diff --git a/test/date.test b/test/date.test index f002334d17..a9a34065c1 100644 --- a/test/date.test +++ b/test/date.test @@ -239,138 +239,70 @@ datetest 5.13 {datetime('1994-04-16 14:00:00Zulu')} NULL datetest 5.14 {datetime('1994-04-16 14:00:00Z +05:00')} NULL datetest 5.15 {datetime('1994-04-16 14:00:00 +05:00 Z')} NULL -# localtime->utc and utc->localtime conversions. These tests only work -# if the localtime is in the US Eastern Time (the time in Charlotte, NC -# and in New York.) +# localtime->utc and utc->localtime conversions. # -# On non-Vista Windows platform, '2006-03-31' is treated incorrectly as being -# in DST giving a 4 hour offset instead of 5. In 2007, DST was extended to -# start three weeks earlier (second Sunday in March) and end one week -# later (first Sunday in November). Older Windows systems apply this -# new rule incorrectly to dates prior to 2007. +# Use SQLITE_TESTCTRL_LOCALTIME_FAULT=2 to set an alternative localtime_r() +# implementation that is not locale-dependent. This testing localtime_r() +# operates as follows: # -# It might be argued that this is masking a problem on non-Vista Windows -# platform. A ticket has already been opened for this issue -# (http://www.sqlite.org/cvstrac/tktview?tn=2322). This is just to prevent -# more confusion/reports of the issue. +# (1) Localtime is 30 minutes earlier than (west of) UTC on +# even days (counting from 1970-01-01) # - -# $tzoffset_old should be 5 if DST is working correctly. -set tzoffset_old [db one { - SELECT CAST(24*(julianday('2006-03-31') - - julianday('2006-03-31','localtime'))+0.5 - AS INT) -}] - -# $tzoffset_new should be 4 if DST is working correctly. -set tzoffset_new [db one { - SELECT CAST(24*(julianday('2007-03-31') - - julianday('2007-03-31','localtime'))+0.5 - AS INT) -}] - -# Warn about possibly broken Windows DST implementations. -if {$::tcl_platform(platform)=="windows" && $tzoffset_new==4 && $tzoffset_old==4} { - puts "******************************************************************" - puts "N.B.: The DST support provided by your current O/S seems to be" - puts "suspect in that it is reporting incorrect DST values for dates" - puts "prior to 2007. This is the known case for most (all?) non-Vista" - puts "Windows versions. Please see ticket #2322 for more information." - puts "******************************************************************" +# (2) Localtime is 30 minutes later than (east of) UTC on odd days. +# +# (3) The function fails for the specific date/time value +# of 2000-05-29 14:16:00 in order to test the ability of +# SQLite to deal with localtime_r() failures. +# +proc local_to_utc {tn utc local} { + do_execsql_test date-$tn "SELECT datetime('$utc','localtime')" [list $local] +} +proc utc_to_local {tn local utc} { + do_execsql_test date-$tn "SELECT datetime('$local','utc')" [list $utc] } -if {$tzoffset_new==4} { - datetest 6.1 {datetime('2000-10-29 05:59:00','localtime')}\ - {2000-10-29 01:59:00} - datetest 6.1.1 {datetime('2006-10-29 05:59:00','localtime')}\ - {2006-10-29 01:59:00} - datetest 6.1.2 {datetime('2007-11-04 05:59:00','localtime')}\ - {2007-11-04 01:59:00} +sqlite3_test_control SQLITE_TESTCTRL_LOCALTIME_FAULT 2 +local_to_utc 6.1 {2000-10-29 12:00:00} {2000-10-29 12:30:00} +utc_to_local 6.2 {2000-10-29 12:30:00} {2000-10-29 12:00:00} +local_to_utc 6.3 {2000-10-30 12:00:00} {2000-10-30 11:30:00} +utc_to_local 6.4 {2000-10-30 11:30:00} {2000-10-30 12:00:00} - # If the new and old DST rules seem to be working correctly... - if {$tzoffset_new==4 && $tzoffset_old==5} { - datetest 6.2 {datetime('2000-10-29 06:00:00','localtime')}\ - {2000-10-29 01:00:00} - datetest 6.2.1 {datetime('2006-10-29 06:00:00','localtime')}\ - {2006-10-29 01:00:00} - } - datetest 6.2.2 {datetime('2007-11-04 06:00:00','localtime')}\ - {2007-11-04 01:00:00} +local_to_utc 6.5 {2000-10-28 23:59:59} {2000-10-28 23:29:59} +local_to_utc 6.6 {2000-10-29 00:00:00} {2000-10-29 00:30:00} - # If the new and old DST rules seem to be working correctly... - if {$tzoffset_new==4 && $tzoffset_old==5} { - datetest 6.3 {datetime('2000-04-02 06:59:00','localtime')}\ - {2000-04-02 01:59:00} - datetest 6.3.1 {datetime('2006-04-02 06:59:00','localtime')}\ - {2006-04-02 01:59:00} - } - datetest 6.3.2 {datetime('2007-03-11 07:00:00','localtime')}\ - {2007-03-11 03:00:00} - - datetest 6.4 {datetime('2000-04-02 07:00:00','localtime')}\ - {2000-04-02 03:00:00} - datetest 6.4.1 {datetime('2006-04-02 07:00:00','localtime')}\ - {2006-04-02 03:00:00} - datetest 6.4.2 {datetime('2007-03-11 07:00:00','localtime')}\ - {2007-03-11 03:00:00} - - datetest 6.5 {datetime('2000-10-29 01:59:00','utc')} {2000-10-29 05:59:00} - datetest 6.5.1 {datetime('2006-10-29 01:59:00','utc')} {2006-10-29 05:59:00} - datetest 6.5.2 {datetime('2007-11-04 01:59:00','utc')} {2007-11-04 05:59:00} - - # If the new and old DST rules seem to be working correctly... - if {$tzoffset_new==4 && $tzoffset_old==5} { - datetest 6.6 {datetime('2000-10-29 02:00:00','utc')} {2000-10-29 07:00:00} - datetest 6.6.1 {datetime('2006-10-29 02:00:00','utc')} {2006-10-29 07:00:00} - } - datetest 6.6.2 {datetime('2007-11-04 02:00:00','utc')} {2007-11-04 07:00:00} - - # If the new and old DST rules seem to be working correctly... - if {$tzoffset_new==4 && $tzoffset_old==5} { - datetest 6.7 {datetime('2000-04-02 01:59:00','utc')} {2000-04-02 06:59:00} - datetest 6.7.1 {datetime('2006-04-02 01:59:00','utc')} {2006-04-02 06:59:00} - } - datetest 6.7.2 {datetime('2007-03-11 01:59:00','utc')} {2007-03-11 06:59:00} - - datetest 6.8 {datetime('2000-04-02 02:00:00','utc')} {2000-04-02 06:00:00} - datetest 6.8.1 {datetime('2006-04-02 02:00:00','utc')} {2006-04-02 06:00:00} - datetest 6.8.2 {datetime('2007-03-11 02:00:00','utc')} {2007-03-11 06:00:00} - - # The 'utc' modifier is a no-op if the LHS is known to already be in UTC - datetest 6.9.1 {datetime('2015-12-23 12:00:00','utc')} {2015-12-23 17:00:00} - datetest 6.9.2 {datetime('2015-12-23 12:00:00z','utc')} {2015-12-23 12:00:00} - datetest 6.9.3 {datetime('2015-12-23 12:00:00-03:00','utc')} \ - {2015-12-23 15:00:00} - datetest 6.9.4 {datetime('2015-12-23 12:00:00','utc','utc','utc')} \ - {2015-12-23 17:00:00} - - - datetest 6.10 {datetime('2000-01-01 12:00:00','localtime')} \ - {2000-01-01 07:00:00} - datetest 6.11 {datetime('1969-01-01 12:00:00','localtime')} \ - {1969-01-01 07:00:00} - datetest 6.12 {datetime('2039-01-01 12:00:00','localtime')} \ - {2039-01-01 07:00:00} - datetest 6.13 {datetime('2000-07-01 12:00:00','localtime')} \ - {2000-07-01 08:00:00} - datetest 6.14 {datetime('1969-07-01 12:00:00','localtime')} \ - {1969-07-01 07:00:00} - datetest 6.15 {datetime('2039-07-01 12:00:00','localtime')} \ - {2039-07-01 07:00:00} - set sqlite_current_time \ - [db eval {SELECT strftime('%s','2000-07-01 12:34:56')}] - datetest 6.16 {datetime('now','localtime')} {2000-07-01 08:34:56} - datetest 6.17 {datetime('now','localtimex')} NULL - datetest 6.18 {datetime('now','localtim')} NULL - set sqlite_current_time 0 -} - -# These two are a bit of a scam. They are added to ensure that 100% of -# the date.c file is covered by testing, even when the time-zone -# is not -0400 (the condition for running of the block of tests above). +# The previous two cases establish that no such localtime as +# 2000-10-29 00:10:00 exists. Verify that we get a reasonable +# answer if we try to convert this non-existant localtime to utc? # -datetest 6.19 {datetime('2039-07-01 12:00:00','localtime',null)} NULL -datetest 6.20 {datetime('2039-07-01 12:00:00','utc',null)} NULL +utc_to_local 6.7 {2000-10-29 00:10:00} {2000-10-28 23:40:00} + +local_to_utc 6.8 {2022-02-10 23:59:59} {2022-02-11 00:29:59} +local_to_utc 6.9 {2022-02-11 00:00:00} {2022-02-10 23:30:00} +local_to_utc 6.10 {2022-02-10 23:45:00} {2022-02-11 00:15:00} +local_to_utc 6.11 {2022-02-11 00:45:00} {2022-02-11 00:15:00} + +# The previous two cases show that two different UTC values give +# the same localtime of 2022-02-11 00:15:00. When converting from +# that localtime back to UTC, we should get one or the other of +# the two UTC values. +# +utc_to_local 6.12 {2022-02-11 00:15:00} {2022-02-11 00:45:00} + +# If localtime_r() fails, the datetime() SQL function should raise an error +# +do_catchsql_test date-6.20 { + SELECT datetime('2000-05-29 14:16:00','localtime'); +} {1 {local time unavailable}} + +# Modifiers work for dates that are way out of band for localtime_r() +# +local_to_utc 6.21 {1800-10-29 12:00:00} {1800-10-29 12:30:00} +utc_to_local 6.22 {1800-10-29 12:30:00} {1800-10-29 12:00:00} +local_to_utc 6.23 {3000-10-30 12:00:00} {3000-10-30 11:30:00} +utc_to_local 6.24 {3000-10-30 11:30:00} {3000-10-30 12:00:00} + +# Restore the use of the OS localtime_r() before going on... +sqlite3_test_control SQLITE_TESTCTRL_LOCALTIME_FAULT 0 # Date-time functions that contain NULL arguments return a NULL # result. diff --git a/test/e_createtable.test b/test/e_createtable.test index fa43d94b54..3ecffae5c6 100644 --- a/test/e_createtable.test +++ b/test/e_createtable.test @@ -493,10 +493,10 @@ do_execsql_test e_createtable-1.7.0 { do_createtable_tests 1.7.1 -error { %s } { 1 "CREATE TABLE t1(a, b)" {{table t1 already exists}} 2 "CREATE TABLE i1(a, b)" {{there is already an index named i1}} - 3 "CREATE TABLE v1(a, b)" {{table v1 already exists}} + 3 "CREATE TABLE v1(a, b)" {{view v1 already exists}} 4 "CREATE TABLE auxa.tbl1(a, b)" {{table tbl1 already exists}} 5 "CREATE TABLE auxa.idx1(a, b)" {{there is already an index named idx1}} - 6 "CREATE TABLE auxa.view1(a, b)" {{table view1 already exists}} + 6 "CREATE TABLE auxa.view1(a, b)" {{view view1 already exists}} } do_createtable_tests 1.7.2 { 1 "CREATE TABLE auxa.t1(a, b)" {} diff --git a/test/fuzz.test b/test/fuzz.test index 0deed3b636..83dc79bc78 100644 --- a/test/fuzz.test +++ b/test/fuzz.test @@ -372,7 +372,7 @@ integrity_check fuzz-7.5.integrity #---------------------------------------------------------------- # Many CREATE and DROP TABLE statements: # -set E [list table duplicate {no such col} {ambiguous column name} {use DROP}] +set E [list table view duplicate {no such col} {ambiguous column name} {use DROP}] do_fuzzy_test fuzz-8.1 -template {[CreateOrDropTableOrView]} -errorlist $E close $::log diff --git a/test/fuzzcheck.c b/test/fuzzcheck.c index f5a7b092e3..2ea0898efa 100644 --- a/test/fuzzcheck.c +++ b/test/fuzzcheck.c @@ -156,6 +156,14 @@ static struct GlobalVars { char zTestName[100]; /* Name of current test */ } g; +/* +** Include the external vt02.c module, if requested by compile-time +** options. +*/ +#ifdef VT02_SOURCES +# include "vt02.c" +#endif + /* ** Print an error message and quit. */ @@ -1052,6 +1060,10 @@ int runCombinedDbSqlInput( ** deserialize to do this because deserialize depends on ATTACH */ sqlite3_set_authorizer(cx.db, block_troublesome_sql, 0); +#ifdef VT02_SOURCES + sqlite3_vt02_init(cx.db, 0, 0); +#endif + /* Consistent PRNG seed */ #ifdef SQLITE_TESTCTRL_PRNG_SEED sqlite3_table_column_metadata(cx.db, 0, "x", 0, 0, 0, 0, 0, 0); diff --git a/test/fuzzdata8.db b/test/fuzzdata8.db index 46112fff5f..de7799f945 100644 Binary files a/test/fuzzdata8.db and b/test/fuzzdata8.db differ diff --git a/test/merge1.test b/test/merge1.test index e4a7d657b3..36969e8fc8 100644 --- a/test/merge1.test +++ b/test/merge1.test @@ -16,6 +16,11 @@ set testdir [file dirname $argv0] source $testdir/tester.tcl set testprefix merge1 +ifcapable !vtab { + finish_test + return +} + load_static_extension db series diff --git a/test/shell1.test b/test/shell1.test index 745990a7c9..cbbadc58c9 100644 --- a/test/shell1.test +++ b/test/shell1.test @@ -53,7 +53,7 @@ do_test shell1-1.1.2 { # error on extra options do_test shell1-1.1.3 { catchcmd "test.db FOO test.db BAD" ".quit" -} {/1 .Error: in prepare, near "FOO": syntax error (1)*/} +} {/1 .Error: in prepare, near "FOO": syntax error*/} # -help do_test shell1-1.2.1 { @@ -78,7 +78,7 @@ do_test shell1-1.3.2 { } {0 {}} do_test shell1-1.3.3 { catchcmd "-init FOO test.db BAD .quit" "" -} {/1 .Error: in prepare, near "BAD": syntax error (1)*/} +} {/1 .Error: in prepare, near "BAD": syntax error*/} # -echo print commands before execution do_test shell1-1.4.1 { @@ -593,7 +593,8 @@ CREATE VIEW v2 AS SELECT x+1 AS y FROM t1 /* v2(y) */; CREATE VIEW v1 AS SELECT y+1 FROM v2 /* v1("y+1") */;}} -db eval {DROP VIEW v1; DROP VIEW v2; DROP TABLE t1;} + + catch {db eval {DROP VIEW v1; DROP VIEW v2; DROP TABLE t1;}} } # .separator STRING Change column separator used by output and .import diff --git a/test/shell2.test b/test/shell2.test index 6b4dff515e..db8cd96ab8 100644 --- a/test/shell2.test +++ b/test/shell2.test @@ -63,7 +63,7 @@ do_test shell2-1.3 { UPDATE OR REPLACE t5 SET a = 4 WHERE a = 1; } -} {1 {Error: near line 9: stepping, too many levels of trigger recursion (1)}} +} {1 {Runtime error near line 9: too many levels of trigger recursion}} diff --git a/test/shell3.test b/test/shell3.test index 243da976fa..e5a0c124e0 100644 --- a/test/shell3.test +++ b/test/shell3.test @@ -68,7 +68,7 @@ do_test shell3-1.6 { } {0 {}} do_test shell3-1.7 { catchcmd "foo.db \"CREATE TABLE\"" -} {1 {Error: in prepare, incomplete input (1)}} +} {1 {Error: in prepare, incomplete input}} #---------------------------------------------------------------------------- # shell3-2.*: Basic tests for running SQL file from command line. @@ -98,7 +98,7 @@ do_test shell3-2.6 { } {0 {}} do_test shell3-2.7 { catchcmd "foo.db" "CREATE TABLE" -} {1 {Error: near line 1: in prepare, incomplete input (1)}} +} {1 {Parse error near line 1: incomplete input}} #---------------------------------------------------------------------------- diff --git a/test/shell5.test b/test/shell5.test index 1e0038d9d5..7599edbbe2 100644 --- a/test/shell5.test +++ b/test/shell5.test @@ -476,4 +476,53 @@ CREATE TABLE t8(a, b, c); db eval { SELECT * FROM t8 } } {1 2 3} +#---------------------------------------------------------------------------- +# Tests for the shell automatic column rename. +# + +# Import columns containing duplicates +do_test shell5-5.1 { + set out [open shell5.csv w] + fconfigure $out -translation lf + puts $out {"","x","x","y","z","z_0","z_5","z"} + puts $out {0,"x2","x3","y4","z5","z6","z7","z8"} + close $out + forcedelete test.db + catchcmd test.db {.import -csv shell5.csv t1 +.mode line +SELECT * FROM t1;} +} {1 { ? = 0 + x_02 = x2 + x_03 = x3 + y = y4 + z_05 = z5 + z_0 = z6 + z_5 = z7 + z_08 = z8 +Columns renamed during .import shell5.csv due to duplicates: +"x" to "x_02", +"x" to "x_03", +"z" to "z_05", +"z" to "z_08"}} + +do_test shell5-5.1 { + set out [open shell5.csv w] + fconfigure $out -translation lf + puts $out {"COW","cow","CoW","cOw"} + puts $out {"uuu","lll","ulu","lul"} + close $out + forcedelete test.db + catchcmd test.db {.import -csv shell5.csv t1 +.mode line +SELECT * FROM t1;} +} {1 {COW_1 = uuu +cow_2 = lll +CoW_3 = ulu +cOw_4 = lul +Columns renamed during .import shell5.csv due to duplicates: +"COW" to "COW_1", +"cow" to "cow_2", +"CoW" to "CoW_3", +"cOw" to "cOw_4"}} + finish_test diff --git a/test/vtabrhs1.test b/test/vtabrhs1.test index 48fb6f1f6f..0476a36f90 100644 --- a/test/vtabrhs1.test +++ b/test/vtabrhs1.test @@ -22,13 +22,13 @@ ifcapable !vtab { } load_static_extension db qpvtab -# EVIDENCE-OF: R-12211-29175 When the sqlite3_vtab_rhs_value(P,J,V) +# EVIDENCE-OF: R-60223-49197 When the sqlite3_vtab_rhs_value(P,J,V) # interface is invoked from within the xBestIndex method of a virtual # table implementation, with P being a copy of the sqlite3_index_info # object pointer passed into xBestIndex and J being a 0-based index into -# P->aConstraint[], then this routine attempts to set *V to be the -# value on the right-hand side of that constraint if the right-hand side -# is a known constant. +# P->aConstraint[], then this routine attempts to set *V to the value +# of the right-hand operand of that constraint if the right-hand operand +# is known. # do_execsql_test 1.1 { SELECT rhs FROM qpvtab @@ -56,8 +56,8 @@ do_execsql_test 1.5 { AND a GLOB x'0123' } {x'0123'} -# EVIDENCE-OF: R-29440-53190 If the right-hand side of the constraint is -# not known, then *V is set to a NULL pointer. +# EVIDENCE-OF: R-37799-62852 If the right-hand operand is not known, +# then *V is set to a NULL pointer. # do_execsql_test 2.1 { SELECT typeof(rhs) FROM qpvtab WHERE cn='a' AND a=format('abc'); diff --git a/test/without_rowid1.test b/test/without_rowid1.test index 1191115527..3c33f733a1 100644 --- a/test/without_rowid1.test +++ b/test/without_rowid1.test @@ -475,15 +475,16 @@ ifcapable altertable { # Omit an assert() from 2013 that no longer serves any purpose and # is no longer always true. # -reset_db -do_execsql_test 15.1 { - PRAGMA writable_schema=ON; - CREATE TABLE sqlite_sequence (name PRIMARY KEY) WITHOUT ROWID; - PRAGMA writable_schema=OFF; - CREATE TABLE c1(x); - INSERT INTO sqlite_sequence(name) VALUES('c0'),('c1'),('c2'); - ALTER TABLE c1 RENAME TO a; - SELECT name FROM sqlite_sequence ORDER BY +name; -} {a c0 c2} - +ifcapable altertable { + reset_db + do_execsql_test 15.1 { + PRAGMA writable_schema=ON; + CREATE TABLE sqlite_sequence (name PRIMARY KEY) WITHOUT ROWID; + PRAGMA writable_schema=OFF; + CREATE TABLE c1(x); + INSERT INTO sqlite_sequence(name) VALUES('c0'),('c1'),('c2'); + ALTER TABLE c1 RENAME TO a; + SELECT name FROM sqlite_sequence ORDER BY +name; + } {a c0 c2} +} finish_test