title: Hazelcast not working correctly with SqlPredicate and Index on optional field
body: <p>We are storing complex objects in Hazelcast maps and need the possibility to search for objects not only based on the key but also on the content of these complex objects. In order to not take too large a performance hit, we are using indices on those search terms.</p>
  
  <p>We are also using spring-data-hazelcast which provides repositories that allow us to use findByAbcXyz() type semantic queries. For some of the more complex queries we are using the @Query annotation (which spring-data-hazelcast internally translates to SqlPredicates).</p>
  
  <p>We have now encountered an issue where under certain situations these @Query based search methods did not return any values, even if we could verify that the searched objects did in fact exist in the map.</p>
  
  <p>I have managed to reproduce this issue with core hazelcast (i.e. without the use of spring-data-hazelcast).</p>
  
  <p>Here is our object structure:</p>
  
  <p><strong>BetriebspunktKey.java</strong></p>
  
  <pre><code>public class BetriebspunktKey implements Serializable {
    private Integer uicLand;
    private Integer nummer;
  
    public BetriebspunktKey(final Integer uicLand, final Integer nummer) {
      this.uicLand = uicLand;
      this.nummer = nummer;
    }
  
    public Integer getUicLand() {
      return uicLand;
    }
  
    public Integer getNummer() {
      return nummer;
    }
  }
  </code></pre>
  
  <p><strong>Betriebspunkt.java</strong></p>
  
  <pre><code>public class Betriebspunkt implements Serializable {
    private BetriebspunktKey key;
    private List&lt;BetriebspunktVersion&gt; versionen;
  
    public Betriebspunkt(final BetriebspunktKey key, final List&lt;BetriebspunktVersion&gt; versionen) {
      this.key = key;
      this.versionen = versionen;
    }
  
    public BetriebspunktKey getKey() {
      return key;
    }
  }
  </code></pre>
  
  <p><strong>BetriebspunktVersion.java</strong></p>
  
  <pre><code>public class BetriebspunktVersion implements Serializable {
    private List&lt;BetriebspunktKey&gt; zusatzbetriebspunkte;
  
    public BetriebspunktVersion(final List&lt;BetriebspunktKey&gt; zusatzbetriebspunkte) {
      this.zusatzbetriebspunkte = zusatzbetriebspunkte;
    }
  }
  </code></pre>
  
  <p>In my main file, I am now setting up hazelcast:</p>
  
  <pre><code>Config config = new Config();
  final MapConfig mapConfig = config.getMapConfig("points");
  mapConfig.addMapIndexConfig(new MapIndexConfig("versionen[any].zusatzbetriebspunkte[any].nummer", false));
  
  HazelcastInstance instance = Hazelcast.newHazelcastInstance(config);
  
  IMap&lt;BetriebspunktKey, Betriebspunkt&gt; map = instance.getMap("points");
  </code></pre>
  
  <p>I am also preparing my search criteria for later on:</p>
  
  <pre><code>Predicate equalPredicate = Predicates.equal("versionen[any].zusatzbetriebspunkte[any].nummer", 53090);
  Predicate sqlPredicate = new SqlPredicate("versionen[any].zusatzbetriebspunkte[any].nummer=53090");
  </code></pre>
  
  <p>Next, I am creating two objects, one with the "full depth" of information, the other does not contain any "zusatzbetriebspunkte":</p>
  
  <pre><code>final Betriebspunkt abc = new Betriebspunkt(
          new BetriebspunktKey(80, 166),
          Collections.singletonList(new BetriebspunktVersion(
              Collections.singletonList(new BetriebspunktKey(80, 53090))
          ))
      );
  
      final Betriebspunkt def = new Betriebspunkt(
          new BetriebspunktKey(83, 141),
          Collections.singletonList(new BetriebspunktVersion(
              Collections.emptyList()
          ))
      );
  </code></pre>
  
  <p>Here is, where things become interesting. If I first insert the "full" object into the map, the search using both the EqualPredicate as well as the SqlPredicate works:</p>
  
  <pre><code>map.put(abc.getKey(), abc);
  map.put(def.getKey(), def);
  
  Collection&lt;Betriebspunkt&gt; equalResults = map.values(equalPredicate);
  Collection&lt;Betriebspunkt&gt; sqlResults = map.values(sqlPredicate);
  
  assertEquals(1, equalResults.size()); // contains "abc"
  assertEquals(1, sqlResults.size());   // contains "abc"
  </code></pre>
  
  <p>However, if I insert the objects into my map in reverse order (i.e. first the "partial" object and then the "full" one), only the EqualPredicate works correctly, the SqlPredicate returns an empty list, no matter what the content of the map or the search criteria.</p>
  
  <pre><code>map.put(abc.getKey(), abc);
  map.put(def.getKey(), def);
  
  Collection&lt;Betriebspunkt&gt; equalResults = map.values(equalPredicate);
  Collection&lt;Betriebspunkt&gt; sqlResults = map.values(sqlPredicate);
  
  assertEquals(1, equalResults.size()); // contains "abc"
  assertEquals(1, sqlResults.size());   // --&gt; this fails, it returns en empty list
  </code></pre>
  
  <p>What is the reason for this behaviour? It looks like a bug in the hazelcast code.</p>