@Test
  public void testBindParamsWithMulitipleClients() throws CacheException {

    final Host host = Host.getHost(0);
    VM vm0 = host.getVM(0);
    VM vm1 = host.getVM(1);
    VM vm2 = host.getVM(2);
    VM vm3 = host.getVM(3);
    final int numberOfEntries = 100;

    final Object[][] params = new Object[][] {{"key-1"}, // 0
        {101}, // 1
        {101}, // 2
        {101}, // 3
        {50, "ibm"}, // 4
        {50, "ibm"}, // 5
    };

    final String[] querys =
        new String[] {"SELECT itr.value FROM " + regName + ".entries itr where itr.key = 'key-1'", // 0
            "SELECT DISTINCT * FROM " + regName + " WHERE id < 101 ORDER BY id", // 1
            "SELECT DISTINCT * FROM " + regName + " WHERE id < 101 ORDER BY id", // 2
            "(SELECT DISTINCT * FROM " + regName + " WHERE id < 101).size", // 3
            "SELECT * FROM " + regName + " WHERE id = 50 and Ticker = 'ibm'", // 4
            "SELECT * FROM " + regName + " WHERE id < 50 and Ticker = 'ibm'", // 5
        };

    // Start server1
    final int port0 = vm0.invoke("Create cache server", () -> {
      setupBridgeServerAndCreateData(regionName, numberOfEntries);
      return getCacheServerPort();
    });

    final String host0 = NetworkUtils.getServerHostName(vm0.getHost());

    // Create client pool.
    final String poolName = "testClientServerQueriesWithParams";
    vm1.invoke("createPool",
        () -> createPool(poolName, new String[] {host0}, new int[] {port0}, true));
    vm2.invoke("createPool",
        () -> createPool(poolName, new String[] {host0}, new int[] {port0}, true));
    vm3.invoke("createPool",
        () -> createPool(poolName, new String[] {host0}, new int[] {port0}, true));

    // Execute client query multiple times and validate results.
    SerializableRunnable executeSameQueries = new CacheSerializableRunnable("Execute queries") {
      @Override
      public void run2() throws CacheException {
        QueryService qService = null;
        SelectResults[][] rs = new SelectResults[1][2];

        try {
          qService = (PoolManager.find(poolName)).getQueryService();
        } catch (Exception e) {
          Assert.fail("Failed to get QueryService.", e);
        }
        // Use minimal query, so that there will be multiple
        // clients using the same compiled query at server.
        for (int j = 0; j < 5; j++) {
          for (int i = 0; i < 2; i++) {
            try {
              logger.info("### Executing Query :" + queryString[i]);
              Query query = qService.newQuery(queryString[i]);
              rs[0][0] = (SelectResults) query.execute(params[i]);
              Query query2 = qService.newQuery(querys[i]);
              rs[0][1] = (SelectResults) query2.execute();
              // Compare results.
            } catch (Exception e) {
              Assert.fail("Failed executing " + queryString[i], e);
            }
            logger.info(
                "### Comparing results for Query :" + ((i + 1) * (j + 1)) + " : " + queryString[i]);
            compareQueryResultsWithoutAndWithIndexes(rs, 1);
            logger.info("### Done Comparing results for Query :" + ((i + 1) * (j + 1)) + " : "
                + queryString[i]);
          }
        }
      }
    };

    vm1.invoke("executeSameQueries", () -> executeSameQueries);
    vm2.invoke("executeSameQueries", () -> executeSameQueries);
    vm3.invoke("executeSameQueries", () -> executeSameQueries);

    // Execute client queries and validate results.
    SerializableRunnable executeQueries = new CacheSerializableRunnable("Execute queries") {
      @Override
      public void run2() throws CacheException {
        QueryService qService = null;
        SelectResults[][] rs = new SelectResults[1][2];

        try {
          qService = (PoolManager.find(poolName)).getQueryService();
        } catch (Exception e) {
          Assert.fail("Failed to get QueryService.", e);
        }
        for (int j = 0; j < queryString.length; j++) {
          for (int i = 0; i < queryString.length; i++) {
            try {
              logger.info("### Executing Query :" + queryString[i]);
              Query query = qService.newQuery(queryString[i]);
              rs[0][0] = (SelectResults) query.execute(params[i]);
              Query query2 = qService.newQuery(querys[i]);
              rs[0][1] = (SelectResults) query2.execute();
              // Compare results.
              compareQueryResultsWithoutAndWithIndexes(rs, 1);
            } catch (Exception e) {
              Assert.fail("Failed executing " + queryString[i], e);
            }
          }
        }
      }
    };

    vm1.invoke("executeQueries", () -> executeQueries);
    vm2.invoke("executeQueries", () -> executeQueries);
    vm3.invoke("executeQueries", () -> executeQueries);

    vm1.invoke("closeClient", this::closeClient);
    vm2.invoke("closeClient", this::closeClient);
    vm3.invoke("closeClient", this::closeClient);

    // Stop server
    vm0.invoke("Stop CacheServer", () -> stopBridgeServer(getCache()));
  }
Tests client-server query using parameters (compiled queries).
geode-core/src/distributedTest/java/org/apache/geode/cache/query/dunit/QueryUsingPoolDUnitTest.java