Skip to content

Commit 2ee3c3e

Browse files
committed
IGNITE-26758: Add test to verify qryResCache and executeFieldsQuery not used for SqlFieldsQuery
1 parent 098ddec commit 2ee3c3e

File tree

2 files changed

+182
-0
lines changed

2 files changed

+182
-0
lines changed

modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheQueryManager.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
import java.util.concurrent.CompletableFuture;
4242
import java.util.concurrent.ConcurrentHashMap;
4343
import java.util.concurrent.ConcurrentMap;
44+
import java.util.concurrent.atomic.AtomicInteger;
4445
import java.util.function.BiFunction;
4546
import javax.cache.Cache;
4647
import org.apache.ignite.Ignite;
@@ -639,6 +640,19 @@ private QueryResult<K, V> executeQuery(CacheQuery<?> qry,
639640
return res;
640641
}
641642

643+
/** Test-only hook: how many times executeFieldsQuery was hit. */
644+
private static final AtomicInteger EXECUTE_FIELDS_QRY_HITS = new AtomicInteger();
645+
646+
/** Test-only hook. */
647+
static void resetExecuteFieldsQueryHitCount() {
648+
EXECUTE_FIELDS_QRY_HITS.set(0);
649+
}
650+
651+
/** Test-only hook. */
652+
static int executeFieldsQueryHitCount() {
653+
return EXECUTE_FIELDS_QRY_HITS.get();
654+
}
655+
642656
/**
643657
* Performs fields query.
644658
*
@@ -652,6 +666,7 @@ private QueryResult<K, V> executeQuery(CacheQuery<?> qry,
652666
*/
653667
private FieldsResult executeFieldsQuery(CacheQuery<?> qry, @Nullable Object[] args,
654668
boolean loc, @Nullable String taskName, Object rcpt) throws IgniteCheckedException {
669+
EXECUTE_FIELDS_QRY_HITS.incrementAndGet();
655670
assert qry != null;
656671
assert qry.type() == SQL_FIELDS : "Unexpected query type: " + qry.type();
657672

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
package org.apache.ignite.internal.processors.cache.query;
2+
3+
import java.io.Serializable;
4+
import java.util.List;
5+
import java.util.concurrent.Callable;
6+
import java.util.concurrent.ExecutorService;
7+
import java.util.concurrent.Executors;
8+
import java.util.concurrent.Future;
9+
10+
import org.apache.ignite.Ignite;
11+
import org.apache.ignite.IgniteCache;
12+
import org.apache.ignite.cache.CacheAtomicityMode;
13+
import org.apache.ignite.cache.query.QueryCursor;
14+
import org.apache.ignite.cache.query.SqlFieldsQuery;
15+
import org.apache.ignite.cache.query.annotations.QuerySqlField;
16+
import org.apache.ignite.configuration.CacheConfiguration;
17+
import org.apache.ignite.configuration.IgniteConfiguration;
18+
import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
19+
import org.junit.Test;
20+
21+
/**
22+
* Reproducer: verify that GridCacheQueryManager.executeFieldsQuery(...) is never called
23+
* for local SQL fields queries (and parallel local SQL fields queries).
24+
*/
25+
public class GridCacheQueryManagerExecuteFieldsQueryTest extends GridCommonAbstractTest {
26+
private static final String CACHE_NAME = "testCache";
27+
28+
@Override
29+
protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception {
30+
IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName);
31+
32+
CacheConfiguration<Integer, Person> ccfg = new CacheConfiguration<>(CACHE_NAME);
33+
ccfg.setAtomicityMode(CacheAtomicityMode.ATOMIC);
34+
35+
ccfg.setIndexedTypes(Integer.class, Person.class);
36+
37+
cfg.setCacheConfiguration(ccfg);
38+
39+
return cfg;
40+
}
41+
42+
@Override
43+
protected void afterTest() throws Exception {
44+
stopAllGrids();
45+
super.afterTest();
46+
}
47+
48+
@Test
49+
public void testLocalSqlFieldsQueryDoesNotHitExecuteFieldsQuery() throws Exception {
50+
Ignite ignite = startGrid(0);
51+
52+
IgniteCache<Integer, Person> cache = ignite.cache(CACHE_NAME);
53+
assertNotNull(cache);
54+
55+
cache.put(1, new Person("Alice", 10));
56+
cache.put(2, new Person("Bob", 20));
57+
58+
GridCacheQueryManager.resetExecuteFieldsQueryHitCount();
59+
60+
SqlFieldsQuery qry = new SqlFieldsQuery(
61+
"select _key, name, age from Person order by _key"
62+
);
63+
qry.setLocal(true);
64+
65+
List<List<?>> rows;
66+
try (QueryCursor<List<?>> cur = cache.query(qry)) {
67+
rows = cur.getAll();
68+
}
69+
70+
assertEquals(2, rows.size());
71+
assertEquals(0, GridCacheQueryManager.executeFieldsQueryHitCount());
72+
}
73+
74+
@Test
75+
public void testTwoParallelLocalSqlFieldsQueriesDoNotHitExecuteFieldsQuery() throws Exception {
76+
Ignite ignite = startGrid(0);
77+
78+
IgniteCache<Integer, Person> cache = ignite.cache(CACHE_NAME);
79+
assertNotNull(cache);
80+
81+
cache.put(1, new Person("Kirill", 10));
82+
cache.put(2, new Person("Michailo", 20));
83+
84+
GridCacheQueryManager.resetExecuteFieldsQueryHitCount();
85+
86+
ExecutorService pool = Executors.newFixedThreadPool(2);
87+
try {
88+
Callable<List<List<?>>> task = () -> {
89+
SqlFieldsQuery qry = new SqlFieldsQuery("select _key, name from Person order by _key");
90+
qry.setLocal(true);
91+
92+
try (QueryCursor<List<?>> cur = cache.query(qry)) {
93+
return (List<List<?>>) (List<?>) cur.getAll();
94+
}
95+
};
96+
97+
Future<List<List<?>>> f1 = pool.submit(task);
98+
Future<List<List<?>>> f2 = pool.submit(task);
99+
100+
List<List<?>> r1 = f1.get();
101+
List<List<?>> r2 = f2.get();
102+
103+
assertEquals(2, r1.size());
104+
assertEquals(2, r2.size());
105+
106+
assertEquals(0, GridCacheQueryManager.executeFieldsQueryHitCount());
107+
} finally {
108+
pool.shutdownNow();
109+
}
110+
}
111+
112+
@Test
113+
public void testNonLocalSqlFieldsQueryHitsExecuteFieldsQuery() throws Exception {
114+
startGrids(2);
115+
116+
Ignite ignite0 = grid(0);
117+
Ignite ignite1 = grid(1);
118+
119+
IgniteCache<Integer, Person> cache0 = ignite0.cache(CACHE_NAME);
120+
121+
awaitPartitionMapExchange();
122+
123+
int kOn1 = 0;
124+
while (!ignite1.affinity(CACHE_NAME).isPrimary(ignite1.cluster().localNode(), kOn1))
125+
kOn1++;
126+
127+
int kOn0 = 0;
128+
while (!ignite0.affinity(CACHE_NAME).isPrimary(ignite0.cluster().localNode(), kOn0))
129+
kOn0++;
130+
131+
cache0.put(kOn0, new Person("On0", 10));
132+
cache0.put(kOn1, new Person("On1", 20));
133+
134+
GridCacheQueryManager.resetExecuteFieldsQueryHitCount();
135+
136+
SqlFieldsQuery qry = new SqlFieldsQuery("select _key, name from Person order by _key");
137+
qry.setLocal(false);
138+
139+
try (QueryCursor<List<?>> cur = cache0.query(qry)) {
140+
List<List<?>> rows = cur.getAll();
141+
assertEquals(2, rows.size());
142+
}
143+
assertTrue(ignite1.affinity(CACHE_NAME).isPrimary(ignite1.cluster().localNode(), kOn1));
144+
assertTrue(ignite0.affinity(CACHE_NAME).isPrimary(ignite0.cluster().localNode(), kOn0));
145+
146+
assertFalse(ignite0.affinity(CACHE_NAME).isPrimary(ignite0.cluster().localNode(), kOn1));
147+
assertFalse(ignite1.affinity(CACHE_NAME).isPrimary(ignite1.cluster().localNode(), kOn0));
148+
149+
assertEquals(0, GridCacheQueryManager.executeFieldsQueryHitCount());
150+
}
151+
152+
/**
153+
* Simple SQL-mapped object.
154+
*/
155+
private static class Person implements Serializable {
156+
@QuerySqlField(index = true)
157+
private String name;
158+
159+
@QuerySqlField(index = true)
160+
private int age;
161+
162+
Person(String name, int age) {
163+
this.name = name;
164+
this.age = age;
165+
}
166+
}
167+
}

0 commit comments

Comments
 (0)