Query Structure
ObjectQuel is inspired by QUEL, the query language from UC Berkeley's Ingres project. Unlike SQL's table-centric approach, ObjectQuel works directly with your domain entities using object-oriented syntax, and supports wildcards, regex, and full-text search alongside standard comparison operators.
The elements of a query
Every ObjectQuel query is built from up to six clauses, written in this order:
Clauses at a Glance
- Flags (optional) — Written before all other clauses, flags adjust query execution behavior. For example,
@InValuesAreFinaltells the optimizer that every value in anINlist will match exactly one row. - Range definitions (required) — Declare which entities you are querying and assign each one a short alias. Every alias used in
retrieve,where, orsort bymust be declared here first. - retrieve (required) — Specifies what to return: full entity objects, specific properties, or a mix. The optional
uniquemodifier removes duplicate rows. - where (optional) — Filters results using comparisons, set membership, null checks, and function calls.
- sort by (optional) — Orders results. Multiple fields are evaluated left-to-right as tie-breakers.
- window (optional) — Paginates results by page number and page size. Always pair with
sort byto keep page boundaries stable.
Query Optimization Flags
Flags are optional and only needed in specific optimization scenarios.
@InValuesAreFinal
By default, ObjectQuel scans all rows even when using an IN clause, because it cannot know whether a column is unique without being told. The @InValuesAreFinal flag asserts that each value in the IN list matches exactly one row, allowing the query planner to stop as soon as all values have been found:
$results = $entityManager->executeQuery("
@InValuesAreFinal
range of p is App\\Entity\\ProductEntity
retrieve (p) where p.productId in (:ids)
", ['ids' => [1, 2, 3, 4, 5]]);
Only use
@InValuesAreFinal when the IN clause targets a primary key or unique column. Applying it to a non-unique column will cause the query to return incomplete results.