1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-11-06 15:49:35 +03:00

Merge all the latest trunk changes into the name-resolution enhancement branch.

FossilOrigin-Name: a5f4d2b641f7fafb6f1a312efeffb10f213d2d0a
This commit is contained in:
drh
2013-01-02 12:29:05 +00:00
22 changed files with 1621 additions and 83 deletions

View File

@@ -370,6 +370,7 @@ TESTSRC = \
$(TOP)/src/test_osinst.c \ $(TOP)/src/test_osinst.c \
$(TOP)/src/test_pcache.c \ $(TOP)/src/test_pcache.c \
$(TOP)/src/test_quota.c \ $(TOP)/src/test_quota.c \
$(TOP)/src/test_regexp.c \
$(TOP)/src/test_rtree.c \ $(TOP)/src/test_rtree.c \
$(TOP)/src/test_schema.c \ $(TOP)/src/test_schema.c \
$(TOP)/src/test_server.c \ $(TOP)/src/test_server.c \

View File

@@ -691,6 +691,7 @@ TESTSRC = \
$(TOP)\src\test_osinst.c \ $(TOP)\src\test_osinst.c \
$(TOP)\src\test_pcache.c \ $(TOP)\src\test_pcache.c \
$(TOP)\src\test_quota.c \ $(TOP)\src\test_quota.c \
$(TOP)\src\test_regexp.c \
$(TOP)\src\test_rtree.c \ $(TOP)\src\test_rtree.c \
$(TOP)\src\test_schema.c \ $(TOP)\src\test_schema.c \
$(TOP)\src\test_server.c \ $(TOP)\src\test_server.c \

View File

@@ -253,6 +253,7 @@ TESTSRC = \
$(TOP)/src/test_osinst.c \ $(TOP)/src/test_osinst.c \
$(TOP)/src/test_pcache.c \ $(TOP)/src/test_pcache.c \
$(TOP)/src/test_quota.c \ $(TOP)/src/test_quota.c \
$(TOP)/src/test_regexp.c \
$(TOP)/src/test_rtree.c \ $(TOP)/src/test_rtree.c \
$(TOP)/src/test_schema.c \ $(TOP)/src/test_schema.c \
$(TOP)/src/test_server.c \ $(TOP)/src/test_server.c \

View File

@@ -1,9 +1,9 @@
C Add\scommentary\sto\sthe\sExprList\sobject\sto\sexplain\show\szSpan\sis\soverloaded.\nAdd\stest\scases\sfor\sthe\snew\sname\sresolution\sfunctionality. C Merge\sall\sthe\slatest\strunk\schanges\sinto\sthe\sname-resolution\senhancement\sbranch.
D 2012-12-19T13:41:03.688 D 2013-01-02T12:29:05.642
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in 690d441a758cbffd13e814dc2724a721a6ebd400 F Makefile.in a48faa9e7dd7d556d84f5456eabe5825dd8a6282
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
F Makefile.msc 5a3b6f34d263b01f8b798c291fac1529fd650308 F Makefile.msc 2b8371775ea8df029d1acf0c3d4c3782d3bd5711
F Makefile.vxworks b18ad88e9a8c6a001f5cf4a389116a4f1a7ab45f F Makefile.vxworks b18ad88e9a8c6a001f5cf4a389116a4f1a7ab45f
F README cd04a36fbc7ea56932a4052d7d0b7f09f27c33d6 F README cd04a36fbc7ea56932a4052d7d0b7f09f27c33d6
F VERSION 6d4f66eaebabc42ef8c2a4d2d0caf4ce7ee81137 F VERSION 6d4f66eaebabc42ef8c2a4d2d0caf4ce7ee81137
@@ -103,7 +103,7 @@ F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de
F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024 F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
F main.mk a0d170ae1a8a8683688e281194e09d47a68eaa3f F main.mk 718265bbf49a846c6898b4da09593eef4068fa39
F mkdll.sh 7d09b23c05d56532e9d44a50868eb4b12ff4f74a F mkdll.sh 7d09b23c05d56532e9d44a50868eb4b12ff4f74a
F mkextu.sh 416f9b7089d80e5590a29692c9d9280a10dbad9f F mkextu.sh 416f9b7089d80e5590a29692c9d9280a10dbad9f
F mkextw.sh 4123480947681d9b434a5e7b1ee08135abe409ac F mkextw.sh 4123480947681d9b434a5e7b1ee08135abe409ac
@@ -118,7 +118,7 @@ F src/alter.c f8db986c03eb0bfb221523fc9bbb9d0b70de3168
F src/analyze.c 7553068d21e32a57fc33ab6b2393fc8c1ba41410 F src/analyze.c 7553068d21e32a57fc33ab6b2393fc8c1ba41410
F src/attach.c ea5247f240e2c08afd608e9beb380814b86655e1 F src/attach.c ea5247f240e2c08afd608e9beb380814b86655e1
F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34 F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34
F src/backup.c cab40f2c1fe79d6eb93d3b4086c78c41ad2fa5d0 F src/backup.c 32e35a3a4ea55b45c0e5f74eeb793aec71491517
F src/bitvec.c 26675fe8e431dc555e6f2d0e11e651d172234aa1 F src/bitvec.c 26675fe8e431dc555e6f2d0e11e651d172234aa1
F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7 F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7
F src/btree.c 7a80e4a67f32a2494c383a28a495bf3bd71cc230 F src/btree.c 7a80e4a67f32a2494c383a28a495bf3bd71cc230
@@ -132,7 +132,7 @@ F src/date.c 067a81c9942c497aafd2c260e13add8a7d0c7dd4
F src/delete.c 9b8d308979114991e5dc7cee958316e07186941d F src/delete.c 9b8d308979114991e5dc7cee958316e07186941d
F src/expr.c 0e41d66d868b37dbc0e041c342e0036fad27e705 F src/expr.c 0e41d66d868b37dbc0e041c342e0036fad27e705
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
F src/fkey.c dcb7c37a4bf526ded7b24a01a60fe071bcd160a2 F src/fkey.c 5b7a12e2f8620e855b0478a9a6798df9967bb277
F src/func.c 8147799b048065a1590805be464d05b4913e652c F src/func.c 8147799b048065a1590805be464d05b4913e652c
F src/global.c e59ecd2c553ad0d4bfbc84ca71231336f8993a7a F src/global.c e59ecd2c553ad0d4bfbc84ca71231336f8993a7a
F src/hash.c ac3470bbf1ca4ae4e306a8ecb0fdf1731810ffe4 F src/hash.c ac3470bbf1ca4ae4e306a8ecb0fdf1731810ffe4
@@ -168,22 +168,22 @@ F src/parse.y 5d5e12772845805fdfeb889163516b84fbb9ae95
F src/pcache.c f8043b433a57aba85384a531e3937a804432a346 F src/pcache.c f8043b433a57aba85384a531e3937a804432a346
F src/pcache.h 1b5dcc3dc8103d03e625b177023ee67764fa6b7c F src/pcache.h 1b5dcc3dc8103d03e625b177023ee67764fa6b7c
F src/pcache1.c 9fd22671c270b35131ef480bbc00392b8b5f8ab9 F src/pcache1.c 9fd22671c270b35131ef480bbc00392b8b5f8ab9
F src/pragma.c 015723c48072781d2740e310ab04dc92956b76d1 F src/pragma.c 8907c559d3127729d3bcedb1fe5c59fc196d3a17
F src/prepare.c 931ad0d852a0df48f79adcba6ce79ca5f475625c F src/prepare.c 931ad0d852a0df48f79adcba6ce79ca5f475625c
F src/printf.c 4a9f882f1c1787a8b494a2987765acf9d97ac21f F src/printf.c 4a9f882f1c1787a8b494a2987765acf9d97ac21f
F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50 F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50
F src/resolve.c 3104a5e4c2cb6e3a813b7266cbd541dc91e26fad F src/resolve.c 3104a5e4c2cb6e3a813b7266cbd541dc91e26fad
F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0 F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0
F src/select.c 3cce5b09cae6eaf23276bb2e5551a9d22cd7ae3d F src/select.c 3cce5b09cae6eaf23276bb2e5551a9d22cd7ae3d
F src/shell.c e392dd1ccbb77cc1d75a8367a89b473c24bea019 F src/shell.c 11c9611580bb2ffce3a232f31f7f8cc310df0843
F src/sqlite.h.in 39cc33bb08897c748fe3383c29ccf56585704177 F src/sqlite.h.in 39cc33bb08897c748fe3383c29ccf56585704177
F src/sqlite3.rc fea433eb0a59f4c9393c8e6d76a6e2596b1fe0c0 F src/sqlite3.rc fea433eb0a59f4c9393c8e6d76a6e2596b1fe0c0
F src/sqlite3ext.h 6904f4aadf976f95241311fbffb00823075d9477 F src/sqlite3ext.h 6904f4aadf976f95241311fbffb00823075d9477
F src/sqliteInt.h c708c868f10c491bd32a7e1210f4a314448fa728 F src/sqliteInt.h 2ce2d742e32be86bf1fc8e29c91ef91c29c32e60
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
F src/status.c bedc37ec1a6bb9399944024d63f4c769971955a9 F src/status.c bedc37ec1a6bb9399944024d63f4c769971955a9
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
F src/tclsqlite.c 515abd8e33e82aa330eeb54675185a7e1e5b6778 F src/tclsqlite.c 5203bb7b71a302bea8896f176cd178e38d7803a4
F src/test1.c f62769c989146149590662ab02de4a813813a9c5 F src/test1.c f62769c989146149590662ab02de4a813813a9c5
F src/test2.c 4178056dd1e7d70f954ad8a1e3edb71a2a784daf F src/test2.c 4178056dd1e7d70f954ad8a1e3edb71a2a784daf
F src/test3.c 3c3c2407fa6ec7a19e24ae23f7cb439d0275a60d F src/test3.c 3c3c2407fa6ec7a19e24ae23f7cb439d0275a60d
@@ -217,6 +217,7 @@ F src/test_osinst.c 90a845c8183013d80eccb1f29e8805608516edba
F src/test_pcache.c a5cd24730cb43c5b18629043314548c9169abb00 F src/test_pcache.c a5cd24730cb43c5b18629043314548c9169abb00
F src/test_quota.c 0e0e2e3bf6766b101ecccd8c042b66e44e9be8f5 F src/test_quota.c 0e0e2e3bf6766b101ecccd8c042b66e44e9be8f5
F src/test_quota.h 8761e463b25e75ebc078bd67d70e39b9c817a0cb F src/test_quota.h 8761e463b25e75ebc078bd67d70e39b9c817a0cb
F src/test_regexp.c d8cb342e08a346a6daeda29e434e2d9a49f557ec
F src/test_rtree.c aba603c949766c4193f1068b91c787f57274e0d9 F src/test_rtree.c aba603c949766c4193f1068b91c787f57274e0d9
F src/test_schema.c 8c06ef9ddb240c7a0fcd31bc221a6a2aade58bf0 F src/test_schema.c 8c06ef9ddb240c7a0fcd31bc221a6a2aade58bf0
F src/test_server.c 2f99eb2837dfa06a4aacf24af24c6affdf66a84f F src/test_server.c 2f99eb2837dfa06a4aacf24af24c6affdf66a84f
@@ -250,7 +251,7 @@ F src/vtab.c b05e5f1f4902461ba9f5fc49bb7eb7c3a0741a83
F src/wal.c f5c7b5027d0ed0e9bc9afeb4a3a8dfea762ec7d2 F src/wal.c f5c7b5027d0ed0e9bc9afeb4a3a8dfea762ec7d2
F src/wal.h 29c197540b19044e6cd73487017e5e47a1d3dac6 F src/wal.h 29c197540b19044e6cd73487017e5e47a1d3dac6
F src/walker.c 3d75ba73de15e0f8cd0737643badbeb0e002f07b F src/walker.c 3d75ba73de15e0f8cd0737643badbeb0e002f07b
F src/where.c 7bdfde434b14ff88cc52ae41ac235ee1acb6b1e1 F src/where.c b971ee2d1a4f5db1b4cfd5cb85e69f34e61781d0
F test/8_3_names.test 631ea964a3edb091cf73c3b540f6bcfdb36ce823 F test/8_3_names.test 631ea964a3edb091cf73c3b540f6bcfdb36ce823
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
F test/aggnested.test 45c0201e28045ad38a530b5a144b73cd4aa2cfd6 F test/aggnested.test 45c0201e28045ad38a530b5a144b73cd4aa2cfd6
@@ -383,7 +384,7 @@ F test/e_delete.test 89aa84d3d1bd284a0689ede04bce10226a5aeaa5
F test/e_droptrigger.test afd5c4d27dec607f5997a66bf7e2498a082cb235 F test/e_droptrigger.test afd5c4d27dec607f5997a66bf7e2498a082cb235
F test/e_dropview.test 583411e470458c5d76148542cfb5a5fa84c8f93e F test/e_dropview.test 583411e470458c5d76148542cfb5a5fa84c8f93e
F test/e_expr.test 5489424d3d9a452ac3701cdf4b680ae31a157894 F test/e_expr.test 5489424d3d9a452ac3701cdf4b680ae31a157894
F test/e_fkey.test a79ab1d3213c7ac64621eec28f8e8bb219775445 F test/e_fkey.test 89a2ff734a33693b997534eff90724573948be7b
F test/e_fts3.test 5c02288842e4f941896fd44afdef564dd5fc1459 F test/e_fts3.test 5c02288842e4f941896fd44afdef564dd5fc1459
F test/e_insert.test d5331cc95e101af2508159fc98b6801631659ffe F test/e_insert.test d5331cc95e101af2508159fc98b6801631659ffe
F test/e_reindex.test dfedfc32c5a282b0596c6537cbcd4217fbb1a216 F test/e_reindex.test dfedfc32c5a282b0596c6537cbcd4217fbb1a216
@@ -407,12 +408,13 @@ F test/exists.test 8f7b27b61c2fbe5822f0a1f899c715d14e416e30
F test/expr.test 67c9fd6f8f829e239dc8b0f4a08a73c08b09196d F test/expr.test 67c9fd6f8f829e239dc8b0f4a08a73c08b09196d
F test/fallocate.test b5d34437bd7ab01d41b1464b8117aefd4d32160e F test/fallocate.test b5d34437bd7ab01d41b1464b8117aefd4d32160e
F test/filectrl.test 14fa712e42c4cb791e09dfd58a6a03efb47ef13a F test/filectrl.test 14fa712e42c4cb791e09dfd58a6a03efb47ef13a
F test/filefmt.test ffa17b5aebc3eb4b1e3be1ccb5ee906ffbd97f6e F test/filefmt.test dbee33e57818249cdffbbb7b13464635217beff1
F test/fkey1.test 01c7de578e11747e720c2d9aeef27f239853c4da F test/fkey1.test 01c7de578e11747e720c2d9aeef27f239853c4da
F test/fkey2.test 080969fe219b3b082b0e097ac18c6af2e5b0631f F test/fkey2.test 5aa44e7153928a1f002803f94aaab4c76a7ceac2
F test/fkey3.test 5ec899d12b13bcf1e9ef40eff7fb692fdb91392e F test/fkey3.test 5ec899d12b13bcf1e9ef40eff7fb692fdb91392e
F test/fkey4.test c6c8f9f9be885f95c85c7bceb26f243ad906fd49 F test/fkey4.test c6c8f9f9be885f95c85c7bceb26f243ad906fd49
F test/fkey_malloc.test c3a12acd053c976de09036498eef09b83afa4a80 F test/fkey5.test 0bf64f2d19ad80433ca0b24edbf604a18b353d5f
F test/fkey_malloc.test bb74c9cb8f8fceed03b58f8a7ef2df98520bbd51
F test/format4.test 1f0cac8ff3895e9359ed87e41aaabee982a812eb F test/format4.test 1f0cac8ff3895e9359ed87e41aaabee982a812eb
F test/fts-9fd058691.test 78b887e30ae6816df0e1fed6259de4b5a64ad33c F test/fts-9fd058691.test 78b887e30ae6816df0e1fed6259de4b5a64ad33c
F test/fts1a.test 46090311f85da51bb33bd5ce84f7948359c6d8d7 F test/fts1a.test 46090311f85da51bb33bd5ce84f7948359c6d8d7
@@ -652,7 +654,7 @@ F test/pagesize.test 1dd51367e752e742f58e861e65ed7390603827a0
F test/pcache.test 065aa286e722ab24f2e51792c1f093bf60656b16 F test/pcache.test 065aa286e722ab24f2e51792c1f093bf60656b16
F test/pcache2.test a83efe2dec0d392f814bfc998def1d1833942025 F test/pcache2.test a83efe2dec0d392f814bfc998def1d1833942025
F test/permutations.test 360b92859c0af814b3fe10b68746936389606501 F test/permutations.test 360b92859c0af814b3fe10b68746936389606501
F test/pragma.test a62f73293b0f0d79b0c87f8dd32d46fe53b0bd17 F test/pragma.test 5ce333cae37d86cfe9b3add840906e375e2272b0
F test/pragma2.test 3a55f82b954242c642f8342b17dffc8b47472947 F test/pragma2.test 3a55f82b954242c642f8342b17dffc8b47472947
F test/printf.test ec9870c4dce8686a37818e0bf1aba6e6a1863552 F test/printf.test ec9870c4dce8686a37818e0bf1aba6e6a1863552
F test/progress.test 5b075c3c790c7b2a61419bc199db87aaf48b8301 F test/progress.test 5b075c3c790c7b2a61419bc199db87aaf48b8301
@@ -665,6 +667,7 @@ F test/quote.test 215897dbe8de1a6f701265836d6601cc6ed103e6
F test/randexpr1.tcl 40dec52119ed3a2b8b2a773bce24b63a3a746459 F test/randexpr1.tcl 40dec52119ed3a2b8b2a773bce24b63a3a746459
F test/randexpr1.test eda062a97e60f9c38ae8d806b03b0ddf23d796df F test/randexpr1.test eda062a97e60f9c38ae8d806b03b0ddf23d796df
F test/rdonly.test c267d050a1d9a6a321de502b737daf28821a518d F test/rdonly.test c267d050a1d9a6a321de502b737daf28821a518d
F test/regexp1.test bbcb74e1bbdc20a7c0b9b2360deda14c4df1b46a
F test/reindex.test 44edd3966b474468b823d481eafef0c305022254 F test/reindex.test 44edd3966b474468b823d481eafef0c305022254
F test/releasetest.mk 2eced2f9ae701fd0a29e714a241760503ccba25a F test/releasetest.mk 2eced2f9ae701fd0a29e714a241760503ccba25a
F test/releasetest.tcl 06d289d8255794073a58d2850742f627924545ce F test/releasetest.tcl 06d289d8255794073a58d2850742f627924545ce
@@ -785,6 +788,7 @@ F test/tkt-8454a207b9.test c583a9f814a82a2b5ba95207f55001c9f0cd816c
F test/tkt-91e2e8ba6f.test 08c4f94ae07696b05c9b822da0b4e5337a2f54c5 F test/tkt-91e2e8ba6f.test 08c4f94ae07696b05c9b822da0b4e5337a2f54c5
F test/tkt-94c04eaadb.test fa9c71192f7e2ea2d51bf078bc34e8da6088bf71 F test/tkt-94c04eaadb.test fa9c71192f7e2ea2d51bf078bc34e8da6088bf71
F test/tkt-9d68c883.test 458f7d82a523d7644b54b497c986378a7d8c8b67 F test/tkt-9d68c883.test 458f7d82a523d7644b54b497c986378a7d8c8b67
F test/tkt-a7b7803e.test 159ef554234fa1f9fb318c751b284bd1cf858da4
F test/tkt-b1d3a2e531.test 610ef582413171b379652663111b1f996d9f8f78 F test/tkt-b1d3a2e531.test 610ef582413171b379652663111b1f996d9f8f78
F test/tkt-b351d95f9.test d14a503c414c5c58fdde3e80f9a3cfef986498c0 F test/tkt-b351d95f9.test d14a503c414c5c58fdde3e80f9a3cfef986498c0
F test/tkt-b72787b1.test a95e8cdad0b98af1853ac7f0afd4ab27b77bf5f3 F test/tkt-b72787b1.test a95e8cdad0b98af1853ac7f0afd4ab27b77bf5f3
@@ -984,7 +988,7 @@ F test/win32lock.test b2a539e85ae6b2d78475e016a9636b4451dc7fb9
F test/zeroblob.test caaecfb4f908f7bc086ed238668049f96774d688 F test/zeroblob.test caaecfb4f908f7bc086ed238668049f96774d688
F test/zerodamage.test e7f77fded01dfcdf92ac2c5400f1e35d7a21463c F test/zerodamage.test e7f77fded01dfcdf92ac2c5400f1e35d7a21463c
F tool/build-all-msvc.bat 74fb6e5cca66ebdb6c9bbafb2f8b802f08146d38 x F tool/build-all-msvc.bat 74fb6e5cca66ebdb6c9bbafb2f8b802f08146d38 x
F tool/build-shell.sh b64a481901fc9ffe5ca8812a2a9255b6cfb77381 F tool/build-shell.sh 562df23cfdd25822b909b382afd5f99d968437fe
F tool/checkSpacing.c 810e51703529a204fc4e1eb060e9ab663e3c06d2 F tool/checkSpacing.c 810e51703529a204fc4e1eb060e9ab663e3c06d2
F tool/diffdb.c 7524b1b5df217c20cd0431f6789851a4e0cb191b F tool/diffdb.c 7524b1b5df217c20cd0431f6789851a4e0cb191b
F tool/extract.c 054069d81b095fbdc189a6f5d4466e40380505e2 F tool/extract.c 054069d81b095fbdc189a6f5d4466e40380505e2
@@ -1027,7 +1031,7 @@ F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac
P 7344e791b9456286ecdca6d45f2f5260fb3f10e2 P 3e7d84db7861911c9b2c7dcdabe0b213bf483d79 5a2ac944839ec0c5b9147a035c6cbf0935f3d202
R be36637b6c87220d87a455d3dd649bed R b00123b22cae8fcb124aaeac1cbbab83
U drh U drh
Z 4a19eec8d8a61f22fdf7238cb2d39c20 Z 0dd559531357e580f4a230ac4f1af1d6

View File

@@ -1 +1 @@
3e7d84db7861911c9b2c7dcdabe0b213bf483d79 a5f4d2b641f7fafb6f1a312efeffb10f213d2d0a

View File

@@ -212,7 +212,12 @@ static int isFatalError(int rc){
** page iSrcPg from the source database. Copy this data into the ** page iSrcPg from the source database. Copy this data into the
** destination database. ** destination database.
*/ */
static int backupOnePage(sqlite3_backup *p, Pgno iSrcPg, const u8 *zSrcData){ static int backupOnePage(
sqlite3_backup *p, /* Backup handle */
Pgno iSrcPg, /* Source database page to backup */
const u8 *zSrcData, /* Source database page data */
int bUpdate /* True for an update, false otherwise */
){
Pager * const pDestPager = sqlite3BtreePager(p->pDest); Pager * const pDestPager = sqlite3BtreePager(p->pDest);
const int nSrcPgsz = sqlite3BtreeGetPageSize(p->pSrc); const int nSrcPgsz = sqlite3BtreeGetPageSize(p->pSrc);
int nDestPgsz = sqlite3BtreeGetPageSize(p->pDest); int nDestPgsz = sqlite3BtreeGetPageSize(p->pDest);
@@ -285,6 +290,9 @@ static int backupOnePage(sqlite3_backup *p, Pgno iSrcPg, const u8 *zSrcData){
*/ */
memcpy(zOut, zIn, nCopy); memcpy(zOut, zIn, nCopy);
((u8 *)sqlite3PagerGetExtra(pDestPg))[0] = 0; ((u8 *)sqlite3PagerGetExtra(pDestPg))[0] = 0;
if( iOff==0 && bUpdate==0 ){
sqlite3Put4byte(&zOut[28], sqlite3BtreeLastPage(p->pSrc));
}
} }
sqlite3PagerUnref(pDestPg); sqlite3PagerUnref(pDestPg);
} }
@@ -391,7 +399,7 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){
DbPage *pSrcPg; /* Source page object */ DbPage *pSrcPg; /* Source page object */
rc = sqlite3PagerGet(pSrcPager, iSrcPg, &pSrcPg); rc = sqlite3PagerGet(pSrcPager, iSrcPg, &pSrcPg);
if( rc==SQLITE_OK ){ if( rc==SQLITE_OK ){
rc = backupOnePage(p, iSrcPg, sqlite3PagerGetData(pSrcPg)); rc = backupOnePage(p, iSrcPg, sqlite3PagerGetData(pSrcPg), 0);
sqlite3PagerUnref(pSrcPg); sqlite3PagerUnref(pSrcPg);
} }
} }
@@ -639,7 +647,7 @@ void sqlite3BackupUpdate(sqlite3_backup *pBackup, Pgno iPage, const u8 *aData){
int rc; int rc;
assert( p->pDestDb ); assert( p->pDestDb );
sqlite3_mutex_enter(p->pDestDb->mutex); sqlite3_mutex_enter(p->pDestDb->mutex);
rc = backupOnePage(p, iPage, aData); rc = backupOnePage(p, iPage, aData, 1);
sqlite3_mutex_leave(p->pDestDb->mutex); sqlite3_mutex_leave(p->pDestDb->mutex);
assert( rc!=SQLITE_BUSY && rc!=SQLITE_LOCKED ); assert( rc!=SQLITE_BUSY && rc!=SQLITE_LOCKED );
if( rc!=SQLITE_OK ){ if( rc!=SQLITE_OK ){

View File

@@ -142,7 +142,7 @@
** A foreign key constraint requires that the key columns in the parent ** A foreign key constraint requires that the key columns in the parent
** table are collectively subject to a UNIQUE or PRIMARY KEY constraint. ** table are collectively subject to a UNIQUE or PRIMARY KEY constraint.
** Given that pParent is the parent table for foreign key constraint pFKey, ** Given that pParent is the parent table for foreign key constraint pFKey,
** search the schema a unique index on the parent key columns. ** search the schema for a unique index on the parent key columns.
** **
** If successful, zero is returned. If the parent key is an INTEGER PRIMARY ** If successful, zero is returned. If the parent key is an INTEGER PRIMARY
** KEY column, then output variable *ppIdx is set to NULL. Otherwise, *ppIdx ** KEY column, then output variable *ppIdx is set to NULL. Otherwise, *ppIdx
@@ -178,7 +178,7 @@
** into pParse. If an OOM error occurs, non-zero is returned and the ** into pParse. If an OOM error occurs, non-zero is returned and the
** pParse->db->mallocFailed flag is set. ** pParse->db->mallocFailed flag is set.
*/ */
static int locateFkeyIndex( int sqlite3FkLocateIndex(
Parse *pParse, /* Parse context to store any error in */ Parse *pParse, /* Parse context to store any error in */
Table *pParent, /* Parent table of FK constraint pFKey */ Table *pParent, /* Parent table of FK constraint pFKey */
FKey *pFKey, /* Foreign key to find index for */ FKey *pFKey, /* Foreign key to find index for */
@@ -275,7 +275,9 @@ static int locateFkeyIndex(
if( !pIdx ){ if( !pIdx ){
if( !pParse->disableTriggers ){ if( !pParse->disableTriggers ){
sqlite3ErrorMsg(pParse, "foreign key mismatch"); sqlite3ErrorMsg(pParse,
"foreign key mismatch - \"%w\" referencing \"%w\"",
pFKey->pFrom->zName, pFKey->zTo);
} }
sqlite3DbFree(pParse->db, aiCol); sqlite3DbFree(pParse->db, aiCol);
return 1; return 1;
@@ -736,7 +738,7 @@ void sqlite3FkCheck(
}else{ }else{
pTo = sqlite3LocateTable(pParse, 0, pFKey->zTo, zDb); pTo = sqlite3LocateTable(pParse, 0, pFKey->zTo, zDb);
} }
if( !pTo || locateFkeyIndex(pParse, pTo, pFKey, &pIdx, &aiFree) ){ if( !pTo || sqlite3FkLocateIndex(pParse, pTo, pFKey, &pIdx, &aiFree) ){
assert( isIgnoreErrors==0 || (regOld!=0 && regNew==0) ); assert( isIgnoreErrors==0 || (regOld!=0 && regNew==0) );
if( !isIgnoreErrors || db->mallocFailed ) return; if( !isIgnoreErrors || db->mallocFailed ) return;
if( pTo==0 ){ if( pTo==0 ){
@@ -816,7 +818,7 @@ void sqlite3FkCheck(
continue; continue;
} }
if( locateFkeyIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ){ if( sqlite3FkLocateIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ){
if( !isIgnoreErrors || db->mallocFailed ) return; if( !isIgnoreErrors || db->mallocFailed ) return;
continue; continue;
} }
@@ -871,7 +873,7 @@ u32 sqlite3FkOldmask(
} }
for(p=sqlite3FkReferences(pTab); p; p=p->pNextTo){ for(p=sqlite3FkReferences(pTab); p; p=p->pNextTo){
Index *pIdx = 0; Index *pIdx = 0;
locateFkeyIndex(pParse, pTab, p, &pIdx, 0); sqlite3FkLocateIndex(pParse, pTab, p, &pIdx, 0);
if( pIdx ){ if( pIdx ){
for(i=0; i<pIdx->nColumn; i++) mask |= COLUMN_MASK(pIdx->aiColumn[i]); for(i=0; i<pIdx->nColumn; i++) mask |= COLUMN_MASK(pIdx->aiColumn[i]);
} }
@@ -997,7 +999,7 @@ static Trigger *fkActionTrigger(
int i; /* Iterator variable */ int i; /* Iterator variable */
Expr *pWhen = 0; /* WHEN clause for the trigger */ Expr *pWhen = 0; /* WHEN clause for the trigger */
if( locateFkeyIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ) return 0; if( sqlite3FkLocateIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ) return 0;
assert( aiCol || pFKey->nCol==1 ); assert( aiCol || pFKey->nCol==1 );
for(i=0; i<pFKey->nCol; i++){ for(i=0; i<pFKey->nCol; i++){

View File

@@ -948,9 +948,11 @@ void sqlite3Pragma(
if( sqlite3ReadSchema(pParse) ) goto pragma_out; if( sqlite3ReadSchema(pParse) ) goto pragma_out;
pTab = sqlite3FindTable(db, zRight, zDb); pTab = sqlite3FindTable(db, zRight, zDb);
if( pTab ){ if( pTab ){
int i; int i, k;
int nHidden = 0; int nHidden = 0;
Column *pCol; Column *pCol;
Index *pPk;
for(pPk=pTab->pIndex; pPk && pPk->autoIndex!=2; pPk=pPk->pNext){}
sqlite3VdbeSetNumCols(v, 6); sqlite3VdbeSetNumCols(v, 6);
pParse->nMem = 6; pParse->nMem = 6;
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "cid", SQLITE_STATIC); sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "cid", SQLITE_STATIC);
@@ -975,8 +977,14 @@ void sqlite3Pragma(
}else{ }else{
sqlite3VdbeAddOp2(v, OP_Null, 0, 5); sqlite3VdbeAddOp2(v, OP_Null, 0, 5);
} }
sqlite3VdbeAddOp2(v, OP_Integer, if( (pCol->colFlags & COLFLAG_PRIMKEY)==0 ){
(pCol->colFlags&COLFLAG_PRIMKEY)!=0, 6); k = 0;
}else if( pPk==0 ){
k = 1;
}else{
for(k=1; ALWAYS(k<=pTab->nCol) && pPk->aiColumn[k-1]!=i; k++){}
}
sqlite3VdbeAddOp2(v, OP_Integer, k, 6);
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 6); sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 6);
} }
} }
@@ -1114,6 +1122,120 @@ void sqlite3Pragma(
}else }else
#endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */ #endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */
#ifndef SQLITE_OMIT_FOREIGN_KEY
if( sqlite3StrICmp(zLeft, "foreign_key_check")==0 ){
FKey *pFK; /* A foreign key constraint */
Table *pTab; /* Child table contain "REFERENCES" keyword */
Table *pParent; /* Parent table that child points to */
Index *pIdx; /* Index in the parent table */
int i; /* Loop counter: Foreign key number for pTab */
int j; /* Loop counter: Field of the foreign key */
HashElem *k; /* Loop counter: Next table in schema */
int x; /* result variable */
int regResult; /* 3 registers to hold a result row */
int regKey; /* Register to hold key for checking the FK */
int regRow; /* Registers to hold a row from pTab */
int addrTop; /* Top of a loop checking foreign keys */
int addrOk; /* Jump here if the key is OK */
int *aiCols; /* child to parent column mapping */
if( sqlite3ReadSchema(pParse) ) goto pragma_out;
regResult = pParse->nMem+1;
pParse->nMem += 4;
regKey = ++pParse->nMem;
regRow = ++pParse->nMem;
v = sqlite3GetVdbe(pParse);
sqlite3VdbeSetNumCols(v, 4);
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "table", SQLITE_STATIC);
sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "rowid", SQLITE_STATIC);
sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "parent", SQLITE_STATIC);
sqlite3VdbeSetColName(v, 3, COLNAME_NAME, "fkid", SQLITE_STATIC);
sqlite3CodeVerifySchema(pParse, iDb);
k = sqliteHashFirst(&db->aDb[iDb].pSchema->tblHash);
while( k ){
if( zRight ){
pTab = sqlite3LocateTable(pParse, 0, zRight, zDb);
k = 0;
}else{
pTab = (Table*)sqliteHashData(k);
k = sqliteHashNext(k);
}
if( pTab==0 || pTab->pFKey==0 ) continue;
sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName);
if( pTab->nCol+regRow>pParse->nMem ) pParse->nMem = pTab->nCol + regRow;
sqlite3OpenTable(pParse, 0, iDb, pTab, OP_OpenRead);
sqlite3VdbeAddOp4(v, OP_String8, 0, regResult, 0, pTab->zName,
P4_TRANSIENT);
for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){
pParent = sqlite3LocateTable(pParse, 0, pFK->zTo, zDb);
if( pParent==0 ) break;
pIdx = 0;
sqlite3TableLock(pParse, iDb, pParent->tnum, 0, pParent->zName);
x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, 0);
if( x==0 ){
if( pIdx==0 ){
sqlite3OpenTable(pParse, i, iDb, pParent, OP_OpenRead);
}else{
KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx);
sqlite3VdbeAddOp3(v, OP_OpenRead, i, pIdx->tnum, iDb);
sqlite3VdbeChangeP4(v, -1, (char*)pKey, P4_KEYINFO_HANDOFF);
}
}else{
k = 0;
break;
}
}
if( pFK ) break;
if( pParse->nTab<i ) pParse->nTab = i;
addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, 0);
for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){
pParent = sqlite3LocateTable(pParse, 0, pFK->zTo, zDb);
assert( pParent!=0 );
pIdx = 0;
aiCols = 0;
x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, &aiCols);
assert( x==0 );
addrOk = sqlite3VdbeMakeLabel(v);
if( pIdx==0 ){
int iKey = pFK->aCol[0].iFrom;
assert( iKey>=0 && iKey<pTab->nCol );
if( iKey!=pTab->iPKey ){
sqlite3VdbeAddOp3(v, OP_Column, 0, iKey, regRow);
sqlite3ColumnDefault(v, pTab, iKey, regRow);
sqlite3VdbeAddOp2(v, OP_IsNull, regRow, addrOk);
sqlite3VdbeAddOp2(v, OP_MustBeInt, regRow,
sqlite3VdbeCurrentAddr(v)+3);
}else{
sqlite3VdbeAddOp2(v, OP_Rowid, 0, regRow);
}
sqlite3VdbeAddOp3(v, OP_NotExists, i, 0, regRow);
sqlite3VdbeAddOp2(v, OP_Goto, 0, addrOk);
sqlite3VdbeJumpHere(v, sqlite3VdbeCurrentAddr(v)-2);
}else{
for(j=0; j<pFK->nCol; j++){
sqlite3ExprCodeGetColumnOfTable(v, pTab, 0,
aiCols ? aiCols[j] : pFK->aCol[0].iFrom, regRow+j);
sqlite3VdbeAddOp2(v, OP_IsNull, regRow+j, addrOk);
}
sqlite3VdbeAddOp3(v, OP_MakeRecord, regRow, pFK->nCol, regKey);
sqlite3VdbeChangeP4(v, -1,
sqlite3IndexAffinityStr(v,pIdx), P4_TRANSIENT);
sqlite3VdbeAddOp4Int(v, OP_Found, i, addrOk, regKey, 0);
}
sqlite3VdbeAddOp2(v, OP_Rowid, 0, regResult+1);
sqlite3VdbeAddOp4(v, OP_String8, 0, regResult+2, 0,
pFK->zTo, P4_TRANSIENT);
sqlite3VdbeAddOp2(v, OP_Integer, i-1, regResult+3);
sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, 4);
sqlite3VdbeResolveLabel(v, addrOk);
sqlite3DbFree(db, aiCols);
}
sqlite3VdbeAddOp2(v, OP_Next, 0, addrTop+1);
sqlite3VdbeJumpHere(v, addrTop);
}
}else
#endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */
#ifndef NDEBUG #ifndef NDEBUG
if( sqlite3StrICmp(zLeft, "parser_trace")==0 ){ if( sqlite3StrICmp(zLeft, "parser_trace")==0 ){
if( zRight ){ if( zRight ){

View File

@@ -1479,6 +1479,12 @@ static void open_db(struct callback_data *p){
} }
#ifndef SQLITE_OMIT_LOAD_EXTENSION #ifndef SQLITE_OMIT_LOAD_EXTENSION
sqlite3_enable_load_extension(p->db, 1); sqlite3_enable_load_extension(p->db, 1);
#endif
#ifdef SQLITE_ENABLE_REGEXP
{
extern int sqlite3_add_regexp_func(sqlite3*);
sqlite3_add_regexp_func(db);
}
#endif #endif
} }
} }

View File

@@ -1486,18 +1486,18 @@ struct UnpackedRecord {
struct Index { struct Index {
char *zName; /* Name of this index */ char *zName; /* Name of this index */
int *aiColumn; /* Which columns are used by this index. 1st is 0 */ int *aiColumn; /* Which columns are used by this index. 1st is 0 */
tRowcnt *aiRowEst; /* Result of ANALYZE: Est. rows selected by each column */ tRowcnt *aiRowEst; /* From ANALYZE: Est. rows selected by each column */
Table *pTable; /* The SQL table being indexed */ Table *pTable; /* The SQL table being indexed */
char *zColAff; /* String defining the affinity of each column */ char *zColAff; /* String defining the affinity of each column */
Index *pNext; /* The next index associated with the same table */ Index *pNext; /* The next index associated with the same table */
Schema *pSchema; /* Schema containing this index */ Schema *pSchema; /* Schema containing this index */
u8 *aSortOrder; /* Array of size Index.nColumn. True==DESC, False==ASC */ u8 *aSortOrder; /* for each column: True==DESC, False==ASC */
char **azColl; /* Array of collation sequence names for index */ char **azColl; /* Array of collation sequence names for index */
int nColumn; /* Number of columns in the table used by this index */ int tnum; /* DB Page containing root of this index */
int tnum; /* Page containing root of this index in database file */ u16 nColumn; /* Number of columns in table used by this index */
u8 onError; /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */ u8 onError; /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */
u8 autoIndex; /* True if is automatically created (ex: by UNIQUE) */ unsigned autoIndex:2; /* 1==UNIQUE, 2==PRIMARY KEY, 0==CREATE INDEX */
u8 bUnordered; /* Use this index for == or IN queries only */ unsigned bUnordered:1; /* Use this index for == or IN queries only */
#ifdef SQLITE_ENABLE_STAT3 #ifdef SQLITE_ENABLE_STAT3
int nSample; /* Number of elements in aSample[] */ int nSample; /* Number of elements in aSample[] */
tRowcnt avgEq; /* Average nEq value for key values not in aSample */ tRowcnt avgEq; /* Average nEq value for key values not in aSample */
@@ -3218,8 +3218,10 @@ const char *sqlite3JournalModename(int);
#endif #endif
#ifndef SQLITE_OMIT_FOREIGN_KEY #ifndef SQLITE_OMIT_FOREIGN_KEY
void sqlite3FkDelete(sqlite3 *, Table*); void sqlite3FkDelete(sqlite3 *, Table*);
int sqlite3FkLocateIndex(Parse*,Table*,FKey*,Index**,int**);
#else #else
#define sqlite3FkDelete(a,b) #define sqlite3FkDelete(a,b)
#define sqlite3FkLocateIndex(a,b,c,d,e)
#endif #endif

View File

@@ -3684,6 +3684,7 @@ static void init_all(Tcl_Interp *interp){
extern int SqlitetestSyscall_Init(Tcl_Interp*); extern int SqlitetestSyscall_Init(Tcl_Interp*);
extern int Sqlitetestfuzzer_Init(Tcl_Interp*); extern int Sqlitetestfuzzer_Init(Tcl_Interp*);
extern int Sqlitetestwholenumber_Init(Tcl_Interp*); extern int Sqlitetestwholenumber_Init(Tcl_Interp*);
extern int Sqlitetestregexp_Init(Tcl_Interp*);
#if defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4) #if defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4)
extern int Sqlitetestfts3_Init(Tcl_Interp *interp); extern int Sqlitetestfts3_Init(Tcl_Interp *interp);
@@ -3727,6 +3728,7 @@ static void init_all(Tcl_Interp *interp){
SqlitetestSyscall_Init(interp); SqlitetestSyscall_Init(interp);
Sqlitetestfuzzer_Init(interp); Sqlitetestfuzzer_Init(interp);
Sqlitetestwholenumber_Init(interp); Sqlitetestwholenumber_Init(interp);
Sqlitetestregexp_Init(interp);
#if defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4) #if defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4)
Sqlitetestfts3_Init(interp); Sqlitetestfts3_Init(interp);

721
src/test_regexp.c Normal file
View File

@@ -0,0 +1,721 @@
/*
** 2012-11-13
**
** 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.
**
******************************************************************************
**
** The code in this file implements a compact but reasonably
** efficient regular-expression matcher for posix extended regular
** expressions against UTF8 text. The following syntax is supported:
**
** X* zero or more occurrences of X
** X+ one or more occurrences of X
** X? zero or one occurrences of X
** X{p,q} between p and q occurrences of X
** (X) match X
** X|Y X or Y
** ^X X occurring at the beginning of the string
** X$ X occurring at the end of the string
** . Match any single character
** \c Character c where c is one of \{}()[]|*+?.
** \c C-language escapes for c in afnrtv. ex: \t or \n
** \uXXXX Where XXXX is exactly 4 hex digits, unicode value XXXX
** \xXXX Where XXX is any number of hex digits, unicode value XXX
** [abc] Any single character from the set abc
** [^abc] Any single character not in the set abc
** [a-z] Any single character in the range a-z
** [^a-z] Any single character not in the range a-z
** \b Word boundary
** \w Word character. [A-Za-z0-9_]
** \W Non-word character
** \d Digit
** \D Non-digit
** \s Whitespace character
** \S Non-whitespace character
**
** A nondeterministic finite automaton (NFA) is used for matching, so the
** performance is bounded by O(N*M) where N is the size of the regular
** expression and M is the size of the input string. The matcher never
** exhibits exponential behavior. Note that the X{p,q} operator expands
** to p copies of X following by q-p copies of X? and that the size of the
** regular expression in the O(N*M) performance bound is computed after
** this expansion.
*/
#include <string.h>
#include <stdlib.h>
#include "sqlite3.h"
/* The end-of-input character */
#define RE_EOF 0 /* End of input */
/* The NFA is implemented as sequence of opcodes taken from the following
** set. Each opcode has a single integer argument.
*/
#define RE_OP_MATCH 1 /* Match the one character in the argument */
#define RE_OP_ANY 2 /* Match any one character. (Implements ".") */
#define RE_OP_ANYSTAR 3 /* Special optimized version of .* */
#define RE_OP_FORK 4 /* Continue to both next and opcode at iArg */
#define RE_OP_GOTO 5 /* Jump to opcode at iArg */
#define RE_OP_ACCEPT 6 /* Halt and indicate a successful match */
#define RE_OP_CC_INC 7 /* Beginning of a [...] character class */
#define RE_OP_CC_EXC 8 /* Beginning of a [^...] character class */
#define RE_OP_CC_VALUE 9 /* Single value in a character class */
#define RE_OP_CC_RANGE 10 /* Range of values in a character class */
#define RE_OP_WORD 11 /* Perl word character [A-Za-z0-9_] */
#define RE_OP_NOTWORD 12 /* Not a perl word character */
#define RE_OP_DIGIT 13 /* digit: [0-9] */
#define RE_OP_NOTDIGIT 14 /* Not a digit */
#define RE_OP_SPACE 15 /* space: [ \t\n\r\v\f] */
#define RE_OP_NOTSPACE 16 /* Not a digit */
#define RE_OP_BOUNDARY 17 /* Boundary between word and non-word */
/* Each opcode is a "state" in the NFA */
typedef unsigned short ReStateNumber;
/* Because this is an NFA and not a DFA, multiple states can be active at
** once. An instance of the following object records all active states in
** the NFA. The implementation is optimized for the common case where the
** number of actives states is small.
*/
typedef struct ReStateSet {
unsigned nState; /* Number of current states */
ReStateNumber *aState; /* Current states */
} ReStateSet;
/* A compiled NFA (or an NFA that is in the process of being compiled) is
** an instance of the following object.
*/
typedef struct ReCompiled {
const unsigned char *zIn; /* Regular expression text */
const char *zErr; /* Error message to return */
char *aOp; /* Operators for the virtual machine */
int *aArg; /* Arguments to each operator */
char zInit[12]; /* Initial text to match */
int nInit; /* Number of characters in zInit */
unsigned nState; /* Number of entries in aOp[] and aArg[] */
unsigned nAlloc; /* Slots allocated for aOp[] and aArg[] */
} ReCompiled;
/* Add a state to the given state set if it is not already there */
static void re_add_state(ReStateSet *pSet, int newState){
unsigned i;
for(i=0; i<pSet->nState; i++) if( pSet->aState[i]==newState ) return;
pSet->aState[pSet->nState++] = newState;
}
/* Extract the next unicode character from *pzIn and return it. Advance
** *pzIn to the first byte past the end of the character returned. To
** be clear: this routine converts utf8 to unicode. This routine is
** optimized for the common case where the next character is a single byte.
*/
static unsigned re_next_char(const unsigned char **pzIn){
unsigned c = **pzIn;
if( c>0 ) (*pzIn)++;
if( c>0x80 ){
if( (c&0xe0)==0xc0 && ((*pzIn)[0]&0xc0)==0x80 ){
c = (c&0x1f)<<6 | ((*pzIn)[0]&0x3f);
(*pzIn)++;
if( c<0x80 ) c = 0xfffd;
}else if( (c&0xf0)==0xe0 && ((*pzIn)[0]&0xc0)==0x80
&& ((*pzIn)[1]&0xc0)==0x80 ){
c = (c&0x0f)<<12 | (((*pzIn)[0]&0x3f)<<6) | ((*pzIn)[1]&0x3f);
*pzIn += 2;
if( c<0x3ff || (c>=0xd800 && c<=0xdfff) ) c = 0xfffd;
}else if( (c&0xf8)==0xf0 && ((*pzIn)[0]&0xc0)==0x80
&& ((*pzIn)[1]&0xc0)==0x80 && ((*pzIn)[2]&0xc0)==0x80 ){
c = (c&0x07)<<18 | (((*pzIn)[0]&0x3f)<<12) | (((*pzIn)[1]&0x3f)<<6)
| ((*pzIn)[2]&0x3f);
*pzIn += 3;
if( c<0xffff ) c = 0xfffd;
}else{
c = 0xfffd;
}
}
return c;
}
/* Return true if c is a perl "word" character: [A-Za-z0-9_] */
static int re_word_char(int c){
return (c>='0' && c<='9') || (c>='a' && c<='z')
|| (c>='A' && c<='Z') || c=='_';
}
/* Return true if c is a "digit" character: [0-9] */
static int re_digit_char(int c){
return (c>='0' && c<='9');
}
/* Return true if c is a perl "space" character: [ \t\r\n\v\f] */
static int re_space_char(int c){
return c==' ' || c=='\t' || c=='\n' || c=='\v' || c=='\f';
}
/* Run a compiled regular expression on the zero-terminated input
** string zIn[]. Return true on a match and false if there is no match.
*/
static int re_exec(ReCompiled *pRe, const unsigned char *zIn){
ReStateSet aStateSet[2], *pThis, *pNext;
ReStateNumber aSpace[100];
ReStateNumber *pToFree;
unsigned int i = 0;
unsigned int iSwap = 0;
int c = RE_EOF+1;
int cPrev = 0;
int rc = 0;
if( pRe->nInit ){
unsigned char x = pRe->zInit[0];
while( zIn[0] && (zIn[0]!=x || memcmp(zIn, pRe->zInit, pRe->nInit)!=0) ){
zIn++;
}
if( zIn[0]==0 ) return 0;
}
if( pRe->nState<=(sizeof(aSpace)/(sizeof(aSpace[0])*2)) ){
pToFree = 0;
aStateSet[0].aState = aSpace;
}else{
pToFree = malloc( sizeof(ReStateNumber)*2*pRe->nState );
if( pToFree==0 ) return -1;
aStateSet[0].aState = pToFree;
}
aStateSet[1].aState = &aStateSet[0].aState[pRe->nState];
pNext = &aStateSet[1];
pNext->nState = 0;
re_add_state(pNext, 0);
while( c!=RE_EOF && pNext->nState>0 ){
cPrev = c;
c = re_next_char(&zIn);
pThis = pNext;
pNext = &aStateSet[iSwap];
iSwap = 1 - iSwap;
pNext->nState = 0;
for(i=0; i<pThis->nState; i++){
int x = pThis->aState[i];
switch( pRe->aOp[x] ){
case RE_OP_MATCH: {
if( pRe->aArg[x]==c ) re_add_state(pNext, x+1);
break;
}
case RE_OP_ANY: {
re_add_state(pNext, x+1);
break;
}
case RE_OP_WORD: {
if( re_word_char(c) ) re_add_state(pNext, x+1);
break;
}
case RE_OP_NOTWORD: {
if( !re_word_char(c) ) re_add_state(pNext, x+1);
break;
}
case RE_OP_DIGIT: {
if( re_digit_char(c) ) re_add_state(pNext, x+1);
break;
}
case RE_OP_NOTDIGIT: {
if( !re_digit_char(c) ) re_add_state(pNext, x+1);
break;
}
case RE_OP_SPACE: {
if( re_space_char(c) ) re_add_state(pNext, x+1);
break;
}
case RE_OP_NOTSPACE: {
if( !re_space_char(c) ) re_add_state(pNext, x+1);
break;
}
case RE_OP_BOUNDARY: {
if( re_word_char(c)!=re_word_char(cPrev) ) re_add_state(pThis, x+1);
break;
}
case RE_OP_ANYSTAR: {
re_add_state(pNext, x);
re_add_state(pThis, x+1);
break;
}
case RE_OP_FORK: {
re_add_state(pThis, x+pRe->aArg[x]);
re_add_state(pThis, x+1);
break;
}
case RE_OP_GOTO: {
re_add_state(pThis, x+pRe->aArg[x]);
break;
}
case RE_OP_ACCEPT: {
rc = 1;
goto re_exec_end;
}
case RE_OP_CC_INC:
case RE_OP_CC_EXC: {
int j = 1;
int n = pRe->aArg[x];
int hit = 0;
for(j=1; j>0 && j<n; j++){
if( pRe->aOp[x+j]==RE_OP_CC_VALUE ){
if( pRe->aArg[x+j]==c ){
hit = 1;
j = -1;
}
}else{
if( pRe->aArg[x+j]<=c && pRe->aArg[x+j+1]>=c ){
hit = 1;
j = -1;
}else{
j++;
}
}
}
if( pRe->aOp[x]==RE_OP_CC_EXC ) hit = !hit;
if( hit ) re_add_state(pNext, x+n);
break;
}
}
}
}
for(i=0; i<pNext->nState; i++){
if( pRe->aOp[pNext->aState[i]]==RE_OP_ACCEPT ){ rc = 1; break; }
}
re_exec_end:
free(pToFree);
return rc;
}
/* Resize the opcode and argument arrays for an RE under construction.
*/
static int re_resize(ReCompiled *p, int N){
char *aOp;
int *aArg;
aOp = realloc(p->aOp, N*sizeof(p->aOp[0]));
if( aOp==0 ) return 1;
p->aOp = aOp;
aArg = realloc(p->aArg, N*sizeof(p->aArg[0]));
if( aArg==0 ) return 1;
p->aArg = aArg;
p->nAlloc = N;
return 0;
}
/* Insert a new opcode and argument into an RE under construction. The
** insertion point is just prior to existing opcode iBefore.
*/
static int re_insert(ReCompiled *p, int iBefore, int op, int arg){
int i;
if( p->nAlloc<=p->nState && re_resize(p, p->nAlloc*2) ) return 0;
for(i=p->nState; i>iBefore; i--){
p->aOp[i] = p->aOp[i-1];
p->aArg[i] = p->aArg[i-1];
}
p->nState++;
p->aOp[iBefore] = op;
p->aArg[iBefore] = arg;
return iBefore;
}
/* Append a new opcode and argument to the end of the RE under construction.
*/
static int re_append(ReCompiled *p, int op, int arg){
return re_insert(p, p->nState, op, arg);
}
/* Make a copy of N opcodes starting at iStart onto the end of the RE
** under construction.
*/
static void re_copy(ReCompiled *p, int iStart, int N){
if( p->nState+N>=p->nAlloc && re_resize(p, p->nAlloc*2+N) ) return;
memcpy(&p->aOp[p->nState], &p->aOp[iStart], N*sizeof(p->aOp[0]));
memcpy(&p->aArg[p->nState], &p->aArg[iStart], N*sizeof(p->aArg[0]));
p->nState += N;
}
/* Return true if c is a hexadecimal digit character: [0-9a-fA-F]
** If c is a hex digit, also set *pV = (*pV)*16 + valueof(c). If
** c is not a hex digit *pV is unchanged.
*/
static int re_hex(int c, int *pV){
if( c>='0' && c<='9' ){
c -= '0';
}else if( c>='a' && c<='f' ){
c -= 'a' - 10;
}else if( c>='A' && c<='F' ){
c -= 'A' - 10;
}else{
return 0;
}
*pV = (*pV)*16 + (c & 0xff);
return 1;
}
/* A backslash character has been seen, read the next character and
** return its intepretation.
*/
static unsigned re_esc_char(ReCompiled *p){
static const char zEsc[] = "afnrtv\\()*.+?[$^{|}]";
static const char zTrans[] = "\a\f\n\r\t\v";
int i, v = 0;
char c = p->zIn[0];
if( c=='u' ){
v = 0;
if( re_hex(p->zIn[1],&v)
&& re_hex(p->zIn[2],&v)
&& re_hex(p->zIn[3],&v)
&& re_hex(p->zIn[4],&v)
){
p->zIn += 5;
return v;
}
}
if( c=='x' ){
v = 0;
for(i=1; re_hex(p->zIn[i], &v); i++){}
if( i>1 ){
p->zIn += i;
return v;
}
}
for(i=0; zEsc[i] && zEsc[i]!=c; i++){}
if( zEsc[i] ){
if( i<6 ) c = zTrans[i];
p->zIn++;
}else{
p->zErr = "unknown \\ escape";
}
return c;
}
/* Forward declaration */
static const char *re_subcompile_string(ReCompiled*);
/* Compile RE text into a sequence of opcodes. Continue up to the
** first unmatched ")" character, then return. If an error is found,
** return a pointer to the error message string.
*/
static const char *re_subcompile_re(ReCompiled *p){
const char *zErr;
int iStart, iEnd, iGoto;
iStart = p->nState;
zErr = re_subcompile_string(p);
if( zErr ) return zErr;
while( p->zIn[0]=='|' ){
iEnd = p->nState;
re_insert(p, iStart, RE_OP_FORK, iEnd + 2 - iStart);
iGoto = re_append(p, RE_OP_GOTO, 0);
p->zIn++;
zErr = re_subcompile_string(p);
if( zErr ) return zErr;
p->aArg[iGoto] = p->nState - iGoto;
}
return 0;
}
/* Compile an element of regular expression text (anything that can be
** an operand to the "|" operator). Return NULL on success or a pointer
** to the error message if there is a problem.
*/
static const char *re_subcompile_string(ReCompiled *p){
int iPrev = -1;
int iStart;
unsigned c;
const char *zErr;
while( (c = re_next_char(&p->zIn))!=0 ){
iStart = p->nState;
switch( c ){
case '|':
case '$':
case ')': {
p->zIn--;
return 0;
}
case '(': {
zErr = re_subcompile_re(p);
if( zErr ) return zErr;
if( p->zIn[0]!=')' ) return "unmatched '('";
p->zIn++;
break;
}
case '.': {
if( p->zIn[0]=='*' ){
re_append(p, RE_OP_ANYSTAR, 0);
p->zIn++;
}else{
re_append(p, RE_OP_ANY, 0);
}
break;
}
case '*': {
if( iPrev<0 ) return "'*' without operand";
re_insert(p, iPrev, RE_OP_GOTO, p->nState - iPrev + 1);
re_append(p, RE_OP_FORK, iPrev - p->nState + 1);
break;
}
case '+': {
if( iPrev<0 ) return "'+' without operand";
re_append(p, RE_OP_FORK, iPrev - p->nState);
break;
}
case '?': {
if( iPrev<0 ) return "'?' without operand";
re_insert(p, iPrev, RE_OP_FORK, p->nState - iPrev+1);
break;
}
case '{': {
int m = 0, n = 0;
int sz, j;
if( iPrev<0 ) return "'{m,n}' without operand";
while( (c=p->zIn[0])>='0' && c<='9' ){ m = m*10 + c - '0'; p->zIn++; }
n = m;
if( c==',' ){
p->zIn++;
n = 0;
while( (c=p->zIn[0])>='0' && c<='9' ){ n = n*10 + c - '0'; p->zIn++; }
}
if( c!='}' ) return "unmatched '{'";
if( n>0 && n<m ) return "n less than m in '{m,n}'";
p->zIn++;
sz = p->nState - iPrev;
if( m==0 ){
if( n==0 ) return "both m and n are zero in '{m,n}'";
re_insert(p, iPrev, RE_OP_FORK, sz+1);
n--;
}else{
for(j=1; j<m; j++) re_copy(p, iPrev, sz);
}
for(j=m; j<n; j++){
re_append(p, RE_OP_FORK, sz+1);
re_copy(p, iPrev, sz);
}
if( n==0 && m>0 ){
re_append(p, RE_OP_FORK, -sz);
}
break;
}
case '[': {
int iFirst = p->nState;
if( p->zIn[0]=='^' ){
re_append(p, RE_OP_CC_EXC, 0);
p->zIn++;
}else{
re_append(p, RE_OP_CC_INC, 0);
}
while( (c = re_next_char(&p->zIn))!=0 ){
if( c=='[' && p->zIn[0]==':' ){
return "POSIX character classes not supported";
}
if( c=='\\' ) c = re_esc_char(p);
if( p->zIn[0]=='-' && p->zIn[1] ){
re_append(p, RE_OP_CC_RANGE, c);
p->zIn++;
c = re_next_char(&p->zIn);
if( c=='\\' ) c = re_esc_char(p);
re_append(p, RE_OP_CC_RANGE, c);
}else{
re_append(p, RE_OP_CC_VALUE, c);
}
if( p->zIn[0]==']' ){ p->zIn++; break; }
}
if( c==0 ) return "unclosed '['";
p->aArg[iFirst] = p->nState - iFirst;
break;
}
case '\\': {
int specialOp = 0;
switch( p->zIn[0] ){
case 'b': specialOp = RE_OP_BOUNDARY; break;
case 'd': specialOp = RE_OP_DIGIT; break;
case 'D': specialOp = RE_OP_NOTDIGIT; break;
case 's': specialOp = RE_OP_SPACE; break;
case 'S': specialOp = RE_OP_NOTSPACE; break;
case 'w': specialOp = RE_OP_WORD; break;
case 'W': specialOp = RE_OP_NOTWORD; break;
}
if( specialOp ){
p->zIn++;
re_append(p, specialOp, 0);
}else{
c = re_esc_char(p);
re_append(p, RE_OP_MATCH, c);
}
break;
}
default: {
re_append(p, RE_OP_MATCH, c);
break;
}
}
iPrev = iStart;
}
return 0;
}
/* Free and reclaim all the memory used by a previously compiled
** regular expression. Applications should invoke this routine once
** for every call to re_compile() to avoid memory leaks.
*/
static void re_free(ReCompiled *pRe){
if( pRe ){
free(pRe->aOp);
free(pRe->aArg);
}
}
/*
** Compile a textual regular expression in zIn[] into a compiled regular
** expression suitable for us by re_exec() and return a pointer to the
** compiled regular expression in *ppRe. Return NULL on success or an
** error message if something goes wrong.
*/
static const char *re_compile(ReCompiled **ppRe, const char *zIn){
ReCompiled *pRe;
const char *zErr;
int i, j;
*ppRe = 0;
pRe = malloc( sizeof(*pRe) );
if( pRe==0 ){
return "out of memory";
}
memset(pRe, 0, sizeof(*pRe));
if( re_resize(pRe, 30) ){
re_free(pRe);
return "out of memory";
}
if( zIn[0]=='^' ){
zIn++;
}else{
re_append(pRe, RE_OP_ANYSTAR, 0);
}
pRe->zIn = (unsigned char*)zIn;
zErr = re_subcompile_re(pRe);
if( zErr ){
re_free(pRe);
return zErr;
}
if( pRe->zIn[0]=='$' && pRe->zIn[1]==0 ){
re_append(pRe, RE_OP_MATCH, RE_EOF);
re_append(pRe, RE_OP_ACCEPT, 0);
*ppRe = pRe;
}else if( pRe->zIn[0]==0 ){
re_append(pRe, RE_OP_ACCEPT, 0);
*ppRe = pRe;
}else{
re_free(pRe);
return "unrecognized character";
}
if( pRe->aOp[0]==RE_OP_ANYSTAR ){
for(j=0, i=1; j<sizeof(pRe->zInit)-2 && pRe->aOp[i]==RE_OP_MATCH; i++){
unsigned x = pRe->aArg[i];
if( x<=127 ){
pRe->zInit[j++] = x;
}else if( x<=0xfff ){
pRe->zInit[j++] = 0xc0 | (x>>6);
pRe->zInit[j++] = 0x80 | (x&0x3f);
}else if( x<=0xffff ){
pRe->zInit[j++] = 0xd0 | (x>>12);
pRe->zInit[j++] = 0x80 | ((x>>6)&0x3f);
pRe->zInit[j++] = 0x80 | ((x>>6)&0x3f);
}else{
break;
}
}
pRe->nInit = j;
}
return pRe->zErr;
}
/*
** Implementation of the regexp() SQL function. This function implements
** the build-in REGEXP operator. The first argument to the function is the
** pattern and the second argument is the string. So, the SQL statements:
**
** A REGEXP B
**
** is implemented as regexp(B,A).
*/
static void re_sql_func(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
ReCompiled *pRe; /* Compiled regular expression */
const char *zPattern; /* The regular expression */
const unsigned char *zStr;/* String being searched */
const char *zErr; /* Compile error message */
pRe = sqlite3_get_auxdata(context, 0);
if( pRe==0 ){
zPattern = (const char*)sqlite3_value_text(argv[0]);
if( zPattern==0 ) return;
zErr = re_compile(&pRe, zPattern);
if( zErr ){
sqlite3_result_error(context, zErr, -1);
return;
}
if( pRe==0 ){
sqlite3_result_error_nomem(context);
return;
}
sqlite3_set_auxdata(context, 0, pRe, (void(*)(void*))re_free);
}
zStr = (const unsigned char*)sqlite3_value_text(argv[1]);
if( zStr!=0 ){
sqlite3_result_int(context, re_exec(pRe, zStr));
}
}
/*
** Invoke this routine in order to install the REGEXP function in an
** SQLite database connection.
**
** Use:
**
** sqlite3_auto_extension(sqlite3_add_regexp_func);
**
** to cause this extension to be automatically loaded into each new
** database connection.
*/
int sqlite3_add_regexp_func(sqlite3 *db){
return sqlite3_create_function(db, "regexp", 2, SQLITE_UTF8, 0,
re_sql_func, 0, 0);
}
/***************************** Test Code ***********************************/
#ifdef SQLITE_TEST
#include <tcl.h>
extern int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb);
/* Implementation of the TCL command:
**
** sqlite3_add_regexp_func $DB
*/
static int tclSqlite3AddRegexpFunc(
void * clientData,
Tcl_Interp *interp,
int objc,
Tcl_Obj *CONST objv[]
){
sqlite3 *db;
if( objc!=2 ){
Tcl_WrongNumArgs(interp, 1, objv, "DB");
return TCL_ERROR;
}
if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
sqlite3_add_regexp_func(db);
return TCL_OK;
}
/* Register the sqlite3_add_regexp_func TCL command with the TCL interpreter.
*/
int Sqlitetestregexp_Init(Tcl_Interp *interp){
Tcl_CreateObjCommand(interp, "sqlite3_add_regexp_func",
tclSqlite3AddRegexpFunc, 0, 0);
return TCL_OK;
}
#endif /* SQLITE_TEST */
/**************************** End Of Test Code *******************************/

View File

@@ -403,7 +403,7 @@ static int whereClauseInsert(WhereClause *pWC, Expr *p, u8 wtFlags){
pWC->nSlot = sqlite3DbMallocSize(db, pWC->a)/sizeof(pWC->a[0]); pWC->nSlot = sqlite3DbMallocSize(db, pWC->a)/sizeof(pWC->a[0]);
} }
pTerm = &pWC->a[idx = pWC->nTerm++]; pTerm = &pWC->a[idx = pWC->nTerm++];
pTerm->pExpr = p; pTerm->pExpr = sqlite3ExprSkipCollate(p);
pTerm->wtFlags = wtFlags; pTerm->wtFlags = wtFlags;
pTerm->pWC = pWC; pTerm->pWC = pWC;
pTerm->iParent = -1; pTerm->iParent = -1;
@@ -1188,7 +1188,8 @@ static void exprAnalyze(
} }
pTerm = &pWC->a[idxTerm]; pTerm = &pWC->a[idxTerm];
pMaskSet = pWC->pMaskSet; pMaskSet = pWC->pMaskSet;
pExpr = sqlite3ExprSkipCollate(pTerm->pExpr); pExpr = pTerm->pExpr;
assert( pExpr->op!=TK_AS && pExpr->op!=TK_COLLATE );
prereqLeft = exprTableUsage(pMaskSet, pExpr->pLeft); prereqLeft = exprTableUsage(pMaskSet, pExpr->pLeft);
op = pExpr->op; op = pExpr->op;
if( op==TK_IN ){ if( op==TK_IN ){

View File

@@ -627,7 +627,8 @@ proc test_efkey_57 {tn isError sql} {
execsql $sql execsql $sql
do_test e_fkey-18.$tn { do_test e_fkey-18.$tn {
catchsql { INSERT INTO t2 VALUES(NULL) } catchsql { INSERT INTO t2 VALUES(NULL) }
} [lindex {{0 {}} {1 {foreign key mismatch}}} $isError] } [lindex {{0 {}} {/1 {foreign key mismatch - ".*" referencing ".*"}/}} \
$isError]
} }
test_efkey_57 2 0 { CREATE TABLE t1(x PRIMARY KEY) } test_efkey_57 2 0 { CREATE TABLE t1(x PRIMARY KEY) }
test_efkey_57 3 0 { CREATE TABLE t1(x UNIQUE) } test_efkey_57 3 0 { CREATE TABLE t1(x UNIQUE) }
@@ -698,16 +699,16 @@ do_test e_fkey-19.2 {
} {} } {}
do_test e_fkey-19.2 { do_test e_fkey-19.2 {
catchsql { INSERT INTO child4 VALUES('xxx', 5) } catchsql { INSERT INTO child4 VALUES('xxx', 5) }
} {1 {foreign key mismatch}} } {1 {foreign key mismatch - "child4" referencing "parent"}}
do_test e_fkey-19.3 { do_test e_fkey-19.3 {
catchsql { INSERT INTO child5 VALUES('xxx', 6) } catchsql { INSERT INTO child5 VALUES('xxx', 6) }
} {1 {foreign key mismatch}} } {1 {foreign key mismatch - "child5" referencing "parent"}}
do_test e_fkey-19.4 { do_test e_fkey-19.4 {
catchsql { INSERT INTO child6 VALUES(2, 3) } catchsql { INSERT INTO child6 VALUES(2, 3) }
} {1 {foreign key mismatch}} } {1 {foreign key mismatch - "child6" referencing "parent"}}
do_test e_fkey-19.5 { do_test e_fkey-19.5 {
catchsql { INSERT INTO child7 VALUES(3) } catchsql { INSERT INTO child7 VALUES(3) }
} {1 {foreign key mismatch}} } {1 {foreign key mismatch - "child7" referencing "parent"}}
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
# Test errors in the database schema that are detected while preparing # Test errors in the database schema that are detected while preparing
@@ -765,12 +766,12 @@ do_test e_fkey-20.1 {
foreach {tn tbl ptbl err} { foreach {tn tbl ptbl err} {
2 c1 {} "no such table: main.nosuchtable" 2 c1 {} "no such table: main.nosuchtable"
3 c2 p2 "foreign key mismatch" 3 c2 p2 "foreign key mismatch - \"c2\" referencing \"p2\""
4 c3 p3 "foreign key mismatch" 4 c3 p3 "foreign key mismatch - \"c3\" referencing \"p3\""
5 c4 p4 "foreign key mismatch" 5 c4 p4 "foreign key mismatch - \"c4\" referencing \"p4\""
6 c5 p5 "foreign key mismatch" 6 c5 p5 "foreign key mismatch - \"c5\" referencing \"p5\""
7 c6 p6 "foreign key mismatch" 7 c6 p6 "foreign key mismatch - \"c6\" referencing \"p6\""
8 c7 p7 "foreign key mismatch" 8 c7 p7 "foreign key mismatch - \"c7\" referencing \"p7\""
} { } {
do_test e_fkey-20.$tn.1 { do_test e_fkey-20.$tn.1 {
catchsql "INSERT INTO $tbl VALUES('a', 'b')" catchsql "INSERT INTO $tbl VALUES('a', 'b')"
@@ -820,22 +821,22 @@ do_test e_fkey-21.2 {
} {} } {}
do_test e_fkey-21.3 { do_test e_fkey-21.3 {
catchsql { INSERT INTO child9 VALUES('I') } catchsql { INSERT INTO child9 VALUES('I') }
} {1 {foreign key mismatch}} } {1 {foreign key mismatch - "child9" referencing "parent2"}}
do_test e_fkey-21.4 { do_test e_fkey-21.4 {
catchsql { INSERT INTO child9 VALUES('II') } catchsql { INSERT INTO child9 VALUES('II') }
} {1 {foreign key mismatch}} } {1 {foreign key mismatch - "child9" referencing "parent2"}}
do_test e_fkey-21.5 { do_test e_fkey-21.5 {
catchsql { INSERT INTO child9 VALUES(NULL) } catchsql { INSERT INTO child9 VALUES(NULL) }
} {1 {foreign key mismatch}} } {1 {foreign key mismatch - "child9" referencing "parent2"}}
do_test e_fkey-21.6 { do_test e_fkey-21.6 {
catchsql { INSERT INTO child10 VALUES('I', 'II', 'III') } catchsql { INSERT INTO child10 VALUES('I', 'II', 'III') }
} {1 {foreign key mismatch}} } {1 {foreign key mismatch - "child10" referencing "parent2"}}
do_test e_fkey-21.7 { do_test e_fkey-21.7 {
catchsql { INSERT INTO child10 VALUES(1, 2, 3) } catchsql { INSERT INTO child10 VALUES(1, 2, 3) }
} {1 {foreign key mismatch}} } {1 {foreign key mismatch - "child10" referencing "parent2"}}
do_test e_fkey-21.8 { do_test e_fkey-21.8 {
catchsql { INSERT INTO child10 VALUES(NULL, NULL, NULL) } catchsql { INSERT INTO child10 VALUES(NULL, NULL, NULL) }
} {1 {foreign key mismatch}} } {1 {foreign key mismatch - "child10" referencing "parent2"}}
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
# Test errors that are reported when creating the child table. # Test errors that are reported when creating the child table.
@@ -1151,7 +1152,7 @@ do_test e_fkey-28.8 {
CREATE TABLE c(a, b, FOREIGN KEY(a,b) REFERENCES p); CREATE TABLE c(a, b, FOREIGN KEY(a,b) REFERENCES p);
} }
catchsql {DELETE FROM p} catchsql {DELETE FROM p}
} {1 {foreign key mismatch}} } {1 {foreign key mismatch - "c" referencing "p"}}
do_test e_fkey-28.9 { do_test e_fkey-28.9 {
drop_all_tables drop_all_tables
execsql { execsql {
@@ -1159,7 +1160,7 @@ do_test e_fkey-28.9 {
CREATE TABLE c(a REFERENCES p); CREATE TABLE c(a REFERENCES p);
} }
catchsql {DELETE FROM p} catchsql {DELETE FROM p}
} {1 {foreign key mismatch}} } {1 {foreign key mismatch - "c" referencing "p"}}
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
@@ -2729,11 +2730,11 @@ do_test e_fkey-60.3 {
do_test e_fkey-60.4 { do_test e_fkey-60.4 {
execsql { CREATE TABLE nosuchtable(x PRIMARY KEY) } execsql { CREATE TABLE nosuchtable(x PRIMARY KEY) }
catchsql { DELETE FROM p } catchsql { DELETE FROM p }
} {1 {foreign key mismatch}} } {1 {foreign key mismatch - "c2" referencing "p"}}
do_test e_fkey-60.5 { do_test e_fkey-60.5 {
execsql { DROP TABLE c1 } execsql { DROP TABLE c1 }
catchsql { DELETE FROM p } catchsql { DELETE FROM p }
} {1 {foreign key mismatch}} } {1 {foreign key mismatch - "c2" referencing "p"}}
do_test e_fkey-60.6 { do_test e_fkey-60.6 {
execsql { DROP TABLE c2 } execsql { DROP TABLE c2 }
execsql { DELETE FROM p } execsql { DELETE FROM p }

View File

@@ -213,4 +213,39 @@ do_execsql_test filefmt-3.3 {
PRAGMA integrity_check; PRAGMA integrity_check;
} {ok} } {ok}
reset_db
do_execsql_test filefmt-4.1 {
PRAGMA auto_vacuum = 1;
CREATE TABLE t1(x, y);
CREATE TABLE t2(x, y);
INSERT INTO t1 VALUES(randomblob(100), randomblob(100));
INSERT INTO t1 VALUES(randomblob(100), randomblob(100));
INSERT INTO t1 VALUES(randomblob(100), randomblob(100));
INSERT INTO t1 VALUES(randomblob(100), randomblob(100));
INSERT INTO t1 VALUES(randomblob(100), randomblob(100));
INSERT INTO t1 VALUES(randomblob(100), randomblob(100));
INSERT INTO t2 SELECT randomblob(100), randomblob(100) FROM t1;
INSERT INTO t2 SELECT randomblob(100), randomblob(100) FROM t1;
INSERT INTO t2 SELECT randomblob(100), randomblob(100) FROM t1;
INSERT INTO t2 SELECT randomblob(100), randomblob(100) FROM t1;
}
do_test filefmt-4.2 {
sql36231 { INSERT INTO t2 SELECT * FROM t1 }
} {}
do_test filefmt-4.3 {
forcedelete bak.db
db backup bak.db
} {}
do_test filefmt-4.4 {
sqlite3 db2 bak.db
db2 eval { PRAGMA integrity_check }
} {ok}
db2 close
finish_test finish_test

View File

@@ -139,14 +139,21 @@ set FkeySimpleTests {
4.17 "UPDATE t7 SET a = 10" {0 {}} 4.17 "UPDATE t7 SET a = 10" {0 {}}
5.1 "INSERT INTO t9 VALUES(1, 3)" {1 {no such table: main.nosuchtable}} 5.1 "INSERT INTO t9 VALUES(1, 3)" {1 {no such table: main.nosuchtable}}
5.2 "INSERT INTO t10 VALUES(1, 3)" {1 {foreign key mismatch}} 5.2 "INSERT INTO t10 VALUES(1, 3)"
{1 {foreign key mismatch - "t10" referencing "t9"}}
} }
do_test fkey2-1.1.0 { do_test fkey2-1.1.0 {
execsql [string map {/D/ {}} $FkeySimpleSchema] execsql [string map {/D/ {}} $FkeySimpleSchema]
} {} } {}
foreach {tn zSql res} $FkeySimpleTests { foreach {tn zSql res} $FkeySimpleTests {
do_test fkey2-1.1.$tn { catchsql $zSql } $res do_test fkey2-1.1.$tn.1 { catchsql $zSql } $res
do_test fkey2-1.1.$tn.2 { execsql {PRAGMA foreign_key_check(t1)} } {}
do_test fkey2-1.1.$tn.3 { execsql {PRAGMA foreign_key_check(t2)} } {}
do_test fkey2-1.1.$tn.4 { execsql {PRAGMA foreign_key_check(t3)} } {}
do_test fkey2-1.1.$tn.5 { execsql {PRAGMA foreign_key_check(t4)} } {}
do_test fkey2-1.1.$tn.6 { execsql {PRAGMA foreign_key_check(t7)} } {}
do_test fkey2-1.1.$tn.7 { execsql {PRAGMA foreign_key_check(t8)} } {}
} }
drop_all_tables drop_all_tables
@@ -155,6 +162,12 @@ do_test fkey2-1.2.0 {
} {} } {}
foreach {tn zSql res} $FkeySimpleTests { foreach {tn zSql res} $FkeySimpleTests {
do_test fkey2-1.2.$tn { catchsql $zSql } $res do_test fkey2-1.2.$tn { catchsql $zSql } $res
do_test fkey2-1.2.$tn.2 { execsql {PRAGMA foreign_key_check(t1)} } {}
do_test fkey2-1.2.$tn.3 { execsql {PRAGMA foreign_key_check(t2)} } {}
do_test fkey2-1.2.$tn.4 { execsql {PRAGMA foreign_key_check(t3)} } {}
do_test fkey2-1.2.$tn.5 { execsql {PRAGMA foreign_key_check(t4)} } {}
do_test fkey2-1.2.$tn.6 { execsql {PRAGMA foreign_key_check(t7)} } {}
do_test fkey2-1.2.$tn.7 { execsql {PRAGMA foreign_key_check(t8)} } {}
} }
drop_all_tables drop_all_tables
@@ -165,6 +178,12 @@ do_test fkey2-1.3.0 {
foreach {tn zSql res} $FkeySimpleTests { foreach {tn zSql res} $FkeySimpleTests {
if {$res == "0 {}"} { set res {0 1} } if {$res == "0 {}"} { set res {0 1} }
do_test fkey2-1.3.$tn { catchsql $zSql } $res do_test fkey2-1.3.$tn { catchsql $zSql } $res
do_test fkey2-1.3.$tn.2 { execsql {PRAGMA foreign_key_check(t1)} } {}
do_test fkey2-1.3.$tn.3 { execsql {PRAGMA foreign_key_check(t2)} } {}
do_test fkey2-1.3.$tn.4 { execsql {PRAGMA foreign_key_check(t3)} } {}
do_test fkey2-1.3.$tn.5 { execsql {PRAGMA foreign_key_check(t4)} } {}
do_test fkey2-1.3.$tn.6 { execsql {PRAGMA foreign_key_check(t7)} } {}
do_test fkey2-1.3.$tn.7 { execsql {PRAGMA foreign_key_check(t8)} } {}
} }
execsql { PRAGMA count_changes = 0 } execsql { PRAGMA count_changes = 0 }
drop_all_tables drop_all_tables
@@ -681,7 +700,7 @@ foreach zSql [list {
do_test fkey2-10.1.[incr tn] { do_test fkey2-10.1.[incr tn] {
execsql $zSql execsql $zSql
catchsql { INSERT INTO c DEFAULT VALUES } catchsql { INSERT INTO c DEFAULT VALUES }
} {1 {foreign key mismatch}} } {/1 {foreign key mismatch - "c" referencing "."}/}
} }
# "rowid" cannot be used as part of a child or parent key definition # "rowid" cannot be used as part of a child or parent key definition
@@ -709,7 +728,7 @@ do_test fkey2-10.2.1 {
INSERT INTO t1(rowid, a, b) VALUES(1, 1, 1); INSERT INTO t1(rowid, a, b) VALUES(1, 1, 1);
INSERT INTO t2 VALUES(1, 1); INSERT INTO t2 VALUES(1, 1);
} }
} {1 {foreign key mismatch}} } {1 {foreign key mismatch - "t2" referencing "t1"}}
do_test fkey2-10.2.2 { do_test fkey2-10.2.2 {
drop_all_tables drop_all_tables
catchsql { catchsql {
@@ -1223,7 +1242,7 @@ do_test fkey-2.14.3.8 {
CREATE TABLE cc(a, b, FOREIGN KEY(a, b) REFERENCES pp(x, z)); CREATE TABLE cc(a, b, FOREIGN KEY(a, b) REFERENCES pp(x, z));
} }
catchsql { INSERT INTO cc VALUES(1, 2) } catchsql { INSERT INTO cc VALUES(1, 2) }
} {1 {foreign key mismatch}} } {1 {foreign key mismatch - "cc" referencing "pp"}}
do_test fkey-2.14.3.9 { do_test fkey-2.14.3.9 {
execsql { DROP TABLE cc } execsql { DROP TABLE cc }
} {} } {}

310
test/fkey5.test Normal file
View File

@@ -0,0 +1,310 @@
# 2012 December 17
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.
#
# This file tests the PRAGMA foreign_key_check command.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
ifcapable {!foreignkey} {
finish_test
return
}
do_test fkey5-1.1 {
db eval {
CREATE TABLE p1(a INTEGER PRIMARY KEY); INSERT INTO p1 VALUES(88),(89);
CREATE TABLE p2(a INT PRIMARY KEY); INSERT INTO p2 VALUES(77),(78);
CREATE TABLE p3(a TEXT PRIMARY KEY);
INSERT INTO p3 VALUES(66),(67),('alpha'),('BRAVO');
CREATE TABLE p4(a TEXT PRIMARY KEY COLLATE nocase);
INSERT INTO p4 VALUES('alpha'),('BRAVO'),('55'),('Delta'),('ECHO');
CREATE TABLE p5(a INTEGER PRIMARY KEY, b, c, UNIQUE(b,c));
INSERT INTO p5 VALUES(1,'Alpha','abc'),(2,'beta','def');
CREATE TABLE p6(a INTEGER PRIMARY KEY, b TEXT COLLATE nocase,
c TEXT COLLATE rtrim, UNIQUE(b,c));
INSERT INTO p6 VALUES(1,'Alpha','abc '),(2,'bETA','def ');
CREATE TABLE c1(x INTEGER PRIMARY KEY references p1);
CREATE TABLE c2(x INTEGER PRIMARY KEY references p2);
CREATE TABLE c3(x INTEGER PRIMARY KEY references p3);
CREATE TABLE c4(x INTEGER PRIMARY KEY references p4);
CREATE TABLE c5(x INT references p1);
CREATE TABLE c6(x INT references p2);
CREATE TABLE c7(x INT references p3);
CREATE TABLE c8(x INT references p4);
CREATE TABLE c9(x TEXT UNIQUE references p1);
CREATE TABLE c10(x TEXT UNIQUE references p2);
CREATE TABLE c11(x TEXT UNIQUE references p3);
CREATE TABLE c12(x TEXT UNIQUE references p4);
CREATE TABLE c13(x TEXT COLLATE nocase references p3);
CREATE TABLE c14(x TEXT COLLATE nocase references p4);
CREATE TABLE c15(x, y, FOREIGN KEY(x,y) REFERENCES p5(b,c));
CREATE TABLE c16(x, y, FOREIGN KEY(x,y) REFERENCES p5(c,b));
CREATE TABLE c17(x, y, FOREIGN KEY(x,y) REFERENCES p6(b,c));
CREATE TABLE c18(x, y, FOREIGN KEY(x,y) REFERENCES p6(c,b));
CREATE TABLE c19(x TEXT COLLATE nocase, y TEXT COLLATE rtrim,
FOREIGN KEY(x,y) REFERENCES p5(b,c));
CREATE TABLE c20(x TEXT COLLATE nocase, y TEXT COLLATE rtrim,
FOREIGN KEY(x,y) REFERENCES p5(c,b));
CREATE TABLE c21(x TEXT COLLATE nocase, y TEXT COLLATE rtrim,
FOREIGN KEY(x,y) REFERENCES p6(b,c));
CREATE TABLE c22(x TEXT COLLATE nocase, y TEXT COLLATE rtrim,
FOREIGN KEY(x,y) REFERENCES p6(c,b));
PRAGMA foreign_key_check;
}
} {}
do_test fkey5-1.2 {
db eval {
INSERT INTO c1 VALUES(90),(87),(88);
PRAGMA foreign_key_check;
}
} {c1 87 p1 0 c1 90 p1 0}
do_test fkey5-1.3 {
db eval {
PRAGMA foreign_key_check(c1);
}
} {c1 87 p1 0 c1 90 p1 0}
do_test fkey5-1.4 {
db eval {
PRAGMA foreign_key_check(c2);
}
} {}
do_test fkey5-2.0 {
db eval {
INSERT INTO c5 SELECT x FROM c1;
DELETE FROM c1;
PRAGMA foreign_key_check;
}
} {c5 1 p1 0 c5 3 p1 0}
do_test fkey5-2.1 {
db eval {
PRAGMA foreign_key_check(c5);
}
} {c5 1 p1 0 c5 3 p1 0}
do_test fkey5-2.2 {
db eval {
PRAGMA foreign_key_check(c1);
}
} {}
do_test fkey5-3.0 {
db eval {
INSERT INTO c9 SELECT x FROM c5;
DELETE FROM c5;
PRAGMA foreign_key_check;
}
} {c9 1 p1 0 c9 3 p1 0}
do_test fkey5-3.1 {
db eval {
PRAGMA foreign_key_check(c9);
}
} {c9 1 p1 0 c9 3 p1 0}
do_test fkey5-3.2 {
db eval {
PRAGMA foreign_key_check(c5);
}
} {}
do_test fkey5-4.0 {
db eval {
DELETE FROM c9;
INSERT INTO c2 VALUES(79),(77),(76);
PRAGMA foreign_key_check;
}
} {c2 76 p2 0 c2 79 p2 0}
do_test fkey5-4.1 {
db eval {
PRAGMA foreign_key_check(c2);
}
} {c2 76 p2 0 c2 79 p2 0}
do_test fkey5-4.2 {
db eval {
INSERT INTO c6 SELECT x FROM c2;
DELETE FROM c2;
PRAGMA foreign_key_check;
}
} {c6 1 p2 0 c6 3 p2 0}
do_test fkey5-4.3 {
db eval {
PRAGMA foreign_key_check(c6);
}
} {c6 1 p2 0 c6 3 p2 0}
do_test fkey5-4.4 {
db eval {
INSERT INTO c10 SELECT x FROM c6;
DELETE FROM c6;
PRAGMA foreign_key_check;
}
} {c10 1 p2 0 c10 3 p2 0}
do_test fkey5-4.5 {
db eval {
PRAGMA foreign_key_check(c10);
}
} {c10 1 p2 0 c10 3 p2 0}
do_test fkey5-5.0 {
db eval {
DELETE FROM c10;
INSERT INTO c3 VALUES(68),(67),(65);
PRAGMA foreign_key_check;
}
} {c3 65 p3 0 c3 68 p3 0}
do_test fkey5-5.1 {
db eval {
PRAGMA foreign_key_check(c3);
}
} {c3 65 p3 0 c3 68 p3 0}
do_test fkey5-5.2 {
db eval {
INSERT INTO c7 SELECT x FROM c3;
INSERT INTO c7 VALUES('Alpha'),('alpha'),('foxtrot');
DELETE FROM c3;
PRAGMA foreign_key_check;
}
} {c7 1 p3 0 c7 3 p3 0 c7 4 p3 0 c7 6 p3 0}
do_test fkey5-5.3 {
db eval {
PRAGMA foreign_key_check(c7);
}
} {c7 1 p3 0 c7 3 p3 0 c7 4 p3 0 c7 6 p3 0}
do_test fkey5-5.4 {
db eval {
INSERT INTO c11 SELECT x FROM c7;
DELETE FROM c7;
PRAGMA foreign_key_check;
}
} {c11 1 p3 0 c11 3 p3 0 c11 4 p3 0 c11 6 p3 0}
do_test fkey5-5.5 {
db eval {
PRAGMA foreign_key_check(c11);
}
} {c11 1 p3 0 c11 3 p3 0 c11 4 p3 0 c11 6 p3 0}
do_test fkey5-6.0 {
db eval {
DELETE FROM c11;
INSERT INTO c4 VALUES(54),(55),(56);
PRAGMA foreign_key_check;
}
} {c4 54 p4 0 c4 56 p4 0}
do_test fkey5-6.1 {
db eval {
PRAGMA foreign_key_check(c4);
}
} {c4 54 p4 0 c4 56 p4 0}
do_test fkey5-6.2 {
db eval {
INSERT INTO c8 SELECT x FROM c4;
INSERT INTO c8 VALUES('Alpha'),('ALPHA'),('foxtrot');
DELETE FROM c4;
PRAGMA foreign_key_check;
}
} {c8 1 p4 0 c8 3 p4 0 c8 6 p4 0}
do_test fkey5-6.3 {
db eval {
PRAGMA foreign_key_check(c8);
}
} {c8 1 p4 0 c8 3 p4 0 c8 6 p4 0}
do_test fkey5-6.4 {
db eval {
INSERT INTO c12 SELECT x FROM c8;
DELETE FROM c8;
PRAGMA foreign_key_check;
}
} {c12 1 p4 0 c12 3 p4 0 c12 6 p4 0}
do_test fkey5-6.5 {
db eval {
PRAGMA foreign_key_check(c12);
}
} {c12 1 p4 0 c12 3 p4 0 c12 6 p4 0}
do_test fkey5-7.1 {
db eval {
INSERT OR IGNORE INTO c13 SELECT * FROM c12;
INSERT OR IGNORE INTO C14 SELECT * FROM c12;
DELETE FROM c12;
PRAGMA foreign_key_check;
}
} {c14 1 p4 0 c14 3 p4 0 c14 6 p4 0 c13 1 p3 0 c13 2 p3 0 c13 3 p3 0 c13 4 p3 0 c13 5 p3 0 c13 6 p3 0}
do_test fkey5-7.2 {
db eval {
PRAGMA foreign_key_check(c14);
}
} {c14 1 p4 0 c14 3 p4 0 c14 6 p4 0}
do_test fkey5-7.3 {
db eval {
PRAGMA foreign_key_check(c13);
}
} {c13 1 p3 0 c13 2 p3 0 c13 3 p3 0 c13 4 p3 0 c13 5 p3 0 c13 6 p3 0}
do_test fkey5-8.0 {
db eval {
DELETE FROM c13;
DELETE FROM c14;
INSERT INTO c19 VALUES('alpha','abc');
PRAGMA foreign_key_check(c19);
}
} {c19 1 p5 0}
do_test fkey5-8.1 {
db eval {
DELETE FROM c19;
INSERT INTO c19 VALUES('Alpha','abc');
PRAGMA foreign_key_check(c19);
}
} {}
do_test fkey5-8.2 {
db eval {
INSERT INTO c20 VALUES('Alpha','abc');
PRAGMA foreign_key_check(c20);
}
} {c20 1 p5 0}
do_test fkey5-8.3 {
db eval {
DELETE FROM c20;
INSERT INTO c20 VALUES('abc','Alpha');
PRAGMA foreign_key_check(c20);
}
} {}
do_test fkey5-8.4 {
db eval {
INSERT INTO c21 VALUES('alpha','abc ');
PRAGMA foreign_key_check(c21);
}
} {}
do_test fkey5-8.5 {
db eval {
DELETE FROM c21;
INSERT INTO c19 VALUES('Alpha','abc');
PRAGMA foreign_key_check(c21);
}
} {}
do_test fkey5-8.6 {
db eval {
INSERT INTO c22 VALUES('Alpha','abc');
PRAGMA foreign_key_check(c22);
}
} {c22 1 p6 0}
do_test fkey5-8.7 {
db eval {
DELETE FROM c22;
INSERT INTO c22 VALUES('abc ','ALPHA');
PRAGMA foreign_key_check(c22);
}
} {}
finish_test

View File

@@ -29,6 +29,7 @@ do_malloc_test fkey_malloc-1 -sqlprep {
INSERT INTO t2 VALUES('aaa'); INSERT INTO t2 VALUES('aaa');
UPDATE t1 SET a = 'bbb'; UPDATE t1 SET a = 'bbb';
DELETE FROM t1; DELETE FROM t1;
PRAGMA foreign_key_check;
} }
do_malloc_test fkey_malloc-2 -sqlprep { do_malloc_test fkey_malloc-2 -sqlprep {
@@ -128,5 +129,3 @@ do_malloc_test fkey_malloc-7 -sqlprep {
} }
finish_test finish_test

View File

@@ -534,12 +534,20 @@ do_test pragma-6.2.2 {
b DEFAULT (5+3), b DEFAULT (5+3),
c TEXT, c TEXT,
d INTEGER DEFAULT NULL, d INTEGER DEFAULT NULL,
e TEXT DEFAULT '' e TEXT DEFAULT '',
UNIQUE(b,c,d),
PRIMARY KEY(e,b,c)
); );
PRAGMA table_info(t5); PRAGMA table_info(t5);
} }
} {0 a TEXT 0 CURRENT_TIMESTAMP 0 1 b {} 0 5+3 0 2 c TEXT 0 <<NULL>> 0 3 d INTEGER 0 NULL 0 4 e TEXT 0 '' 0} } {0 a TEXT 0 CURRENT_TIMESTAMP 0 1 b {} 0 5+3 2 2 c TEXT 0 <<NULL>> 3 3 d INTEGER 0 NULL 0 4 e TEXT 0 '' 1}
db nullvalue {} db nullvalue {}
do_test pragma-6.2.3 {
execsql {
CREATE TABLE t2_3(a,b INTEGER PRIMARY KEY,c);
pragma table_info(t2_3)
}
} {0 a {} 0 {} 0 1 b INTEGER 0 {} 1 2 c {} 0 {} 0}
ifcapable {foreignkey} { ifcapable {foreignkey} {
do_test pragma-6.3.1 { do_test pragma-6.3.1 {
execsql { execsql {
@@ -1619,5 +1627,3 @@ do_test 22.4.3 {
} {ok} } {ok}
finish_test finish_test

211
test/regexp1.test Normal file
View File

@@ -0,0 +1,211 @@
# 2012 December 31
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
#
# This file implements test for the REGEXP operator in test_regexp.c.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
do_test regexp1-1.1 {
sqlite3_add_regexp_func db
db eval {
CREATE TABLE t1(x INTEGER PRIMARY KEY, y TEXT);
INSERT INTO t1 VALUES(1, 'For since by man came death,');
INSERT INTO t1 VALUES(2, 'by man came also the resurrection of the dead.');
INSERT INTO t1 VALUES(3, 'For as in Adam all die,');
INSERT INTO t1 VALUES(4, 'even so in Christ shall all be made alive.');
SELECT x FROM t1 WHERE y REGEXP '^For ' ORDER BY x;
}
} {1 3}
do_execsql_test regexp1-1.2 {
SELECT x FROM t1 WHERE y REGEXP 'by|in' ORDER BY x;
} {1 2 3 4}
do_execsql_test regexp1-1.3 {
SELECT x FROM t1 WHERE y REGEXP 'by|Christ' ORDER BY x;
} {1 2 4}
do_execsql_test regexp1-1.4 {
SELECT x FROM t1 WHERE y REGEXP 'shal+ al+' ORDER BY x;
} {4}
do_execsql_test regexp1-1.5 {
SELECT x FROM t1 WHERE y REGEXP 'shall x*y*z*all' ORDER BY x;
} {4}
do_execsql_test regexp1-1.6 {
SELECT x FROM t1 WHERE y REGEXP 'shallx?y? ?z?all' ORDER BY x;
} {4}
do_execsql_test regexp1-1.7 {
SELECT x FROM t1 WHERE y REGEXP 'r{2}' ORDER BY x;
} {2}
do_execsql_test regexp1-1.8 {
SELECT x FROM t1 WHERE y REGEXP 'r{3}' ORDER BY x;
} {}
do_execsql_test regexp1-1.9 {
SELECT x FROM t1 WHERE y REGEXP 'r{1}' ORDER BY x;
} {1 2 3 4}
do_execsql_test regexp1-1.10 {
SELECT x FROM t1 WHERE y REGEXP 'ur{2,10}e' ORDER BY x;
} {2}
do_execsql_test regexp1-1.11 {
SELECT x FROM t1 WHERE y REGEXP '[Aa]dam' ORDER BY x;
} {3}
do_execsql_test regexp1-1.12 {
SELECT x FROM t1 WHERE y REGEXP '[^Aa]dam' ORDER BY x;
} {}
do_execsql_test regexp1-1.13 {
SELECT x FROM t1 WHERE y REGEXP '[^b-zB-Z]dam' ORDER BY x;
} {3}
do_execsql_test regexp1-1.14 {
SELECT x FROM t1 WHERE y REGEXP 'alive' ORDER BY x;
} {4}
do_execsql_test regexp1-1.15 {
SELECT x FROM t1 WHERE y REGEXP '^alive' ORDER BY x;
} {}
do_execsql_test regexp1-1.16 {
SELECT x FROM t1 WHERE y REGEXP 'alive$' ORDER BY x;
} {}
do_execsql_test regexp1-1.17 {
SELECT x FROM t1 WHERE y REGEXP 'alive.$' ORDER BY x;
} {4}
do_execsql_test regexp1-1.18 {
SELECT x FROM t1 WHERE y REGEXP 'alive\.$' ORDER BY x;
} {4}
do_execsql_test regexp1-1.19 {
SELECT x FROM t1 WHERE y REGEXP 'ma[nd]' ORDER BY x;
} {1 2 4}
do_execsql_test regexp1-1.20 {
SELECT x FROM t1 WHERE y REGEXP '\bma[nd]' ORDER BY x;
} {1 2 4}
do_execsql_test regexp1-1.21 {
SELECT x FROM t1 WHERE y REGEXP 'ma[nd]\b' ORDER BY x;
} {1 2}
do_execsql_test regexp1-1.22 {
SELECT x FROM t1 WHERE y REGEXP 'ma\w' ORDER BY x;
} {1 2 4}
do_execsql_test regexp1-1.23 {
SELECT x FROM t1 WHERE y REGEXP 'ma\W' ORDER BY x;
} {}
do_execsql_test regexp1-1.24 {
SELECT x FROM t1 WHERE y REGEXP '\sma\w' ORDER BY x;
} {1 2 4}
do_execsql_test regexp1-1.25 {
SELECT x FROM t1 WHERE y REGEXP '\Sma\w' ORDER BY x;
} {}
do_execsql_test regexp1-1.26 {
SELECT x FROM t1 WHERE y REGEXP 'alive\S$' ORDER BY x;
} {4}
do_execsql_test regexp1-1.27 {
SELECT x FROM t1 WHERE y REGEXP
'\b(unto|us|son|given|his|name|called|' ||
'wonderful|councelor|mighty|god|everlasting|father|' ||
'prince|peace|alive)\b';
} {4}
do_execsql_test regexp1-2.1 {
SELECT 'aaaabbbbcccc' REGEXP 'ab*c',
'aaaacccc' REGEXP 'ab*c';
} {1 1}
do_execsql_test regexp1-2.2 {
SELECT 'aaaabbbbcccc' REGEXP 'ab+c',
'aaaacccc' REGEXP 'ab+c';
} {1 0}
do_execsql_test regexp1-2.3 {
SELECT 'aaaabbbbcccc' REGEXP 'ab?c',
'aaaacccc' REGEXP 'ab?c';
} {0 1}
do_execsql_test regexp1-2.4 {
SELECT 'aaaabbbbbbcccc' REGEXP 'ab{3,5}c',
'aaaabbbbbcccc' REGEXP 'ab{3,5}c',
'aaaabbbbcccc' REGEXP 'ab{3,5}c',
'aaaabbbcccc' REGEXP 'ab{3,5}c',
'aaaabbcccc' REGEXP 'ab{3,5}c',
'aaaabcccc' REGEXP 'ab{3,5}c'
} {0 1 1 1 0 0}
do_execsql_test regexp1-2.5 {
SELECT 'aaaabbbbcccc' REGEXP 'a(a|b|c)+c',
'aaaabbbbcccc' REGEXP '^a(a|b|c){11}c$',
'aaaabbbbcccc' REGEXP '^a(a|b|c){10}c$',
'aaaabbbbcccc' REGEXP '^a(a|b|c){9}c$'
} {1 0 1 0}
do_execsql_test regexp1-2.6 {
SELECT 'aaaabbbbcccc' REGEXP '^a(a|bb|c)+c$',
'aaaabbbbcccc' REGEXP '^a(a|bbb|c)+c$',
'aaaabbbbcccc' REGEXP '^a(a|bbbb|c)+c$'
} {1 0 1}
do_execsql_test regexp1-2.7 {
SELECT 'aaaabbbbcccc' REGEXP '^a([ac]+|bb){3}c$',
'aaaabbbbcccc' REGEXP '^a([ac]+|bb){4}c$',
'aaaabbbbcccc' REGEXP '^a([ac]+|bb){5}c$'
} {0 1 1}
do_execsql_test regexp1-2.8 {
SELECT 'abc*def+ghi.jkl[mno]pqr' REGEXP 'c.d',
'abc*def+ghi.jkl[mno]pqr' REGEXP 'c\*d',
'abc*def+ghi.jkl[mno]pqr' REGEXP 'f\+g',
'abc*def+ghi.jkl[mno]pqr' REGEXP 'i\.j',
'abc*def+ghi.jkl[mno]pqr' REGEXP 'l\[mno\]p'
} {1 1 1 1 1}
do_test regexp1-2.9 {
set v1 "abc\ndef"
db eval {SELECT $v1 REGEXP '^abc\ndef$'}
} {1}
do_test regexp1-2.10 {
set v1 "abc\adef"
db eval {SELECT $v1 REGEXP '^abc\adef$'}
} {1}
do_test regexp1-2.11 {
set v1 "abc\tdef"
db eval {SELECT $v1 REGEXP '^abc\tdef$'}
} {1}
do_test regexp1-2.12 {
set v1 "abc\rdef"
db eval {SELECT $v1 REGEXP '^abc\rdef$'}
} {1}
do_test regexp1-2.13 {
set v1 "abc\fdef"
db eval {SELECT $v1 REGEXP '^abc\fdef$'}
} {1}
do_test regexp1-2.14 {
set v1 "abc\vdef"
db eval {SELECT $v1 REGEXP '^abc\vdef$'}
} {1}
do_execsql_test regexp1-2.15 {
SELECT 'abc\def' REGEXP '^abc\\def',
'abc(def' REGEXP '^abc\(def',
'abc)def' REGEXP '^abc\)def',
'abc*def' REGEXP '^abc\*def',
'abc.def' REGEXP '^abc\.def',
'abc+def' REGEXP '^abc\+def',
'abc?def' REGEXP '^abc\?def',
'abc[def' REGEXP '^abc\[def',
'abc$def' REGEXP '^abc\$',
'^def' REGEXP '\^def',
'abc{4}x' REGEXP '^abc\{4\}x$',
'abc|def' REGEXP '^abc\|def$'
} {1 1 1 1 1 1 1 1 1 1 1 1}
do_execsql_test regexp1-2.20 {
SELECT 'abc$¢€xyz' REGEXP '^abc\u0024\u00a2\u20acxyz$',
'abc$¢€xyz' REGEXP '^abc\u0024\u00A2\u20ACxyz$',
'abc$¢€xyz' REGEXP '^abc\x24\xa2\x20acxyz$'
} {1 1 1}
do_execsql_test regexp1-2.21 {
SELECT 'abc$¢€xyz' REGEXP '^abc[\u0024][\u00a2][\u20ac]xyz$',
'abc$¢€xyz' REGEXP '^abc[\u0024\u00A2\u20AC]{3}xyz$',
'abc$¢€xyz' REGEXP '^abc[\x24][\xa2\x20ac]+xyz$'
} {1 1 1}
do_execsql_test regexp1-2.22 {
SELECT 'abc$¢€xyz' REGEXP '^abc[^\u0025-X][^ -\u007f][^\u20ab]xyz$'
} {1}
finish_test

84
test/tkt-a7b7803e.test Normal file
View File

@@ -0,0 +1,84 @@
# 2012 December 19
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library. Specifically,
# it tests that ticket [a7b7803e8d1e8699cd8a460a38133b98892d2e17] has
# been fixed.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/lock_common.tcl
source $testdir/malloc_common.tcl
do_test tkt-a7b7803e.1 {
db eval {
CREATE TABLE t1(a,b);
INSERT INTO t1 VALUES(0,'first'),(99,'fuzzy');
SELECT (t1.a==0) AS x, b
FROM t1
WHERE a=0 OR x;
}
} {1 first}
do_test tkt-a7b7803e.2 {
db eval {
SELECT a, (t1.b='fuzzy') AS x
FROM t1
WHERE x
}
} {99 1}
do_test tkt-a7b7803e.3 {
db eval {
SELECT (a=99) AS x, (t1.b='fuzzy') AS y, *
FROM t1
WHERE x AND y
}
} {1 1 99 fuzzy}
do_test tkt-a7b7803e.4 {
db eval {
SELECT (a=99) AS x, (t1.b='first') AS y, *
FROM t1
WHERE x OR y
ORDER BY a
}
} {0 1 0 first 1 0 99 fuzzy}
do_test tkt-a7b7803e.5 {
db eval {
SELECT (M.a=99) AS x, M.b, (N.b='first') AS y, N.b
FROM t1 M, t1 N
WHERE x OR y
ORDER BY M.a, N.a
}
} {0 first 1 first 1 fuzzy 1 first 1 fuzzy 0 fuzzy}
do_test tkt-a7b7803e.6 {
db eval {
SELECT (M.a=99) AS x, M.b, (N.b='first') AS y, N.b
FROM t1 M, t1 N
WHERE x AND y
ORDER BY M.a, N.a
}
} {1 fuzzy 1 first}
do_test tkt-a7b7803e.7 {
db eval {
SELECT (M.a=99) AS x, M.b, (N.b='first') AS y, N.b
FROM t1 M JOIN t1 N ON x AND y
ORDER BY M.a, N.a
}
} {1 fuzzy 1 first}
do_test tkt-a7b7803e.8 {
db eval {
SELECT (M.a=99) AS x, M.b, (N.b='first') AS y, N.b
FROM t1 M JOIN t1 N ON x
ORDER BY M.a, N.a
}
} {1 fuzzy 1 first 1 fuzzy 0 fuzzy}
finish_test

View File

@@ -15,7 +15,9 @@ gcc -o sqlite3 -g -Os -I. \
-DSQLITE_ENABLE_STAT3 \ -DSQLITE_ENABLE_STAT3 \
-DSQLITE_ENABLE_FTS4 \ -DSQLITE_ENABLE_FTS4 \
-DSQLITE_ENABLE_RTREE \ -DSQLITE_ENABLE_RTREE \
-DSQLITE_ENABLE_REGEXP \
-DHAVE_READLINE \ -DHAVE_READLINE \
-DHAVE_USLEEP=1 \ -DHAVE_USLEEP=1 \
../sqlite/src/shell.c ../sqlite/src/test_vfstrace.c \ ../sqlite/src/shell.c ../sqlite/src/test_vfstrace.c \
../sqlite/src/test_regexp.c \
sqlite3.c -ldl -lreadline -lncurses sqlite3.c -ldl -lreadline -lncurses