Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Collection attributes indexed with [any] causes wrong SqlQuery results if first data inserted to map has no value for the attribute or the collection is empty #14358

gokhanoner opened this Issue Jan 8, 2019 · 0 comments


None yet
3 participants
Copy link

gokhanoner commented Jan 8, 2019

Please see:

The problem here, when initializing TypeConverter inside the index, if the indexed property is in a collection and when

  • the collection is null
  • the collection is empty
  • the collection is not empty but the attribute is null for all entries

Then QueryableEntry.getConverter returns IDENTITY_CONVERTER. This causes wrong converter type initialization and causing SqlPredicate to return wrong results.

Suggested Fix:

from getConverter method:

 else {
            AttributeType attributeType = extractAttributeType(attributeName, attribute);
            return attributeType == null ? IDENTITY_CONVERTER : attributeType.getConverter();

The only case attributeType is null is when the attribute is the type of MultiResult and either all values in it is null or it is an instance of ImmutableMultiResut which means Collection itself is null or empty. In this case, we should return NULL_CONVERTER instead of IDENTITY_CONVERTER so that index can continue to find correct TypeConverter with next entry.

Simple reproducer:

    public static void main(String[] args) {
        Config config = new Config();
        final MapConfig mapConfig = config.getMapConfig("data");
        mapConfig.addMapIndexConfig(new MapIndexConfig("nested[any].number", false));

        HazelcastInstance instance = Hazelcast.newHazelcastInstance(config);

        IMap<Integer, Data> map = instance.getMap("data");

        Data data1 = new Data(Collections.emptyList());
        Data data2 = new Data(Arrays.asList(new SubData(1)));

        Predicate equalPredicate = Predicates.equal("nested[any].number", 1);
        Predicate sqlPredicate = new SqlPredicate("nested[any].number=1");

        map.put(1, data1);
        map.put(2, data2);

        Collection<Data> equalResults = map.values(equalPredicate);
        Collection<Data> sqlResults = map.values(sqlPredicate);

        assertEquals(1, equalResults.size()); // contains "1"
        assertEquals(1, sqlResults.size());   // --> this fails, it returns en empty list

    static class Data implements Serializable {
        private final List<SubData> nested;

        public Data(List<SubData> nested) {
            this.nested = nested;

        public List<SubData> getNested() {
            return nested;

    static class SubData implements Serializable {
        private final Integer number;

        public SubData(Integer number) {
            this.number = number;

        public Integer getNumber() {
            return number;

@mmedenjak mmedenjak added this to the 3.12 milestone Jan 9, 2019

@taburet taburet self-assigned this Feb 18, 2019

taburet added a commit to taburet/hazelcast that referenced this issue Feb 18, 2019

taburet added a commit to taburet/hazelcast that referenced this issue Feb 18, 2019

taburet added a commit to taburet/hazelcast that referenced this issue Feb 20, 2019

taburet added a commit that referenced this issue Feb 28, 2019

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.