/*- * See the file LICENSE for redistribution information. * * Copyright (c) 2000, 2015 Oracle and/or its affiliates. All rights reserved. * */ package com.sleepycat.collections.test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; import java.util.Map; import org.junit.After; import org.junit.Before; import org.junit.Test; import com.sleepycat.bind.serial.StoredClassCatalog; import com.sleepycat.bind.serial.test.MarshalledObject; import com.sleepycat.collections.StoredCollection; import com.sleepycat.collections.StoredContainer; import com.sleepycat.collections.StoredIterator; import com.sleepycat.collections.StoredMap; import com.sleepycat.collections.TransactionRunner; import com.sleepycat.collections.TransactionWorker; import com.sleepycat.collections.TupleSerialFactory; import com.sleepycat.compat.DbCompat; import com.sleepycat.db.Database; import com.sleepycat.db.DatabaseConfig; import com.sleepycat.db.Environment; import com.sleepycat.db.SecondaryConfig; import com.sleepycat.db.SecondaryDatabase; import com.sleepycat.util.test.SharedTestUtils; import com.sleepycat.util.test.TestBase; import com.sleepycat.util.test.TestEnv; /** * @author Mark Hayes */ public class JoinTest extends TestBase implements TransactionWorker { private static final String MATCH_DATA = "d4"; // matches both keys = "yes" private static final String MATCH_KEY = "k4"; // matches both keys = "yes" private static final String[] VALUES = {"yes", "yes"}; private Environment env; private TransactionRunner runner; private StoredClassCatalog catalog; private TupleSerialFactory factory; private Database store; private SecondaryDatabase index1; private SecondaryDatabase index2; private StoredMap storeMap; private StoredMap indexMap1; private StoredMap indexMap2; public JoinTest() { customName = "JoinTest"; } @Before public void setUp() throws Exception { SharedTestUtils.printTestName(customName); env = TestEnv.TXN.open(customName); runner = new TransactionRunner(env); createDatabase(); } @After public void tearDown() { try { if (index1 != null) { index1.close(); } if (index2 != null) { index2.close(); } if (store != null) { store.close(); } if (catalog != null) { catalog.close(); } if (env != null) { env.close(); } } catch (Exception e) { System.out.println("Ignored exception during tearDown: " + e); } finally { /* Ensure that GC can cleanup. */ index1 = null; index2 = null; store = null; catalog = null; env = null; runner = null; factory = null; storeMap = null; indexMap1 = null; indexMap2 = null; } } @Test public void runTest() throws Exception { runner.run(this); } public void doWork() { createViews(); writeAndRead(); } private void createDatabase() throws Exception { catalog = new StoredClassCatalog(openDb("catalog.db")); factory = new TupleSerialFactory(catalog); assertSame(catalog, factory.getCatalog()); store = openDb("store.db"); index1 = openSecondaryDb(store, "index1.db", "1"); index2 = openSecondaryDb(store, "index2.db", "2"); } private Database openDb(String file) throws Exception { DatabaseConfig config = new DatabaseConfig(); DbCompat.setTypeBtree(config); config.setTransactional(true); config.setAllowCreate(true); return DbCompat.testOpenDatabase(env, null, file, null, config); } private SecondaryDatabase openSecondaryDb(Database primary, String file, String keyName) throws Exception { SecondaryConfig secConfig = new SecondaryConfig(); DbCompat.setTypeBtree(secConfig); secConfig.setTransactional(true); secConfig.setAllowCreate(true); DbCompat.setSortedDuplicates(secConfig, true); secConfig.setKeyCreator(factory.getKeyCreator(MarshalledObject.class, keyName)); return DbCompat.testOpenSecondaryDatabase (env, null, file, null, primary, secConfig); } private void createViews() { storeMap = factory.newMap(store, String.class, MarshalledObject.class, true); indexMap1 = factory.newMap(index1, String.class, MarshalledObject.class, true); indexMap2 = factory.newMap(index2, String.class, MarshalledObject.class, true); } private void writeAndRead() { // write records: Data, PrimaryKey, IndexKey1, IndexKey2 assertNull(storeMap.put(null, new MarshalledObject("d1", "k1", "no", "yes"))); assertNull(storeMap.put(null, new MarshalledObject("d2", "k2", "no", "no"))); assertNull(storeMap.put(null, new MarshalledObject("d3", "k3", "no", "yes"))); assertNull(storeMap.put(null, new MarshalledObject("d4", "k4", "yes", "yes"))); assertNull(storeMap.put(null, new MarshalledObject("d5", "k5", "yes", "no"))); Object o; Map.Entry e; // join values with index maps o = doJoin((StoredCollection) storeMap.values()); assertEquals(MATCH_DATA, ((MarshalledObject) o).getData()); // join keySet with index maps o = doJoin((StoredCollection) storeMap.keySet()); assertEquals(MATCH_KEY, o); // join entrySet with index maps o = doJoin((StoredCollection) storeMap.entrySet()); e = (Map.Entry) o; assertEquals(MATCH_KEY, e.getKey()); assertEquals(MATCH_DATA, ((MarshalledObject) e.getValue()).getData()); } private Object doJoin(StoredCollection coll) { StoredContainer[] indices = { indexMap1, indexMap2 }; StoredIterator i = coll.join(indices, VALUES, null); try { assertTrue(i.hasNext()); Object result = i.next(); assertNotNull(result); assertFalse(i.hasNext()); return result; } finally { i.close(); } } }