---
title:  Continuous Queries
---

<!--
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.
-->

The C++ and .NET clients can initiate queries that run on the <%=vars.product_name%> cache server
and notify the client when the query results have changed.  For details on the server-side setup for
continuous queries, see [How Continuous Querying Works](/serverman/developing/continuous_querying/how_continuous_querying_works.html) 
in the *<%=vars.product_name%> User Guide*.

## <a id="cq_main_features" ></a>Continuous Query Basics

Continuous querying provides the following features:

-   **Standard <%=vars.product_name%> native client query syntax and semantics**. Continuous queries are expressed in the same language used for other native client queries. See [Remote Queries](remote-queries.html).

- **Standard <%=vars.product_name%> events-based management of CQ events**. The event handling used
to process CQ events is based on the standard <%=vars.product_name%> event handling framework. 

- **Complete integration with the client/server architecture**. CQ functionality uses existing
server-to-client messaging mechanisms to send events. All tuning of your server-to-client
messaging also tunes the messaging of your CQ events. If your system is configured for high
availability then your CQs are highly available, with seamless failover provided in case of
server failure (see [High Availability for Client-to-Server Communication](preserving-data/high-availability-client-server.html)). 
If your clients are durable, you can also define any of your CQs as durable (see [Durable Client Messaging](preserving-data/durable-client-messaging.html)).

- **Interest criteria based on data values**. Continuous queries are run against the region's entry values. 
Compare this to register interest by reviewing [Registering Interest for Entries](client-cache/registering-interest-for-entries.html).

-   **Active query execution**. Once initialized, the queries operate only on new events, rather than on the entire region data set. 
Events that change the query result are sent to the client immediately.

## <a id="cq_api"></a>Typical Continuous Query Lifecycle

1.  The client creates the CQ. This sets up everything for running the query and provides the client with a `CqQuery` object, but does not execute the CQ. At this point, the query is in a `STOPPED `state, ready to be closed or run.
2.  The client initiates the CQ with an API call to one of the `CqQuery execute*` methods. This puts the query into a `RUNNING` state on the client and on the server.  The server remotely evaluates the query string, and optionally returns the results to the client.
1.  The CqListener waits for events. When it receives events, it takes action accordingly. Events are not result sets. If the action requires doing something with the data, the data must first be retrieved.
3.  The CQ is closed by a client call to `CqQuery.close`. This de-allocates all resources in use for the CQ on the client and server. At this point, the cycle could begin again with the creation of a new `CqQuery` instance.

## <a id="ExecutingACQ"></a>Executing a Continuous Query from the Client

The essential steps to create and execute a continuous query are:

1.  Create an instance of the `QueryService` class. If you are using the pool API (recommended), you should obtain the `QueryService` from the pool.
1.  Create a `CqListener` to field events sent from the server.
1.  Use the `Query.execute()` method to submit the query string to the cache server. The server
   remotely evaluates the query string, then monitors those results and notifies the client if they change.
1.  Iterate through the returned objects.
1.  When finished, close down the continuous query.

### <a id="DotNetCQExample"></a>.NET Continuous Query Example

These C# code excerpts are from the `examples\dotnet\ContinuousQueryCs` example included in your client
distribution. See the example for full context.

Following the steps listed above,

1. Create a query service:

    ```
    var queryService = pool.GetQueryService();
    ```

1. Create a CQ Listener:

    ```
    var cqListener = new MyCqListener<string, Order>();
    ```

1. Insert the CQ Listener into a CQ attributes object:

    ```
    var cqAttributesFactory = new CqAttributesFactory<string, Order>();
    cqAttributesFactory.AddCqListener(cqListener);
    var cqAttributes = cqAttributesFactory.Create();
    ```

1. Create a Continuous Query using the query service and the CQ attributes:

    ```
    var query = queryService.NewCq("MyCq", "SELECT * FROM /example_orderobject WHERE quantity > 30", cqAttributes, false);
    ```

1. Wait for events and do something with them.

    ```
	/* Excerpt from the CqListener */

	/* Determine OP Type */
           switch (ev.getQueryOperation())
            {
                case CqOperation.OP_TYPE_CREATE:
                    operationType = "CREATE";
                    break;
                case CqOperation.OP_TYPE_UPDATE:
                    operationType = "UPDATE";
                    break;
                case CqOperation.OP_TYPE_DESTROY:
                    operationType = "DESTROY";
                    break;
                default:
                    break;
            }

	...

	/* Take action based on OP Type */

    ```

1. When finished, close up shop.

    ```
    query.Execute();
    ... (respond to events as they arrive)

    query.Stop();
    query.Close();

    cache.Close();
    ```

### <a id="CppCQExample"></a>C++ Continuous Query Example

These C++ code excerpts are from the `examples/cpp/continuousquery` example included in your client
distribution. See the example for full context.

Following the steps listed above,

1. Create a query service:

    ```
    auto queryService = pool->getQueryService();
    ```

1. Create a CQ Listener:

    ```
    class MyCqListener : public CqListener {
    ```

1. Insert the CQ Listener into a CQ attributes object:

    ```
    CqAttributesFactory cqFactory;

    auto cqListener = std::make_shared<MyCqListener>();

    cqFactory.addCqListener(cqListener);
    auto cqAttributes = cqFactory.create();
    ```

1. Create a Continuous Query using the query service and the CQ attributes:

    ```
      auto query = queryService->newCq(
	  "MyCq", "SELECT * FROM /custom_orders c WHERE c.quantity > 30",
	  cqAttributes);
    ```

1. Wait for events and do something with them.

    ```
	/* Excerpt from the CqListener */

	/* Determine OP Type */
	switch (cqEvent.getQueryOperation()) {
	case CqOperation::OP_TYPE_CREATE:
	  opStr = "CREATE";
	  break;
	case CqOperation::OP_TYPE_UPDATE:
	  opStr = "UPDATE";
	  break;
	case CqOperation::OP_TYPE_DESTROY:
	  opStr = "DESTROY";
	  break;
	default:
	  break;
	}

	...

	/* Take action based on OP Type */

    ```

1. When finished, close up shop.

    ```
    query->execute();

    ... (respond to events as they arrive)

    query->stop();
    query->close();

    cache.close();
    ```
