Syntax & grammar
Defining a measure
Section titled “Defining a measure”MeasureName := <expression>
// names with spaces use the bracket form[Average Order Value] := Divide([Revenue], [Orders])Names are unique per model (case-insensitively), up to 160 characters. Expressions are stored in a canonical form — consistent casing and whitespace — so format-on-save never changes meaning.
References & literals
Section titled “References & literals”| Form | Meaning |
|---|---|
[Measure Name] |
another measure in the same model |
Table.Column |
a column, resolved against model tables (plain dotted path — no quoting) |
Table.Column:grain |
a date column at an explicit grain: day, week, month, quarter, year |
"text" or 'text' |
string literal (canonical form prints double quotes) |
42, 4.2 |
numbers |
true, false |
booleans |
The inline grain is a SquareX exclusive — Fixed(Date.Date:month, …)
replaces a whole class of date-truncation boilerplate. There is no date
literal type: compare an ISO string against a date column
(Date.Date >= "2026-01-01") and the compiler emits a properly typed date
comparison on every database.
Operators & precedence
Section titled “Operators & precedence”From loosest to tightest binding:
| Level | Operators |
|---|---|
| 1 | or |
| 2 | and |
| 3 | = <> < <= > >= |
| 4 | & (string concatenation) |
| 5 | + - |
| 6 | * / % |
| 7 | unary -, not |
Worth knowing:
- Logic uses words —
and,or,not— not&&/||. &binds looser than arithmetic, so"total: " & ToText(a + b)needs no extra parentheses.&takes strings only — wrap numbers inToText.- Unary
notbinds tightest:not a = bparses as(not a) = b. Writenot (a = b)when that’s what you mean. /is always real division (integers are cast — no silent integer division). PreferDividefor ratios; it’s safe on zero.- Parentheses are always allowed.
Case & comments
Section titled “Case & comments”Function names and keywords are case-insensitive — sum, Sum, and
SUM all work and are stored canonically. // starts a comment that runs to
end of line, is legal inside expressions, and survives save — measures
can document themselves:
// The override idiom: remove-then-add wins over any dashboard Region filterWestRevenue := Calculate([Revenue], Sales.Region = "West", RemoveFilters(Sales.Region))Naming rules
Section titled “Naming rules”- Identifiers are letters, digits, and underscores, starting with a letter or
underscore; anything else in a measure name is reachable via
[brackets](a literal]doubles:]]). - Function names and keywords are reserved as bare identifiers — a measure
may still be named
Sum, but you’ll reference it as[Sum](and get a SQXW02 warning suggesting a rename). - A
Letbinding can’t shadow a function name (SQX013).
Compatibility promise
Section titled “Compatibility promise”Saved expressions keep parsing forever: grammar changes are additive only (new functions, new optional arguments) — existing syntax is never repurposed.
Related
Section titled “Related”- The SquareX guide — concepts with worked examples.
- Filter context & evaluation
- Function reference