1 8 9 package com.sleepycat.persist.test; 10 11 import static com.sleepycat.persist.model.DeleteAction.ABORT; 12 import static com.sleepycat.persist.model.DeleteAction.CASCADE; 13 import static com.sleepycat.persist.model.DeleteAction.NULLIFY; 14 import static com.sleepycat.persist.model.Relationship.ONE_TO_ONE; 15 16 import java.util.Enumeration ; 17 18 import junit.framework.Test; 19 import junit.framework.TestSuite; 20 21 import com.sleepycat.je.DatabaseException; 22 import com.sleepycat.je.Transaction; 23 import com.sleepycat.je.test.TxnTestCase; 24 import com.sleepycat.persist.EntityStore; 25 import com.sleepycat.persist.PrimaryIndex; 26 import com.sleepycat.persist.SecondaryIndex; 27 import com.sleepycat.persist.StoreConfig; 28 import com.sleepycat.persist.model.DeleteAction; 29 import com.sleepycat.persist.model.Entity; 30 import com.sleepycat.persist.model.PrimaryKey; 31 import com.sleepycat.persist.model.SecondaryKey; 32 33 36 public class ForeignKeyTest extends TxnTestCase { 37 38 private static final DeleteAction[] ACTIONS = { 39 ABORT, 40 NULLIFY, 41 CASCADE, 42 }; 43 private static final String [] ACTION_LABELS = { 44 "ABORT", 45 "NULLIFY", 46 "CASCADE", 47 }; 48 49 public static Test suite() { 50 TestSuite suite = new TestSuite(); 51 for (int i = 0; i < ACTIONS.length; i += 1) { 52 TestSuite txnSuite = txnTestSuite 53 (ForeignKeyTest.class, null, null); Enumeration e = txnSuite.tests(); 55 while (e.hasMoreElements()) { 56 ForeignKeyTest test = (ForeignKeyTest) e.nextElement(); 57 test.onDelete = ACTIONS[i]; 58 test.onDeleteLabel = ACTION_LABELS[i]; 59 suite.addTest(test); 60 } 61 } 62 return suite; 63 } 64 65 private EntityStore store; 66 private PrimaryIndex<String ,Entity1> pri1; 67 private PrimaryIndex<String ,Entity2> pri2; 68 private SecondaryIndex<String ,String ,Entity1> sec1; 69 private SecondaryIndex<String ,String ,Entity2> sec2; 70 private DeleteAction onDelete; 71 private String onDeleteLabel; 72 73 public void tearDown() 74 throws Exception { 75 76 super.tearDown(); 77 setName(getName() + '-' + onDeleteLabel); 78 } 79 80 private void open() 81 throws DatabaseException { 82 83 StoreConfig config = new StoreConfig(); 84 config.setAllowCreate(envConfig.getAllowCreate()); 85 config.setTransactional(envConfig.getTransactional()); 86 87 store = new EntityStore(env, "test", config); 88 89 pri1 = store.getPrimaryIndex(String .class, Entity1.class); 90 sec1 = store.getSecondaryIndex(pri1, String .class, "sk"); 91 pri2 = store.getPrimaryIndex(String .class, Entity2.class); 92 sec2 = store.getSecondaryIndex 93 (pri2, String .class, "sk_" + onDeleteLabel); 94 } 95 96 private void close() 97 throws DatabaseException { 98 99 store.close(); 100 } 101 102 public void testForeignKeys() 103 throws Exception { 104 105 open(); 106 Transaction txn = txnBegin(); 107 108 Entity1 o1 = new Entity1("pk1", "sk1"); 109 assertNull(pri1.put(txn, o1)); 110 111 assertEquals(o1, pri1.get(txn, "pk1", null)); 112 assertEquals(o1, sec1.get(txn, "sk1", null)); 113 114 Entity2 o2 = new Entity2("pk2", "pk1", onDelete); 115 assertNull(pri2.put(txn, o2)); 116 117 assertEquals(o2, pri2.get(txn, "pk2", null)); 118 assertEquals(o2, sec2.get(txn, "pk1", null)); 119 120 txnCommit(txn); 121 txn = txnBegin(); 122 123 129 130 if (onDelete == ABORT) { 131 132 133 134 try { 135 pri1.delete(txn, "pk1"); 136 fail(); 137 } catch (DatabaseException expected) { 138 txnAbort(txn); 139 txn = txnBegin(); 140 } 141 142 144 145 o2 = new Entity2("pk2", null, onDelete); 146 assertNotNull(pri2.put(txn, o2)); 147 assertEquals(o2, pri2.get(txn, "pk2", null)); 148 149 151 152 assertNull(sec2.get(txn, "pk1", null)); 153 154 156 157 assertNotNull(pri1.delete(txn, "pk1")); 158 assertNull(pri1.get(txn, "pk1", null)); 159 assertNull(sec1.get(txn, "sk1", null)); 160 161 } else if (onDelete == NULLIFY) { 162 163 164 165 assertNotNull(pri1.delete(txn, "pk1")); 166 assertNull(pri1.get(txn, "pk1", null)); 167 assertNull(sec1.get(txn, "sk1", null)); 168 169 171 172 o2 = pri2.get(txn, "pk2", null); 173 assertNotNull(o2); 174 assertEquals("pk2", o2.pk); 175 assertEquals(null, o2.getSk(onDelete)); 176 177 } else if (onDelete == CASCADE) { 178 179 180 181 assertNotNull(pri1.delete(txn, "pk1")); 182 assertNull(pri1.get(txn, "pk1", null)); 183 assertNull(sec1.get(txn, "sk1", null)); 184 185 186 187 assertNull(pri2.get(txn, "pk2", null)); 188 assertNull(sec2.get(txn, "pk1", null)); 189 190 } else { 191 throw new IllegalStateException (); 192 } 193 194 198 Entity2 o3 = new Entity2("pk3", "pk2", onDelete); 199 try { 200 pri2.put(txn, o3); 201 fail(); 202 } catch (DatabaseException expected) { 203 } 204 205 txnCommit(txn); 206 close(); 207 } 208 209 @Entity 210 static class Entity1 { 211 212 @PrimaryKey 213 String pk; 214 215 @SecondaryKey(relate=ONE_TO_ONE) 216 String sk; 217 218 private Entity1() {} 219 220 Entity1(String pk, String sk) { 221 this.pk = pk; 222 this.sk = sk; 223 } 224 225 @Override 226 public boolean equals(Object other) { 227 Entity1 o = (Entity1) other; 228 return nullOrEqual(pk, o.pk) && 229 nullOrEqual(sk, o.sk); 230 } 231 } 232 233 @Entity 234 static class Entity2 { 235 236 @PrimaryKey 237 String pk; 238 239 @SecondaryKey(relate=ONE_TO_ONE, relatedEntity=Entity1.class, 240 onRelatedEntityDelete=ABORT) 241 String sk_ABORT; 242 243 @SecondaryKey(relate=ONE_TO_ONE, relatedEntity=Entity1.class, 244 onRelatedEntityDelete=CASCADE) 245 String sk_CASCADE; 246 247 @SecondaryKey(relate=ONE_TO_ONE, relatedEntity=Entity1.class, 248 onRelatedEntityDelete=NULLIFY) 249 String sk_NULLIFY; 250 251 private Entity2() {} 252 253 Entity2(String pk, String sk, DeleteAction action) { 254 this.pk = pk; 255 switch (action) { 256 case ABORT: 257 sk_ABORT = sk; 258 break; 259 case CASCADE: 260 sk_CASCADE = sk; 261 break; 262 case NULLIFY: 263 sk_NULLIFY = sk; 264 break; 265 default: 266 throw new IllegalArgumentException (); 267 } 268 } 269 270 String getSk(DeleteAction action) { 271 switch (action) { 272 case ABORT: 273 return sk_ABORT; 274 case CASCADE: 275 return sk_CASCADE; 276 case NULLIFY: 277 return sk_NULLIFY; 278 default: 279 throw new IllegalArgumentException (); 280 } 281 } 282 283 @Override 284 public boolean equals(Object other) { 285 Entity2 o = (Entity2) other; 286 return nullOrEqual(pk, o.pk) && 287 nullOrEqual(sk_ABORT, o.sk_ABORT) && 288 nullOrEqual(sk_CASCADE, o.sk_CASCADE) && 289 nullOrEqual(sk_NULLIFY, o.sk_NULLIFY); 290 } 291 } 292 293 static boolean nullOrEqual(Object o1, Object o2) { 294 if (o1 == null) { 295 return o2 == null; 296 } else { 297 return o1.equals(o2); 298 } 299 } 300 } 301 | Popular Tags |