blob: c48e328beb5ede12825b872b1a831a0d3aede7d3 [file] [log] [blame]
---
title: Performing an Equi-Join Query on Partitioned Regions
---
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
In order to perform equi-join operations on partitioned regions or partitioned regions and replicated regions, you need to use the `query.execute` method and supply it with a function execution context. You need to use <%=vars.product_name%>'s FunctionService executor because join operations are not yet directly supported for partitioned regions without providing a function execution context.
See [Partitioned Region Query Restrictions](../query_additional/partitioned_region_query_restrictions.html#concept_5353476380D44CC1A7F586E5AE1CE7E8) for more information on partitioned region query limitations.
For example, let's say your equi-join query is the following:
``` pre
SELECT DISTINCT * FROM /QueryRegion1 r1,
/QueryRegion2 r2 WHERE r1.ID = r2.ID
```
In this example QueryRegion2 is colocated with QueryRegion1, and both regions have same type of data objects.
On the server side:
``` pre
Function prQueryFunction1 = new QueryFunction();
FunctionService.registerFunction(prQueryFunction1);
public class QueryFunction extends FunctionAdapter {
@Override
public void execute(FunctionContext context) {
Cache cache = CacheFactory.getAnyInstance();
QueryService queryService = cache.getQueryService();
ArrayList allQueryResults = new ArrayList();
ArrayList arguments = (ArrayList)(context.getArguments());
String qstr = (String)arguments.get(0);
try {
Query query = queryService.newQuery(qstr);
SelectResults result = (SelectResults)query
.execute((RegionFunctionContext)context);
ArrayList arrayResult = (ArrayList)result.asList();
context.getResultSender().sendResult((ArrayList)result.asList());
context.getResultSender().lastResult(null);
} catch (Exception e) {
// handle exception
}
}
}
```
On the server side, `Query.execute()` operates on the local data of the partitioned region.
On the client side:
``` pre
Function function = new QueryFunction();
String queryString = "SELECT DISTINCT * FROM /QueryRegion1 r1,
/QueryRegion2 r2 WHERE r1.ID = r2.ID";
ArrayList argList = new ArrayList();
argList.add(queryString);
Object result = FunctionService.onRegion(CacheFactory.getAnyInstance()
.getRegion("QueryRegion1" ))
.setArguments(argList).execute(function).getResult();
ArrayList resultList = (ArrayList)result;
resultList.trimToSize();
List queryResults = null;
if (resultList.size() != 0) {
queryResults = new ArrayList();
for (Object obj : resultList) {
if (obj != null ) {
queryResults.addAll((ArrayList)obj);
}
}
}
```
On the client side, note that you can specify a bucket filter while invoking FunctionService.onRegion(). In this case, the query engine relies on FunctionService to direct the query to specific nodes.
**Additional Notes on Using the Query.execute and RegionFunctionContext APIs**
You can also pass multiple parameters (besides the query itself) to the query function by specifying the parameters in the client-side code (`FunctionService.onRegion(..).setArguments()`). Then you can handle the parameters inside the function on the server side using `context.getArguments`. Note that it does not matter which order you specify the parameters as long as you match the parameter handling order on the server with the order specified in the client.