diff --git a/hazelcast/src/main/java/com/hazelcast/query/impl/IndexImpl.java b/hazelcast/src/main/java/com/hazelcast/query/impl/IndexImpl.java index 13a936e5d6588..7ecb0fe08798c 100644 --- a/hazelcast/src/main/java/com/hazelcast/query/impl/IndexImpl.java +++ b/hazelcast/src/main/java/com/hazelcast/query/impl/IndexImpl.java @@ -39,22 +39,22 @@ public class IndexImpl implements Index { protected final InternalSerializationService ss; protected final IndexStore indexStore; + protected final Extractors extractors; private final IndexCopyBehavior copyQueryResultOn; private volatile TypeConverter converter; private final String attributeName; private final boolean ordered; - private final Extractors extractors; public IndexImpl(String attributeName, boolean ordered, InternalSerializationService ss, Extractors extractors, IndexCopyBehavior copyQueryResultOn) { this.attributeName = attributeName; this.ordered = ordered; this.ss = ss; + this.extractors = extractors; this.copyQueryResultOn = copyQueryResultOn; this.indexStore = createIndexStore(ordered); - this.extractors = extractors; } public IndexStore createIndexStore(boolean ordered) { diff --git a/hazelcast/src/test/java/com/hazelcast/map/impl/query/ExtractorsAndIndexesTest.java b/hazelcast/src/test/java/com/hazelcast/map/impl/query/ExtractorsAndIndexesTest.java new file mode 100644 index 0000000000000..7b2b7a16e46c8 --- /dev/null +++ b/hazelcast/src/test/java/com/hazelcast/map/impl/query/ExtractorsAndIndexesTest.java @@ -0,0 +1,93 @@ +package com.hazelcast.map.impl.query; + +import com.hazelcast.config.Config; +import com.hazelcast.config.InMemoryFormat; +import com.hazelcast.config.MapAttributeConfig; +import com.hazelcast.config.MapIndexConfig; +import com.hazelcast.core.HazelcastInstance; +import com.hazelcast.core.IMap; +import com.hazelcast.query.Predicate; +import com.hazelcast.query.Predicates; +import com.hazelcast.query.extractor.ValueCollector; +import com.hazelcast.query.extractor.ValueExtractor; +import com.hazelcast.spi.properties.GroupProperty; +import com.hazelcast.test.HazelcastParallelParametersRunnerFactory; +import com.hazelcast.test.HazelcastTestSupport; +import com.hazelcast.test.annotation.ParallelTest; +import com.hazelcast.test.annotation.QuickTest; +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.io.Serializable; +import java.util.Collection; + +import static com.hazelcast.query.Predicates.equal; +import static java.util.Arrays.asList; +import static org.junit.Assert.assertEquals; + +@RunWith(Parameterized.class) +@Parameterized.UseParametersRunnerFactory(HazelcastParallelParametersRunnerFactory.class) +@Category({QuickTest.class, ParallelTest.class}) +public class ExtractorsAndIndexesTest extends HazelcastTestSupport { + + @Parameterized.Parameters(name = "format:{0}") + public static Collection parameters() { + return asList(new Object[][]{{InMemoryFormat.OBJECT}, {InMemoryFormat.BINARY}}); + } + + @Parameterized.Parameter + public InMemoryFormat inMemoryFormat; + + @Test + public void testExtractorsAreRespectedByEntriesReturnedFromIndexes() { + String mapName = randomMapName(); + + Config config = new Config(); + config.getMapConfig(mapName).setInMemoryFormat(inMemoryFormat).addMapIndexConfig(new MapIndexConfig("last", true)) + .addMapAttributeConfig(new MapAttributeConfig("generated", Extractor.class.getName())); + config.getNativeMemoryConfig().setEnabled(true); + + config.setProperty(GroupProperty.PARTITION_COUNT.getName(), "1"); + HazelcastInstance instance = createHazelcastInstance(config); + + IMap map = instance.getMap(mapName); + populateMap(map); + + // this predicate queries the index + Predicate lastPredicate = equal("last", "last"); + + // this predicate is not indexed and acts on the entries returned from + // the index which must support extractors otherwise this test will fail + Predicate alwaysFirst = equal("generated", "first"); + + Predicate composed = Predicates.and(lastPredicate, alwaysFirst); + + Collection values = map.values(composed); + assertEquals(100, values.size()); + } + + public static class Person implements Serializable { + public String first; + public String last; + } + + public static class Extractor extends ValueExtractor { + @SuppressWarnings("unchecked") + @Override + public void extract(Person person, Void aVoid, ValueCollector valueCollector) { + valueCollector.addObject("first"); + } + } + + private void populateMap(IMap map) { + for (int i = 0; i < 100; i++) { + Person p = new Person(); + p.first = "first" + i; + p.last = "last"; + map.put(i, p); + } + } + +} \ No newline at end of file