Query Scope
Deephaven query strings allow complex queries to be expressed with a concise syntax. These query strings can implement formulas or filters that use Groovy variables. For example, the query string in this update uses the variable a from Groovy.
This guide will walk you through Groovy's scoping rules and the process for adding variables and using functions in Groovy query strings. There are many reasons to use variables: more understandable code, better reusability, and in some cases, improved efficiency.
If you'd like to learn more about query strings and the basic rationale of the query scope, see our conceptual guide.
Note
Variable names and function names are case-sensitive.
Query scope in Groovy
In Groovy, the Deephaven Query Language resolves variables using the QueryScope. Unlike some other languages, Groovy requires explicit management of the query scope for most use cases. Groovy's query scope resolution follows these rules in order:
- Local (function) scope: Variables explicitly added to the query scope using
QueryScope.addParam()are checked first - Script-level scope: Variables defined at the top level of a Groovy script are automatically added to the query scope and checked second
- Global scope: Built-in functions and globally available variables are checked last
This means that local variables (when explicitly added) take precedence over script-level variables, which in turn take precedence over global variables. Unlike Python's LEGB (Local, Enclosing, Global, Built-in) scoping rule where variables are automatically resolved, Groovy requires explicit management of the query scope for variables that are not at the script level.
Examples
Script-level scope
Variables defined at the top level of a Groovy script are automatically available in query strings without any additional setup.
Local (function) scope
Variables defined within functions, closures, or any local scope must be explicitly added to the query scope to be used in query strings.
Enclosing (nonlocal) scope
Variables from enclosing scopes (such as variables in outer functions) are not automatically available in query strings and must be explicitly added to the query scope.
Encapsulated query logic in functions
It is very common to encapsulate query logic within functions to create cleaner, more readable code. Such functions may use variables in query strings. In Groovy, function parameters and local variables are not automatically available to query strings - they must be manually added to the query scope using QueryScope.addParam().
In this example, the compute function performs a query using the source table and the input parameter a. Since a is a function parameter (not a top-level script variable), it must be explicitly added to the query scope to be used in the query string.
Global scope
Deephaven provides built-in functions, constants, and variables that are globally available in all query strings without any additional setup. These include mathematical functions, type conversion utilities, and other commonly used operations. The following query demonstrates using built-in global functions and constants in query strings.
Use variables in a query string
In Groovy, variables can be made available to query strings in two ways: manually using QueryScope.addParam() and automatically for top-level script variables.
Manually
To add the variable by hand, use this basic syntax:
In the following example, the value 7 is assigned to the variable a.
This variable can be used inside a query string.
Automatically
Variables defined at the top level of a Groovy script are automatically added to the query scope. This only applies to variables declared directly in the script, not within functions or closures.
In the next example, b = 3 is defined at the top level, so it's automatically available in query strings.
This variable can be used inside a query string.
Use functions in a query string
We can also define a function and use it inside a query string.
In the next example, myFunction is defined and is called from the query string.
Example
In this example, we want to know how much sales tax we will pay in various states given how much money is spent. The query scope is helpful because we can easily change the value of money spent as we call the function more than once.
Note that sales_price must be explicitly added to the query scope since it's a function parameter, not a top-level variable.