From dac577d3660bc3de4e3afb19e54bc013b0a6da92 Mon Sep 17 00:00:00 2001 From: Reza Taroosheh Date: Fri, 23 Oct 2026 23:42:38 +0200 Subject: [PATCH 1/2] IGNITE-29199 Fix local IndexQuery returning binary objects for a cache not in keep-binary mode --- .../cache/query/GridCacheQueryManager.java | 2 +- .../cache/query/IndexQueryLocalTest.java | 41 +++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheQueryManager.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheQueryManager.java index f875972047c78..8260f10400e62 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheQueryManager.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheQueryManager.java @@ -1160,7 +1160,7 @@ public GridCloseableIterator indexQueryLocal(final CacheQuery qry) throws Ignite private int cnt; @Override protected Object onNext() throws IgniteCheckedException { - IgniteBiTuple entry = iter.nextX(); + IgniteBiTuple entry = (IgniteBiTuple)cctx.unwrapBinaryIfNeeded(iter.nextX(), qry.keepBinary(), false, null); cnt++; return new CacheEntryImpl<>(entry.getKey(), entry.getValue()); diff --git a/modules/indexing/src/test/java/org/apache/ignite/cache/query/IndexQueryLocalTest.java b/modules/indexing/src/test/java/org/apache/ignite/cache/query/IndexQueryLocalTest.java index f3780f25abdbe..6f3384e5e8fc6 100644 --- a/modules/indexing/src/test/java/org/apache/ignite/cache/query/IndexQueryLocalTest.java +++ b/modules/indexing/src/test/java/org/apache/ignite/cache/query/IndexQueryLocalTest.java @@ -17,11 +17,14 @@ package org.apache.ignite.cache.query; +import java.util.List; import java.util.Objects; +import javax.cache.Cache; import org.apache.ignite.Ignite; import org.apache.ignite.IgniteCache; import org.apache.ignite.IgniteDataStreamer; import org.apache.ignite.IgniteException; +import org.apache.ignite.binary.BinaryObject; import org.apache.ignite.cache.CacheMode; import org.apache.ignite.cache.query.annotations.QuerySqlField; import org.apache.ignite.configuration.CacheConfiguration; @@ -99,6 +102,44 @@ public void testServerNodePartitionedCache() { assertEquals(CNT / 2, resultSize); } + /** Should return deserialized values for a cache that is not in keep-binary mode. */ + @Test + public void testLocalQueryReturnsDeserializedValues() { + IgniteCache cache = crd.createCache(ccfg(CacheMode.REPLICATED)); + + insertData(crd, cache); + + IndexQuery qry = new IndexQuery(Person.class, IDX) + .setCriteria(lt("id", CNT / 2)); + + List> res = cache.query(qry.setLocal(true)).getAll(); + + for (Cache.Entry e : res) + assertEquals(new Person(e.getKey().intValue()), e.getValue()); + + assertEquals(CNT / 2, res.size()); + } + + /** Should keep binary values for a cache in keep-binary mode. */ + @Test + public void testLocalQueryKeepBinaryReturnsBinaryValues() { + IgniteCache cache = crd.createCache(ccfg(CacheMode.REPLICATED)); + + insertData(crd, cache); + + IgniteCache binCache = cache.withKeepBinary(); + + IndexQuery qry = new IndexQuery(Person.class, IDX) + .setCriteria(lt("id", CNT / 2)); + + List> res = binCache.query(qry.setLocal(true)).getAll(); + + for (Cache.Entry e : res) + assertEquals(new Person(e.getKey().intValue()), e.getValue().deserialize()); + + assertEquals(CNT / 2, res.size()); + } + /** Should fail as no data on nodes. */ @Test public void testClientNodeReplicatedCache() throws Exception { From c4d6dbdb0a11934047ca306af741190e321777ea Mon Sep 17 00:00:00 2001 From: Reza Taroosheh Date: Sun, 25 Oct 2026 20:57:55 +0100 Subject: [PATCH 2/2] IGNITE-29199 Unwrap key and value separately, use POJO key in tests --- .../cache/query/GridCacheQueryManager.java | 6 +- .../cache/query/IndexQueryLocalTest.java | 85 ++++++++++++++++--- 2 files changed, 75 insertions(+), 16 deletions(-) diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheQueryManager.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheQueryManager.java index 8260f10400e62..fa657f3293f0c 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheQueryManager.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheQueryManager.java @@ -1160,10 +1160,12 @@ public GridCloseableIterator indexQueryLocal(final CacheQuery qry) throws Ignite private int cnt; @Override protected Object onNext() throws IgniteCheckedException { - IgniteBiTuple entry = (IgniteBiTuple)cctx.unwrapBinaryIfNeeded(iter.nextX(), qry.keepBinary(), false, null); + IgniteBiTuple entry = iter.nextX(); + K key = (K)cctx.unwrapBinaryIfNeeded(entry.getKey(), qry.keepBinary(), false, null); + V val = (V)cctx.unwrapBinaryIfNeeded(entry.getValue(), qry.keepBinary(), false, null); cnt++; - return new CacheEntryImpl<>(entry.getKey(), entry.getValue()); + return new CacheEntryImpl<>(key, val); } @Override protected boolean onHasNext() throws IgniteCheckedException { diff --git a/modules/indexing/src/test/java/org/apache/ignite/cache/query/IndexQueryLocalTest.java b/modules/indexing/src/test/java/org/apache/ignite/cache/query/IndexQueryLocalTest.java index 6f3384e5e8fc6..70aa35f6e291b 100644 --- a/modules/indexing/src/test/java/org/apache/ignite/cache/query/IndexQueryLocalTest.java +++ b/modules/indexing/src/test/java/org/apache/ignite/cache/query/IndexQueryLocalTest.java @@ -105,37 +105,44 @@ public void testServerNodePartitionedCache() { /** Should return deserialized values for a cache that is not in keep-binary mode. */ @Test public void testLocalQueryReturnsDeserializedValues() { - IgniteCache cache = crd.createCache(ccfg(CacheMode.REPLICATED)); + IgniteCache cache = crd.createCache(ccfgObjectKey(CacheMode.REPLICATED)); - insertData(crd, cache); + insertDataWithPersonIdKey(crd, cache); - IndexQuery qry = new IndexQuery(Person.class, IDX) + IndexQuery qry = new IndexQuery(Person.class, IDX) .setCriteria(lt("id", CNT / 2)); - List> res = cache.query(qry.setLocal(true)).getAll(); + List> res = cache.query(qry.setLocal(true)).getAll(); - for (Cache.Entry e : res) - assertEquals(new Person(e.getKey().intValue()), e.getValue()); + for (Cache.Entry e : res) { + assertEquals(new PersonId(e.getValue().id), e.getKey()); + assertEquals(new Person(e.getKey().id), e.getValue()); + } assertEquals(CNT / 2, res.size()); } - /** Should keep binary values for a cache in keep-binary mode. */ + /** Should keep binary keys and values for a cache in keep-binary mode. */ @Test public void testLocalQueryKeepBinaryReturnsBinaryValues() { - IgniteCache cache = crd.createCache(ccfg(CacheMode.REPLICATED)); + IgniteCache cache = crd.createCache(ccfgObjectKey(CacheMode.REPLICATED)); - insertData(crd, cache); + insertDataWithPersonIdKey(crd, cache); - IgniteCache binCache = cache.withKeepBinary(); + IgniteCache binCache = cache.withKeepBinary(); - IndexQuery qry = new IndexQuery(Person.class, IDX) + IndexQuery qry = new IndexQuery(Person.class, IDX) .setCriteria(lt("id", CNT / 2)); - List> res = binCache.query(qry.setLocal(true)).getAll(); + List> res = binCache.query(qry.setLocal(true)).getAll(); - for (Cache.Entry e : res) - assertEquals(new Person(e.getKey().intValue()), e.getValue().deserialize()); + for (Cache.Entry e : res) { + PersonId key = e.getKey().deserialize(); + Person val = e.getValue().deserialize(); + + assertEquals(new PersonId(val.id), key); + assertEquals(new Person(key.id), val); + } assertEquals(CNT / 2, res.size()); } @@ -177,6 +184,14 @@ private void insertData(Ignite ignite, IgniteCache cache) { } } + /** */ + private void insertDataWithPersonIdKey(Ignite ignite, IgniteCache cache) { + try (IgniteDataStreamer streamer = ignite.dataStreamer(cache.getName())) { + for (int i = 0; i < CNT; i++) + streamer.addData(new PersonId(i), new Person(i)); + } + } + /** */ private CacheConfiguration ccfg(CacheMode cacheMode) { return new CacheConfiguration() @@ -186,6 +201,15 @@ private CacheConfiguration ccfg(CacheMode cacheMode) { .setBackups(2); } + /** */ + private CacheConfiguration ccfgObjectKey(CacheMode cacheMode) { + return new CacheConfiguration() + .setName(CACHE) + .setIndexedTypes(PersonId.class, Person.class) + .setCacheMode(cacheMode) + .setBackups(2); + } + /** */ private static class Person { /** */ @@ -219,4 +243,37 @@ private static class Person { return Objects.hash(id); } } + + /** */ + private static class PersonId { + /** */ + final int id; + + /** */ + PersonId(int id) { + this.id = id; + } + + /** {@inheritDoc} */ + @Override public String toString() { + return "PersonId[id=" + id + "]"; + } + + /** {@inheritDoc} */ + @Override public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + + PersonId personId = (PersonId)o; + + return Objects.equals(id, personId.id); + } + + /** {@inheritDoc} */ + @Override public int hashCode() { + return Objects.hash(id); + } + } }