Query-context parameters
A query-context parameter is a named, typed value that the engine resolves per request from the connection’s session attributes. Unlike a calculated member (fixed at author time) or Looker-style Liquid (arbitrary runtime SQL), a query parameter is bounded and sandboxed: it is typed, optionally restricted to a fixed set of allowed values, and can only be used as a bind value — never interpolated into SQL.
You declare a <QueryParameter> once in the schema, supply its value at connect time via a session.<name> property, and reference it where the engine accepts a bound value — today, in predicate-based row security.
The security model
The no-injection guarantee comes from typing plus enumeration, not from escaping:
- Every supplied value is coerced to the declared type (
String,Numeric,Date,Member) and, when an allowed-value set is declared, checked against it — before it can ever become part of a query. - A value that is the wrong type or outside the allowed set is rejected at connect time (the connection fails loudly), never silently passed through.
- The validated value reaches SQL only as a bound literal at a single, audited substitution point. There is no free-form templating.
Declaring a parameter
A <QueryParameter> is a top-level schema element (alongside <Role>). Give it a name, a type, an optional defaultValue, and an optional list of <QueryParameterValue> allowed values (the closed enumeration).
<QueryParameter name="region" type="String" defaultValue="EAST"> <QueryParameterValue>EAST</QueryParameterValue> <QueryParameterValue>WEST</QueryParameterValue></QueryParameter>parameters: - name: region type: String default_value: EAST allowed_values: [EAST, WEST]type | Coerced to | Notes |
|---|---|---|
String | string | |
Numeric | number | |
Date | ISO date (yyyy-MM-dd) | |
Member | a member’s leaf key | Single-key levels only |
If allowed_values is omitted the parameter is unconstrained (still type-checked). A declared default_value must itself be in the allowed set.
Supplying a value at connect time
Values arrive on the connection through session.<name> properties — the same channel Saiku uses to pass user attributes, and the same one dynamic roles read.
Provider=mondrian;Jdbc=...;Catalog=...;session.region=WESTWhen the connection is established the engine builds a validated parameter context: each declared parameter takes its session.<name> value if present, otherwise its default; the value is coerced and checked against the allowed set. An illegal value fails the connection rather than producing wrong results.
Using a parameter for row security
The primary use is predicate-based row security: restrict a measure group’s fact rows to those whose real fact column matches the requesting user’s parameter value. Declare a <PredicateGrant> on a role; the Calcite adapter injects it as a WHERE filter on every segment load for that measure group, pre-aggregation, so totals are correctly restricted.
<Role name="Regional"> <SchemaGrant access="all"> <CubeGrant cube="Sales" access="all"> <!-- restrict Sales fact rows to the user's region --> <PredicateGrant measureGroup="Sales" column="region" operator="eq" parameter="region"/> </CubeGrant> </SchemaGrant></Role>roles: - name: Regional schema_grant: access: all cube_grants: - cube: Sales access: all predicate_grants: - measure_group: Sales column: region operator: eq # or: in parameter: regionNow two users connecting with session.region=EAST and session.region=WEST see correctly different, non-overlapping totals over the same query — and the predicate appears in the generated SQL on every load of the secured measure group.
Field-switching
A parameter can also select which of a fixed set of pre-declared measures or columns is active — Looker’s parameter field-switching pattern. On the engine side you declare the set; the selection is injected at the query layer as a standard MDX WITH MEMBER / WITH SET that reads the parameter context, so it stays within the bounded, no-templating contract.
Migrating from Looker
A LookML parameter field maps directly to a <QueryParameter> (type + allowed_values + default). A parameter’s use inside {% parameter %} Liquid SQL is the dynamic-templating case the importer still refuses — see Migrating from Looker.