1
0

fkey2.test 60 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017
  1. # 2009 September 15
  2. #
  3. # The author disclaims copyright to this source code. In place of
  4. # a legal notice, here is a blessing:
  5. #
  6. # May you do good and not evil.
  7. # May you find forgiveness for yourself and forgive others.
  8. # May you share freely, never taking more than you give.
  9. #
  10. #***********************************************************************
  11. # This file implements regression tests for SQLite library.
  12. #
  13. # This file implements tests for foreign keys.
  14. #
  15. set testdir [file dirname $argv0]
  16. source $testdir/tester.tcl
  17. ifcapable {!foreignkey||!trigger} {
  18. finish_test
  19. return
  20. }
  21. #-------------------------------------------------------------------------
  22. # Test structure:
  23. #
  24. # fkey2-1.*: Simple tests to check that immediate and deferred foreign key
  25. # constraints work when not inside a transaction.
  26. #
  27. # fkey2-2.*: Tests to verify that deferred foreign keys work inside
  28. # explicit transactions (i.e that processing really is deferred).
  29. #
  30. # fkey2-3.*: Tests that a statement transaction is rolled back if an
  31. # immediate foreign key constraint is violated.
  32. #
  33. # fkey2-4.*: Test that FK actions may recurse even when recursive triggers
  34. # are disabled.
  35. #
  36. # fkey2-5.*: Check that if foreign-keys are enabled, it is not possible
  37. # to write to an FK column using the incremental blob API.
  38. #
  39. # fkey2-6.*: Test that FK processing is automatically disabled when
  40. # running VACUUM.
  41. #
  42. # fkey2-7.*: Test using an IPK as the key in the child (referencing) table.
  43. #
  44. # fkey2-8.*: Test that enabling/disabling foreign key support while a
  45. # transaction is active is not possible.
  46. #
  47. # fkey2-9.*: Test SET DEFAULT actions.
  48. #
  49. # fkey2-10.*: Test errors.
  50. #
  51. # fkey2-11.*: Test CASCADE actions.
  52. #
  53. # fkey2-12.*: Test RESTRICT actions.
  54. #
  55. # fkey2-13.*: Test that FK processing is performed when a row is REPLACED by
  56. # an UPDATE or INSERT statement.
  57. #
  58. # fkey2-14.*: Test the ALTER TABLE and DROP TABLE commands.
  59. #
  60. # fkey2-15.*: Test that if there are no (known) outstanding foreign key
  61. # constraint violations in the database, inserting into a parent
  62. # table or deleting from a child table does not cause SQLite
  63. # to check if this has repaired an outstanding violation.
  64. #
  65. # fkey2-16.*: Test that rows that refer to themselves may be inserted,
  66. # updated and deleted.
  67. #
  68. # fkey2-17.*: Test that the "count_changes" pragma does not interfere with
  69. # FK constraint processing.
  70. #
  71. # fkey2-18.*: Test that the authorization callback is invoked when processing
  72. # FK constraints.
  73. #
  74. # fkey2-20.*: Test that ON CONFLICT clauses specified as part of statements
  75. # do not affect the operation of FK constraints.
  76. #
  77. # fkey2-genfkey.*: Tests that were used with the shell tool .genfkey
  78. # command. Recycled to test the built-in implementation.
  79. #
  80. # fkey2-dd08e5.*: Tests to verify that ticket dd08e5a988d00decc4a543daa8d
  81. # has been fixed.
  82. #
  83. execsql { PRAGMA foreign_keys = on }
  84. set FkeySimpleSchema {
  85. PRAGMA foreign_keys = on;
  86. CREATE TABLE t1(a PRIMARY KEY, b);
  87. CREATE TABLE t2(c REFERENCES t1(a) /D/ , d);
  88. CREATE TABLE t3(a PRIMARY KEY, b);
  89. CREATE TABLE t4(c REFERENCES t3 /D/, d);
  90. CREATE TABLE t7(a, b INTEGER PRIMARY KEY);
  91. CREATE TABLE t8(c REFERENCES t7 /D/, d);
  92. CREATE TABLE t9(a REFERENCES nosuchtable, b);
  93. CREATE TABLE t10(a REFERENCES t9(c) /D/, b);
  94. }
  95. set FkeySimpleTests {
  96. 1.1 "INSERT INTO t2 VALUES(1, 3)" {1 {foreign key constraint failed}}
  97. 1.2 "INSERT INTO t1 VALUES(1, 2)" {0 {}}
  98. 1.3 "INSERT INTO t2 VALUES(1, 3)" {0 {}}
  99. 1.4 "INSERT INTO t2 VALUES(2, 4)" {1 {foreign key constraint failed}}
  100. 1.5 "INSERT INTO t2 VALUES(NULL, 4)" {0 {}}
  101. 1.6 "UPDATE t2 SET c=2 WHERE d=4" {1 {foreign key constraint failed}}
  102. 1.7 "UPDATE t2 SET c=1 WHERE d=4" {0 {}}
  103. 1.9 "UPDATE t2 SET c=1 WHERE d=4" {0 {}}
  104. 1.10 "UPDATE t2 SET c=NULL WHERE d=4" {0 {}}
  105. 1.11 "DELETE FROM t1 WHERE a=1" {1 {foreign key constraint failed}}
  106. 1.12 "UPDATE t1 SET a = 2" {1 {foreign key constraint failed}}
  107. 1.13 "UPDATE t1 SET a = 1" {0 {}}
  108. 2.1 "INSERT INTO t4 VALUES(1, 3)" {1 {foreign key constraint failed}}
  109. 2.2 "INSERT INTO t3 VALUES(1, 2)" {0 {}}
  110. 2.3 "INSERT INTO t4 VALUES(1, 3)" {0 {}}
  111. 4.1 "INSERT INTO t8 VALUES(1, 3)" {1 {foreign key constraint failed}}
  112. 4.2 "INSERT INTO t7 VALUES(2, 1)" {0 {}}
  113. 4.3 "INSERT INTO t8 VALUES(1, 3)" {0 {}}
  114. 4.4 "INSERT INTO t8 VALUES(2, 4)" {1 {foreign key constraint failed}}
  115. 4.5 "INSERT INTO t8 VALUES(NULL, 4)" {0 {}}
  116. 4.6 "UPDATE t8 SET c=2 WHERE d=4" {1 {foreign key constraint failed}}
  117. 4.7 "UPDATE t8 SET c=1 WHERE d=4" {0 {}}
  118. 4.9 "UPDATE t8 SET c=1 WHERE d=4" {0 {}}
  119. 4.10 "UPDATE t8 SET c=NULL WHERE d=4" {0 {}}
  120. 4.11 "DELETE FROM t7 WHERE b=1" {1 {foreign key constraint failed}}
  121. 4.12 "UPDATE t7 SET b = 2" {1 {foreign key constraint failed}}
  122. 4.13 "UPDATE t7 SET b = 1" {0 {}}
  123. 4.14 "INSERT INTO t8 VALUES('a', 'b')" {1 {foreign key constraint failed}}
  124. 4.15 "UPDATE t7 SET b = 5" {1 {foreign key constraint failed}}
  125. 4.16 "UPDATE t7 SET rowid = 5" {1 {foreign key constraint failed}}
  126. 4.17 "UPDATE t7 SET a = 10" {0 {}}
  127. 5.1 "INSERT INTO t9 VALUES(1, 3)" {1 {no such table: main.nosuchtable}}
  128. 5.2 "INSERT INTO t10 VALUES(1, 3)"
  129. {1 {foreign key mismatch - "t10" referencing "t9"}}
  130. }
  131. do_test fkey2-1.1.0 {
  132. execsql [string map {/D/ {}} $FkeySimpleSchema]
  133. } {}
  134. foreach {tn zSql res} $FkeySimpleTests {
  135. do_test fkey2-1.1.$tn.1 { catchsql $zSql } $res
  136. do_test fkey2-1.1.$tn.2 { execsql {PRAGMA foreign_key_check(t1)} } {}
  137. do_test fkey2-1.1.$tn.3 { execsql {PRAGMA foreign_key_check(t2)} } {}
  138. do_test fkey2-1.1.$tn.4 { execsql {PRAGMA foreign_key_check(t3)} } {}
  139. do_test fkey2-1.1.$tn.5 { execsql {PRAGMA foreign_key_check(t4)} } {}
  140. do_test fkey2-1.1.$tn.6 { execsql {PRAGMA foreign_key_check(t7)} } {}
  141. do_test fkey2-1.1.$tn.7 { execsql {PRAGMA foreign_key_check(t8)} } {}
  142. }
  143. drop_all_tables
  144. do_test fkey2-1.2.0 {
  145. execsql [string map {/D/ {DEFERRABLE INITIALLY DEFERRED}} $FkeySimpleSchema]
  146. } {}
  147. foreach {tn zSql res} $FkeySimpleTests {
  148. do_test fkey2-1.2.$tn { catchsql $zSql } $res
  149. do_test fkey2-1.2.$tn.2 { execsql {PRAGMA foreign_key_check(t1)} } {}
  150. do_test fkey2-1.2.$tn.3 { execsql {PRAGMA foreign_key_check(t2)} } {}
  151. do_test fkey2-1.2.$tn.4 { execsql {PRAGMA foreign_key_check(t3)} } {}
  152. do_test fkey2-1.2.$tn.5 { execsql {PRAGMA foreign_key_check(t4)} } {}
  153. do_test fkey2-1.2.$tn.6 { execsql {PRAGMA foreign_key_check(t7)} } {}
  154. do_test fkey2-1.2.$tn.7 { execsql {PRAGMA foreign_key_check(t8)} } {}
  155. }
  156. drop_all_tables
  157. do_test fkey2-1.3.0 {
  158. execsql [string map {/D/ {}} $FkeySimpleSchema]
  159. execsql { PRAGMA count_changes = 1 }
  160. } {}
  161. foreach {tn zSql res} $FkeySimpleTests {
  162. if {$res == "0 {}"} { set res {0 1} }
  163. do_test fkey2-1.3.$tn { catchsql $zSql } $res
  164. do_test fkey2-1.3.$tn.2 { execsql {PRAGMA foreign_key_check(t1)} } {}
  165. do_test fkey2-1.3.$tn.3 { execsql {PRAGMA foreign_key_check(t2)} } {}
  166. do_test fkey2-1.3.$tn.4 { execsql {PRAGMA foreign_key_check(t3)} } {}
  167. do_test fkey2-1.3.$tn.5 { execsql {PRAGMA foreign_key_check(t4)} } {}
  168. do_test fkey2-1.3.$tn.6 { execsql {PRAGMA foreign_key_check(t7)} } {}
  169. do_test fkey2-1.3.$tn.7 { execsql {PRAGMA foreign_key_check(t8)} } {}
  170. }
  171. execsql { PRAGMA count_changes = 0 }
  172. drop_all_tables
  173. do_test fkey2-1.4.0 {
  174. execsql [string map {/D/ {}} $FkeySimpleSchema]
  175. execsql { PRAGMA count_changes = 1 }
  176. } {}
  177. foreach {tn zSql res} $FkeySimpleTests {
  178. if {$res == "0 {}"} { set res {0 1} }
  179. execsql BEGIN
  180. do_test fkey2-1.4.$tn { catchsql $zSql } $res
  181. execsql COMMIT
  182. }
  183. execsql { PRAGMA count_changes = 0 }
  184. drop_all_tables
  185. # Special test: When the parent key is an IPK, make sure the affinity of
  186. # the IPK is not applied to the child key value before it is inserted
  187. # into the child table.
  188. do_test fkey2-1.5.1 {
  189. execsql {
  190. CREATE TABLE i(i INTEGER PRIMARY KEY);
  191. CREATE TABLE j(j REFERENCES i);
  192. INSERT INTO i VALUES(35);
  193. INSERT INTO j VALUES('35.0');
  194. SELECT j, typeof(j) FROM j;
  195. }
  196. } {35.0 text}
  197. do_test fkey2-1.5.2 {
  198. catchsql { DELETE FROM i }
  199. } {1 {foreign key constraint failed}}
  200. # Same test using a regular primary key with integer affinity.
  201. drop_all_tables
  202. do_test fkey2-1.6.1 {
  203. execsql {
  204. CREATE TABLE i(i INT UNIQUE);
  205. CREATE TABLE j(j REFERENCES i(i));
  206. INSERT INTO i VALUES('35.0');
  207. INSERT INTO j VALUES('35.0');
  208. SELECT j, typeof(j) FROM j;
  209. SELECT i, typeof(i) FROM i;
  210. }
  211. } {35.0 text 35 integer}
  212. do_test fkey2-1.6.2 {
  213. catchsql { DELETE FROM i }
  214. } {1 {foreign key constraint failed}}
  215. # Use a collation sequence on the parent key.
  216. drop_all_tables
  217. do_test fkey2-1.7.1 {
  218. execsql {
  219. CREATE TABLE i(i TEXT COLLATE nocase PRIMARY KEY);
  220. CREATE TABLE j(j TEXT COLLATE binary REFERENCES i(i));
  221. INSERT INTO i VALUES('SQLite');
  222. INSERT INTO j VALUES('sqlite');
  223. }
  224. catchsql { DELETE FROM i }
  225. } {1 {foreign key constraint failed}}
  226. # Use the parent key collation even if it is default and the child key
  227. # has an explicit value.
  228. drop_all_tables
  229. do_test fkey2-1.7.2 {
  230. execsql {
  231. CREATE TABLE i(i TEXT PRIMARY KEY); -- Colseq is "BINARY"
  232. CREATE TABLE j(j TEXT COLLATE nocase REFERENCES i(i));
  233. INSERT INTO i VALUES('SQLite');
  234. }
  235. catchsql { INSERT INTO j VALUES('sqlite') }
  236. } {1 {foreign key constraint failed}}
  237. do_test fkey2-1.7.3 {
  238. execsql {
  239. INSERT INTO i VALUES('sqlite');
  240. INSERT INTO j VALUES('sqlite');
  241. DELETE FROM i WHERE i = 'SQLite';
  242. }
  243. catchsql { DELETE FROM i WHERE i = 'sqlite' }
  244. } {1 {foreign key constraint failed}}
  245. #-------------------------------------------------------------------------
  246. # This section (test cases fkey2-2.*) contains tests to check that the
  247. # deferred foreign key constraint logic works.
  248. #
  249. proc fkey2-2-test {tn nocommit sql {res {}}} {
  250. if {$res eq "FKV"} {
  251. set expected {1 {foreign key constraint failed}}
  252. } else {
  253. set expected [list 0 $res]
  254. }
  255. do_test fkey2-2.$tn [list catchsql $sql] $expected
  256. if {$nocommit} {
  257. do_test fkey2-2.${tn}c {
  258. catchsql COMMIT
  259. } {1 {foreign key constraint failed}}
  260. }
  261. }
  262. fkey2-2-test 1 0 {
  263. CREATE TABLE node(
  264. nodeid PRIMARY KEY,
  265. parent REFERENCES node DEFERRABLE INITIALLY DEFERRED
  266. );
  267. CREATE TABLE leaf(
  268. cellid PRIMARY KEY,
  269. parent REFERENCES node DEFERRABLE INITIALLY DEFERRED
  270. );
  271. }
  272. fkey2-2-test 1 0 "INSERT INTO node VALUES(1, 0)" FKV
  273. fkey2-2-test 2 0 "BEGIN"
  274. fkey2-2-test 3 1 "INSERT INTO node VALUES(1, 0)"
  275. fkey2-2-test 4 0 "UPDATE node SET parent = NULL"
  276. fkey2-2-test 5 0 "COMMIT"
  277. fkey2-2-test 6 0 "SELECT * FROM node" {1 {}}
  278. fkey2-2-test 7 0 "BEGIN"
  279. fkey2-2-test 8 1 "INSERT INTO leaf VALUES('a', 2)"
  280. fkey2-2-test 9 1 "INSERT INTO node VALUES(2, 0)"
  281. fkey2-2-test 10 0 "UPDATE node SET parent = 1 WHERE nodeid = 2"
  282. fkey2-2-test 11 0 "COMMIT"
  283. fkey2-2-test 12 0 "SELECT * FROM node" {1 {} 2 1}
  284. fkey2-2-test 13 0 "SELECT * FROM leaf" {a 2}
  285. fkey2-2-test 14 0 "BEGIN"
  286. fkey2-2-test 15 1 "DELETE FROM node WHERE nodeid = 2"
  287. fkey2-2-test 16 0 "INSERT INTO node VALUES(2, NULL)"
  288. fkey2-2-test 17 0 "COMMIT"
  289. fkey2-2-test 18 0 "SELECT * FROM node" {1 {} 2 {}}
  290. fkey2-2-test 19 0 "SELECT * FROM leaf" {a 2}
  291. fkey2-2-test 20 0 "BEGIN"
  292. fkey2-2-test 21 0 "INSERT INTO leaf VALUES('b', 1)"
  293. fkey2-2-test 22 0 "SAVEPOINT save"
  294. fkey2-2-test 23 0 "DELETE FROM node WHERE nodeid = 1"
  295. fkey2-2-test 24 0 "ROLLBACK TO save"
  296. fkey2-2-test 25 0 "COMMIT"
  297. fkey2-2-test 26 0 "SELECT * FROM node" {1 {} 2 {}}
  298. fkey2-2-test 27 0 "SELECT * FROM leaf" {a 2 b 1}
  299. fkey2-2-test 28 0 "BEGIN"
  300. fkey2-2-test 29 0 "INSERT INTO leaf VALUES('c', 1)"
  301. fkey2-2-test 30 0 "SAVEPOINT save"
  302. fkey2-2-test 31 0 "DELETE FROM node WHERE nodeid = 1"
  303. fkey2-2-test 32 1 "RELEASE save"
  304. fkey2-2-test 33 1 "DELETE FROM leaf WHERE cellid = 'b'"
  305. fkey2-2-test 34 0 "DELETE FROM leaf WHERE cellid = 'c'"
  306. fkey2-2-test 35 0 "COMMIT"
  307. fkey2-2-test 36 0 "SELECT * FROM node" {2 {}}
  308. fkey2-2-test 37 0 "SELECT * FROM leaf" {a 2}
  309. fkey2-2-test 38 0 "SAVEPOINT outer"
  310. fkey2-2-test 39 1 "INSERT INTO leaf VALUES('d', 3)"
  311. fkey2-2-test 40 1 "RELEASE outer" FKV
  312. fkey2-2-test 41 1 "INSERT INTO leaf VALUES('e', 3)"
  313. fkey2-2-test 42 0 "INSERT INTO node VALUES(3, 2)"
  314. fkey2-2-test 43 0 "RELEASE outer"
  315. fkey2-2-test 44 0 "SAVEPOINT outer"
  316. fkey2-2-test 45 1 "DELETE FROM node WHERE nodeid=3"
  317. fkey2-2-test 47 0 "INSERT INTO node VALUES(3, 2)"
  318. fkey2-2-test 48 0 "ROLLBACK TO outer"
  319. fkey2-2-test 49 0 "RELEASE outer"
  320. fkey2-2-test 50 0 "SAVEPOINT outer"
  321. fkey2-2-test 51 1 "INSERT INTO leaf VALUES('f', 4)"
  322. fkey2-2-test 52 1 "SAVEPOINT inner"
  323. fkey2-2-test 53 1 "INSERT INTO leaf VALUES('g', 4)"
  324. fkey2-2-test 54 1 "RELEASE outer" FKV
  325. fkey2-2-test 55 1 "ROLLBACK TO inner"
  326. fkey2-2-test 56 0 "COMMIT" FKV
  327. fkey2-2-test 57 0 "INSERT INTO node VALUES(4, NULL)"
  328. fkey2-2-test 58 0 "RELEASE outer"
  329. fkey2-2-test 59 0 "SELECT * FROM node" {2 {} 3 2 4 {}}
  330. fkey2-2-test 60 0 "SELECT * FROM leaf" {a 2 d 3 e 3 f 4}
  331. # The following set of tests check that if a statement that affects
  332. # multiple rows violates some foreign key constraints, then strikes a
  333. # constraint that causes the statement-transaction to be rolled back,
  334. # the deferred constraint counter is correctly reset to the value it
  335. # had before the statement-transaction was opened.
  336. #
  337. fkey2-2-test 61 0 "BEGIN"
  338. fkey2-2-test 62 0 "DELETE FROM leaf"
  339. fkey2-2-test 63 0 "DELETE FROM node"
  340. fkey2-2-test 64 1 "INSERT INTO leaf VALUES('a', 1)"
  341. fkey2-2-test 65 1 "INSERT INTO leaf VALUES('b', 2)"
  342. fkey2-2-test 66 1 "INSERT INTO leaf VALUES('c', 1)"
  343. do_test fkey2-2-test-67 {
  344. catchsql "INSERT INTO node SELECT parent, 3 FROM leaf"
  345. } {1 {column nodeid is not unique}}
  346. fkey2-2-test 68 0 "COMMIT" FKV
  347. fkey2-2-test 69 1 "INSERT INTO node VALUES(1, NULL)"
  348. fkey2-2-test 70 0 "INSERT INTO node VALUES(2, NULL)"
  349. fkey2-2-test 71 0 "COMMIT"
  350. fkey2-2-test 72 0 "BEGIN"
  351. fkey2-2-test 73 1 "DELETE FROM node"
  352. fkey2-2-test 74 0 "INSERT INTO node(nodeid) SELECT DISTINCT parent FROM leaf"
  353. fkey2-2-test 75 0 "COMMIT"
  354. #-------------------------------------------------------------------------
  355. # Test cases fkey2-3.* test that a program that executes foreign key
  356. # actions (CASCADE, SET DEFAULT, SET NULL etc.) or tests FK constraints
  357. # opens a statement transaction if required.
  358. #
  359. # fkey2-3.1.*: Test UPDATE statements.
  360. # fkey2-3.2.*: Test DELETE statements.
  361. #
  362. drop_all_tables
  363. do_test fkey2-3.1.1 {
  364. execsql {
  365. CREATE TABLE ab(a PRIMARY KEY, b);
  366. CREATE TABLE cd(
  367. c PRIMARY KEY REFERENCES ab ON UPDATE CASCADE ON DELETE CASCADE,
  368. d
  369. );
  370. CREATE TABLE ef(
  371. e REFERENCES cd ON UPDATE CASCADE,
  372. f, CHECK (e!=5)
  373. );
  374. }
  375. } {}
  376. do_test fkey2-3.1.2 {
  377. execsql {
  378. INSERT INTO ab VALUES(1, 'b');
  379. INSERT INTO cd VALUES(1, 'd');
  380. INSERT INTO ef VALUES(1, 'e');
  381. }
  382. } {}
  383. do_test fkey2-3.1.3 {
  384. catchsql { UPDATE ab SET a = 5 }
  385. } {1 {constraint failed}}
  386. do_test fkey2-3.1.4 {
  387. execsql { SELECT * FROM ab }
  388. } {1 b}
  389. do_test fkey2-3.1.4 {
  390. execsql BEGIN;
  391. catchsql { UPDATE ab SET a = 5 }
  392. } {1 {constraint failed}}
  393. do_test fkey2-3.1.5 {
  394. execsql COMMIT;
  395. execsql { SELECT * FROM ab; SELECT * FROM cd; SELECT * FROM ef }
  396. } {1 b 1 d 1 e}
  397. do_test fkey2-3.2.1 {
  398. execsql BEGIN;
  399. catchsql { DELETE FROM ab }
  400. } {1 {foreign key constraint failed}}
  401. do_test fkey2-3.2.2 {
  402. execsql COMMIT
  403. execsql { SELECT * FROM ab; SELECT * FROM cd; SELECT * FROM ef }
  404. } {1 b 1 d 1 e}
  405. #-------------------------------------------------------------------------
  406. # Test cases fkey2-4.* test that recursive foreign key actions
  407. # (i.e. CASCADE) are allowed even if recursive triggers are disabled.
  408. #
  409. drop_all_tables
  410. do_test fkey2-4.1 {
  411. execsql {
  412. CREATE TABLE t1(
  413. node PRIMARY KEY,
  414. parent REFERENCES t1 ON DELETE CASCADE
  415. );
  416. CREATE TABLE t2(node PRIMARY KEY, parent);
  417. CREATE TRIGGER t2t AFTER DELETE ON t2 BEGIN
  418. DELETE FROM t2 WHERE parent = old.node;
  419. END;
  420. INSERT INTO t1 VALUES(1, NULL);
  421. INSERT INTO t1 VALUES(2, 1);
  422. INSERT INTO t1 VALUES(3, 1);
  423. INSERT INTO t1 VALUES(4, 2);
  424. INSERT INTO t1 VALUES(5, 2);
  425. INSERT INTO t1 VALUES(6, 3);
  426. INSERT INTO t1 VALUES(7, 3);
  427. INSERT INTO t2 SELECT * FROM t1;
  428. }
  429. } {}
  430. do_test fkey2-4.2 {
  431. execsql { PRAGMA recursive_triggers = off }
  432. execsql {
  433. BEGIN;
  434. DELETE FROM t1 WHERE node = 1;
  435. SELECT node FROM t1;
  436. }
  437. } {}
  438. do_test fkey2-4.3 {
  439. execsql {
  440. DELETE FROM t2 WHERE node = 1;
  441. SELECT node FROM t2;
  442. ROLLBACK;
  443. }
  444. } {4 5 6 7}
  445. do_test fkey2-4.4 {
  446. execsql { PRAGMA recursive_triggers = on }
  447. execsql {
  448. BEGIN;
  449. DELETE FROM t1 WHERE node = 1;
  450. SELECT node FROM t1;
  451. }
  452. } {}
  453. do_test fkey2-4.3 {
  454. execsql {
  455. DELETE FROM t2 WHERE node = 1;
  456. SELECT node FROM t2;
  457. ROLLBACK;
  458. }
  459. } {}
  460. #-------------------------------------------------------------------------
  461. # Test cases fkey2-5.* verify that the incremental blob API may not
  462. # write to a foreign key column while foreign-keys are enabled.
  463. #
  464. drop_all_tables
  465. ifcapable incrblob {
  466. do_test fkey2-5.1 {
  467. execsql {
  468. CREATE TABLE t1(a PRIMARY KEY, b);
  469. CREATE TABLE t2(a PRIMARY KEY, b REFERENCES t1(a));
  470. INSERT INTO t1 VALUES('hello', 'world');
  471. INSERT INTO t2 VALUES('key', 'hello');
  472. }
  473. } {}
  474. do_test fkey2-5.2 {
  475. set rc [catch { set fd [db incrblob t2 b 1] } msg]
  476. list $rc $msg
  477. } {1 {cannot open foreign key column for writing}}
  478. do_test fkey2-5.3 {
  479. set rc [catch { set fd [db incrblob -readonly t2 b 1] } msg]
  480. close $fd
  481. set rc
  482. } {0}
  483. do_test fkey2-5.4 {
  484. execsql { PRAGMA foreign_keys = off }
  485. set rc [catch { set fd [db incrblob t2 b 1] } msg]
  486. close $fd
  487. set rc
  488. } {0}
  489. do_test fkey2-5.5 {
  490. execsql { PRAGMA foreign_keys = on }
  491. } {}
  492. }
  493. drop_all_tables
  494. ifcapable vacuum {
  495. do_test fkey2-6.1 {
  496. execsql {
  497. CREATE TABLE t1(a REFERENCES t2(c), b);
  498. CREATE TABLE t2(c UNIQUE, b);
  499. INSERT INTO t2 VALUES(1, 2);
  500. INSERT INTO t1 VALUES(1, 2);
  501. VACUUM;
  502. }
  503. } {}
  504. }
  505. #-------------------------------------------------------------------------
  506. # Test that it is possible to use an INTEGER PRIMARY KEY as the child key
  507. # of a foreign constraint.
  508. #
  509. drop_all_tables
  510. do_test fkey2-7.1 {
  511. execsql {
  512. CREATE TABLE t1(a PRIMARY KEY, b);
  513. CREATE TABLE t2(c INTEGER PRIMARY KEY REFERENCES t1, b);
  514. }
  515. } {}
  516. do_test fkey2-7.2 {
  517. catchsql { INSERT INTO t2 VALUES(1, 'A'); }
  518. } {1 {foreign key constraint failed}}
  519. do_test fkey2-7.3 {
  520. execsql {
  521. INSERT INTO t1 VALUES(1, 2);
  522. INSERT INTO t1 VALUES(2, 3);
  523. INSERT INTO t2 VALUES(1, 'A');
  524. }
  525. } {}
  526. do_test fkey2-7.4 {
  527. execsql { UPDATE t2 SET c = 2 }
  528. } {}
  529. do_test fkey2-7.5 {
  530. catchsql { UPDATE t2 SET c = 3 }
  531. } {1 {foreign key constraint failed}}
  532. do_test fkey2-7.6 {
  533. catchsql { DELETE FROM t1 WHERE a = 2 }
  534. } {1 {foreign key constraint failed}}
  535. do_test fkey2-7.7 {
  536. execsql { DELETE FROM t1 WHERE a = 1 }
  537. } {}
  538. do_test fkey2-7.8 {
  539. catchsql { UPDATE t1 SET a = 3 }
  540. } {1 {foreign key constraint failed}}
  541. do_test fkey2-7.9 {
  542. catchsql { UPDATE t2 SET rowid = 3 }
  543. } {1 {foreign key constraint failed}}
  544. #-------------------------------------------------------------------------
  545. # Test that it is not possible to enable/disable FK support while a
  546. # transaction is open.
  547. #
  548. drop_all_tables
  549. proc fkey2-8-test {tn zSql value} {
  550. do_test fkey-2.8.$tn.1 [list execsql $zSql] {}
  551. do_test fkey-2.8.$tn.2 { execsql "PRAGMA foreign_keys" } $value
  552. }
  553. fkey2-8-test 1 { PRAGMA foreign_keys = 0 } 0
  554. fkey2-8-test 2 { PRAGMA foreign_keys = 1 } 1
  555. fkey2-8-test 3 { BEGIN } 1
  556. fkey2-8-test 4 { PRAGMA foreign_keys = 0 } 1
  557. fkey2-8-test 5 { COMMIT } 1
  558. fkey2-8-test 6 { PRAGMA foreign_keys = 0 } 0
  559. fkey2-8-test 7 { BEGIN } 0
  560. fkey2-8-test 8 { PRAGMA foreign_keys = 1 } 0
  561. fkey2-8-test 9 { COMMIT } 0
  562. fkey2-8-test 10 { PRAGMA foreign_keys = 1 } 1
  563. fkey2-8-test 11 { PRAGMA foreign_keys = off } 0
  564. fkey2-8-test 12 { PRAGMA foreign_keys = on } 1
  565. fkey2-8-test 13 { PRAGMA foreign_keys = no } 0
  566. fkey2-8-test 14 { PRAGMA foreign_keys = yes } 1
  567. fkey2-8-test 15 { PRAGMA foreign_keys = false } 0
  568. fkey2-8-test 16 { PRAGMA foreign_keys = true } 1
  569. #-------------------------------------------------------------------------
  570. # The following tests, fkey2-9.*, test SET DEFAULT actions.
  571. #
  572. drop_all_tables
  573. do_test fkey2-9.1.1 {
  574. execsql {
  575. CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
  576. CREATE TABLE t2(
  577. c INTEGER PRIMARY KEY,
  578. d INTEGER DEFAULT 1 REFERENCES t1 ON DELETE SET DEFAULT
  579. );
  580. DELETE FROM t1;
  581. }
  582. } {}
  583. do_test fkey2-9.1.2 {
  584. execsql {
  585. INSERT INTO t1 VALUES(1, 'one');
  586. INSERT INTO t1 VALUES(2, 'two');
  587. INSERT INTO t2 VALUES(1, 2);
  588. SELECT * FROM t2;
  589. DELETE FROM t1 WHERE a = 2;
  590. SELECT * FROM t2;
  591. }
  592. } {1 2 1 1}
  593. do_test fkey2-9.1.3 {
  594. execsql {
  595. INSERT INTO t1 VALUES(2, 'two');
  596. UPDATE t2 SET d = 2;
  597. DELETE FROM t1 WHERE a = 1;
  598. SELECT * FROM t2;
  599. }
  600. } {1 2}
  601. do_test fkey2-9.1.4 {
  602. execsql { SELECT * FROM t1 }
  603. } {2 two}
  604. do_test fkey2-9.1.5 {
  605. catchsql { DELETE FROM t1 }
  606. } {1 {foreign key constraint failed}}
  607. do_test fkey2-9.2.1 {
  608. execsql {
  609. CREATE TABLE pp(a, b, c, PRIMARY KEY(b, c));
  610. CREATE TABLE cc(d DEFAULT 3, e DEFAULT 1, f DEFAULT 2,
  611. FOREIGN KEY(f, d) REFERENCES pp
  612. ON UPDATE SET DEFAULT
  613. ON DELETE SET NULL
  614. );
  615. INSERT INTO pp VALUES(1, 2, 3);
  616. INSERT INTO pp VALUES(4, 5, 6);
  617. INSERT INTO pp VALUES(7, 8, 9);
  618. }
  619. } {}
  620. do_test fkey2-9.2.2 {
  621. execsql {
  622. INSERT INTO cc VALUES(6, 'A', 5);
  623. INSERT INTO cc VALUES(6, 'B', 5);
  624. INSERT INTO cc VALUES(9, 'A', 8);
  625. INSERT INTO cc VALUES(9, 'B', 8);
  626. UPDATE pp SET b = 1 WHERE a = 7;
  627. SELECT * FROM cc;
  628. }
  629. } {6 A 5 6 B 5 3 A 2 3 B 2}
  630. do_test fkey2-9.2.3 {
  631. execsql {
  632. DELETE FROM pp WHERE a = 4;
  633. SELECT * FROM cc;
  634. }
  635. } {{} A {} {} B {} 3 A 2 3 B 2}
  636. #-------------------------------------------------------------------------
  637. # The following tests, fkey2-10.*, test "foreign key mismatch" and
  638. # other errors.
  639. #
  640. set tn 0
  641. foreach zSql [list {
  642. CREATE TABLE p(a PRIMARY KEY, b);
  643. CREATE TABLE c(x REFERENCES p(c));
  644. } {
  645. CREATE TABLE c(x REFERENCES v(y));
  646. CREATE VIEW v AS SELECT x AS y FROM c;
  647. } {
  648. CREATE TABLE p(a, b, PRIMARY KEY(a, b));
  649. CREATE TABLE c(x REFERENCES p);
  650. } {
  651. CREATE TABLE p(a COLLATE binary, b);
  652. CREATE UNIQUE INDEX i ON p(a COLLATE nocase);
  653. CREATE TABLE c(x REFERENCES p(a));
  654. }] {
  655. drop_all_tables
  656. do_test fkey2-10.1.[incr tn] {
  657. execsql $zSql
  658. catchsql { INSERT INTO c DEFAULT VALUES }
  659. } {/1 {foreign key mismatch - "c" referencing "."}/}
  660. }
  661. # "rowid" cannot be used as part of a child or parent key definition
  662. # unless it happens to be the name of an explicitly declared column.
  663. #
  664. do_test fkey2-10.2.1 {
  665. drop_all_tables
  666. catchsql {
  667. CREATE TABLE t1(a PRIMARY KEY, b);
  668. CREATE TABLE t2(c, d, FOREIGN KEY(rowid) REFERENCES t1(a));
  669. }
  670. } {1 {unknown column "rowid" in foreign key definition}}
  671. do_test fkey2-10.2.2 {
  672. drop_all_tables
  673. catchsql {
  674. CREATE TABLE t1(a PRIMARY KEY, b);
  675. CREATE TABLE t2(rowid, d, FOREIGN KEY(rowid) REFERENCES t1(a));
  676. }
  677. } {0 {}}
  678. do_test fkey2-10.2.1 {
  679. drop_all_tables
  680. catchsql {
  681. CREATE TABLE t1(a, b);
  682. CREATE TABLE t2(c, d, FOREIGN KEY(c) REFERENCES t1(rowid));
  683. INSERT INTO t1(rowid, a, b) VALUES(1, 1, 1);
  684. INSERT INTO t2 VALUES(1, 1);
  685. }
  686. } {1 {foreign key mismatch - "t2" referencing "t1"}}
  687. do_test fkey2-10.2.2 {
  688. drop_all_tables
  689. catchsql {
  690. CREATE TABLE t1(rowid PRIMARY KEY, b);
  691. CREATE TABLE t2(c, d, FOREIGN KEY(c) REFERENCES t1(rowid));
  692. INSERT INTO t1(rowid, b) VALUES(1, 1);
  693. INSERT INTO t2 VALUES(1, 1);
  694. }
  695. } {0 {}}
  696. #-------------------------------------------------------------------------
  697. # The following tests, fkey2-11.*, test CASCADE actions.
  698. #
  699. drop_all_tables
  700. do_test fkey2-11.1.1 {
  701. execsql {
  702. CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
  703. CREATE TABLE t2(c, d, FOREIGN KEY(c) REFERENCES t1(a) ON UPDATE CASCADE);
  704. INSERT INTO t1 VALUES(10, 100);
  705. INSERT INTO t2 VALUES(10, 100);
  706. UPDATE t1 SET a = 15;
  707. SELECT * FROM t2;
  708. }
  709. } {15 100}
  710. #-------------------------------------------------------------------------
  711. # The following tests, fkey2-12.*, test RESTRICT actions.
  712. #
  713. drop_all_tables
  714. do_test fkey2-12.1.1 {
  715. execsql {
  716. CREATE TABLE t1(a, b PRIMARY KEY);
  717. CREATE TABLE t2(
  718. x REFERENCES t1 ON UPDATE RESTRICT DEFERRABLE INITIALLY DEFERRED
  719. );
  720. INSERT INTO t1 VALUES(1, 'one');
  721. INSERT INTO t1 VALUES(2, 'two');
  722. INSERT INTO t1 VALUES(3, 'three');
  723. }
  724. } {}
  725. do_test fkey2-12.1.2 {
  726. execsql "BEGIN"
  727. execsql "INSERT INTO t2 VALUES('two')"
  728. } {}
  729. do_test fkey2-12.1.3 {
  730. execsql "UPDATE t1 SET b = 'four' WHERE b = 'one'"
  731. } {}
  732. do_test fkey2-12.1.4 {
  733. catchsql "UPDATE t1 SET b = 'five' WHERE b = 'two'"
  734. } {1 {foreign key constraint failed}}
  735. do_test fkey2-12.1.5 {
  736. execsql "DELETE FROM t1 WHERE b = 'two'"
  737. } {}
  738. do_test fkey2-12.1.6 {
  739. catchsql "COMMIT"
  740. } {1 {foreign key constraint failed}}
  741. do_test fkey2-12.1.7 {
  742. execsql {
  743. INSERT INTO t1 VALUES(2, 'two');
  744. COMMIT;
  745. }
  746. } {}
  747. drop_all_tables
  748. do_test fkey2-12.2.1 {
  749. execsql {
  750. CREATE TABLE t1(x COLLATE NOCASE PRIMARY KEY);
  751. CREATE TRIGGER tt1 AFTER DELETE ON t1
  752. WHEN EXISTS ( SELECT 1 FROM t2 WHERE old.x = y )
  753. BEGIN
  754. INSERT INTO t1 VALUES(old.x);
  755. END;
  756. CREATE TABLE t2(y REFERENCES t1);
  757. INSERT INTO t1 VALUES('A');
  758. INSERT INTO t1 VALUES('B');
  759. INSERT INTO t2 VALUES('a');
  760. INSERT INTO t2 VALUES('b');
  761. SELECT * FROM t1;
  762. SELECT * FROM t2;
  763. }
  764. } {A B a b}
  765. do_test fkey2-12.2.2 {
  766. execsql { DELETE FROM t1 }
  767. execsql {
  768. SELECT * FROM t1;
  769. SELECT * FROM t2;
  770. }
  771. } {A B a b}
  772. do_test fkey2-12.2.3 {
  773. execsql {
  774. DROP TABLE t2;
  775. CREATE TABLE t2(y REFERENCES t1 ON DELETE RESTRICT);
  776. INSERT INTO t2 VALUES('a');
  777. INSERT INTO t2 VALUES('b');
  778. }
  779. catchsql { DELETE FROM t1 }
  780. } {1 {foreign key constraint failed}}
  781. do_test fkey2-12.2.4 {
  782. execsql {
  783. SELECT * FROM t1;
  784. SELECT * FROM t2;
  785. }
  786. } {A B a b}
  787. drop_all_tables
  788. do_test fkey2-12.3.1 {
  789. execsql {
  790. CREATE TABLE up(
  791. c00, c01, c02, c03, c04, c05, c06, c07, c08, c09,
  792. c10, c11, c12, c13, c14, c15, c16, c17, c18, c19,
  793. c20, c21, c22, c23, c24, c25, c26, c27, c28, c29,
  794. c30, c31, c32, c33, c34, c35, c36, c37, c38, c39,
  795. PRIMARY KEY(c34, c35)
  796. );
  797. CREATE TABLE down(
  798. c00, c01, c02, c03, c04, c05, c06, c07, c08, c09,
  799. c10, c11, c12, c13, c14, c15, c16, c17, c18, c19,
  800. c20, c21, c22, c23, c24, c25, c26, c27, c28, c29,
  801. c30, c31, c32, c33, c34, c35, c36, c37, c38, c39,
  802. FOREIGN KEY(c39, c38) REFERENCES up ON UPDATE CASCADE
  803. );
  804. }
  805. } {}
  806. do_test fkey2-12.3.2 {
  807. execsql {
  808. INSERT INTO up(c34, c35) VALUES('yes', 'no');
  809. INSERT INTO down(c39, c38) VALUES('yes', 'no');
  810. UPDATE up SET c34 = 'possibly';
  811. SELECT c38, c39 FROM down;
  812. DELETE FROM down;
  813. }
  814. } {no possibly}
  815. do_test fkey2-12.3.3 {
  816. catchsql { INSERT INTO down(c39, c38) VALUES('yes', 'no') }
  817. } {1 {foreign key constraint failed}}
  818. do_test fkey2-12.3.4 {
  819. execsql {
  820. INSERT INTO up(c34, c35) VALUES('yes', 'no');
  821. INSERT INTO down(c39, c38) VALUES('yes', 'no');
  822. }
  823. catchsql { DELETE FROM up WHERE c34 = 'yes' }
  824. } {1 {foreign key constraint failed}}
  825. do_test fkey2-12.3.5 {
  826. execsql {
  827. DELETE FROM up WHERE c34 = 'possibly';
  828. SELECT c34, c35 FROM up;
  829. SELECT c39, c38 FROM down;
  830. }
  831. } {yes no yes no}
  832. #-------------------------------------------------------------------------
  833. # The following tests, fkey2-13.*, test that FK processing is performed
  834. # when rows are REPLACEd.
  835. #
  836. drop_all_tables
  837. do_test fkey2-13.1.1 {
  838. execsql {
  839. CREATE TABLE pp(a UNIQUE, b, c, PRIMARY KEY(b, c));
  840. CREATE TABLE cc(d, e, f UNIQUE, FOREIGN KEY(d, e) REFERENCES pp);
  841. INSERT INTO pp VALUES(1, 2, 3);
  842. INSERT INTO cc VALUES(2, 3, 1);
  843. }
  844. } {}
  845. foreach {tn stmt} {
  846. 1 "REPLACE INTO pp VALUES(1, 4, 5)"
  847. 2 "REPLACE INTO pp(rowid, a, b, c) VALUES(1, 2, 3, 4)"
  848. } {
  849. do_test fkey2-13.1.$tn.1 {
  850. catchsql $stmt
  851. } {1 {foreign key constraint failed}}
  852. do_test fkey2-13.1.$tn.2 {
  853. execsql {
  854. SELECT * FROM pp;
  855. SELECT * FROM cc;
  856. }
  857. } {1 2 3 2 3 1}
  858. do_test fkey2-13.1.$tn.3 {
  859. execsql BEGIN;
  860. catchsql $stmt
  861. } {1 {foreign key constraint failed}}
  862. do_test fkey2-13.1.$tn.4 {
  863. execsql {
  864. COMMIT;
  865. SELECT * FROM pp;
  866. SELECT * FROM cc;
  867. }
  868. } {1 2 3 2 3 1}
  869. }
  870. do_test fkey2-13.1.3 {
  871. execsql {
  872. REPLACE INTO pp(rowid, a, b, c) VALUES(1, 2, 2, 3);
  873. SELECT rowid, * FROM pp;
  874. SELECT * FROM cc;
  875. }
  876. } {1 2 2 3 2 3 1}
  877. do_test fkey2-13.1.4 {
  878. execsql {
  879. REPLACE INTO pp(rowid, a, b, c) VALUES(2, 2, 2, 3);
  880. SELECT rowid, * FROM pp;
  881. SELECT * FROM cc;
  882. }
  883. } {2 2 2 3 2 3 1}
  884. #-------------------------------------------------------------------------
  885. # The following tests, fkey2-14.*, test that the "DROP TABLE" and "ALTER
  886. # TABLE" commands work as expected wrt foreign key constraints.
  887. #
  888. # fkey2-14.1*: ALTER TABLE ADD COLUMN
  889. # fkey2-14.2*: ALTER TABLE RENAME TABLE
  890. # fkey2-14.3*: DROP TABLE
  891. #
  892. drop_all_tables
  893. ifcapable altertable {
  894. do_test fkey2-14.1.1 {
  895. # Adding a column with a REFERENCES clause is not supported.
  896. execsql {
  897. CREATE TABLE t1(a PRIMARY KEY);
  898. CREATE TABLE t2(a, b);
  899. }
  900. catchsql { ALTER TABLE t2 ADD COLUMN c REFERENCES t1 }
  901. } {0 {}}
  902. do_test fkey2-14.1.2 {
  903. catchsql { ALTER TABLE t2 ADD COLUMN d DEFAULT NULL REFERENCES t1 }
  904. } {0 {}}
  905. do_test fkey2-14.1.3 {
  906. catchsql { ALTER TABLE t2 ADD COLUMN e REFERENCES t1 DEFAULT NULL}
  907. } {0 {}}
  908. do_test fkey2-14.1.4 {
  909. catchsql { ALTER TABLE t2 ADD COLUMN f REFERENCES t1 DEFAULT 'text'}
  910. } {1 {Cannot add a REFERENCES column with non-NULL default value}}
  911. do_test fkey2-14.1.5 {
  912. catchsql { ALTER TABLE t2 ADD COLUMN g DEFAULT CURRENT_TIME REFERENCES t1 }
  913. } {1 {Cannot add a REFERENCES column with non-NULL default value}}
  914. do_test fkey2-14.1.6 {
  915. execsql {
  916. PRAGMA foreign_keys = off;
  917. ALTER TABLE t2 ADD COLUMN h DEFAULT 'text' REFERENCES t1;
  918. PRAGMA foreign_keys = on;
  919. SELECT sql FROM sqlite_master WHERE name='t2';
  920. }
  921. } {{CREATE TABLE t2(a, b, c REFERENCES t1, d DEFAULT NULL REFERENCES t1, e REFERENCES t1 DEFAULT NULL, h DEFAULT 'text' REFERENCES t1)}}
  922. # Test the sqlite_rename_parent() function directly.
  923. #
  924. proc test_rename_parent {zCreate zOld zNew} {
  925. db eval {SELECT sqlite_rename_parent($zCreate, $zOld, $zNew)}
  926. }
  927. do_test fkey2-14.2.1.1 {
  928. test_rename_parent {CREATE TABLE t1(a REFERENCES t2)} t2 t3
  929. } {{CREATE TABLE t1(a REFERENCES "t3")}}
  930. do_test fkey2-14.2.1.2 {
  931. test_rename_parent {CREATE TABLE t1(a REFERENCES t2)} t4 t3
  932. } {{CREATE TABLE t1(a REFERENCES t2)}}
  933. do_test fkey2-14.2.1.3 {
  934. test_rename_parent {CREATE TABLE t1(a REFERENCES "t2")} t2 t3
  935. } {{CREATE TABLE t1(a REFERENCES "t3")}}
  936. # Test ALTER TABLE RENAME TABLE a bit.
  937. #
  938. do_test fkey2-14.2.2.1 {
  939. drop_all_tables
  940. execsql {
  941. CREATE TABLE t1(a PRIMARY KEY, b REFERENCES t1);
  942. CREATE TABLE t2(a PRIMARY KEY, b REFERENCES t1, c REFERENCES t2);
  943. CREATE TABLE t3(a REFERENCES t1, b REFERENCES t2, c REFERENCES t1);
  944. }
  945. execsql { SELECT sql FROM sqlite_master WHERE type = 'table'}
  946. } [list \
  947. {CREATE TABLE t1(a PRIMARY KEY, b REFERENCES t1)} \
  948. {CREATE TABLE t2(a PRIMARY KEY, b REFERENCES t1, c REFERENCES t2)} \
  949. {CREATE TABLE t3(a REFERENCES t1, b REFERENCES t2, c REFERENCES t1)} \
  950. ]
  951. do_test fkey2-14.2.2.2 {
  952. execsql { ALTER TABLE t1 RENAME TO t4 }
  953. execsql { SELECT sql FROM sqlite_master WHERE type = 'table'}
  954. } [list \
  955. {CREATE TABLE "t4"(a PRIMARY KEY, b REFERENCES "t4")} \
  956. {CREATE TABLE t2(a PRIMARY KEY, b REFERENCES "t4", c REFERENCES t2)} \
  957. {CREATE TABLE t3(a REFERENCES "t4", b REFERENCES t2, c REFERENCES "t4")} \
  958. ]
  959. do_test fkey2-14.2.2.3 {
  960. catchsql { INSERT INTO t3 VALUES(1, 2, 3) }
  961. } {1 {foreign key constraint failed}}
  962. do_test fkey2-14.2.2.4 {
  963. execsql { INSERT INTO t4 VALUES(1, NULL) }
  964. } {}
  965. do_test fkey2-14.2.2.5 {
  966. catchsql { UPDATE t4 SET b = 5 }
  967. } {1 {foreign key constraint failed}}
  968. do_test fkey2-14.2.2.6 {
  969. catchsql { UPDATE t4 SET b = 1 }
  970. } {0 {}}
  971. do_test fkey2-14.2.2.7 {
  972. execsql { INSERT INTO t3 VALUES(1, NULL, 1) }
  973. } {}
  974. # Repeat for TEMP tables
  975. #
  976. drop_all_tables
  977. do_test fkey2-14.1tmp.1 {
  978. # Adding a column with a REFERENCES clause is not supported.
  979. execsql {
  980. CREATE TEMP TABLE t1(a PRIMARY KEY);
  981. CREATE TEMP TABLE t2(a, b);
  982. }
  983. catchsql { ALTER TABLE t2 ADD COLUMN c REFERENCES t1 }
  984. } {0 {}}
  985. do_test fkey2-14.1tmp.2 {
  986. catchsql { ALTER TABLE t2 ADD COLUMN d DEFAULT NULL REFERENCES t1 }
  987. } {0 {}}
  988. do_test fkey2-14.1tmp.3 {
  989. catchsql { ALTER TABLE t2 ADD COLUMN e REFERENCES t1 DEFAULT NULL}
  990. } {0 {}}
  991. do_test fkey2-14.1tmp.4 {
  992. catchsql { ALTER TABLE t2 ADD COLUMN f REFERENCES t1 DEFAULT 'text'}
  993. } {1 {Cannot add a REFERENCES column with non-NULL default value}}
  994. do_test fkey2-14.1tmp.5 {
  995. catchsql { ALTER TABLE t2 ADD COLUMN g DEFAULT CURRENT_TIME REFERENCES t1 }
  996. } {1 {Cannot add a REFERENCES column with non-NULL default value}}
  997. do_test fkey2-14.1tmp.6 {
  998. execsql {
  999. PRAGMA foreign_keys = off;
  1000. ALTER TABLE t2 ADD COLUMN h DEFAULT 'text' REFERENCES t1;
  1001. PRAGMA foreign_keys = on;
  1002. SELECT sql FROM sqlite_temp_master WHERE name='t2';
  1003. }
  1004. } {{CREATE TABLE t2(a, b, c REFERENCES t1, d DEFAULT NULL REFERENCES t1, e REFERENCES t1 DEFAULT NULL, h DEFAULT 'text' REFERENCES t1)}}
  1005. do_test fkey2-14.2tmp.1.1 {
  1006. test_rename_parent {CREATE TABLE t1(a REFERENCES t2)} t2 t3
  1007. } {{CREATE TABLE t1(a REFERENCES "t3")}}
  1008. do_test fkey2-14.2tmp.1.2 {
  1009. test_rename_parent {CREATE TABLE t1(a REFERENCES t2)} t4 t3
  1010. } {{CREATE TABLE t1(a REFERENCES t2)}}
  1011. do_test fkey2-14.2tmp.1.3 {
  1012. test_rename_parent {CREATE TABLE t1(a REFERENCES "t2")} t2 t3
  1013. } {{CREATE TABLE t1(a REFERENCES "t3")}}
  1014. # Test ALTER TABLE RENAME TABLE a bit.
  1015. #
  1016. do_test fkey2-14.2tmp.2.1 {
  1017. drop_all_tables
  1018. execsql {
  1019. CREATE TEMP TABLE t1(a PRIMARY KEY, b REFERENCES t1);
  1020. CREATE TEMP TABLE t2(a PRIMARY KEY, b REFERENCES t1, c REFERENCES t2);
  1021. CREATE TEMP TABLE t3(a REFERENCES t1, b REFERENCES t2, c REFERENCES t1);
  1022. }
  1023. execsql { SELECT sql FROM sqlite_temp_master WHERE type = 'table'}
  1024. } [list \
  1025. {CREATE TABLE t1(a PRIMARY KEY, b REFERENCES t1)} \
  1026. {CREATE TABLE t2(a PRIMARY KEY, b REFERENCES t1, c REFERENCES t2)} \
  1027. {CREATE TABLE t3(a REFERENCES t1, b REFERENCES t2, c REFERENCES t1)} \
  1028. ]
  1029. do_test fkey2-14.2tmp.2.2 {
  1030. execsql { ALTER TABLE t1 RENAME TO t4 }
  1031. execsql { SELECT sql FROM sqlite_temp_master WHERE type = 'table'}
  1032. } [list \
  1033. {CREATE TABLE "t4"(a PRIMARY KEY, b REFERENCES "t4")} \
  1034. {CREATE TABLE t2(a PRIMARY KEY, b REFERENCES "t4", c REFERENCES t2)} \
  1035. {CREATE TABLE t3(a REFERENCES "t4", b REFERENCES t2, c REFERENCES "t4")} \
  1036. ]
  1037. do_test fkey2-14.2tmp.2.3 {
  1038. catchsql { INSERT INTO t3 VALUES(1, 2, 3) }
  1039. } {1 {foreign key constraint failed}}
  1040. do_test fkey2-14.2tmp.2.4 {
  1041. execsql { INSERT INTO t4 VALUES(1, NULL) }
  1042. } {}
  1043. do_test fkey2-14.2tmp.2.5 {
  1044. catchsql { UPDATE t4 SET b = 5 }
  1045. } {1 {foreign key constraint failed}}
  1046. do_test fkey2-14.2tmp.2.6 {
  1047. catchsql { UPDATE t4 SET b = 1 }
  1048. } {0 {}}
  1049. do_test fkey2-14.2tmp.2.7 {
  1050. execsql { INSERT INTO t3 VALUES(1, NULL, 1) }
  1051. } {}
  1052. # Repeat for ATTACH-ed tables
  1053. #
  1054. drop_all_tables
  1055. do_test fkey2-14.1aux.1 {
  1056. # Adding a column with a REFERENCES clause is not supported.
  1057. execsql {
  1058. ATTACH ':memory:' AS aux;
  1059. CREATE TABLE aux.t1(a PRIMARY KEY);
  1060. CREATE TABLE aux.t2(a, b);
  1061. }
  1062. catchsql { ALTER TABLE t2 ADD COLUMN c REFERENCES t1 }
  1063. } {0 {}}
  1064. do_test fkey2-14.1aux.2 {
  1065. catchsql { ALTER TABLE t2 ADD COLUMN d DEFAULT NULL REFERENCES t1 }
  1066. } {0 {}}
  1067. do_test fkey2-14.1aux.3 {
  1068. catchsql { ALTER TABLE t2 ADD COLUMN e REFERENCES t1 DEFAULT NULL}
  1069. } {0 {}}
  1070. do_test fkey2-14.1aux.4 {
  1071. catchsql { ALTER TABLE t2 ADD COLUMN f REFERENCES t1 DEFAULT 'text'}
  1072. } {1 {Cannot add a REFERENCES column with non-NULL default value}}
  1073. do_test fkey2-14.1aux.5 {
  1074. catchsql { ALTER TABLE t2 ADD COLUMN g DEFAULT CURRENT_TIME REFERENCES t1 }
  1075. } {1 {Cannot add a REFERENCES column with non-NULL default value}}
  1076. do_test fkey2-14.1aux.6 {
  1077. execsql {
  1078. PRAGMA foreign_keys = off;
  1079. ALTER TABLE t2 ADD COLUMN h DEFAULT 'text' REFERENCES t1;
  1080. PRAGMA foreign_keys = on;
  1081. SELECT sql FROM aux.sqlite_master WHERE name='t2';
  1082. }
  1083. } {{CREATE TABLE t2(a, b, c REFERENCES t1, d DEFAULT NULL REFERENCES t1, e REFERENCES t1 DEFAULT NULL, h DEFAULT 'text' REFERENCES t1)}}
  1084. do_test fkey2-14.2aux.1.1 {
  1085. test_rename_parent {CREATE TABLE t1(a REFERENCES t2)} t2 t3
  1086. } {{CREATE TABLE t1(a REFERENCES "t3")}}
  1087. do_test fkey2-14.2aux.1.2 {
  1088. test_rename_parent {CREATE TABLE t1(a REFERENCES t2)} t4 t3
  1089. } {{CREATE TABLE t1(a REFERENCES t2)}}
  1090. do_test fkey2-14.2aux.1.3 {
  1091. test_rename_parent {CREATE TABLE t1(a REFERENCES "t2")} t2 t3
  1092. } {{CREATE TABLE t1(a REFERENCES "t3")}}
  1093. # Test ALTER TABLE RENAME TABLE a bit.
  1094. #
  1095. do_test fkey2-14.2aux.2.1 {
  1096. drop_all_tables
  1097. execsql {
  1098. CREATE TABLE aux.t1(a PRIMARY KEY, b REFERENCES t1);
  1099. CREATE TABLE aux.t2(a PRIMARY KEY, b REFERENCES t1, c REFERENCES t2);
  1100. CREATE TABLE aux.t3(a REFERENCES t1, b REFERENCES t2, c REFERENCES t1);
  1101. }
  1102. execsql { SELECT sql FROM aux.sqlite_master WHERE type = 'table'}
  1103. } [list \
  1104. {CREATE TABLE t1(a PRIMARY KEY, b REFERENCES t1)} \
  1105. {CREATE TABLE t2(a PRIMARY KEY, b REFERENCES t1, c REFERENCES t2)} \
  1106. {CREATE TABLE t3(a REFERENCES t1, b REFERENCES t2, c REFERENCES t1)} \
  1107. ]
  1108. do_test fkey2-14.2aux.2.2 {
  1109. execsql { ALTER TABLE t1 RENAME TO t4 }
  1110. execsql { SELECT sql FROM aux.sqlite_master WHERE type = 'table'}
  1111. } [list \
  1112. {CREATE TABLE "t4"(a PRIMARY KEY, b REFERENCES "t4")} \
  1113. {CREATE TABLE t2(a PRIMARY KEY, b REFERENCES "t4", c REFERENCES t2)} \
  1114. {CREATE TABLE t3(a REFERENCES "t4", b REFERENCES t2, c REFERENCES "t4")} \
  1115. ]
  1116. do_test fkey2-14.2aux.2.3 {
  1117. catchsql { INSERT INTO t3 VALUES(1, 2, 3) }
  1118. } {1 {foreign key constraint failed}}
  1119. do_test fkey2-14.2aux.2.4 {
  1120. execsql { INSERT INTO t4 VALUES(1, NULL) }
  1121. } {}
  1122. do_test fkey2-14.2aux.2.5 {
  1123. catchsql { UPDATE t4 SET b = 5 }
  1124. } {1 {foreign key constraint failed}}
  1125. do_test fkey2-14.2aux.2.6 {
  1126. catchsql { UPDATE t4 SET b = 1 }
  1127. } {0 {}}
  1128. do_test fkey2-14.2aux.2.7 {
  1129. execsql { INSERT INTO t3 VALUES(1, NULL, 1) }
  1130. } {}
  1131. }
  1132. do_test fkey-2.14.3.1 {
  1133. drop_all_tables
  1134. execsql {
  1135. CREATE TABLE t1(a, b REFERENCES nosuchtable);
  1136. DROP TABLE t1;
  1137. }
  1138. } {}
  1139. do_test fkey-2.14.3.2 {
  1140. execsql {
  1141. CREATE TABLE t1(a PRIMARY KEY, b);
  1142. INSERT INTO t1 VALUES('a', 1);
  1143. CREATE TABLE t2(x REFERENCES t1);
  1144. INSERT INTO t2 VALUES('a');
  1145. }
  1146. } {}
  1147. do_test fkey-2.14.3.3 {
  1148. catchsql { DROP TABLE t1 }
  1149. } {1 {foreign key constraint failed}}
  1150. do_test fkey-2.14.3.4 {
  1151. execsql {
  1152. DELETE FROM t2;
  1153. DROP TABLE t1;
  1154. }
  1155. } {}
  1156. do_test fkey-2.14.3.4 {
  1157. catchsql { INSERT INTO t2 VALUES('x') }
  1158. } {1 {no such table: main.t1}}
  1159. do_test fkey-2.14.3.5 {
  1160. execsql {
  1161. CREATE TABLE t1(x PRIMARY KEY);
  1162. INSERT INTO t1 VALUES('x');
  1163. }
  1164. execsql { INSERT INTO t2 VALUES('x') }
  1165. } {}
  1166. do_test fkey-2.14.3.6 {
  1167. catchsql { DROP TABLE t1 }
  1168. } {1 {foreign key constraint failed}}
  1169. do_test fkey-2.14.3.7 {
  1170. execsql {
  1171. DROP TABLE t2;
  1172. DROP TABLE t1;
  1173. }
  1174. } {}
  1175. do_test fkey-2.14.3.8 {
  1176. execsql {
  1177. CREATE TABLE pp(x, y, PRIMARY KEY(x, y));
  1178. CREATE TABLE cc(a, b, FOREIGN KEY(a, b) REFERENCES pp(x, z));
  1179. }
  1180. catchsql { INSERT INTO cc VALUES(1, 2) }
  1181. } {1 {foreign key mismatch - "cc" referencing "pp"}}
  1182. do_test fkey-2.14.3.9 {
  1183. execsql { DROP TABLE cc }
  1184. } {}
  1185. do_test fkey-2.14.3.10 {
  1186. execsql {
  1187. CREATE TABLE cc(a, b,
  1188. FOREIGN KEY(a, b) REFERENCES pp DEFERRABLE INITIALLY DEFERRED
  1189. );
  1190. }
  1191. execsql {
  1192. INSERT INTO pp VALUES('a', 'b');
  1193. INSERT INTO cc VALUES('a', 'b');
  1194. BEGIN;
  1195. DROP TABLE pp;
  1196. CREATE TABLE pp(a, b, c, PRIMARY KEY(b, c));
  1197. INSERT INTO pp VALUES(1, 'a', 'b');
  1198. COMMIT;
  1199. }
  1200. } {}
  1201. do_test fkey-2.14.3.11 {
  1202. execsql {
  1203. BEGIN;
  1204. DROP TABLE cc;
  1205. DROP TABLE pp;
  1206. COMMIT;
  1207. }
  1208. } {}
  1209. do_test fkey-2.14.3.12 {
  1210. execsql {
  1211. CREATE TABLE b1(a, b);
  1212. CREATE TABLE b2(a, b REFERENCES b1);
  1213. DROP TABLE b1;
  1214. }
  1215. } {}
  1216. do_test fkey-2.14.3.13 {
  1217. execsql {
  1218. CREATE TABLE b3(a, b REFERENCES b2 DEFERRABLE INITIALLY DEFERRED);
  1219. DROP TABLE b2;
  1220. }
  1221. } {}
  1222. # Test that nothing goes wrong when dropping a table that refers to a view.
  1223. # Or dropping a view that an existing FK (incorrectly) refers to. Or either
  1224. # of the above scenarios with a virtual table.
  1225. drop_all_tables
  1226. do_test fkey-2.14.4.1 {
  1227. execsql {
  1228. CREATE TABLE t1(x REFERENCES v);
  1229. CREATE VIEW v AS SELECT * FROM t1;
  1230. }
  1231. } {}
  1232. do_test fkey-2.14.4.2 {
  1233. execsql {
  1234. DROP VIEW v;
  1235. }
  1236. } {}
  1237. ifcapable vtab {
  1238. register_echo_module db
  1239. do_test fkey-2.14.4.3 {
  1240. execsql { CREATE VIRTUAL TABLE v USING echo(t1) }
  1241. } {}
  1242. do_test fkey-2.14.4.2 {
  1243. execsql {
  1244. DROP TABLE v;
  1245. }
  1246. } {}
  1247. }
  1248. #-------------------------------------------------------------------------
  1249. # The following tests, fkey2-15.*, test that unnecessary FK related scans
  1250. # and lookups are avoided when the constraint counters are zero.
  1251. #
  1252. drop_all_tables
  1253. proc execsqlS {zSql} {
  1254. set ::sqlite_search_count 0
  1255. set ::sqlite_found_count 0
  1256. set res [uplevel [list execsql $zSql]]
  1257. concat [expr $::sqlite_found_count + $::sqlite_search_count] $res
  1258. }
  1259. do_test fkey2-15.1.1 {
  1260. execsql {
  1261. CREATE TABLE pp(a PRIMARY KEY, b);
  1262. CREATE TABLE cc(x, y REFERENCES pp DEFERRABLE INITIALLY DEFERRED);
  1263. INSERT INTO pp VALUES(1, 'one');
  1264. INSERT INTO pp VALUES(2, 'two');
  1265. INSERT INTO cc VALUES('neung', 1);
  1266. INSERT INTO cc VALUES('song', 2);
  1267. }
  1268. } {}
  1269. do_test fkey2-15.1.2 {
  1270. execsqlS { INSERT INTO pp VALUES(3, 'three') }
  1271. } {0}
  1272. do_test fkey2-15.1.3 {
  1273. execsql {
  1274. BEGIN;
  1275. INSERT INTO cc VALUES('see', 4); -- Violates deferred constraint
  1276. }
  1277. execsqlS { INSERT INTO pp VALUES(5, 'five') }
  1278. } {2}
  1279. do_test fkey2-15.1.4 {
  1280. execsql { DELETE FROM cc WHERE x = 'see' }
  1281. execsqlS { INSERT INTO pp VALUES(6, 'six') }
  1282. } {0}
  1283. do_test fkey2-15.1.5 {
  1284. execsql COMMIT
  1285. } {}
  1286. do_test fkey2-15.1.6 {
  1287. execsql BEGIN
  1288. execsqlS {
  1289. DELETE FROM cc WHERE x = 'neung';
  1290. ROLLBACK;
  1291. }
  1292. } {1}
  1293. do_test fkey2-15.1.7 {
  1294. execsql {
  1295. BEGIN;
  1296. DELETE FROM pp WHERE a = 2;
  1297. }
  1298. execsqlS {
  1299. DELETE FROM cc WHERE x = 'neung';
  1300. ROLLBACK;
  1301. }
  1302. } {2}
  1303. #-------------------------------------------------------------------------
  1304. # This next block of tests, fkey2-16.*, test that rows that refer to
  1305. # themselves may be inserted and deleted.
  1306. #
  1307. foreach {tn zSchema} {
  1308. 1 { CREATE TABLE self(a INTEGER PRIMARY KEY, b REFERENCES self(a)) }
  1309. 2 { CREATE TABLE self(a PRIMARY KEY, b REFERENCES self(a)) }
  1310. 3 { CREATE TABLE self(a UNIQUE, b INTEGER PRIMARY KEY REFERENCES self(a)) }
  1311. } {
  1312. drop_all_tables
  1313. do_test fkey2-16.1.$tn.1 {
  1314. execsql $zSchema
  1315. execsql { INSERT INTO self VALUES(13, 13) }
  1316. } {}
  1317. do_test fkey2-16.1.$tn.2 {
  1318. execsql { UPDATE self SET a = 14, b = 14 }
  1319. } {}
  1320. do_test fkey2-16.1.$tn.3 {
  1321. catchsql { UPDATE self SET b = 15 }
  1322. } {1 {foreign key constraint failed}}
  1323. do_test fkey2-16.1.$tn.4 {
  1324. catchsql { UPDATE self SET a = 15 }
  1325. } {1 {foreign key constraint failed}}
  1326. do_test fkey2-16.1.$tn.5 {
  1327. catchsql { UPDATE self SET a = 15, b = 16 }
  1328. } {1 {foreign key constraint failed}}
  1329. do_test fkey2-16.1.$tn.6 {
  1330. catchsql { UPDATE self SET a = 17, b = 17 }
  1331. } {0 {}}
  1332. do_test fkey2-16.1.$tn.7 {
  1333. execsql { DELETE FROM self }
  1334. } {}
  1335. do_test fkey2-16.1.$tn.8 {
  1336. catchsql { INSERT INTO self VALUES(20, 21) }
  1337. } {1 {foreign key constraint failed}}
  1338. }
  1339. #-------------------------------------------------------------------------
  1340. # This next block of tests, fkey2-17.*, tests that if "PRAGMA count_changes"
  1341. # is turned on statements that violate immediate FK constraints return
  1342. # SQLITE_CONSTRAINT immediately, not after returning a number of rows.
  1343. # Whereas statements that violate deferred FK constraints return the number
  1344. # of rows before failing.
  1345. #
  1346. # Also test that rows modified by FK actions are not counted in either the
  1347. # returned row count or the values returned by sqlite3_changes(). Like
  1348. # trigger related changes, they are included in sqlite3_total_changes() though.
  1349. #
  1350. drop_all_tables
  1351. do_test fkey2-17.1.1 {
  1352. execsql { PRAGMA count_changes = 1 }
  1353. execsql {
  1354. CREATE TABLE one(a, b, c, UNIQUE(b, c));
  1355. CREATE TABLE two(d, e, f, FOREIGN KEY(e, f) REFERENCES one(b, c));
  1356. INSERT INTO one VALUES(1, 2, 3);
  1357. }
  1358. } {1}
  1359. do_test fkey2-17.1.2 {
  1360. set STMT [sqlite3_prepare_v2 db "INSERT INTO two VALUES(4, 5, 6)" -1 dummy]
  1361. sqlite3_step $STMT
  1362. } {SQLITE_CONSTRAINT}
  1363. verify_ex_errcode fkey2-17.1.2b SQLITE_CONSTRAINT_FOREIGNKEY
  1364. ifcapable autoreset {
  1365. do_test fkey2-17.1.3 {
  1366. sqlite3_step $STMT
  1367. } {SQLITE_CONSTRAINT}
  1368. verify_ex_errcode fkey2-17.1.3b SQLITE_CONSTRAINT_FOREIGNKEY
  1369. } else {
  1370. do_test fkey2-17.1.3 {
  1371. sqlite3_step $STMT
  1372. } {SQLITE_MISUSE}
  1373. }
  1374. do_test fkey2-17.1.4 {
  1375. sqlite3_finalize $STMT
  1376. } {SQLITE_CONSTRAINT}
  1377. verify_ex_errcode fkey2-17.1.4b SQLITE_CONSTRAINT_FOREIGNKEY
  1378. do_test fkey2-17.1.5 {
  1379. execsql {
  1380. INSERT INTO one VALUES(2, 3, 4);
  1381. INSERT INTO one VALUES(3, 4, 5);
  1382. INSERT INTO two VALUES(1, 2, 3);
  1383. INSERT INTO two VALUES(2, 3, 4);
  1384. INSERT INTO two VALUES(3, 4, 5);
  1385. }
  1386. } {1 1 1 1 1}
  1387. do_test fkey2-17.1.6 {
  1388. catchsql {
  1389. BEGIN;
  1390. INSERT INTO one VALUES(0, 0, 0);
  1391. UPDATE two SET e=e+1, f=f+1;
  1392. }
  1393. } {1 {foreign key constraint failed}}
  1394. do_test fkey2-17.1.7 {
  1395. execsql { SELECT * FROM one }
  1396. } {1 2 3 2 3 4 3 4 5 0 0 0}
  1397. do_test fkey2-17.1.8 {
  1398. execsql { SELECT * FROM two }
  1399. } {1 2 3 2 3 4 3 4 5}
  1400. do_test fkey2-17.1.9 {
  1401. execsql COMMIT
  1402. } {}
  1403. do_test fkey2-17.1.10 {
  1404. execsql {
  1405. CREATE TABLE three(
  1406. g, h, i,
  1407. FOREIGN KEY(h, i) REFERENCES one(b, c) DEFERRABLE INITIALLY DEFERRED
  1408. );
  1409. }
  1410. } {}
  1411. do_test fkey2-17.1.11 {
  1412. set STMT [sqlite3_prepare_v2 db "INSERT INTO three VALUES(7, 8, 9)" -1 dummy]
  1413. sqlite3_step $STMT
  1414. } {SQLITE_ROW}
  1415. do_test fkey2-17.1.12 {
  1416. sqlite3_column_text $STMT 0
  1417. } {1}
  1418. do_test fkey2-17.1.13 {
  1419. sqlite3_step $STMT
  1420. } {SQLITE_CONSTRAINT}
  1421. verify_ex_errcode fkey2-17.1.13b SQLITE_CONSTRAINT_FOREIGNKEY
  1422. do_test fkey2-17.1.14 {
  1423. sqlite3_finalize $STMT
  1424. } {SQLITE_CONSTRAINT}
  1425. verify_ex_errcode fkey2-17.1.14b SQLITE_CONSTRAINT_FOREIGNKEY
  1426. drop_all_tables
  1427. do_test fkey2-17.2.1 {
  1428. execsql {
  1429. CREATE TABLE high("a'b!" PRIMARY KEY, b);
  1430. CREATE TABLE low(
  1431. c,
  1432. "d&6" REFERENCES high ON UPDATE CASCADE ON DELETE CASCADE
  1433. );
  1434. }
  1435. } {}
  1436. do_test fkey2-17.2.2 {
  1437. execsql {
  1438. INSERT INTO high VALUES('a', 'b');
  1439. INSERT INTO low VALUES('b', 'a');
  1440. }
  1441. db changes
  1442. } {1}
  1443. set nTotal [db total_changes]
  1444. do_test fkey2-17.2.3 {
  1445. execsql { UPDATE high SET "a'b!" = 'c' }
  1446. } {1}
  1447. do_test fkey2-17.2.4 {
  1448. db changes
  1449. } {1}
  1450. do_test fkey2-17.2.5 {
  1451. expr [db total_changes] - $nTotal
  1452. } {2}
  1453. do_test fkey2-17.2.6 {
  1454. execsql { SELECT * FROM high ; SELECT * FROM low }
  1455. } {c b b c}
  1456. do_test fkey2-17.2.7 {
  1457. execsql { DELETE FROM high }
  1458. } {1}
  1459. do_test fkey2-17.2.8 {
  1460. db changes
  1461. } {1}
  1462. do_test fkey2-17.2.9 {
  1463. expr [db total_changes] - $nTotal
  1464. } {4}
  1465. do_test fkey2-17.2.10 {
  1466. execsql { SELECT * FROM high ; SELECT * FROM low }
  1467. } {}
  1468. execsql { PRAGMA count_changes = 0 }
  1469. #-------------------------------------------------------------------------
  1470. # Test that the authorization callback works.
  1471. #
  1472. ifcapable auth {
  1473. do_test fkey2-18.1 {
  1474. execsql {
  1475. CREATE TABLE long(a, b PRIMARY KEY, c);
  1476. CREATE TABLE short(d, e, f REFERENCES long);
  1477. CREATE TABLE mid(g, h, i REFERENCES long DEFERRABLE INITIALLY DEFERRED);
  1478. }
  1479. } {}
  1480. proc auth {args} {eval lappend ::authargs $args ; return SQLITE_OK}
  1481. db auth auth
  1482. # An insert on the parent table must read the child key of any deferred
  1483. # foreign key constraints. But not the child key of immediate constraints.
  1484. set authargs {}
  1485. do_test fkey2-18.2 {
  1486. execsql { INSERT INTO long VALUES(1, 2, 3) }
  1487. set authargs
  1488. } {SQLITE_INSERT long {} main {} SQLITE_READ mid i main {}}
  1489. # An insert on the child table of an immediate constraint must read the
  1490. # parent key columns (to see if it is a violation or not).
  1491. set authargs {}
  1492. do_test fkey2-18.3 {
  1493. execsql { INSERT INTO short VALUES(1, 3, 2) }
  1494. set authargs
  1495. } {SQLITE_INSERT short {} main {} SQLITE_READ long b main {}}
  1496. # As must an insert on the child table of a deferred constraint.
  1497. set authargs {}
  1498. do_test fkey2-18.4 {
  1499. execsql { INSERT INTO mid VALUES(1, 3, 2) }
  1500. set authargs
  1501. } {SQLITE_INSERT mid {} main {} SQLITE_READ long b main {}}
  1502. do_test fkey2-18.5 {
  1503. execsql {
  1504. CREATE TABLE nought(a, b PRIMARY KEY, c);
  1505. CREATE TABLE cross(d, e, f,
  1506. FOREIGN KEY(e) REFERENCES nought(b) ON UPDATE CASCADE
  1507. );
  1508. }
  1509. execsql { INSERT INTO nought VALUES(2, 1, 2) }
  1510. execsql { INSERT INTO cross VALUES(0, 1, 0) }
  1511. set authargs [list]
  1512. execsql { UPDATE nought SET b = 5 }
  1513. set authargs
  1514. } {SQLITE_UPDATE nought b main {} SQLITE_READ cross e main {} SQLITE_READ cross e main {} SQLITE_READ nought b main {} SQLITE_READ nought b main {} SQLITE_READ nought b main {} SQLITE_UPDATE cross e main {} SQLITE_READ nought b main {} SQLITE_READ cross e main {} SQLITE_READ nought b main {} SQLITE_READ nought b main {}}
  1515. do_test fkey2-18.6 {
  1516. execsql {SELECT * FROM cross}
  1517. } {0 5 0}
  1518. do_test fkey2-18.7 {
  1519. execsql {
  1520. CREATE TABLE one(a INTEGER PRIMARY KEY, b);
  1521. CREATE TABLE two(b, c REFERENCES one);
  1522. INSERT INTO one VALUES(101, 102);
  1523. }
  1524. set authargs [list]
  1525. execsql { INSERT INTO two VALUES(100, 101); }
  1526. set authargs
  1527. } {SQLITE_INSERT two {} main {} SQLITE_READ one a main {}}
  1528. # Return SQLITE_IGNORE to requests to read from the parent table. This
  1529. # causes inserts of non-NULL keys into the child table to fail.
  1530. #
  1531. rename auth {}
  1532. proc auth {args} {
  1533. if {[lindex $args 1] == "long"} {return SQLITE_IGNORE}
  1534. return SQLITE_OK
  1535. }
  1536. do_test fkey2-18.8 {
  1537. catchsql { INSERT INTO short VALUES(1, 3, 2) }
  1538. } {1 {foreign key constraint failed}}
  1539. do_test fkey2-18.9 {
  1540. execsql { INSERT INTO short VALUES(1, 3, NULL) }
  1541. } {}
  1542. do_test fkey2-18.10 {
  1543. execsql { SELECT * FROM short }
  1544. } {1 3 2 1 3 {}}
  1545. do_test fkey2-18.11 {
  1546. catchsql { UPDATE short SET f = 2 WHERE f IS NULL }
  1547. } {1 {foreign key constraint failed}}
  1548. db auth {}
  1549. unset authargs
  1550. }
  1551. do_test fkey2-19.1 {
  1552. execsql {
  1553. CREATE TABLE main(id INTEGER PRIMARY KEY);
  1554. CREATE TABLE sub(id INT REFERENCES main(id));
  1555. INSERT INTO main VALUES(1);
  1556. INSERT INTO main VALUES(2);
  1557. INSERT INTO sub VALUES(2);
  1558. }
  1559. } {}
  1560. do_test fkey2-19.2 {
  1561. set S [sqlite3_prepare_v2 db "DELETE FROM main WHERE id = ?" -1 dummy]
  1562. sqlite3_bind_int $S 1 2
  1563. sqlite3_step $S
  1564. } {SQLITE_CONSTRAINT}
  1565. verify_ex_errcode fkey2-19.2b SQLITE_CONSTRAINT_FOREIGNKEY
  1566. do_test fkey2-19.3 {
  1567. sqlite3_reset $S
  1568. } {SQLITE_CONSTRAINT}
  1569. verify_ex_errcode fkey2-19.3b SQLITE_CONSTRAINT_FOREIGNKEY
  1570. do_test fkey2-19.4 {
  1571. sqlite3_bind_int $S 1 1
  1572. sqlite3_step $S
  1573. } {SQLITE_DONE}
  1574. do_test fkey2-19.4 {
  1575. sqlite3_finalize $S
  1576. } {SQLITE_OK}
  1577. drop_all_tables
  1578. do_test fkey2-20.1 {
  1579. execsql {
  1580. CREATE TABLE pp(a PRIMARY KEY, b);
  1581. CREATE TABLE cc(c PRIMARY KEY, d REFERENCES pp);
  1582. }
  1583. } {}
  1584. foreach {tn insert} {
  1585. 1 "INSERT"
  1586. 2 "INSERT OR IGNORE"
  1587. 3 "INSERT OR ABORT"
  1588. 4 "INSERT OR ROLLBACK"
  1589. 5 "INSERT OR REPLACE"
  1590. 6 "INSERT OR FAIL"
  1591. } {
  1592. do_test fkey2-20.2.$tn.1 {
  1593. catchsql "$insert INTO cc VALUES(1, 2)"
  1594. } {1 {foreign key constraint failed}}
  1595. do_test fkey2-20.2.$tn.2 {
  1596. execsql { SELECT * FROM cc }
  1597. } {}
  1598. do_test fkey2-20.2.$tn.3 {
  1599. execsql {
  1600. BEGIN;
  1601. INSERT INTO pp VALUES(2, 'two');
  1602. INSERT INTO cc VALUES(1, 2);
  1603. }
  1604. catchsql "$insert INTO cc VALUES(3, 4)"
  1605. } {1 {foreign key constraint failed}}
  1606. do_test fkey2-20.2.$tn.4 {
  1607. execsql { COMMIT ; SELECT * FROM cc }
  1608. } {1 2}
  1609. do_test fkey2-20.2.$tn.5 {
  1610. execsql { DELETE FROM cc ; DELETE FROM pp }
  1611. } {}
  1612. }
  1613. foreach {tn update} {
  1614. 1 "UPDATE"
  1615. 2 "UPDATE OR IGNORE"
  1616. 3 "UPDATE OR ABORT"
  1617. 4 "UPDATE OR ROLLBACK"
  1618. 5 "UPDATE OR REPLACE"
  1619. 6 "UPDATE OR FAIL"
  1620. } {
  1621. do_test fkey2-20.3.$tn.1 {
  1622. execsql {
  1623. INSERT INTO pp VALUES(2, 'two');
  1624. INSERT INTO cc VALUES(1, 2);
  1625. }
  1626. } {}
  1627. do_test fkey2-20.3.$tn.2 {
  1628. catchsql "$update pp SET a = 1"
  1629. } {1 {foreign key constraint failed}}
  1630. do_test fkey2-20.3.$tn.3 {
  1631. execsql { SELECT * FROM pp }
  1632. } {2 two}
  1633. do_test fkey2-20.3.$tn.4 {
  1634. catchsql "$update cc SET d = 1"
  1635. } {1 {foreign key constraint failed}}
  1636. do_test fkey2-20.3.$tn.5 {
  1637. execsql { SELECT * FROM cc }
  1638. } {1 2}
  1639. do_test fkey2-20.3.$tn.6 {
  1640. execsql {
  1641. BEGIN;
  1642. INSERT INTO pp VALUES(3, 'three');
  1643. }
  1644. catchsql "$update pp SET a = 1 WHERE a = 2"
  1645. } {1 {foreign key constraint failed}}
  1646. do_test fkey2-20.3.$tn.7 {
  1647. execsql { COMMIT ; SELECT * FROM pp }
  1648. } {2 two 3 three}
  1649. do_test fkey2-20.3.$tn.8 {
  1650. execsql {
  1651. BEGIN;
  1652. INSERT INTO cc VALUES(2, 2);
  1653. }
  1654. catchsql "$update cc SET d = 1 WHERE c = 1"
  1655. } {1 {foreign key constraint failed}}
  1656. do_test fkey2-20.3.$tn.9 {
  1657. execsql { COMMIT ; SELECT * FROM cc }
  1658. } {1 2 2 2}
  1659. do_test fkey2-20.3.$tn.10 {
  1660. execsql { DELETE FROM cc ; DELETE FROM pp }
  1661. } {}
  1662. }
  1663. #-------------------------------------------------------------------------
  1664. # The following block of tests, those prefixed with "fkey2-genfkey.", are
  1665. # the same tests that were used to test the ".genfkey" command provided
  1666. # by the shell tool. So these tests show that the built-in foreign key
  1667. # implementation is more or less compatible with the triggers generated
  1668. # by genfkey.
  1669. #
  1670. drop_all_tables
  1671. do_test fkey2-genfkey.1.1 {
  1672. execsql {
  1673. CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c, UNIQUE(b, c));
  1674. CREATE TABLE t2(e REFERENCES t1, f);
  1675. CREATE TABLE t3(g, h, i, FOREIGN KEY (h, i) REFERENCES t1(b, c));
  1676. }
  1677. } {}
  1678. do_test fkey2-genfkey.1.2 {
  1679. catchsql { INSERT INTO t2 VALUES(1, 2) }
  1680. } {1 {foreign key constraint failed}}
  1681. do_test fkey2-genfkey.1.3 {
  1682. execsql {
  1683. INSERT INTO t1 VALUES(1, 2, 3);
  1684. INSERT INTO t2 VALUES(1, 2);
  1685. }
  1686. } {}
  1687. do_test fkey2-genfkey.1.4 {
  1688. execsql { INSERT INTO t2 VALUES(NULL, 3) }
  1689. } {}
  1690. do_test fkey2-genfkey.1.5 {
  1691. catchsql { UPDATE t2 SET e = 5 WHERE e IS NULL }
  1692. } {1 {foreign key constraint failed}}
  1693. do_test fkey2-genfkey.1.6 {
  1694. execsql { UPDATE t2 SET e = 1 WHERE e IS NULL }
  1695. } {}
  1696. do_test fkey2-genfkey.1.7 {
  1697. execsql { UPDATE t2 SET e = NULL WHERE f = 3 }
  1698. } {}
  1699. do_test fkey2-genfkey.1.8 {
  1700. catchsql { UPDATE t1 SET a = 10 }
  1701. } {1 {foreign key constraint failed}}
  1702. do_test fkey2-genfkey.1.9 {
  1703. catchsql { UPDATE t1 SET a = NULL }
  1704. } {1 {datatype mismatch}}
  1705. do_test fkey2-genfkey.1.10 {
  1706. catchsql { DELETE FROM t1 }
  1707. } {1 {foreign key constraint failed}}
  1708. do_test fkey2-genfkey.1.11 {
  1709. execsql { UPDATE t2 SET e = NULL }
  1710. } {}
  1711. do_test fkey2-genfkey.1.12 {
  1712. execsql {
  1713. UPDATE t1 SET a = 10;
  1714. DELETE FROM t1;
  1715. DELETE FROM t2;
  1716. }
  1717. } {}
  1718. do_test fkey2-genfkey.1.13 {
  1719. execsql {
  1720. INSERT INTO t3 VALUES(1, NULL, NULL);
  1721. INSERT INTO t3 VALUES(1, 2, NULL);
  1722. INSERT INTO t3 VALUES(1, NULL, 3);
  1723. }
  1724. } {}
  1725. do_test fkey2-genfkey.1.14 {
  1726. catchsql { INSERT INTO t3 VALUES(3, 1, 4) }
  1727. } {1 {foreign key constraint failed}}
  1728. do_test fkey2-genfkey.1.15 {
  1729. execsql {
  1730. INSERT INTO t1 VALUES(1, 1, 4);
  1731. INSERT INTO t3 VALUES(3, 1, 4);
  1732. }
  1733. } {}
  1734. do_test fkey2-genfkey.1.16 {
  1735. catchsql { DELETE FROM t1 }
  1736. } {1 {foreign key constraint failed}}
  1737. do_test fkey2-genfkey.1.17 {
  1738. catchsql { UPDATE t1 SET b = 10}
  1739. } {1 {foreign key constraint failed}}
  1740. do_test fkey2-genfkey.1.18 {
  1741. execsql { UPDATE t1 SET a = 10}
  1742. } {}
  1743. do_test fkey2-genfkey.1.19 {
  1744. catchsql { UPDATE t3 SET h = 'hello' WHERE i = 3}
  1745. } {1 {foreign key constraint failed}}
  1746. drop_all_tables
  1747. do_test fkey2-genfkey.2.1 {
  1748. execsql {
  1749. CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c, UNIQUE(b, c));
  1750. CREATE TABLE t2(e REFERENCES t1 ON UPDATE CASCADE ON DELETE CASCADE, f);
  1751. CREATE TABLE t3(g, h, i,
  1752. FOREIGN KEY (h, i)
  1753. REFERENCES t1(b, c) ON UPDATE CASCADE ON DELETE CASCADE
  1754. );
  1755. }
  1756. } {}
  1757. do_test fkey2-genfkey.2.2 {
  1758. execsql {
  1759. INSERT INTO t1 VALUES(1, 2, 3);
  1760. INSERT INTO t1 VALUES(4, 5, 6);
  1761. INSERT INTO t2 VALUES(1, 'one');
  1762. INSERT INTO t2 VALUES(4, 'four');
  1763. }
  1764. } {}
  1765. do_test fkey2-genfkey.2.3 {
  1766. execsql {
  1767. UPDATE t1 SET a = 2 WHERE a = 1;
  1768. SELECT * FROM t2;
  1769. }
  1770. } {2 one 4 four}
  1771. do_test fkey2-genfkey.2.4 {
  1772. execsql {
  1773. DELETE FROM t1 WHERE a = 4;
  1774. SELECT * FROM t2;
  1775. }
  1776. } {2 one}
  1777. do_test fkey2-genfkey.2.5 {
  1778. execsql {
  1779. INSERT INTO t3 VALUES('hello', 2, 3);
  1780. UPDATE t1 SET c = 2;
  1781. SELECT * FROM t3;
  1782. }
  1783. } {hello 2 2}
  1784. do_test fkey2-genfkey.2.6 {
  1785. execsql {
  1786. DELETE FROM t1;
  1787. SELECT * FROM t3;
  1788. }
  1789. } {}
  1790. drop_all_tables
  1791. do_test fkey2-genfkey.3.1 {
  1792. execsql {
  1793. CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c, UNIQUE(c, b));
  1794. CREATE TABLE t2(e REFERENCES t1 ON UPDATE SET NULL ON DELETE SET NULL, f);
  1795. CREATE TABLE t3(g, h, i,
  1796. FOREIGN KEY (h, i)
  1797. REFERENCES t1(b, c) ON UPDATE SET NULL ON DELETE SET NULL
  1798. );
  1799. }
  1800. } {}
  1801. do_test fkey2-genfkey.3.2 {
  1802. execsql {
  1803. INSERT INTO t1 VALUES(1, 2, 3);
  1804. INSERT INTO t1 VALUES(4, 5, 6);
  1805. INSERT INTO t2 VALUES(1, 'one');
  1806. INSERT INTO t2 VALUES(4, 'four');
  1807. }
  1808. } {}
  1809. do_test fkey2-genfkey.3.3 {
  1810. execsql {
  1811. UPDATE t1 SET a = 2 WHERE a = 1;
  1812. SELECT * FROM t2;
  1813. }
  1814. } {{} one 4 four}
  1815. do_test fkey2-genfkey.3.4 {
  1816. execsql {
  1817. DELETE FROM t1 WHERE a = 4;
  1818. SELECT * FROM t2;
  1819. }
  1820. } {{} one {} four}
  1821. do_test fkey2-genfkey.3.5 {
  1822. execsql {
  1823. INSERT INTO t3 VALUES('hello', 2, 3);
  1824. UPDATE t1 SET c = 2;
  1825. SELECT * FROM t3;
  1826. }
  1827. } {hello {} {}}
  1828. do_test fkey2-genfkey.3.6 {
  1829. execsql {
  1830. UPDATE t3 SET h = 2, i = 2;
  1831. DELETE FROM t1;
  1832. SELECT * FROM t3;
  1833. }
  1834. } {hello {} {}}
  1835. #-------------------------------------------------------------------------
  1836. # Verify that ticket dd08e5a988d00decc4a543daa8dbbfab9c577ad8 has been
  1837. # fixed.
  1838. #
  1839. do_test fkey2-dd08e5.1.1 {
  1840. execsql {
  1841. PRAGMA foreign_keys=ON;
  1842. CREATE TABLE tdd08(a INTEGER PRIMARY KEY, b);
  1843. CREATE UNIQUE INDEX idd08 ON tdd08(a,b);
  1844. INSERT INTO tdd08 VALUES(200,300);
  1845. CREATE TABLE tdd08_b(w,x,y, FOREIGN KEY(x,y) REFERENCES tdd08(a,b));
  1846. INSERT INTO tdd08_b VALUES(100,200,300);
  1847. }
  1848. } {}
  1849. do_test fkey2-dd08e5.1.2 {
  1850. catchsql {
  1851. DELETE FROM tdd08;
  1852. }
  1853. } {1 {foreign key constraint failed}}
  1854. do_test fkey2-dd08e5.1.3 {
  1855. execsql {
  1856. SELECT * FROM tdd08;
  1857. }
  1858. } {200 300}
  1859. do_test fkey2-dd08e5.1.4 {
  1860. catchsql {
  1861. INSERT INTO tdd08_b VALUES(400,500,300);
  1862. }
  1863. } {1 {foreign key constraint failed}}
  1864. do_test fkey2-dd08e5.1.5 {
  1865. catchsql {
  1866. UPDATE tdd08_b SET x=x+1;
  1867. }
  1868. } {1 {foreign key constraint failed}}
  1869. do_test fkey2-dd08e5.1.6 {
  1870. catchsql {
  1871. UPDATE tdd08 SET a=a+1;
  1872. }
  1873. } {1 {foreign key constraint failed}}
  1874. #-------------------------------------------------------------------------
  1875. # Verify that ticket ce7c133ea6cc9ccdc1a60d80441f80b6180f5eba
  1876. # fixed.
  1877. #
  1878. do_test fkey2-ce7c13.1.1 {
  1879. execsql {
  1880. CREATE TABLE tce71(a INTEGER PRIMARY KEY, b);
  1881. CREATE UNIQUE INDEX ice71 ON tce71(a,b);
  1882. INSERT INTO tce71 VALUES(100,200);
  1883. CREATE TABLE tce72(w, x, y, FOREIGN KEY(x,y) REFERENCES tce71(a,b));
  1884. INSERT INTO tce72 VALUES(300,100,200);
  1885. UPDATE tce71 set b = 200 where a = 100;
  1886. SELECT * FROM tce71, tce72;
  1887. }
  1888. } {100 200 300 100 200}
  1889. do_test fkey2-ce7c13.1.2 {
  1890. catchsql {
  1891. UPDATE tce71 set b = 201 where a = 100;
  1892. }
  1893. } {1 {foreign key constraint failed}}
  1894. do_test fkey2-ce7c13.1.3 {
  1895. catchsql {
  1896. UPDATE tce71 set a = 101 where a = 100;
  1897. }
  1898. } {1 {foreign key constraint failed}}
  1899. do_test fkey2-ce7c13.1.4 {
  1900. execsql {
  1901. CREATE TABLE tce73(a INTEGER PRIMARY KEY, b, UNIQUE(a,b));
  1902. INSERT INTO tce73 VALUES(100,200);
  1903. CREATE TABLE tce74(w, x, y, FOREIGN KEY(x,y) REFERENCES tce73(a,b));
  1904. INSERT INTO tce74 VALUES(300,100,200);
  1905. UPDATE tce73 set b = 200 where a = 100;
  1906. SELECT * FROM tce73, tce74;
  1907. }
  1908. } {100 200 300 100 200}
  1909. do_test fkey2-ce7c13.1.5 {
  1910. catchsql {
  1911. UPDATE tce73 set b = 201 where a = 100;
  1912. }
  1913. } {1 {foreign key constraint failed}}
  1914. do_test fkey2-ce7c13.1.6 {
  1915. catchsql {
  1916. UPDATE tce73 set a = 101 where a = 100;
  1917. }
  1918. } {1 {foreign key constraint failed}}
  1919. finish_test