ForeignKeyTest.java revision 6be69eb5aa66706ff5880e12c17ea6e62c35eda3
10045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar/* 20045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar * Copyright (C) 2017 The Android Open Source Project 30045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar * 40045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar * Licensed under the Apache License, Version 2.0 (the "License"); 50045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar * you may not use this file except in compliance with the License. 60045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar * You may obtain a copy of the License at 70045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar * 80045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar * http://www.apache.org/licenses/LICENSE-2.0 90045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar * 100045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar * Unless required by applicable law or agreed to in writing, software 110045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar * distributed under the License is distributed on an "AS IS" BASIS, 120045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 130045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar * See the License for the specific language governing permissions and 140045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar * limitations under the License. 150045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar */ 160045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar 1764db0cc15b78b62a1d44a70fc8b4552e660d952cYigit Boyarpackage android.arch.persistence.room.integration.testapp.test; 180045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar 1924b0c2d5bde2848da5caa57d9b1ec2a95d12bcd9Yuichi Arakiimport static org.hamcrest.CoreMatchers.both; 200045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyarimport static org.hamcrest.CoreMatchers.containsString; 2124b0c2d5bde2848da5caa57d9b1ec2a95d12bcd9Yuichi Arakiimport static org.hamcrest.CoreMatchers.either; 220045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyarimport static org.hamcrest.CoreMatchers.equalTo; 230045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyarimport static org.hamcrest.CoreMatchers.instanceOf; 240045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyarimport static org.hamcrest.CoreMatchers.notNullValue; 250045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyarimport static org.hamcrest.CoreMatchers.nullValue; 260045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyarimport static org.hamcrest.MatcherAssert.assertThat; 2724b0c2d5bde2848da5caa57d9b1ec2a95d12bcd9Yuichi Arakiimport static org.hamcrest.core.Is.is; 280045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar 2964db0cc15b78b62a1d44a70fc8b4552e660d952cYigit Boyarimport android.arch.persistence.room.Dao; 3064db0cc15b78b62a1d44a70fc8b4552e660d952cYigit Boyarimport android.arch.persistence.room.Database; 3164db0cc15b78b62a1d44a70fc8b4552e660d952cYigit Boyarimport android.arch.persistence.room.Delete; 3264db0cc15b78b62a1d44a70fc8b4552e660d952cYigit Boyarimport android.arch.persistence.room.Entity; 3364db0cc15b78b62a1d44a70fc8b4552e660d952cYigit Boyarimport android.arch.persistence.room.ForeignKey; 3464db0cc15b78b62a1d44a70fc8b4552e660d952cYigit Boyarimport android.arch.persistence.room.Ignore; 3564db0cc15b78b62a1d44a70fc8b4552e660d952cYigit Boyarimport android.arch.persistence.room.Index; 3664db0cc15b78b62a1d44a70fc8b4552e660d952cYigit Boyarimport android.arch.persistence.room.Insert; 3764db0cc15b78b62a1d44a70fc8b4552e660d952cYigit Boyarimport android.arch.persistence.room.PrimaryKey; 3864db0cc15b78b62a1d44a70fc8b4552e660d952cYigit Boyarimport android.arch.persistence.room.Query; 3964db0cc15b78b62a1d44a70fc8b4552e660d952cYigit Boyarimport android.arch.persistence.room.Room; 4064db0cc15b78b62a1d44a70fc8b4552e660d952cYigit Boyarimport android.arch.persistence.room.RoomDatabase; 413542101509120586bbae17b1f748f302e1fb82a3Yigit Boyarimport android.database.sqlite.SQLiteException; 423542101509120586bbae17b1f748f302e1fb82a3Yigit Boyarimport android.support.test.InstrumentationRegistry; 433542101509120586bbae17b1f748f302e1fb82a3Yigit Boyarimport android.support.test.filters.SmallTest; 443542101509120586bbae17b1f748f302e1fb82a3Yigit Boyarimport android.support.test.runner.AndroidJUnit4; 450045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar 4624b0c2d5bde2848da5caa57d9b1ec2a95d12bcd9Yuichi Arakiimport org.hamcrest.Matcher; 470045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyarimport org.junit.Before; 480045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyarimport org.junit.Test; 490045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyarimport org.junit.runner.RunWith; 500045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar 5136023a6ffdcc24a64c3f86efd4e754cfc3493761Yigit Boyarimport java.util.Locale; 5236023a6ffdcc24a64c3f86efd4e754cfc3493761Yigit Boyar 530045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar@RunWith(AndroidJUnit4.class) 540045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar@SmallTest 550045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyarpublic class ForeignKeyTest { 560045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar @Database(version = 1, entities = {A.class, B.class, C.class, D.class, E.class}, 570045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar exportSchema = false) 580045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar abstract static class ForeignKeyDb extends RoomDatabase { 590045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar abstract FkDao dao(); 600045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar } 610045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar 620045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar @SuppressWarnings({"SqlNoDataSourceInspection", "SameParameterValue"}) 630045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar @Dao 640045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar interface FkDao { 650045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar @Insert 660045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar void insert(A... a); 670045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar 680045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar @Insert 690045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar void insert(B... b); 700045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar 710045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar @Insert 720045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar void insert(C... c); 730045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar 740045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar @Insert 750045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar void insert(D... d); 760045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar 773542101509120586bbae17b1f748f302e1fb82a3Yigit Boyar @Query("SELECT * FROM A WHERE id = :id") 780045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar A loadA(int id); 790045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar 803542101509120586bbae17b1f748f302e1fb82a3Yigit Boyar @Query("SELECT * FROM B WHERE id = :id") 810045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar B loadB(int id); 820045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar 833542101509120586bbae17b1f748f302e1fb82a3Yigit Boyar @Query("SELECT * FROM C WHERE id = :id") 840045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar C loadC(int id); 850045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar 863542101509120586bbae17b1f748f302e1fb82a3Yigit Boyar @Query("SELECT * FROM D WHERE id = :id") 870045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar D loadD(int id); 880045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar 893542101509120586bbae17b1f748f302e1fb82a3Yigit Boyar @Query("SELECT * FROM E WHERE id = :id") 900045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar E loadE(int id); 910045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar 920045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar @Delete 930045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar void delete(A... a); 940045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar 950045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar @Delete 960045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar void delete(B... b); 970045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar 980045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar @Delete 990045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar void delete(C... c); 1000045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar 1010045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar @Query("UPDATE A SET name = :newName WHERE id = :id") 1020045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar void changeNameA(int id, String newName); 1030045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar 1040045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar @Insert 1050045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar void insert(E... e); 1060045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar 1070045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar 1080045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar } 1090045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar 1100045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar @Entity(indices = {@Index(value = "name", unique = true), 1110045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar @Index(value = {"name", "lastName"}, unique = true)}) 1120045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar static class A { 1130045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar @PrimaryKey(autoGenerate = true) 1140045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar public int id; 1150045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar public String name; 1160045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar public String lastName; 1170045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar 1180045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar A(String name) { 1190045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar this.name = name; 1200045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar } 1210045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar 122f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar @Ignore 1230045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar A(String name, String lastName) { 1240045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar this.name = name; 1250045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar this.lastName = lastName; 1260045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar } 1270045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar } 1280045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar 1290045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar @SuppressWarnings("WeakerAccess") 1300045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar @Entity(foreignKeys = { 1310045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar @ForeignKey(entity = A.class, 1320045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar parentColumns = "name", 1330045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar childColumns = "aName")}) 1340045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar 1350045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar static class B { 1360045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar @PrimaryKey(autoGenerate = true) 1370045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar public int id; 1380045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar public String aName; 1390045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar 1400045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar B(String aName) { 1410045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar this.aName = aName; 1420045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar } 1430045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar } 1440045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar 1450045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar @SuppressWarnings("WeakerAccess") 1460045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar @Entity(foreignKeys = { 1470045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar @ForeignKey(entity = A.class, 1480045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar parentColumns = "name", 1490045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar childColumns = "aName", 1500045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar deferred = true)}) 1510045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar static class C { 1520045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar @PrimaryKey(autoGenerate = true) 1530045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar public int id; 1540045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar public String aName; 1550045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar 1560045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar C(String aName) { 1570045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar this.aName = aName; 1580045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar } 1590045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar } 1600045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar 1610045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar @SuppressWarnings("WeakerAccess") 1620045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar @Entity(foreignKeys = { 1630045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar @ForeignKey(entity = A.class, 1640045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar parentColumns = "name", 1650045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar childColumns = "aName", 1660045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar onDelete = ForeignKey.CASCADE, 1670045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar onUpdate = ForeignKey.CASCADE)}) 1680045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar static class D { 1690045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar @PrimaryKey(autoGenerate = true) 1700045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar public int id; 1710045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar public String aName; 1720045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar 1730045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar D(String aName) { 1740045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar this.aName = aName; 1750045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar } 1760045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar } 1770045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar 1780045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar @SuppressWarnings("WeakerAccess") 1790045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar @Entity(foreignKeys = { 1800045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar @ForeignKey(entity = A.class, 1810045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar parentColumns = {"name", "lastName"}, 1820045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar childColumns = {"aName", "aLastName"}, 1830045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar onDelete = ForeignKey.SET_NULL, 1840045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar onUpdate = ForeignKey.CASCADE)}) 1850045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar static class E { 1860045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar @PrimaryKey(autoGenerate = true) 1870045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar public int id; 1880045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar public String aName; 1890045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar public String aLastName; 1900045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar 1910045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar E() { 1920045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar } 1930045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar 194f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar @Ignore 1950045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar E(String aName, String aLastName) { 1960045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar this.aName = aName; 1970045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar this.aLastName = aLastName; 1980045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar } 1990045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar } 2000045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar 2010045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar 2020045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar private ForeignKeyDb mDb; 2030045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar private FkDao mDao; 2040045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar 2050045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar @Before 2060045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar public void openDb() { 2076be69eb5aa66706ff5880e12c17ea6e62c35eda3Yuichi Araki mDb = Room.inMemoryDatabaseBuilder(InstrumentationRegistry.getTargetContext(), 2080045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar ForeignKeyDb.class).build(); 2090045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar mDao = mDb.dao(); 2100045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar } 2110045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar 2120045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar @Test 2130045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar public void simpleForeignKeyFailure() { 2140045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar Throwable t = catchException(new ThrowingRunnable() { 2150045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar @Override 2160045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar public void run() throws Exception { 2170045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar mDao.insert(new B("foo")); 2180045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar } 2190045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar }); 2200045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar assertThat(t, instanceOf(SQLiteException.class)); 22124b0c2d5bde2848da5caa57d9b1ec2a95d12bcd9Yuichi Araki assertThat(t.getMessage().toUpperCase(Locale.US), is(foreignKeyErrorMessage())); 2220045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar } 2230045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar 2240045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar @Test 2250045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar public void simpleForeignKeyDeferredFailure() { 2260045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar Throwable t = catchException(new ThrowingRunnable() { 2270045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar @Override 2280045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar public void run() throws Exception { 2290045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar mDao.insert(new C("foo")); 2300045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar } 2310045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar }); 2320045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar assertThat(t, instanceOf(SQLiteException.class)); 23324b0c2d5bde2848da5caa57d9b1ec2a95d12bcd9Yuichi Araki assertThat(t.getMessage().toUpperCase(Locale.US), is(foreignKeyErrorMessage())); 2340045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar } 2350045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar 2360045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar @Test 2370045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar public void immediateForeignKeyFailure() { 2380045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar Throwable t = catchException(new ThrowingRunnable() { 2390045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar @Override 2400045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar public void run() throws Exception { 2410045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar try { 2420045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar mDb.beginTransaction(); 2430045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar mDao.insert(new B("foo")); 2440045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar mDao.insert(new A("foo")); 2450045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar mDb.setTransactionSuccessful(); 2460045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar } finally { 2470045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar mDb.endTransaction(); 2480045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar } 2490045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar } 2500045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar }); 2510045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar assertThat(t, instanceOf(SQLiteException.class)); 2520045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar } 2530045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar 2540045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar @Test 2550045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar public void deferredForeignKeySuccess() { 2560045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar try { 2570045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar mDb.beginTransaction(); 2580045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar mDao.insert(new C("foo")); 2590045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar mDao.insert(new A("foo")); 2600045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar mDb.setTransactionSuccessful(); 2610045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar } finally { 2620045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar mDb.endTransaction(); 2630045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar } 2640045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar assertThat(mDao.loadA(1), notNullValue()); 2650045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar assertThat(mDao.loadC(1), notNullValue()); 2660045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar } 2670045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar 2680045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar @Test 2690045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar public void onDelete_noAction() { 2700045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar mDao.insert(new A("a1")); 2710045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar final A a = mDao.loadA(1); 2720045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar mDao.insert(new B("a1")); 2730045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar Throwable t = catchException(new ThrowingRunnable() { 2740045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar @Override 2750045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar public void run() throws Exception { 2760045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar mDao.delete(a); 2770045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar } 2780045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar }); 2790045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar assertThat(t, instanceOf(SQLiteException.class)); 28024b0c2d5bde2848da5caa57d9b1ec2a95d12bcd9Yuichi Araki assertThat(t.getMessage().toUpperCase(Locale.US), is(foreignKeyErrorMessage())); 2810045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar } 2820045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar 2830045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar @Test 2840045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar public void onDelete_noAction_withTransaction() { 2850045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar mDao.insert(new A("a1")); 2860045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar final A a = mDao.loadA(1); 2870045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar mDao.insert(new B("a1")); 2880045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar final B b = mDao.loadB(1); 2890045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar Throwable t = catchException(new ThrowingRunnable() { 2900045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar @Override 2910045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar public void run() throws Exception { 2920045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar deleteInTransaction(a, b); 2930045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar } 2940045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar }); 2950045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar assertThat(t, instanceOf(SQLiteException.class)); 29624b0c2d5bde2848da5caa57d9b1ec2a95d12bcd9Yuichi Araki assertThat(t.getMessage().toUpperCase(Locale.US), is(foreignKeyErrorMessage())); 2970045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar } 2980045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar 2990045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar @Test 3000045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar public void onDelete_noAction_deferred() { 3010045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar mDao.insert(new A("a1")); 3020045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar final A a = mDao.loadA(1); 3030045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar mDao.insert(new C("a1")); 3040045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar Throwable t = catchException(new ThrowingRunnable() { 3050045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar @Override 3060045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar public void run() throws Exception { 3070045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar mDao.delete(a); 3080045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar } 3090045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar }); 3100045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar assertThat(t, instanceOf(SQLiteException.class)); 31124b0c2d5bde2848da5caa57d9b1ec2a95d12bcd9Yuichi Araki assertThat(t.getMessage().toUpperCase(Locale.US), is(foreignKeyErrorMessage())); 3120045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar } 3130045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar 3140045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar @Test 3150045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar public void onDelete_noAction__deferredWithTransaction() { 3160045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar mDao.insert(new A("a1")); 3170045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar final A a = mDao.loadA(1); 3180045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar mDao.insert(new C("a1")); 3190045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar final C c = mDao.loadC(1); 3200045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar deleteInTransaction(a, c); 3210045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar } 3220045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar 3230045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar @Test 3240045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar public void onDelete_cascade() { 3250045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar mDao.insert(new A("a1")); 3260045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar final A a = mDao.loadA(1); 3270045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar mDao.insert(new D("a1")); 3280045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar final D d = mDao.loadD(1); 3290045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar assertThat("test sanity", d, notNullValue()); 3300045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar mDao.delete(a); 3310045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar assertThat(mDao.loadD(1), nullValue()); 3320045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar } 3330045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar 3340045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar @Test 3350045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar public void onUpdate_cascade() { 3360045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar mDao.insert(new A("a1")); 3370045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar mDao.insert(new D("a1")); 3380045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar final D d = mDao.loadD(1); 3390045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar assertThat("test sanity", d, notNullValue()); 3400045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar mDao.changeNameA(1, "bla"); 3410045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar assertThat(mDao.loadD(1).aName, equalTo("bla")); 3420045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar assertThat(mDao.loadA(1).name, equalTo("bla")); 3430045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar } 3440045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar 3450045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar @Test 3460045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar public void multipleReferences() { 3470045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar mDao.insert(new A("a1", "a2")); 3480045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar final A a = mDao.loadA(1); 3490045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar assertThat("test sanity", a, notNullValue()); 3500045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar Throwable t = catchException(new ThrowingRunnable() { 3510045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar @Override 3520045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar public void run() throws Exception { 3530045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar mDao.insert(new E("a1", "dsa")); 3540045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar } 3550045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar }); 35624b0c2d5bde2848da5caa57d9b1ec2a95d12bcd9Yuichi Araki assertThat(t.getMessage().toUpperCase(Locale.US), is(foreignKeyErrorMessage())); 3570045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar } 3580045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar 3590045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar @Test 3600045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar public void onDelete_setNull_multipleReferences() { 3610045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar mDao.insert(new A("a1", "a2")); 3620045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar final A a = mDao.loadA(1); 3630045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar mDao.insert(new E("a1", "a2")); 3640045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar assertThat(mDao.loadE(1), notNullValue()); 3650045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar mDao.delete(a); 3660045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar E e = mDao.loadE(1); 3670045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar assertThat(e, notNullValue()); 3680045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar assertThat(e.aName, nullValue()); 3690045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar assertThat(e.aLastName, nullValue()); 3700045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar } 3710045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar 3720045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar @Test 3730045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar public void onUpdate_cascade_multipleReferences() { 3740045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar mDao.insert(new A("a1", "a2")); 3750045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar final A a = mDao.loadA(1); 3760045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar mDao.insert(new E("a1", "a2")); 3770045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar assertThat(mDao.loadE(1), notNullValue()); 3780045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar mDao.changeNameA(1, "foo"); 3790045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar assertThat(mDao.loadE(1), notNullValue()); 3800045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar assertThat(mDao.loadE(1).aName, equalTo("foo")); 3810045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar assertThat(mDao.loadE(1).aLastName, equalTo("a2")); 3820045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar } 3830045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar 38424b0c2d5bde2848da5caa57d9b1ec2a95d12bcd9Yuichi Araki private static Matcher<String> foreignKeyErrorMessage() { 38524b0c2d5bde2848da5caa57d9b1ec2a95d12bcd9Yuichi Araki return either(containsString("FOREIGN KEY")) 38624b0c2d5bde2848da5caa57d9b1ec2a95d12bcd9Yuichi Araki .or(both(containsString("CODE 19")).and(containsString("CONSTRAINT FAILED"))); 38724b0c2d5bde2848da5caa57d9b1ec2a95d12bcd9Yuichi Araki } 38824b0c2d5bde2848da5caa57d9b1ec2a95d12bcd9Yuichi Araki 3890045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar @SuppressWarnings("Duplicates") 3900045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar private void deleteInTransaction(A a, B b) { 3910045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar mDb.beginTransaction(); 3920045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar try { 3930045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar mDao.delete(a); 3940045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar mDao.delete(b); 3950045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar mDb.setTransactionSuccessful(); 3960045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar } finally { 3970045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar mDb.endTransaction(); 3980045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar } 3990045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar } 4000045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar 4010045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar @SuppressWarnings("Duplicates") 4020045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar private void deleteInTransaction(A a, C c) { 4030045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar mDb.beginTransaction(); 4040045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar try { 4050045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar mDao.delete(a); 4060045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar mDao.delete(c); 4070045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar mDb.setTransactionSuccessful(); 4080045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar } finally { 4090045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar mDb.endTransaction(); 4100045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar } 4110045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar } 4120045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar 4130045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar private static Throwable catchException(ThrowingRunnable throwingRunnable) { 4140045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar try { 4150045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar throwingRunnable.run(); 4160045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar } catch (Throwable t) { 4170045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar return t; 4180045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar } 4190045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar throw new RuntimeException("didn't throw an exception"); 4200045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar } 4210045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar 4220045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar private interface ThrowingRunnable { 4230045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar void run() throws Exception; 4240045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar } 4250045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar} 426