KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sleepycat > persist > test > ForeignKeyTest


1 /*-
2  * See the file LICENSE for redistribution information.
3  *
4  * Copyright (c) 2000,2006 Oracle. All rights reserved.
5  *
6  * $Id: ForeignKeyTest.java,v 1.4 2006/10/30 21:14:55 bostic Exp $
7  */

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 JavaDoc;
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 /**
34  * @author Mark Hayes
35  */

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 JavaDoc[] 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);//envConfig, txnTypes);
54
Enumeration JavaDoc 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 JavaDoc,Entity1> pri1;
67     private PrimaryIndex<String JavaDoc,Entity2> pri2;
68     private SecondaryIndex<String JavaDoc,String JavaDoc,Entity1> sec1;
69     private SecondaryIndex<String JavaDoc,String JavaDoc,Entity2> sec2;
70     private DeleteAction onDelete;
71     private String JavaDoc onDeleteLabel;
72     
73     public void tearDown()
74         throws Exception JavaDoc {
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 JavaDoc.class, Entity1.class);
90         sec1 = store.getSecondaryIndex(pri1, String JavaDoc.class, "sk");
91         pri2 = store.getPrimaryIndex(String JavaDoc.class, Entity2.class);
92         sec2 = store.getSecondaryIndex
93             (pri2, String JavaDoc.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 JavaDoc {
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         /*
124          * pri1 contains o1 with primary key "pk1" and index key "sk1".
125          *
126          * pri2 contains o2 with primary key "pk2" and foreign key "pk1",
127          * which is the primary key of pri1.
128          */

129
130         if (onDelete == ABORT) {
131
132             /* Test that we abort trying to delete a referenced key. */
133
134             try {
135                 pri1.delete(txn, "pk1");
136                 fail();
137             } catch (DatabaseException expected) {
138                 txnAbort(txn);
139                 txn = txnBegin();
140             }
141
142             /* Test that we can put a record into store2 with a null foreign
143              * key value. */

144
145             o2 = new Entity2("pk2", null, onDelete);
146             assertNotNull(pri2.put(txn, o2));
147             assertEquals(o2, pri2.get(txn, "pk2", null));
148
149             /* The index2 record should have been deleted since the key was set
150              * to null above. */

151
152             assertNull(sec2.get(txn, "pk1", null));
153
154             /* Test that now we can delete the record in store1, since it is no
155              * longer referenced. */

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             /* Delete the referenced key. */
164
165             assertNotNull(pri1.delete(txn, "pk1"));
166             assertNull(pri1.get(txn, "pk1", null));
167             assertNull(sec1.get(txn, "sk1", null));
168
169             /* The store2 record should still exist, but should have an empty
170              * secondary key since it was nullified. */

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             /* Delete the referenced key. */
180
181             assertNotNull(pri1.delete(txn, "pk1"));
182             assertNull(pri1.get(txn, "pk1", null));
183             assertNull(sec1.get(txn, "sk1", null));
184
185             /* The store2 record should have deleted also. */
186
187             assertNull(pri2.get(txn, "pk2", null));
188             assertNull(sec2.get(txn, "pk1", null));
189
190         } else {
191             throw new IllegalStateException JavaDoc();
192         }
193
194         /*
195          * Test that a foreign key value may not be used that is not present
196          * in the foreign store. "pk2" is not in store1 in this case.
197          */

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 JavaDoc pk;
214
215         @SecondaryKey(relate=ONE_TO_ONE)
216         String JavaDoc sk;
217
218         private Entity1() {}
219
220         Entity1(String JavaDoc pk, String JavaDoc sk) {
221             this.pk = pk;
222             this.sk = sk;
223         }
224
225         @Override JavaDoc
226         public boolean equals(Object JavaDoc 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 JavaDoc pk;
238
239         @SecondaryKey(relate=ONE_TO_ONE, relatedEntity=Entity1.class,
240                                          onRelatedEntityDelete=ABORT)
241         String JavaDoc sk_ABORT;
242
243         @SecondaryKey(relate=ONE_TO_ONE, relatedEntity=Entity1.class,
244                                          onRelatedEntityDelete=CASCADE)
245         String JavaDoc sk_CASCADE;
246
247         @SecondaryKey(relate=ONE_TO_ONE, relatedEntity=Entity1.class,
248                                          onRelatedEntityDelete=NULLIFY)
249         String JavaDoc sk_NULLIFY;
250
251         private Entity2() {}
252
253         Entity2(String JavaDoc pk, String JavaDoc 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 JavaDoc();
267             }
268         }
269
270         String JavaDoc 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 JavaDoc();
280             }
281         }
282
283         @Override JavaDoc
284         public boolean equals(Object JavaDoc 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 JavaDoc o1, Object JavaDoc o2) {
294         if (o1 == null) {
295             return o2 == null;
296         } else {
297             return o1.equals(o2);
298         }
299     }
300 }
301
Popular Tags