1/*- 2 * See the file LICENSE for redistribution information. 3 * 4 * Copyright (c) 2002,2008 Oracle. All rights reserved. 5 * 6 * $Id: JoinTest.java,v 1.1 2008/02/07 17:12:32 mark Exp $ 7 */ 8 9package com.sleepycat.persist.test; 10 11import static com.sleepycat.persist.model.Relationship.MANY_TO_ONE; 12 13import java.util.ArrayList; 14import java.util.List; 15 16import junit.framework.Test; 17 18import com.sleepycat.db.DatabaseException; 19import com.sleepycat.db.Transaction; 20import com.sleepycat.persist.EntityJoin; 21import com.sleepycat.persist.EntityStore; 22import com.sleepycat.persist.ForwardCursor; 23import com.sleepycat.persist.PrimaryIndex; 24import com.sleepycat.persist.SecondaryIndex; 25import com.sleepycat.persist.StoreConfig; 26import com.sleepycat.persist.model.Entity; 27import com.sleepycat.persist.model.PrimaryKey; 28import com.sleepycat.persist.model.SecondaryKey; 29import com.sleepycat.util.test.TxnTestCase; 30 31/** 32 * @author Mark Hayes 33 */ 34public class JoinTest extends TxnTestCase { 35 36 private static final int N_RECORDS = 5; 37 38 public static Test suite() { 39 return txnTestSuite(JoinTest.class, null, null); 40 } 41 42 private EntityStore store; 43 private PrimaryIndex<Integer,MyEntity> primary; 44 private SecondaryIndex<Integer,Integer,MyEntity> sec1; 45 private SecondaryIndex<Integer,Integer,MyEntity> sec2; 46 private SecondaryIndex<Integer,Integer,MyEntity> sec3; 47 48 /** 49 * Opens the store. 50 */ 51 private void open() 52 throws DatabaseException { 53 54 StoreConfig config = new StoreConfig(); 55 config.setAllowCreate(envConfig.getAllowCreate()); 56 config.setTransactional(envConfig.getTransactional()); 57 58 store = new EntityStore(env, "test", config); 59 60 primary = store.getPrimaryIndex(Integer.class, MyEntity.class); 61 sec1 = store.getSecondaryIndex(primary, Integer.class, "k1"); 62 sec2 = store.getSecondaryIndex(primary, Integer.class, "k2"); 63 sec3 = store.getSecondaryIndex(primary, Integer.class, "k3"); 64 } 65 66 /** 67 * Closes the store. 68 */ 69 private void close() 70 throws DatabaseException { 71 72 store.close(); 73 } 74 75 public void testJoin() 76 throws DatabaseException { 77 78 open(); 79 80 /* 81 * Primary keys: { 0, 1, 2, 3, 4 } 82 * Secondary k1: { 0:0, 0:1, 0:2, 0:3, 0:4 } 83 * Secondary k2: { 0:0, 1:1, 0:2, 1:3, 0:4 } 84 * Secondary k3: { 0:0, 1:1, 2:2, 0:3, 1:4 } 85 */ 86 Transaction txn = txnBegin(); 87 for (int i = 0; i < N_RECORDS; i += 1) { 88 MyEntity e = new MyEntity(i, 0, i % 2, i % 3); 89 boolean ok = primary.putNoOverwrite(txn, e); 90 assertTrue(ok); 91 } 92 txnCommit(txn); 93 94 /* 95 * k1, k2, k3, -> { primary keys } 96 * -1 means don't include the key in the join. 97 */ 98 doJoin( 0, 0, 0, new int[] { 0 }); 99 doJoin( 0, 0, 1, new int[] { 4 }); 100 doJoin( 0, 0, -1, new int[] { 0, 2, 4 }); 101 doJoin(-1, 1, 1, new int[] { 1 }); 102 doJoin(-1, 2, 2, new int[] { }); 103 doJoin(-1, -1, 2, new int[] { 2 }); 104 105 close(); 106 } 107 108 private void doJoin(int k1, int k2, int k3, int[] expectKeys) 109 throws DatabaseException { 110 111 List<Integer> expect = new ArrayList<Integer>(); 112 for (int i : expectKeys) { 113 expect.add(i); 114 } 115 EntityJoin join = new EntityJoin(primary); 116 if (k1 >= 0) { 117 join.addCondition(sec1, k1); 118 } 119 if (k2 >= 0) { 120 join.addCondition(sec2, k2); 121 } 122 if (k3 >= 0) { 123 join.addCondition(sec3, k3); 124 } 125 List<Integer> found; 126 Transaction txn = txnBegin(); 127 128 /* Keys */ 129 found = new ArrayList<Integer>(); 130 ForwardCursor<Integer> keys = join.keys(txn, null); 131 for (int i : keys) { 132 found.add(i); 133 } 134 keys.close(); 135 assertEquals(expect, found); 136 137 /* Entities */ 138 found = new ArrayList<Integer>(); 139 ForwardCursor<MyEntity> entities = join.entities(txn, null); 140 for (MyEntity e : entities) { 141 found.add(e.id); 142 } 143 entities.close(); 144 assertEquals(expect, found); 145 146 txnCommit(txn); 147 } 148 149 @Entity 150 private static class MyEntity { 151 @PrimaryKey 152 int id; 153 @SecondaryKey(relate=MANY_TO_ONE) 154 int k1; 155 @SecondaryKey(relate=MANY_TO_ONE) 156 int k2; 157 @SecondaryKey(relate=MANY_TO_ONE) 158 int k3; 159 160 private MyEntity() {} 161 162 MyEntity(int id, int k1, int k2, int k3) { 163 this.id = id; 164 this.k1 = k1; 165 this.k2 = k2; 166 this.k3 = k3; 167 } 168 169 @Override 170 public String toString() { 171 return "MyEntity " + id + ' ' + k1 + ' ' + k2 + ' ' + k3; 172 } 173 } 174} 175