Syntax & Grammar
A FOQL query is a single select statement. It always begins with a select list and a from module, followed by optional where, group by, order by, limit, and offset clauses — in that order.
Grammar specification (EBNF)#
The following EBNF describes the accepted FOQL grammar. Terminals are shown in "quotes"; { ... } means zero or more; [ ... ] means optional; | is alternation.
query ::= select_clause from_clause [ where_clause ] [ group_by_clause ] [ order_by_clause ] [ limit_clause ] [ offset_clause ] ;
select_clause ::= "select" select_list ;select_list ::= select_item { "," select_item } ;select_item ::= ( field_path | aggregate ) [ "as" alias ] ;aggregate ::= agg_func "(" field_path ")" ;agg_func ::= "sum" | "avg" | "min" | "max" | "count" ;
from_clause ::= "from" module_name ;
where_clause ::= "where" condition ;condition ::= predicate | "(" condition ")" | condition "and" condition | condition "or" condition ;predicate ::= field_path operator value | field_path "is" [ "not" ] "null" | field_path [ "not" ] "in" "(" value_list ")" | field_path [ "not" ] "between" value "and" value | field_path [ "not" ] "like" string_literal ;operator ::= "=" | "!=" | ">" | ">=" | "<" | "<=" ;
group_by_clause ::= "group" "by" field_path { "," field_path } ;order_by_clause ::= "order" "by" order_item { "," order_item } ;order_item ::= ( field_path | alias ) [ "asc" | "desc" ] ;limit_clause ::= "limit" integer ;offset_clause ::= "offset" integer ;
field_path ::= field { "." field } ; (* dot = lookup traversal *)field ::= identifier ;module_name ::= identifier ;alias ::= identifier ;value ::= string_literal | number | boolean | "null" ;value_list ::= value { "," value } ;string_literal ::= "'" { character } "'" ;boolean ::= "true" | "false" ;identifier ::= letter { letter | digit | "_" } ;Annotated reference query#
This query exercises most of the language at once — scalar fields, an aggregate, lookup traversals, an alias, filtering, grouping, multi-field ordering, and pagination:
select id, sum(totalCost), serialNumber, subject, status, multi_enum_field_workorder as enumLabels, multi_lookup_field_workorder, priority, priority.displayName, vendor, vendor.name, lookup_workorder_1, vendor.moduleState, vendor.moduleState.displayNamefrom workorderwhere priority = 'Low'group by category, statusorder by createdTime desc, id asclimit 100 offset 0| Token | Meaning |
|---|---|
id | A scalar field of workorder. |
sum(totalCost) | Aggregate function over the totalCost field. |
serialNumber, subject | Scalar fields. |
status | A lookup field; returns the related state id as a flat value unless traversed. |
multi_enum_field_workorder as enumLabels | A multi-enum field, returned under the alias enumLabels. |
multi_lookup_field_workorder | A multi-lookup field (returns a list of related record ids). |
priority | A lookup field; by itself returns the related record id as a flat value. |
priority.displayName | Traversal: the displayName field of the priority lookup's target module. |
vendor / vendor.name | vendor returns a flat id ("vendor": 88); vendor.name pulls name from the vendor module. |
lookup_workorder_1 | A custom lookup field on workorder. |
vendor.moduleState.displayName | Two-hop traversal: vendor → its moduleState (status) → that state's displayName. |
from workorder | Base module. |
where priority = 'Low' | Filter. |
group by category, status | Grouping (required when aggregates are mixed with scalar columns). |
order by createdTime desc, id asc | Multi-field sort. |
limit 100 offset 0 | Pagination. |
tip
For the meaning of each clause in depth, see Clauses. For how dotted lookups like vendor.moduleState.displayName resolve, see Lookup Traversal.