**Source URL:** https://general.veevavault.dev/clinical/vault-sdk/services/query-service.md

# Query Service



`QueryService` provides methods to create, execute, validate, and count query requests.

For example, imagine a simple VQL query to return the name and ID of all documents where the product is Cholecap.

```
SELECT name__v, id
FROM documents
WHERE product__v = '00P000000000119'

```

The example below creates a new instance of `QueryService` called queryService, then uses the Query Builder to create the same query as shown above.

```
QueryService queryService = ServiceLocator.locate(QueryService.class);
Query myQuery= queryService.newQueryBuilder()
.withSelect(VaultCollections.asList("name__v", "id"))
.withFrom("documents")
.withWhere("product__v = '00P000000000119'")
.build();

```

Other interfaces in the query package also provide builders that you can use with a defined query. You can use `QueryExecutonRequest` to execute the query, `QueryValidationRequest` to validate the query, or `QueryCountRequest` to retrieve the total number of records the query returns without a full query execution.

Use `QueryOperation` to execute a query and to specify success and error handlers. Vault returns query results as instances of `QueryExecutionResponse`. You can retrieve individual field values using `QueryExecutionResult.getValue()`. When querying formula fields, Vault returns the value of the field after running the formula expression, not the expression itself.

<Aside type="note" title="Note">Query strings executed using `QueryService` have a maximum length of 225,000 characters. Search terms in the `FIND` clause have a maximum length of 250 characters.

</Aside>

## Using Tokens in a Query {#Token_Request_Query_Builder}

You can include [Custom tokens](/vault-sdk/sdk-integrations/tokens/custom-tokens/) and [Vault tokens](/vault-sdk/sdk-integrations/tokens/vault-tokens/) in queries.

`QueryCountRequest.Builder`, `QueryExecutionRequest.Builder`, and `QueryValidationRequest.Builder` provide `withTokenRequest()` methods which accept a `TokenRequest` and a `QueryEscapeOverride`. If you omit overrides, Vault escapes all Strings.

The following example uses the Query Builder to create a query containing two custom tokens, `status_list` and  `approved_date`. It defines these tokens using the Token Request Builder to create a `TokenRequest`. Finally, it uses the Query Execution Request Builder to include both the Query and Token requests in a `QueryExecutionRequest`.

```
Query query = queryService.newQueryBuilder()
      .withSelect(asList("id"))
      .withFrom("documents")
      .withWhere("TONAME(status__v) CONTAINS (${Custom.status_list})")
      .appendWhere(QueryLogicalOperator.AND,
            "approved_date__c > ${Custom.approved_date}")
      .withMaxRows(50)
      .withOrderBy(asList("name__v"))
      .build();

TokenService tokenService = ServiceLocator.locate(TokenService.class);
TokenRequest tokenRequest = tokenService.newTokenRequestBuilder()
      .withValue("Custom.approved_date", LocalDate.now().minusDays(7))
      .withValue("Custom.status_list", asList("final__c","approved__c"))
      .build();

QueryExecutionRequest queryRequest = queryService
      .newQueryExecutionRequestBuilder()
      .withQuery(query)
      .withTokenRequest(tokenRequest)
      .build();

```

Vault resolves tokens in query responses, but not in error responses or when retrieving query strings with `Query#getQueryString()`.

The following limitations apply:

* You cannot reference System-managed Vault tokens in custom code.

* Vault does not support tokens in queries using deprecated SDK interfaces.

* Custom tokens must be formatted `${Custom.my_token__c}`.

* Vault tokens must be formatted  `${Vault.my_token__c}`.

Learn more in the [Javadocs](https://repo.veevavault.com/).

## Using Record Properties {#Using_Record_Properties}

Record properties provide more information about a record than a query response normally provides. For example, you can retrieve a List of editable fields or the target of a hyperlink in a formula field.

You can request record properties using the `QueryExecutionRequest#withQueryRecordPropertyTypes` method, which accepts a List of `QueryRecordPropertyType` values. For example, the `HIDDEN` type provides a List of fields that are hidden due to Atomic Security, and the `RECORD_PERMISSIONS` type provides the *Edit*, *Delete*, *Create*, and *Read* permissions for the record.

Each property type has its own response object containing additional data about a record and methods to retrieve that data. For example, the `QueryRedactedFieldResult` response object for the `REDACTED` type provides the `#getFieldNames()` method to retrieve the names of redacted fields.

The following example uses `QueryService` and `LogService` to log record properties for `my_object__c`. The `QueryHiddenFieldResult#getFieldNames()` method checks whether `possible_hidden_field__c` is hidden. The `QueryWeblinkResult#getWeblinks()` method retrieves the target attribute for *Link* formula field `my_weblink__c`.

```
LogService logService = ServiceLocator.locate(LogService.class);
QueryService queryService = ServiceLocator.locate(QueryService.class);

QueryExecutionRequest request = queryService
    .newQueryExecutionRequestBuilder()
    .withQueryString("SELECT id, possible_hidden_field__c, my_weblink__c FROM my_object__c")
    .withQueryRecordPropertyTypes(VaultCollections.asList(QueryRecordPropertyType.HIDDEN, QueryRecordPropertyType.WEB_LINK))
    .build();

queryService.query(request)
    .onSuccess(response -> {
        response.streamResults().forEach(row -> {
            String id = row.getValue("id", ValueType.STRING);
            boolean fieldIsHidden = row
                .getTypedQueryRecordProperty(QueryHiddenFields.class)
                .getFieldNames()
                .contains("possible_hidden_field__c");

            QueryWebLinkTarget webLinkTarget = row
                .getTypedQueryRecordProperty(QueryWeblinkFields)
                .getWeblinks()
                .stream()
                .filter(w -> "my_weblink__c".equals(w.getFieldName()))
                .findFirst()
                .map(QueryWeblinkResult::getTarget).orElse(null);

            logService.info(String.format("Record: [%s], hidden: [%s], web link target: [%s]", id, fieldIsHidden, webLinkTarget));
        });
    })
    .onError(error -> {
        logService.error(error.getMessage());
    }).execute();

```

Learn more in the [Javadocs](https://repo.veevavault.com/).

# Token Service {#Token_Service}

`TokenService` provides methods to define and resolve Custom tokens. You can use these tokens with:

* `HttpService` to reference tokens in the URL of an *External Connection* record.

* `QueryService` to reference tokens in a VQL query.

* `QueueService` to reference tokens in Spark messages.

You can define custom tokens using `TokenRequest.Builder` as shown in the example below.

```
TokenService tokenService = ServiceLocator.locate(TokenService.class);
      TokenRequest.Builder builder = tokenService.newTokenRequestBuilder();

      builder.withValue("Custom.api_version", "1.0");
      builder.withValue("Custom.is_case_sensitive", Boolean.TRUE);
      builder.withValue("Custom.max_amount", new BigDecimal(100));

      TokenRequest tokenRequest = builder.build();

```

`TokenService` can only be used for Custom tokens. For [Authorization tokens](/vault-sdk/sdk-integrations/tokens/authorization-tokens/) and [Session tokens](/vault-sdk/sdk-integrations/tokens/session-tokens/), use `HttpService`. For [Vault tokens](/vault-sdk/sdk-integrations/tokens/vault-tokens/), use `HttpService`, `QueryService`, or `QueueService`.



---

**Previous:** [Log Service & Vault Information Service](/clinical/vault-sdk/services/logservice-informationservice)  
**Next:** [Token Service](/clinical/vault-sdk/services/token-service)