| 1 21 package com.db4o.db4ounit.common.fieldindex; 22 23 import com.db4o.*; 24 import com.db4o.config.*; 25 import com.db4o.db4ounit.common.btree.BTreeAssert; 26 import com.db4o.db4ounit.common.foundation.IntArrays4; 27 import com.db4o.inside.btree.BTree; 28 import com.db4o.inside.fieldindex.*; 29 import com.db4o.query.*; 30 31 import db4ounit.Assert; 32 33 34 public class FieldIndexProcessorTestCase extends FieldIndexProcessorTestCaseBase { 35 36 public static void main(String [] args) { 37 new FieldIndexProcessorTestCase().runSolo(); 38 } 39 40 protected void configure(Configuration config) { 41 super.configure(config); 42 indexField(config,NonIndexedFieldIndexItem.class, "indexed"); 43 } 44 45 protected void store() { 46 storeItems(new int[] { 3, 4, 7, 9 }); 47 storeComplexItems( 48 new int[] { 3, 4, 7, 9 }, 49 new int[] { 2, 2, 8, 8 }); 50 } 51 52 public void testIdentity(){ 53 Query query = createComplexItemQuery(); 54 query.descend("foo").constrain(new Integer (3)); 55 ComplexFieldIndexItem item = (ComplexFieldIndexItem) query.execute().next(); 56 57 query = createComplexItemQuery(); 58 query.descend("child").constrain(item).identity(); 59 assertExpectedFoos(ComplexFieldIndexItem.class, new int[]{4}, query); 60 } 61 62 63 public void testSingleIndexNotSmaller(){ 64 final Query query = createItemQuery(); 65 query.descend("foo").constrain(new Integer (5)).smaller().not(); 66 assertExpectedFoos(FieldIndexItem.class, new int[]{7, 9}, query); 67 } 68 69 public void testSingleIndexNotGreater(){ 70 final Query query = createItemQuery(); 71 query.descend("foo").constrain(new Integer (4)).greater().not(); 72 assertExpectedFoos(FieldIndexItem.class, new int[]{3, 4}, query); 73 } 74 75 public void testSingleIndexSmallerOrEqual() { 76 final Query query = createItemQuery(); 77 query.descend("foo").constrain(new Integer (7)).smaller().equal(); 78 assertExpectedFoos(FieldIndexItem.class, new int[] { 3,4,7 }, query); 79 } 80 81 public void testSingleIndexGreaterOrEqual() { 82 final Query query = createItemQuery(); 83 query.descend("foo").constrain(new Integer (7)).greater().equal(); 84 assertExpectedFoos(FieldIndexItem.class, new int[] { 7, 9 }, query); 85 } 86 87 public void testSingleIndexRange(){ 88 final Query query = createItemQuery(); 89 query.descend("foo").constrain(new Integer (3)).greater(); 90 query.descend("foo").constrain(new Integer (9)).smaller(); 91 assertExpectedFoos(FieldIndexItem.class, new int[] { 4, 7 }, query); 92 } 93 94 public void testSingleIndexAndRange(){ 95 final Query query = createItemQuery(); 96 Constraint c1 = query.descend("foo").constrain(new Integer (3)).greater(); 97 Constraint c2 = query.descend("foo").constrain(new Integer (9)).smaller(); 98 c1.and(c2); 99 assertExpectedFoos(FieldIndexItem.class, new int[] { 4, 7 }, query); 100 } 101 102 public void testSingleIndexOr(){ 103 final Query query = createItemQuery(); 104 Constraint c1 = query.descend("foo").constrain(new Integer (4)).smaller(); 105 Constraint c2 = query.descend("foo").constrain(new Integer (7)).greater(); 106 c1.or(c2); 107 assertExpectedFoos(FieldIndexItem.class, new int[] { 3, 9 }, query); 108 } 109 110 public void testExplicitAndOverOr() { 111 assertAndOverOrQuery(true); 112 } 113 114 public void testImplicitAndOverOr() { 115 assertAndOverOrQuery(false); 116 } 117 118 private void assertAndOverOrQuery(boolean explicitAnd) { 119 Query query = createItemQuery(); 120 Constraint c1 = query.descend("foo").constrain(new Integer (3)); 121 Constraint c2 = query.descend("foo").constrain(new Integer (9)); 122 Constraint c3 = query.descend("foo").constrain(new Integer (3)); 123 Constraint c4 = query.descend("foo").constrain(new Integer (7)); 124 Constraint cc1 = c1.or(c2); 125 Constraint cc2 = c3.or(c4); 126 if (explicitAnd) { 127 cc1.and(cc2); 128 } 129 assertExpectedFoos(FieldIndexItem.class, new int[] { 3 }, query); 130 } 131 132 public void testSingleIndexOrRange() { 133 Query query = createItemQuery(); 134 Constraint c1 = query.descend("foo").constrain(new Integer (1)).greater(); 135 Constraint c2 = query.descend("foo").constrain(new Integer (4)).smaller(); 136 Constraint c3 = query.descend("foo").constrain(new Integer (4)).greater(); 137 Constraint c4 = query.descend("foo").constrain(new Integer (10)).smaller(); 138 Constraint cc1 = c1.and(c2); 139 Constraint cc2 = c3.and(c4); 140 cc1.or(cc2); 141 assertExpectedFoos(FieldIndexItem.class, new int[] { 3, 7, 9 }, query); 142 } 143 144 public void testImplicitAndOnOrs() { 145 Query query = createItemQuery(); 146 Constraint c1 = query.descend("foo").constrain(new Integer (4)).smaller(); 147 Constraint c2 = query.descend("foo").constrain(new Integer (3)).greater(); 148 Constraint c3 = query.descend("foo").constrain(new Integer (4)).greater(); 149 c1.or(c2); 150 c1.or(c3); 151 152 assertExpectedFoos(FieldIndexItem.class, new int[] { 3, 4, 7, 9 }, query); 153 } 154 155 public void testTwoLevelDescendOr() { 156 Query query = createComplexItemQuery(); 157 Constraint c1 = query.descend("child").descend("foo").constrain(new Integer (4)).smaller(); 158 Constraint c2 = query.descend("child").descend("foo").constrain(new Integer (4)).greater(); 159 c1.or(c2); 160 assertExpectedFoos(ComplexFieldIndexItem.class, new int[] { 4, 9 }, query); 161 } 162 163 public void _testOrOnDifferentFields(){ 164 final Query query = createComplexItemQuery(); 165 Constraint c1 = query.descend("foo").constrain(new Integer (3)); 166 Constraint c2 = query.descend("bar").constrain(new Integer (8)); 167 c1.or(c2); 168 assertExpectedFoos(ComplexFieldIndexItem.class, new int[] { 3, 7, 9 }, query); 169 } 170 171 public void testCantOptimizeOrInvolvingNonIndexedField() { 172 final Query query = createQuery(NonIndexedFieldIndexItem.class); 173 final Constraint c1 = query.descend("indexed").constrain(new Integer (1)); 174 final Constraint c2 = query.descend("foo").constrain(new Integer (2)); 175 c1.or(c2); 176 assertCantOptimize(query); 177 } 178 179 public void testCantOptimizeDifferentLevels(){ 180 final Query query = createComplexItemQuery(); 181 Constraint c1 = query.descend("child").descend("foo").constrain(new Integer (4)).smaller(); 182 Constraint c2 = query.descend("foo").constrain(new Integer (7)).greater(); 183 c1.or(c2); 184 assertCantOptimize(query); 185 } 186 187 public void testCantOptimizeJoinOnNonIndexedFields() { 188 final Query query = createQuery(NonIndexedFieldIndexItem.class); 189 final Constraint c1 = query.descend("foo").constrain(new Integer (1)); 190 final Constraint c2 = query.descend("foo").constrain(new Integer (2)); 191 c1.or(c2); 192 assertCantOptimize(query); 193 } 194 195 private void assertCantOptimize(Query query) { 196 final FieldIndexProcessorResult result = executeProcessor(query); 197 Assert.areSame(FieldIndexProcessorResult.NO_INDEX_FOUND, result); 198 } 199 200 public void testIndexSelection() { 201 Query query = createComplexItemQuery(); 202 query.descend("bar").constrain(new Integer (2)); 203 query.descend("foo").constrain(new Integer (3)); 204 205 assertBestIndex("foo", query); 206 207 query = createComplexItemQuery(); 208 query.descend("foo").constrain(new Integer (3)); 209 query.descend("bar").constrain(new Integer (2)); 210 211 assertBestIndex("foo", query); 212 } 213 214 private void assertBestIndex(String expectedFieldIndex, final Query query) { 215 IndexedNode node = selectBestIndex(query); 216 assertComplexItemIndex(expectedFieldIndex, node); 217 } 218 219 public void testDoubleDescendingOnQuery() { 220 final Query query = createComplexItemQuery(); 221 query.descend("child").descend("foo").constrain(new Integer (3)); 222 assertExpectedFoos(ComplexFieldIndexItem.class, new int[] { 4 }, query); 223 } 224 225 public void testTripleDescendingOnQuery() { 226 final Query query = createComplexItemQuery(); 227 query.descend("child").descend("child").descend("foo").constrain(new Integer (3)); 228 assertExpectedFoos(ComplexFieldIndexItem.class, new int[] { 7 }, query); 229 } 230 231 public void testMultiTransactionSmallerWithCommit() { 232 final Transaction transaction = newTransaction(); 233 fillTransactionWith(transaction, 0); 234 235 int[] expectedZeros = newBTreeNodeSizedArray(0); 236 assertSmaller(transaction, expectedZeros, 3); 237 238 transaction.commit(); 239 240 fillTransactionWith(transaction, 5); 241 assertSmaller(IntArrays4.concat(expectedZeros, new int[] { 3, 4 }), 7); 242 } 243 244 public void testMultiTransactionWithRollback() { 245 final Transaction transaction = newTransaction(); 246 fillTransactionWith(transaction, 0); 247 248 int[] expectedZeros = newBTreeNodeSizedArray(0); 249 assertSmaller(transaction, expectedZeros, 3); 250 251 transaction.rollback(); 252 253 assertSmaller(transaction, new int[0], 3); 254 255 fillTransactionWith(transaction, 5); 256 assertSmaller(new int[] { 3, 4 }, 7); 257 } 258 259 public void testMultiTransactionSmaller() { 260 final Transaction transaction = newTransaction(); 261 fillTransactionWith(transaction, 0); 262 263 int[] expected = newBTreeNodeSizedArray(0); 264 assertSmaller(transaction, expected, 3); 265 266 fillTransactionWith(transaction, 5); 267 assertSmaller(new int[] { 3, 4 }, 7); 268 } 269 270 public void testMultiTransactionGreater() { 271 fillTransactionWith(systemTrans(), 10); 272 fillTransactionWith(systemTrans(), 5); 273 assertGreater(new int[] { 4, 7, 9 }, 3); 274 removeFromTransaction(systemTrans(), 5); 275 assertGreater(new int[] { 4, 7, 9 }, 3); 276 removeFromTransaction(systemTrans(), 10); 277 assertGreater(new int[] { 4, 7, 9 }, 3); 278 } 279 280 public void testSingleIndexEquals() { 281 final int expectedBar = 3; 282 assertExpectedFoos(FieldIndexItem.class, new int[] { expectedBar }, createQuery(expectedBar)); 283 } 284 285 public void testSingleIndexSmaller() { 286 assertSmaller(new int[] { 3, 4 }, 7); 287 } 288 289 public void testSingleIndexGreater() { 290 assertGreater(new int[] { 4, 7, 9 }, 3); 291 } 292 293 private void assertGreater(int[] expectedFoos, int greaterThan) { 294 final Query query = createItemQuery(); 295 query.descend("foo").constrain(new Integer (greaterThan)).greater(); 296 assertExpectedFoos(FieldIndexItem.class, expectedFoos, query); 297 } 298 299 private void assertExpectedFoos(Class itemClass, final int[] expectedFoos, final Query query) { 300 final Transaction trans = transactionFromQuery(query); 301 final int[] expectedIds = mapToObjectIds(createQuery(trans, itemClass), expectedFoos); 302 assertExpectedIDs(expectedIds, query); 303 } 304 305 private void assertExpectedIDs(final int[] expectedIds, final Query query) { 306 final FieldIndexProcessorResult result = executeProcessor(query); 307 if (expectedIds.length == 0) { 308 Assert.areSame(FieldIndexProcessorResult.FOUND_INDEX_BUT_NO_MATCH, result); 309 return; 310 } 311 312 assertTreeInt(expectedIds, result.toTreeInt()); 313 } 314 315 private FieldIndexProcessorResult executeProcessor(final Query query) { 316 return createProcessor(query).run(); 317 } 318 319 private Transaction transactionFromQuery(Query query) { 320 return ((QQuery)query).getTransaction(); 321 } 322 323 private BTree btree(){ 324 return fieldIndexBTree(FieldIndexItem.class, "foo"); 325 } 326 327 private void store(final Transaction trans, final FieldIndexItem item) { 328 stream().set(trans, item); 329 } 330 331 private void fillTransactionWith(Transaction trans, final int bar) { 332 for (int i=0; i<BTreeAssert.fillSize(btree()); ++i) { 333 store(trans, new FieldIndexItem(bar)); 334 } 335 } 336 337 private int[] newBTreeNodeSizedArray(int value) { 338 final BTree btree = btree(); 339 return BTreeAssert.newBTreeNodeSizedArray(btree, value); 340 } 341 342 private void removeFromTransaction(Transaction trans, final int foo) { 343 final ObjectSet found = createItemQuery(trans).execute(); 344 while (found.hasNext()) { 345 FieldIndexItem item = (FieldIndexItem)found.next(); 346 if (item.foo == foo) { 347 stream().delete(trans, item); 348 } 349 } 350 } 351 352 private void assertSmaller(final int[] expectedFoos, final int smallerThan) { 353 assertSmaller(trans(), expectedFoos, smallerThan); 354 } 355 356 private void assertSmaller(final Transaction transaction, final int[] expectedFoos, final int smallerThan) { 357 final Query query = createItemQuery(transaction); 358 query.descend("foo").constrain(new Integer (smallerThan)).smaller(); 359 assertExpectedFoos(FieldIndexItem.class, expectedFoos, query); 360 } 361 362 } 363 | Popular Tags |