Parameter descriptions are shown in the UI. When you add
-- comments above a param declaration, they appear as help text in the ontology query panel. Use them to document expected formats, example values, and allowed filter keys.Two File Shapes
TQL files come in two forms.Plain SQL Template
Use this when the template is essentially SQL with a few direct parameters.${...} interpolates a param name directly into SQL.
Expression Body
Use this when you need branching, reusable fragments,matchSet, or semantic-view logic.
SqlFragment using sql"..." or sql'' ... ''.
Params
Params are declared in aparams { ... } block — one per line, no commas.
Supported Types
| TQL Type | JSON Shape | Notes |
|---|---|---|
Int | integer | Non-integer numbers are rejected |
Float | number | Integers also accepted |
String | string | |
Bool | boolean | |
Date | string | Document the expected format in -- comments |
Timestamp | string | Same note as Date |
Set<"..."> | array of strings | Values validated against allowed labels |
List<T> | array | Elements validated recursively |
FilterInput | object | Used inside List<FilterInput> for dynamic filtering |
Nullability and Defaults
?marks a nullable param. Omitting it resolves tonull.- Non-nullable params without a default are required.
- Defaults are supported for scalars and empty lists/sets.
Param Descriptions
-- comments directly above a param declaration are exposed by inspect and shown in the UI as help text.
Expressions
let Bindings
Conditionals
Records and Field Access
SQL Fragments
Usesql"..." for short fragments and sql'' ... '' for multiline SQL.
NULL, not as an omitted clause. Use if for optional predicates:
Builtins
matchSet
The core tool for set-driven SQL structure. Maps each label in a Set<"..."> param to a SQL fragment or record.
filterWhere
Lowers user-supplied FilterInput values against an authored filter registry.
equals, not_equals, gt, gte, lt, lte, like, starts_with, ends_with, between, in, not_in, is_null, is_not_null.
concatSep
Concatenates a list of SqlFragment values with a separator. Empty fragments are skipped.
wrap
Adds a prefix and suffix to a fragment, but only if the fragment is non-empty.
isEmpty
Returns true for empty fragments, strings, sets, lists, and null.
map, any, contains
Semantic-View Pattern
The recommended pattern for reusable query surfaces combinesmetrics, dimensions, and filters params with matchSet and filterWhere.
Common Gotchas
`=` is not equality
`=` is not equality
Use
= for param defaults, let bindings, and record fields. Use == / != for expression equality comparisons.Optional filters need explicit branching
Optional filters need explicit branching
Nullable params interpolate as
NULL — they do not remove SQL clauses automatically. Use if or isEmpty for optional predicates.Sets cannot be interpolated directly
Sets cannot be interpolated directly
SELECT ${metrics} fails. Use matchSet or contains to work with set values.`concatSep` and `wrap` only accept trusted literals
`concatSep` and `wrap` only accept trusted literals
The separator and prefix/suffix must be authored string literals, not params.
Plain-body interpolation is limited
Plain-body interpolation is limited
In a plain SQL body,
${...} only interpolates a param name. For computed fragments like ${select_expr}, switch to expression-style TQL with sql"...".Authoring Checklist
Before saving a new.tql file:
- Params are in
params { ... }, one per line, no commas - String defaults use double quotes
- Equality tests use
==/!= - Optional clauses use
iforisEmpty - Interpolations are not wrapped in SQL quotes
- List interpolations are not wrapped in extra parentheses
- Semantic-view metrics have stable
AS ...aliases filterscomments document allowed keys and operators