22
33import java .io .Serializable ;
44import java .util .List ;
5+ import java .util .Set ;
6+ import java .util .UUID ;
57import java .util .concurrent .Callable ;
68import java .util .concurrent .ExecutorService ;
79import java .util .concurrent .Executors ;
810import java .util .concurrent .Future ;
11+ import java .util .stream .Collectors ;
12+ import javax .cache .Cache ;
913
1014import org .apache .ignite .Ignite ;
1115import org .apache .ignite .IgniteCache ;
1216import org .apache .ignite .cache .CacheAtomicityMode ;
1317import org .apache .ignite .cache .query .QueryCursor ;
1418import org .apache .ignite .cache .query .SqlFieldsQuery ;
19+ import org .apache .ignite .cache .query .SqlQuery ;
1520import org .apache .ignite .cache .query .annotations .QuerySqlField ;
1621import org .apache .ignite .configuration .CacheConfiguration ;
1722import org .apache .ignite .configuration .IgniteConfiguration ;
@@ -32,6 +37,8 @@ protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws
3237 CacheConfiguration <Integer , Person > ccfg = new CacheConfiguration <>(CACHE_NAME );
3338 ccfg .setAtomicityMode (CacheAtomicityMode .ATOMIC );
3439
40+ ccfg .setBackups (0 );
41+
3542 ccfg .setIndexedTypes (Integer .class , Person .class );
3643
3744 cfg .setCacheConfiguration (ccfg );
@@ -149,6 +156,113 @@ public void testNonLocalSqlFieldsQueryHitsExecuteFieldsQuery() throws Exception
149156 assertEquals (0 , GridCacheQueryManager .executeFieldsQueryHitCount ());
150157 }
151158
159+ @ Test
160+ public void testLocalSqlQueryDoesNotHitExecuteFieldsQuery () throws Exception {
161+ startGrids (2 );
162+
163+ Ignite ignite0 = grid (0 );
164+ Ignite ignite1 = grid (1 );
165+
166+ awaitPartitionMapExchange ();
167+
168+ IgniteCache <Integer , Person > cache0 = ignite0 .cache (CACHE_NAME );
169+
170+ int [] keys = pickKeysForDifferentPrimaries (ignite0 , ignite1 );
171+ int k0 = keys [0 ];
172+ int k1 = keys [1 ];
173+
174+ cache0 .put (k0 , new Person ("On0" , 10 ));
175+ cache0 .put (k1 , new Person ("On1" , 20 ));
176+
177+ GridCacheQueryManager .resetExecuteFieldsQueryHitCount ();
178+
179+ SqlQuery <Integer , Person > qry = new SqlQuery <>(Person .class , "age >= ?" );
180+ qry .setArgs (0 );
181+ qry .setLocal (true );
182+
183+ List <Cache .Entry <Integer , Person >> res0 ;
184+ try (QueryCursor <Cache .Entry <Integer , Person >> cur = ignite0 .cache (CACHE_NAME ).query (qry )) {
185+ res0 = cur .getAll ();
186+ }
187+
188+ List <Cache .Entry <Integer , Person >> res1 ;
189+ try (QueryCursor <Cache .Entry <Integer , Person >> cur = ignite1 .cache (CACHE_NAME ).query (qry )) {
190+ res1 = cur .getAll ();
191+ }
192+
193+ assertEquals (1 , res0 .size ());
194+ assertEquals (1 , res1 .size ());
195+
196+ assertEquals (k0 , res0 .get (0 ).getKey ().intValue ());
197+ assertEquals (k1 , res1 .get (0 ).getKey ().intValue ());
198+
199+ assertEquals (0 , GridCacheQueryManager .executeFieldsQueryHitCount ());
200+ }
201+
202+ /**
203+ * The same intent, but also verify we got exactly the keys we inserted.
204+ */
205+ @ Test
206+ public void testDistributedSqlQueryDoesNotHitExecuteFieldsQuery () throws Exception {
207+ Ignite ignite0 = startGrid (0 );
208+ Ignite ignite1 = startGrid (1 );
209+
210+ awaitPartitionMapExchange ();
211+
212+ IgniteCache <Integer , Person > cache0 = ignite0 .cache (CACHE_NAME );
213+
214+ int [] keys = pickKeysForDifferentPrimaries (ignite0 , ignite1 );
215+ int k0 = keys [0 ];
216+ int k1 = keys [1 ];
217+
218+ cache0 .put (k0 , new Person ("Alice" , 10 ));
219+ cache0 .put (k1 , new Person ("Bob" , 20 ));
220+
221+ GridCacheQueryManager .resetExecuteFieldsQueryHitCount ();
222+
223+ SqlQuery <Integer , Person > qry = new SqlQuery <>(Person .class , "age >= ?" );
224+ qry .setArgs (0 );
225+ qry .setLocal (false );
226+
227+ List <Cache .Entry <Integer , Person >> res ;
228+ try (QueryCursor <Cache .Entry <Integer , Person >> cur = cache0 .query (qry )) {
229+ res = cur .getAll ();
230+ }
231+
232+ assertEquals (2 , res .size ());
233+
234+ Set <Integer > gotKeys = res .stream ().map (Cache .Entry ::getKey ).collect (Collectors .toSet ());
235+ assertTrue ("Expected to get both keys back [k0 = " + k0 + ", k1 = " + k1 + ", got = " + gotKeys + ']' ,
236+ gotKeys .contains (k0 ) && gotKeys .contains (k1 ));
237+
238+ assertEquals (0 , GridCacheQueryManager .executeFieldsQueryHitCount ());
239+ }
240+
241+ /**
242+ * Picks two keys such that one is primary on ignite0 and the other is primary on ignite1.
243+ */
244+ private int [] pickKeysForDifferentPrimaries (Ignite ignite0 , Ignite ignite1 ) {
245+ int k0 = -1 , k1 = -1 ;
246+
247+ UUID id0 = ignite0 .cluster ().localNode ().id ();
248+ UUID id1 = ignite1 .cluster ().localNode ().id ();
249+
250+ for (int k = 1 ; k < 100000 ; k ++) {
251+ UUID primaryId = ignite0 .affinity (CACHE_NAME ).mapKeyToNode (k ).id ();
252+
253+ if (primaryId .equals (id0 ) && k0 < 0 ) k0 = k ;
254+ if (primaryId .equals (id1 ) && k1 < 0 ) k1 = k ;
255+
256+ if (k0 > 0 && k1 > 0 )
257+ break ;
258+ }
259+
260+ assertTrue ("Failed to pick keys for different primaries [k0 = " + k0 + ", k1 = " + k1 + ']' ,
261+ k0 > 0 && k1 > 0 );
262+
263+ return new int []{k0 , k1 };
264+ }
265+
152266 /**
153267 * Simple SQL-mapped object.
154268 */
0 commit comments