/** @throws Exception If failed. */
  public void testScanQueryReconnect() throws Exception {
    Ignite cln = grid(serverCount());

    assertTrue(cln.cluster().localNode().isClient());

    final Ignite srv = clientRouter(cln);

    final IgniteCache<Integer, Person> clnCache = cln.getOrCreateCache(QUERY_CACHE);

    final IgniteCache<Integer, Person> srvCache = srv.getOrCreateCache(QUERY_CACHE);

    for (int i = 0; i < 10_000; i++) clnCache.put(i, new Person(i, "name-" + i, "surname-" + i));

    final ScanQuery<Integer, Person> scanQry = new ScanQuery<>();

    scanQry.setPageSize(1);

    scanQry.setFilter(
        new IgniteBiPredicate<Integer, Person>() {
          @Override
          public boolean apply(Integer integer, Person person) {
            return true;
          }
        });

    QueryCursor<Cache.Entry<Integer, Person>> qryCursor = clnCache.query(scanQry);

    reconnectClientNode(
        cln,
        srv,
        new Runnable() {
          @Override
          public void run() {
            srvCache.put(10_001, new Person(10_001, "name", "surname"));

            try {
              clnCache.query(scanQry);

              fail();
            } catch (CacheException e) {
              check(e);
            }
          }
        });

    try {
      qryCursor.getAll();

      fail();
    } catch (CacheException e) {
      checkAndWait(e);
    }

    qryCursor = clnCache.query(scanQry);

    assertEquals(10_001, qryCursor.getAll().size());
  }
  /** @throws Exception If failed. */
  public void testObjectArgument() throws Exception {
    IgniteCache<TestKey, Person> cache = ignite(0).cache(null);

    for (int i = 0; i < 100; i++) cache.put(new TestKey(i), new Person("name-" + i));

    SqlQuery<TestKey, Person> qry = new SqlQuery<>(Person.class, "where _key=?");

    IgniteBinary binary = ignite(0).binary();

    for (int i = 0; i < 100; i++) {
      Object key = new TestKey(i);

      if (i % 2 == 0) key = binary.toBinary(key);

      qry.setArgs(key);

      List<Cache.Entry<TestKey, Person>> res = cache.query(qry).getAll();

      assertEquals(1, res.size());

      Person p = res.get(0).getValue();

      assertEquals("name-" + i, p.name);
    }
  }
  /**
   * Query all purchases made at a specific store for 3 specific products. This query uses
   * cross-cache joins between {@link DimStore}, {@link DimProduct} objects stored in {@code
   * 'replicated'} cache and {@link FactPurchase} objects stored in {@code 'partitioned'} cache.
   *
   * @throws IgniteException If failed.
   */
  private static void queryProductPurchases() {
    IgniteCache<Integer, FactPurchase> factCache = Ignition.ignite().cache(PARTITIONED_CACHE_NAME);

    // All purchases for certain product made at store2.
    // =================================================

    DimProduct p1 = rand(dataProduct.values());
    DimProduct p2 = rand(dataProduct.values());
    DimProduct p3 = rand(dataProduct.values());

    System.out.println(
        "IDs of products [p1=" + p1.getId() + ", p2=" + p2.getId() + ", p3=" + p3.getId() + ']');

    // Create cross cache query to get all purchases made at store2
    // for specified products.
    QueryCursor<Cache.Entry<Integer, FactPurchase>> prodPurchases =
        factCache.query(
            new SqlQuery(
                    FactPurchase.class,
                    "from \""
                        + REPLICATED_CACHE_NAME
                        + "\".DimStore, \""
                        + REPLICATED_CACHE_NAME
                        + "\".DimProduct, "
                        + "\""
                        + PARTITIONED_CACHE_NAME
                        + "\".FactPurchase "
                        + "where DimStore.id=FactPurchase.storeId and DimProduct.id=FactPurchase.productId "
                        + "and DimStore.name=? and DimProduct.id in(?, ?, ?)")
                .setArgs("Store2", p1.getId(), p2.getId(), p3.getId()));

    printQueryResults(
        "All purchases made at store2 for 3 specific products:", prodPurchases.getAll());
  }
  /** @throws Exception If failed. */
  public void testQueryReconnect() throws Exception {
    Ignite cln = grid(serverCount());

    assertTrue(cln.cluster().localNode().isClient());

    final Ignite srv = clientRouter(cln);

    final IgniteCache<Integer, Person> clnCache = cln.getOrCreateCache(QUERY_CACHE);

    final IgniteCache<Integer, Person> srvCache = srv.getOrCreateCache(QUERY_CACHE);

    clnCache.put(1, new Person(1, "name1", "surname1"));
    clnCache.put(2, new Person(2, "name2", "surname2"));
    clnCache.put(3, new Person(3, "name3", "surname3"));

    final SqlQuery<Integer, Person> qry = new SqlQuery<>(Person.class, "_key <> 0");

    qry.setPageSize(1);

    QueryCursor<Cache.Entry<Integer, Person>> cur = clnCache.query(qry);

    reconnectClientNode(
        cln,
        srv,
        new Runnable() {
          @Override
          public void run() {
            srvCache.put(4, new Person(4, "name4", "surname4"));

            try {
              clnCache.query(qry);

              fail();
            } catch (CacheException e) {
              check(e);
            }
          }
        });

    List<Cache.Entry<Integer, Person>> res = cur.getAll();

    assertNotNull(res);
    assertEquals(4, res.size());
  }
  /**
   * Query all purchases made at a specific store. This query uses cross-cache joins between {@link
   * DimStore} objects stored in {@code 'replicated'} cache and {@link FactPurchase} objects stored
   * in {@code 'partitioned'} cache.
   *
   * @throws IgniteException If failed.
   */
  private static void queryStorePurchases() {
    IgniteCache<Integer, FactPurchase> factCache = Ignition.ignite().cache(PARTITIONED_CACHE_NAME);

    // All purchases for store1.
    // ========================

    // Create cross cache query to get all purchases made at store1.
    QueryCursor<Cache.Entry<Integer, FactPurchase>> storePurchases =
        factCache.query(
            new SqlQuery(
                    FactPurchase.class,
                    "from \""
                        + REPLICATED_CACHE_NAME
                        + "\".DimStore, \""
                        + PARTITIONED_CACHE_NAME
                        + "\".FactPurchase "
                        + "where DimStore.id=FactPurchase.storeId and DimStore.name=?")
                .setArgs("Store1"));

    printQueryResults("All purchases made at store1:", storePurchases.getAll());
  }
  /**
   * @param setPart If {@code true} sets partition for scan query.
   * @throws Exception If failed.
   */
  private void scanQueryReconnectInProgress(boolean setPart) throws Exception {
    Ignite cln = grid(serverCount());

    assertTrue(cln.cluster().localNode().isClient());

    final Ignite srv = clientRouter(cln);

    final IgniteCache<Integer, Person> clnCache = cln.getOrCreateCache(QUERY_CACHE);

    clnCache.put(1, new Person(1, "name1", "surname1"));
    clnCache.put(2, new Person(2, "name2", "surname2"));
    clnCache.put(3, new Person(3, "name3", "surname3"));

    final ScanQuery<Integer, Person> scanQry = new ScanQuery<>();

    scanQry.setPageSize(1);

    scanQry.setFilter(
        new IgniteBiPredicate<Integer, Person>() {
          @Override
          public boolean apply(Integer integer, Person person) {
            return true;
          }
        });

    if (setPart) scanQry.setPartition(1);

    blockMessage(GridCacheQueryResponse.class);

    final IgniteInternalFuture<Object> fut =
        GridTestUtils.runAsync(
            new Callable<Object>() {
              @Override
              public Object call() throws Exception {
                try {
                  QueryCursor<Cache.Entry<Integer, Person>> qryCursor = clnCache.query(scanQry);

                  qryCursor.getAll();
                } catch (CacheException e) {
                  checkAndWait(e);

                  return true;
                }

                return false;
              }
            });

    // Check that client waiting operation.
    GridTestUtils.assertThrows(
        log,
        new Callable<Object>() {
          @Override
          public Object call() throws Exception {
            return fut.get(200);
          }
        },
        IgniteFutureTimeoutCheckedException.class,
        null);

    assertNotDone(fut);

    unblockMessage();

    reconnectClientNode(cln, srv, null);

    assertTrue((Boolean) fut.get(2, SECONDS));

    QueryCursor<Cache.Entry<Integer, Person>> qryCursor2 = clnCache.query(scanQry);

    assertEquals(setPart ? 1 : 3, qryCursor2.getAll().size());
  }
  /** @throws Exception If failed. */
  public void testReconnectQueryInProgress() throws Exception {
    Ignite cln = grid(serverCount());

    assertTrue(cln.cluster().localNode().isClient());

    final Ignite srv = clientRouter(cln);

    final IgniteCache<Integer, Person> clnCache = cln.getOrCreateCache(QUERY_CACHE);

    clnCache.put(1, new Person(1, "name1", "surname1"));
    clnCache.put(2, new Person(2, "name2", "surname2"));
    clnCache.put(3, new Person(3, "name3", "surname3"));

    blockMessage(GridQueryNextPageResponse.class);

    final SqlQuery<Integer, Person> qry = new SqlQuery<>(Person.class, "_key <> 0");

    qry.setPageSize(1);

    final QueryCursor<Cache.Entry<Integer, Person>> cur1 = clnCache.query(qry);

    final IgniteInternalFuture<Object> fut =
        GridTestUtils.runAsync(
            new Callable<Object>() {
              @Override
              public Object call() throws Exception {
                try {
                  cur1.getAll();
                } catch (CacheException e) {
                  checkAndWait(e);

                  return true;
                }

                return false;
              }
            });

    // Check that client waiting operation.
    GridTestUtils.assertThrows(
        log,
        new Callable<Object>() {
          @Override
          public Object call() throws Exception {
            return fut.get(200);
          }
        },
        IgniteFutureTimeoutCheckedException.class,
        null);

    assertNotDone(fut);

    unblockMessage();

    reconnectClientNode(cln, srv, null);

    assertTrue((Boolean) fut.get(2, SECONDS));

    QueryCursor<Cache.Entry<Integer, Person>> cur2 = clnCache.query(qry);

    assertEquals(3, cur2.getAll().size());
  }
 /**
  * @param c Cache.
  * @param qry Query.
  * @param args Arguments.
  * @return Column as list.
  */
 private static <X> List<X> columnQuery(IgniteCache<?, ?> c, String qry, Object... args) {
   return column(0, c.query(new SqlFieldsQuery(qry).setArgs(args)).getAll());
 }