1/*-
2 * See the file LICENSE for redistribution information.
3 *
4 * Copyright (c) 2000,2008 Oracle.  All rights reserved.
5 *
6 * $Id: JoinTest.java,v 12.9 2008/02/07 17:12:31 mark Exp $
7 */
8
9package com.sleepycat.collections.test;
10
11import java.util.Map;
12
13import junit.framework.Test;
14import junit.framework.TestCase;
15
16import com.sleepycat.bind.serial.StoredClassCatalog;
17import com.sleepycat.bind.serial.test.MarshalledObject;
18import com.sleepycat.collections.StoredCollection;
19import com.sleepycat.collections.StoredContainer;
20import com.sleepycat.collections.StoredIterator;
21import com.sleepycat.collections.StoredMap;
22import com.sleepycat.collections.TransactionRunner;
23import com.sleepycat.collections.TransactionWorker;
24import com.sleepycat.collections.TupleSerialFactory;
25import com.sleepycat.compat.DbCompat;
26import com.sleepycat.db.Database;
27import com.sleepycat.db.DatabaseConfig;
28import com.sleepycat.db.Environment;
29import com.sleepycat.db.SecondaryConfig;
30import com.sleepycat.db.SecondaryDatabase;
31import com.sleepycat.util.test.SharedTestUtils;
32import com.sleepycat.util.test.TestEnv;
33
34/**
35 * @author Mark Hayes
36 */
37public class JoinTest extends TestCase
38    implements TransactionWorker {
39
40    private static final String MATCH_DATA = "d4"; // matches both keys = "yes"
41    private static final String MATCH_KEY  = "k4"; // matches both keys = "yes"
42    private static final String[] VALUES = {"yes", "yes"};
43
44    public static void main(String[] args)
45        throws Exception {
46
47        junit.framework.TestResult tr =
48            junit.textui.TestRunner.run(suite());
49        if (tr.errorCount() > 0 ||
50            tr.failureCount() > 0) {
51            System.exit(1);
52        } else {
53            System.exit(0);
54        }
55    }
56
57    public static Test suite()
58        throws Exception {
59
60        return new JoinTest();
61    }
62
63    private Environment env;
64    private TransactionRunner runner;
65    private StoredClassCatalog catalog;
66    private TupleSerialFactory factory;
67    private Database store;
68    private SecondaryDatabase index1;
69    private SecondaryDatabase index2;
70    private StoredMap storeMap;
71    private StoredMap indexMap1;
72    private StoredMap indexMap2;
73
74    public JoinTest() {
75
76        super("JoinTest");
77    }
78
79    public void setUp()
80        throws Exception {
81
82        SharedTestUtils.printTestName(getName());
83        env = TestEnv.TXN.open(getName());
84        runner = new TransactionRunner(env);
85        createDatabase();
86    }
87
88    public void tearDown() {
89
90        try {
91            if (index1 != null) {
92                index1.close();
93            }
94            if (index2 != null) {
95                index2.close();
96            }
97            if (store != null) {
98                store.close();
99            }
100            if (catalog != null) {
101                catalog.close();
102            }
103            if (env != null) {
104                env.close();
105            }
106        } catch (Exception e) {
107            System.out.println("Ignored exception during tearDown: " + e);
108        } finally {
109            /* Ensure that GC can cleanup. */
110            index1 = null;
111            index2 = null;
112            store = null;
113            catalog = null;
114            env = null;
115            runner = null;
116            factory = null;
117            storeMap = null;
118            indexMap1 = null;
119            indexMap2 = null;
120        }
121    }
122
123    public void runTest()
124        throws Exception {
125
126        runner.run(this);
127    }
128
129    public void doWork()
130        throws Exception {
131
132        createViews();
133        writeAndRead();
134    }
135
136    private void createDatabase()
137        throws Exception {
138
139        catalog = new StoredClassCatalog(openDb("catalog.db"));
140        factory = new TupleSerialFactory(catalog);
141        assertSame(catalog, factory.getCatalog());
142
143        store = openDb("store.db");
144        index1 = openSecondaryDb(store, "index1.db", "1");
145        index2 = openSecondaryDb(store, "index2.db", "2");
146    }
147
148    private Database openDb(String file)
149        throws Exception {
150
151        DatabaseConfig config = new DatabaseConfig();
152        DbCompat.setTypeBtree(config);
153        config.setTransactional(true);
154        config.setAllowCreate(true);
155
156        return DbCompat.testOpenDatabase(env, null, file, null, config);
157    }
158
159    private SecondaryDatabase openSecondaryDb(Database primary,
160                                              String file,
161                                              String keyName)
162        throws Exception {
163
164        SecondaryConfig secConfig = new SecondaryConfig();
165        DbCompat.setTypeBtree(secConfig);
166        secConfig.setTransactional(true);
167        secConfig.setAllowCreate(true);
168        DbCompat.setSortedDuplicates(secConfig, true);
169        secConfig.setKeyCreator(factory.getKeyCreator(MarshalledObject.class,
170                                                      keyName));
171
172        return DbCompat.testOpenSecondaryDatabase
173            (env, null, file, null, primary, secConfig);
174    }
175
176    private void createViews()
177        throws Exception {
178
179        storeMap = factory.newMap(store, String.class,
180                                         MarshalledObject.class, true);
181        indexMap1 = factory.newMap(index1, String.class,
182                                           MarshalledObject.class, true);
183        indexMap2 = factory.newMap(index2, String.class,
184                                           MarshalledObject.class, true);
185    }
186
187    private void writeAndRead()
188        throws Exception {
189
190        // write records: Data, PrimaryKey, IndexKey1, IndexKey2
191        assertNull(storeMap.put(null,
192            new MarshalledObject("d1", "k1", "no",  "yes")));
193        assertNull(storeMap.put(null,
194            new MarshalledObject("d2", "k2", "no",  "no")));
195        assertNull(storeMap.put(null,
196            new MarshalledObject("d3", "k3", "no",  "yes")));
197        assertNull(storeMap.put(null,
198            new MarshalledObject("d4", "k4", "yes", "yes")));
199        assertNull(storeMap.put(null,
200            new MarshalledObject("d5", "k5", "yes", "no")));
201
202        Object o;
203        Map.Entry e;
204
205        // join values with index maps
206        o = doJoin((StoredCollection) storeMap.values());
207        assertEquals(MATCH_DATA, ((MarshalledObject) o).getData());
208
209        // join keySet with index maps
210        o = doJoin((StoredCollection) storeMap.keySet());
211        assertEquals(MATCH_KEY, o);
212
213        // join entrySet with index maps
214        o = doJoin((StoredCollection) storeMap.entrySet());
215        e = (Map.Entry) o;
216        assertEquals(MATCH_KEY, e.getKey());
217        assertEquals(MATCH_DATA, ((MarshalledObject) e.getValue()).getData());
218    }
219
220    private Object doJoin(StoredCollection coll) {
221
222        StoredContainer[] indices = { indexMap1, indexMap2 };
223        StoredIterator i = coll.join(indices, VALUES, null);
224        try {
225            assertTrue(i.hasNext());
226            Object result = i.next();
227            assertNotNull(result);
228            assertFalse(i.hasNext());
229            return result;
230        } finally { i.close(); }
231    }
232}
233
234