Groovy variables in query strings
Using your own Groovy variables, closures, and classes in Deephaven query strings is one of Deephaven's most powerful features. This guide covers three common kinds of Groovy variables: scalars, strings, and lists or arrays. It starts with the rules that decide which variables a query string can see and what column types they produce.
Rules for Groovy variables in query strings
Query strings find Groovy variables through Deephaven's query scope. In a Groovy session, the query scope is the script session's variable binding, which holds the variables a script assigns without def or a type.
The first four rules below decide which variables a query string can see:
- A variable assigned without
defor a type is in the binding, so a query string can use it by name. This includes a top-level assignment such asa = 4. It also includes an assignment inside a closure, such as{ -> z = 5 }, once the closure runs. - A variable declared with
defor a type, such asdef a = 4orint a = 4, is local to the script and isn't in the binding. Neither is a variable declared inside a method or closure. A query string that uses one fails with a "Cannot find variable or class" error. To fix it, add the variable withQueryScope.addParam, as Local (function) scope shows. - A variable with the same name as a column of the table is hidden, even when it's in the binding. The query string reads the column instead, with no error. See Columns take precedence over variables.
- A variable named
i,ii, orkis hidden too. Those names are built-in variables for row position and row key, so the query string always reads the built-in. The namenotis reserved as well. Give your variable a different name.
The last two rules decide what column types those variables produce:
- A column's type comes from the variable's Groovy type:
- Indexing into a Groovy list returns
Object, so cast the element to the type you want. Indexing into a Java primitive array, such asint[], keeps the element type. See Lists and arrays.
Every example on this page assigns its variables at the top level, without def or a type, so they are all in the binding.
Scalars
Scalars are single values, such as numbers or booleans. A query string uses a scalar by its variable name, with no special syntax. The following example uses Groovy variables in query strings to create new columns in a table:
The meta table, sourceMeta, shows each column's type:
Ais anint.BandCarejava.math.BigDecimal. Groovy reads every decimal literal as aBigDecimal, including one with an exponent such as-1.91e7.Dis ajava.lang.Boolean.
To get a double column instead of a BigDecimal one, do one of these:
- Cast the variable in the query string:
"B = (double)b". See type casts. - Give the literal a
dsuffix:b = 3.14d.
Strings
Like scalars, a Groovy string goes into a query string by its variable name, with no special syntax. The following example creates a table with two string columns:
The meta table, sourceMeta, shows that both columns are java.lang.String.
A string that interpolates a value, such as "Hello ${name}", is a Groovy GString, not a java.lang.String. In a query string, it makes a GStringImpl column. A match filter that compares it with a String column finds no rows, and it raises no error. To avoid this, call toString when you assign the string, for example greeting = "Hello ${name}".toString(). See Strings for more.
Lists and arrays
You can also use Groovy lists and Java arrays in query strings. A Groovy list literal such as [1, 2, 3] is a java.util.ArrayList:
The sourceListMeta table shows that ListColumn holds the whole list as a single java.util.ArrayList object.
You can also extract individual elements in a query string. For a list, myList[0] becomes myList.get(0), which returns Object. Use type casts to get the column type you want:
With the casts, FirstElement, SecondElement, and ThirdElement are all int columns.
To use a Java primitive array instead, convert the list with as, for example myArray = [1, 2, 3] as int[]. Don't declare it as int[] myArray = [1, 2, 3]. A typed declaration isn't in the binding, so a query string can't see it.
In the following example, ArrayColumn holds the whole int[]. Indexing into a primitive array keeps the element type, so FirstElement is an int with no cast: