From 4ee8c0cfc1ae84ed07c3b54a41564d8900a03e03 Mon Sep 17 00:00:00 2001 From: Augusto Passalacqua Date: Tue, 25 Aug 2026 14:12:58 +0200 Subject: [PATCH 1/4] Document parenthesized branches of unions in OQL starting from 11.15.0 --- .../modeling/domain-model/oql/_index.md | 1 + .../modeling/domain-model/oql/oql-clauses.md | 45 +++++++++++++++++-- .../modeling/domain-model/oql/oql-v2.md | 18 +++++++- 3 files changed, 59 insertions(+), 5 deletions(-) diff --git a/content/en/docs/refguide/modeling/domain-model/oql/_index.md b/content/en/docs/refguide/modeling/domain-model/oql/_index.md index 44ad444ff5a..d9d9e4cb78d 100644 --- a/content/en/docs/refguide/modeling/domain-model/oql/_index.md +++ b/content/en/docs/refguide/modeling/domain-model/oql/_index.md @@ -37,6 +37,7 @@ OQL is under constant development so some expressions and features are not avail | Feature | Mendix Version | | --- | --- | | Comments | 11.7.0 | +| Parentheses around individual `UNION` branches | 11.15.0 | ### [OQL Expressions](/refguide/oql-expression-syntax/) diff --git a/content/en/docs/refguide/modeling/domain-model/oql/oql-clauses.md b/content/en/docs/refguide/modeling/domain-model/oql/oql-clauses.md index da0eae1fdd9..4be523c791b 100644 --- a/content/en/docs/refguide/modeling/domain-model/oql/oql-clauses.md +++ b/content/en/docs/refguide/modeling/domain-model/oql/oql-clauses.md @@ -36,7 +36,7 @@ Clauses must be presented in the following order, but can be left out if they ar 7. [`LIMIT`](#limit-offset) 8. [`OFFSET`](#limit-offset) -The `UNION` clause defies the usual order presented above. It will be presented in a [Union Clause](#oql-union) section at the end. +The `UNION` clause defies the usual order presented above. It will be presented in a [Union Clause](#oql-union) section at the end. When a branch of a `UNION` is wrapped in parentheses, the clauses inside that branch still follow the same order. The domain model used in the various examples is shown below: @@ -853,7 +853,7 @@ This clause can include items that do not appear in the `SELECT` clause, except {{% alert color="info" %}} The `ORDER BY` clause cannot be used in view entities without a `LIMIT` or an `OFFSET` clause. See [Sorting of View Entity Results](/refguide/use-view-entities/#sorting) in *How To Use View Entities* for more details. -If OQL v2 is enabled, an `ORDER BY` clause cannot be used in subqueries without a `LIMIT` or an `OFFSET` clause because the order of the subquery results may not be retained in the outer query. See the [`ORDER BY` in Subquery](/refguide/oql-v2/#order-by-in-subquery) section of *OQL Version 2 Features* for more details. +If OQL v2 is enabled, an `ORDER BY` clause cannot be used in subqueries without a `LIMIT` or an `OFFSET` clause because the order of the subquery results may not be retained in the outer query. The same restriction applies to a parenthesized branch of a `UNION`. See the [`ORDER BY` in Subquery and `UNION` Branches](/refguide/oql-v2/#order-by-in-subquery) section of *OQL Version 2 Features* for more details. {{% /alert %}} ### Syntax @@ -1076,15 +1076,21 @@ All select queries must define the same number of columns in the same order and The syntax is as follows: ```sql - select_query + select_query | ( select_query ) { - UNION [ALL] select_query + UNION [ALL] { select_query | ( select_query ) } } [ ,...n ] [ order_by_clause ] [ LIMIT number ] [ OFFSET number ] ``` +A `select_query` in a `UNION` can be wrapped in parentheses. A parenthesized `select_query` can itself be a nested `UNION` of `select_query` statements, following this same syntax. When wrapped in parentheses, a branch can have its own `order_by_clause`, `LIMIT`, and `OFFSET`, which are then scoped to that individual branch instead of, or in addition to, the `UNION` as a whole. See [Parenthesized `UNION` Branches](#oql-union-parentheses), below, for an example. + +{{% alert color="info" %}} +Parentheses in union branches if a feature that was introduced in Mendix version 11.15.0. It is supported only in Java actions. +{{% /alert %}} + ### Result data type {#oql-union-type} The data types used in `select_query` statements are considered when determining the final return type of the `UNION` clause. All data types used in `select_query` statements must be compatible. All data types are compatible with themselves. Differing types are only compatible in these cases: @@ -1196,6 +1202,37 @@ SELECT LastName AS Name FROM Sales.Customer | Doe | | Moose | +#### Parenthesized `UNION` Branches {#oql-union-parentheses} + +{{% alert color="info" %}} +This feature was introduced in Mendix version 11.15.0. It is supported only in Java actions. +{{% /alert %}} + +Instead of sorting and limiting the result of the `UNION` as a whole, you can wrap an individual branch in parentheses to sort and limit that branch on its own. This also allows a branch to combine its own `ORDER BY`, `LIMIT` and `OFFSET` clauses. + +```sql +( + SELECT Brand, City, Stock + FROM Sales.Location + ORDER BY Stock DESC + LIMIT 1 +) +UNION +( + SELECT Brand, City, Stock + FROM Sales.Location + ORDER BY Stock ASC + LIMIT 1 + OFFSET 1 +) +ORDER BY Stock ASC +``` + +| Brand | City | Stock | +| ------ | ----------| ----- | +| Veidt | Utrecht | 2 | +| Veidt | Rotterdam | 23 | + #### Union of different types Presume two entities that have columns of types `INTEGER` and `DECIMAL`: diff --git a/content/en/docs/refguide/modeling/domain-model/oql/oql-v2.md b/content/en/docs/refguide/modeling/domain-model/oql/oql-v2.md index 0771917250c..4523dd17633 100644 --- a/content/en/docs/refguide/modeling/domain-model/oql/oql-v2.md +++ b/content/en/docs/refguide/modeling/domain-model/oql/oql-v2.md @@ -183,7 +183,7 @@ JOIN (SELECT Name AS N FROM Module.City) C ON P/Residence = C/Name ``` -### `ORDER BY` in Subquery {#order-by-in-subquery} +### `ORDER BY` in Subquery and `UNION` Branches {#order-by-in-subquery} You must now have a `LIMIT` and/or `OFFSET` in subquery containing `ORDER BY`. Using `ORDER BY` in subquery makes sense only when it is combined with `LIMIT` and/or `OFFSET`. Without the limitations, database engines do not guarantee that the row order in the subquery will be preserved in the outer query. @@ -212,6 +212,22 @@ FROM ( ) ``` +The same restriction applies to a `select_query`, or a nested `UNION`, wrapped in parentheses as a branch of a [`UNION`](/refguide/oql-clauses/#oql-union). Consequently, you can only use `ORDER BY` in a parenthesized `UNION` branch if it is combined with `LIMIT` and/or `OFFSET`: + +```sql +( + SELECT Name + FROM Module.Person + ORDER BY Name + LIMIT 20 +) +UNION +( + SELECT Name + FROM Module.City +) +``` + ### `ORDER BY` in View Entities For [view entities](/refguide/view-entities/), you must now have a `LIMIT` and `OFFSET` in all `ORDER BY` clauses, even for the top level query. From 2aa0033edfb1406f2dd0d32c0332308bfac5f50b Mon Sep 17 00:00:00 2001 From: MarkvanMents Date: Fri, 28 Aug 2026 13:24:34 +0200 Subject: [PATCH 2/4] Add descriptions to OQL pages. --- content/en/docs/refguide/modeling/domain-model/oql/_index.md | 1 + .../en/docs/refguide/modeling/domain-model/oql/oql-clauses.md | 1 + content/en/docs/refguide/modeling/domain-model/oql/oql-v2.md | 1 + 3 files changed, 3 insertions(+) diff --git a/content/en/docs/refguide/modeling/domain-model/oql/_index.md b/content/en/docs/refguide/modeling/domain-model/oql/_index.md index d9d9e4cb78d..02fc93d78a9 100644 --- a/content/en/docs/refguide/modeling/domain-model/oql/_index.md +++ b/content/en/docs/refguide/modeling/domain-model/oql/_index.md @@ -1,6 +1,7 @@ --- title: "OQL" url: /refguide/oql/ +description: "An introduction to the Mendix Object Query Language with links to further information." weight: 90 --- diff --git a/content/en/docs/refguide/modeling/domain-model/oql/oql-clauses.md b/content/en/docs/refguide/modeling/domain-model/oql/oql-clauses.md index 4be523c791b..8d85e690769 100644 --- a/content/en/docs/refguide/modeling/domain-model/oql/oql-clauses.md +++ b/content/en/docs/refguide/modeling/domain-model/oql/oql-clauses.md @@ -1,6 +1,7 @@ --- title: "OQL Clauses" url: /refguide/oql-clauses/ +description: "A reference guide to OQL clauses" weight: 10 aliases: - /refguide/oql-from-clause/ diff --git a/content/en/docs/refguide/modeling/domain-model/oql/oql-v2.md b/content/en/docs/refguide/modeling/domain-model/oql/oql-v2.md index 4523dd17633..54aaf531d67 100644 --- a/content/en/docs/refguide/modeling/domain-model/oql/oql-v2.md +++ b/content/en/docs/refguide/modeling/domain-model/oql/oql-v2.md @@ -1,6 +1,7 @@ --- title: "OQL Version 2 Features" linktitle: "Switching to OQL Version 2" +description: "A guide to the differences between Mendix OQL versions 1 and 2, plus a guide to switching to version 2" url: /refguide/oql-v2/ weight: 100 --- From 3671afbdf96fb8c391ed0dba621122de429cabd5 Mon Sep 17 00:00:00 2001 From: MarkvanMents Date: Fri, 28 Aug 2026 14:46:07 +0200 Subject: [PATCH 3/4] Proofread and change "branch" to "subquery". --- .../modeling/domain-model/oql/oql-clauses.md | 24 ++++++++++++------- .../modeling/domain-model/oql/oql-v2.md | 4 ++-- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/content/en/docs/refguide/modeling/domain-model/oql/oql-clauses.md b/content/en/docs/refguide/modeling/domain-model/oql/oql-clauses.md index 8d85e690769..34e452ccc33 100644 --- a/content/en/docs/refguide/modeling/domain-model/oql/oql-clauses.md +++ b/content/en/docs/refguide/modeling/domain-model/oql/oql-clauses.md @@ -37,7 +37,7 @@ Clauses must be presented in the following order, but can be left out if they ar 7. [`LIMIT`](#limit-offset) 8. [`OFFSET`](#limit-offset) -The `UNION` clause defies the usual order presented above. It will be presented in a [Union Clause](#oql-union) section at the end. When a branch of a `UNION` is wrapped in parentheses, the clauses inside that branch still follow the same order. +The `UNION` clause joins multiple SELECT subclauses but each SELECT clause must maintain the order presented above. See [`UNION` Clause](#oql-union), below. The domain model used in the various examples is shown below: @@ -854,7 +854,7 @@ This clause can include items that do not appear in the `SELECT` clause, except {{% alert color="info" %}} The `ORDER BY` clause cannot be used in view entities without a `LIMIT` or an `OFFSET` clause. See [Sorting of View Entity Results](/refguide/use-view-entities/#sorting) in *How To Use View Entities* for more details. -If OQL v2 is enabled, an `ORDER BY` clause cannot be used in subqueries without a `LIMIT` or an `OFFSET` clause because the order of the subquery results may not be retained in the outer query. The same restriction applies to a parenthesized branch of a `UNION`. See the [`ORDER BY` in Subquery and `UNION` Branches](/refguide/oql-v2/#order-by-in-subquery) section of *OQL Version 2 Features* for more details. +If OQL v2 is enabled, an `ORDER BY` clause cannot be used in subqueries without a `LIMIT` or an `OFFSET` clause because the order of the subquery results may not be retained in the outer query. See the [`ORDER BY` in Subqueries](/refguide/oql-v2/#order-by-in-subqueries) section of *OQL Version 2 Features* for more details. {{% /alert %}} ### Syntax @@ -1086,13 +1086,13 @@ The syntax is as follows: [ OFFSET number ] ``` -A `select_query` in a `UNION` can be wrapped in parentheses. A parenthesized `select_query` can itself be a nested `UNION` of `select_query` statements, following this same syntax. When wrapped in parentheses, a branch can have its own `order_by_clause`, `LIMIT`, and `OFFSET`, which are then scoped to that individual branch instead of, or in addition to, the `UNION` as a whole. See [Parenthesized `UNION` Branches](#oql-union-parentheses), below, for an example. +By default, any `order_by_clause`, `LIMIT`, or `OFFSET` in a `UNION` clause will apply to the whole query. If you wrap the `select_query` subquery of a `UNION` in parentheses, you can nest a `UNION` of `select_query` statements, and give each `select_query` its own `order_by_clause`, `LIMIT`, and `OFFSET`, which are then scoped to that subquery. The `UNION` as a whole can have its own `order_by_clause`, `LIMIT`, and `OFFSET`. See [Parenthesized `UNION` Branches](#oql-union-parentheses), below, for an example. {{% alert color="info" %}} -Parentheses in union branches if a feature that was introduced in Mendix version 11.15.0. It is supported only in Java actions. +Adding parentheses in union branches was introduced in Mendix version 11.15.0. It is supported only in Java actions. {{% /alert %}} -### Result data type {#oql-union-type} +### Result Data Type {#oql-union-type} The data types used in `select_query` statements are considered when determining the final return type of the `UNION` clause. All data types used in `select_query` statements must be compatible. All data types are compatible with themselves. Differing types are only compatible in these cases: @@ -1203,13 +1203,15 @@ SELECT LastName AS Name FROM Sales.Customer | Doe | | Moose | -#### Parenthesized `UNION` Branches {#oql-union-parentheses} +#### Parenthesized `UNION` Subqueries {#oql-union-parentheses} {{% alert color="info" %}} This feature was introduced in Mendix version 11.15.0. It is supported only in Java actions. {{% /alert %}} -Instead of sorting and limiting the result of the `UNION` as a whole, you can wrap an individual branch in parentheses to sort and limit that branch on its own. This also allows a branch to combine its own `ORDER BY`, `LIMIT` and `OFFSET` clauses. +You can wrap an individual subquery in parentheses to sort and limit only the results from that subquery rather than the sorting and limiting applying to the result of the `UNION`. This is done by giving each subquery its own `ORDER BY`, `LIMIT` and `OFFSET` clauses. + +For example, the following query uses `UNION` to return the brand and location with the highest and lowest stock levels, sorted in ascending order of the amount of stock. ```sql ( @@ -1234,7 +1236,7 @@ ORDER BY Stock ASC | Veidt | Utrecht | 2 | | Veidt | Rotterdam | 23 | -#### Union of different types +#### Union of Different Types Presume two entities that have columns of types `INTEGER` and `DECIMAL`: @@ -1273,7 +1275,7 @@ SELECT Sale FROM Sales.Sales | 42.25 | | 15.5 | -#### Union of associations +#### Union of Associations Performing a `UNION` with columns that are associations is possible, given the columns refer to the same entity for all select clauses. @@ -1312,6 +1314,10 @@ SELECT Cust.LastName as CustomerName FROM ( A subquery is an OQL query nested inside another query. A subquery can contain the same clauses as a regular OQL query. The entities from the outer query can be referred to in a subquery. A subquery can be used in different parts of the query. +{{% alert color="info" %}} +For the use of subqueries in `UNION` clauses, see [Parenthesized `UNION` Subqueries](#oql-union-parentheses), above. +{{% /alert %}} + ### Subquery in `SELECT` {#subquery-in-select} A subquery can be used as a column in the `SELECT` clause. It can refer to other tables and expressions in `FROM`. diff --git a/content/en/docs/refguide/modeling/domain-model/oql/oql-v2.md b/content/en/docs/refguide/modeling/domain-model/oql/oql-v2.md index 54aaf531d67..c2ee398c4f7 100644 --- a/content/en/docs/refguide/modeling/domain-model/oql/oql-v2.md +++ b/content/en/docs/refguide/modeling/domain-model/oql/oql-v2.md @@ -184,7 +184,7 @@ JOIN (SELECT Name AS N FROM Module.City) C ON P/Residence = C/Name ``` -### `ORDER BY` in Subquery and `UNION` Branches {#order-by-in-subquery} +### `ORDER BY` in Subqueries {#order-by-in-subqueries} You must now have a `LIMIT` and/or `OFFSET` in subquery containing `ORDER BY`. Using `ORDER BY` in subquery makes sense only when it is combined with `LIMIT` and/or `OFFSET`. Without the limitations, database engines do not guarantee that the row order in the subquery will be preserved in the outer query. @@ -213,7 +213,7 @@ FROM ( ) ``` -The same restriction applies to a `select_query`, or a nested `UNION`, wrapped in parentheses as a branch of a [`UNION`](/refguide/oql-clauses/#oql-union). Consequently, you can only use `ORDER BY` in a parenthesized `UNION` branch if it is combined with `LIMIT` and/or `OFFSET`: +The same restriction applies to a subquery which is a `select_query`, or a nested `UNION` as part of a [`UNION`](/refguide/oql-clauses/#oql-union). Consequently, you can only use `ORDER BY` in a parenthesized `UNION` branch if it is combined with `LIMIT` and/or `OFFSET`: ```sql ( From 9fc776d7dcde811954f17df8b42094862d368206 Mon Sep 17 00:00:00 2001 From: MarkvanMents Date: Fri, 28 Aug 2026 14:49:36 +0200 Subject: [PATCH 4/4] Remove references to "branch" --- content/en/docs/refguide/modeling/domain-model/oql/_index.md | 2 +- .../en/docs/refguide/modeling/domain-model/oql/oql-clauses.md | 4 ++-- content/en/docs/refguide/modeling/domain-model/oql/oql-v2.md | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/content/en/docs/refguide/modeling/domain-model/oql/_index.md b/content/en/docs/refguide/modeling/domain-model/oql/_index.md index 02fc93d78a9..29d89d22b7c 100644 --- a/content/en/docs/refguide/modeling/domain-model/oql/_index.md +++ b/content/en/docs/refguide/modeling/domain-model/oql/_index.md @@ -38,7 +38,7 @@ OQL is under constant development so some expressions and features are not avail | Feature | Mendix Version | | --- | --- | | Comments | 11.7.0 | -| Parentheses around individual `UNION` branches | 11.15.0 | +| Parentheses around individual `UNION` subqueries | 11.15.0 | ### [OQL Expressions](/refguide/oql-expression-syntax/) diff --git a/content/en/docs/refguide/modeling/domain-model/oql/oql-clauses.md b/content/en/docs/refguide/modeling/domain-model/oql/oql-clauses.md index 34e452ccc33..753875c5d7c 100644 --- a/content/en/docs/refguide/modeling/domain-model/oql/oql-clauses.md +++ b/content/en/docs/refguide/modeling/domain-model/oql/oql-clauses.md @@ -1086,10 +1086,10 @@ The syntax is as follows: [ OFFSET number ] ``` -By default, any `order_by_clause`, `LIMIT`, or `OFFSET` in a `UNION` clause will apply to the whole query. If you wrap the `select_query` subquery of a `UNION` in parentheses, you can nest a `UNION` of `select_query` statements, and give each `select_query` its own `order_by_clause`, `LIMIT`, and `OFFSET`, which are then scoped to that subquery. The `UNION` as a whole can have its own `order_by_clause`, `LIMIT`, and `OFFSET`. See [Parenthesized `UNION` Branches](#oql-union-parentheses), below, for an example. +By default, any `order_by_clause`, `LIMIT`, or `OFFSET` in a `UNION` clause will apply to the whole query. If you wrap the `select_query` subquery of a `UNION` in parentheses, you can nest a `UNION` of `select_query` statements, and give each `select_query` its own `order_by_clause`, `LIMIT`, and `OFFSET`, which are then scoped to that subquery. The `UNION` as a whole can have its own `order_by_clause`, `LIMIT`, and `OFFSET`. See [Parenthesized `UNION` Subqueries](#oql-union-parentheses), below, for an example. {{% alert color="info" %}} -Adding parentheses in union branches was introduced in Mendix version 11.15.0. It is supported only in Java actions. +Adding parentheses in `UNION` clauses was introduced in Mendix version 11.15.0. It is supported only in Java actions. {{% /alert %}} ### Result Data Type {#oql-union-type} diff --git a/content/en/docs/refguide/modeling/domain-model/oql/oql-v2.md b/content/en/docs/refguide/modeling/domain-model/oql/oql-v2.md index c2ee398c4f7..62829cc7ee9 100644 --- a/content/en/docs/refguide/modeling/domain-model/oql/oql-v2.md +++ b/content/en/docs/refguide/modeling/domain-model/oql/oql-v2.md @@ -213,7 +213,7 @@ FROM ( ) ``` -The same restriction applies to a subquery which is a `select_query`, or a nested `UNION` as part of a [`UNION`](/refguide/oql-clauses/#oql-union). Consequently, you can only use `ORDER BY` in a parenthesized `UNION` branch if it is combined with `LIMIT` and/or `OFFSET`: +The same restriction applies to a subquery which is a `select_query`, or a nested `UNION` as part of a [`UNION`](/refguide/oql-clauses/#oql-union). Consequently, you can only use `ORDER BY` in a parenthesized `UNION` clause if it is combined with `LIMIT` and/or `OFFSET`: ```sql (