From e73e8ce9b5e9770b1a1d566e84d4d6d35c58dd65 Mon Sep 17 00:00:00 2001 From: Gavin King Date: Sat, 12 Aug 2023 15:49:48 +0200 Subject: [PATCH] add union/intersect/except to JPQL and criteria see #398 --- .../persistence/criteria/CriteriaBuilder.java | 53 +++++++++++++++++++ spec/src/main/asciidoc/appendixes.adoc | 2 + spec/src/main/asciidoc/ch02-entities.adoc | 2 +- .../main/asciidoc/ch04-query-language.adoc | 44 +++++++++++---- 4 files changed, 91 insertions(+), 10 deletions(-) diff --git a/api/src/main/java/jakarta/persistence/criteria/CriteriaBuilder.java b/api/src/main/java/jakarta/persistence/criteria/CriteriaBuilder.java index bfe07d44..61abe716 100644 --- a/api/src/main/java/jakarta/persistence/criteria/CriteriaBuilder.java +++ b/api/src/main/java/jakarta/persistence/criteria/CriteriaBuilder.java @@ -1766,6 +1766,59 @@ Expression function(String name, Class type, */ Root treat(Root root, Class type); + /** + * Create a query which is the union of the given queries. + * @return a new criteria query which returns the union of + * the results of the given queries + * @since 3.2 + */ + CriteriaQuery union(CriteriaQuery left, CriteriaQuery right); + + /** + * Create a query which is the union of the given queries, + * without elimination of duplicate results. + * @return a new criteria query which returns the union of + * the results of the given queries + * @since 3.2 + */ + CriteriaQuery unionAll(CriteriaQuery left, CriteriaQuery right); + + /** + * Create a query which is the intersection of the given queries. + * @return a new criteria query which returns the intersection of + * the results of the given queries + * @since 3.2 + */ + CriteriaQuery intersect(CriteriaQuery left, CriteriaQuery right); + + /** + * Create a query which is the intersection of the given queries, + * without elimination of duplicate results. + * @return a new criteria query which returns the intersection of + * the results of the given queries + * @since 3.2 + */ + CriteriaQuery intersectAll(CriteriaQuery left, CriteriaQuery right); + + /** + * Create a query by (setwise) subtraction of the second query + * from the first query. + * @return a new criteria query which returns the result of + * subtracting the results of the second query from the + * results of the first query + * @since 3.2 + */ + CriteriaQuery except(CriteriaQuery left, CriteriaQuery right); + + /** + * Create a query by (setwise) subtraction of the second query + * from the first query, without elimination of duplicate results. + * @return a new criteria query which returns the result of + * subtracting the results of the second query from the + * results of the first query + * @since 3.2 + */ + CriteriaQuery exceptAll(CriteriaQuery left, CriteriaQuery right); } diff --git a/spec/src/main/asciidoc/appendixes.adoc b/spec/src/main/asciidoc/appendixes.adoc index f4d11a68..b67fbe17 100644 --- a/spec/src/main/asciidoc/appendixes.adoc +++ b/spec/src/main/asciidoc/appendixes.adoc @@ -108,6 +108,8 @@ Added support for Java record types as embeddable classes Added support for _java.time.Instant_ and _java.time.Year_ and clarified JDBC mappings for basic types +Added `union`, `intersect`, and `except` for JPQL and criteria queries + Added `||` string concatenation operator Added support for specifying null precedence when ordering JPQL and criteria queries diff --git a/spec/src/main/asciidoc/ch02-entities.adoc b/spec/src/main/asciidoc/ch02-entities.adoc index 66dcc542..ec53008c 100644 --- a/spec/src/main/asciidoc/ch02-entities.adoc +++ b/spec/src/main/asciidoc/ch02-entities.adoc @@ -1921,7 +1921,7 @@ primary key of _PATENT_. This foreign key column is named _PATENTS__ , where denotes the name of the primary key column of table _PATENT_. -=== Inheritance +=== Inheritance [[a765]] An entity may inherit from another entity class. Entities support inheritance, polymorphic associations, and diff --git a/spec/src/main/asciidoc/ch04-query-language.adoc b/spec/src/main/asciidoc/ch04-query-language.adoc index 45a32b6f..c475d674 100644 --- a/spec/src/main/asciidoc/ch04-query-language.adoc +++ b/spec/src/main/asciidoc/ch04-query-language.adoc @@ -89,8 +89,7 @@ All statement types may have parameters. ==== Select Statements -A select statement is a string which consists -of the following clauses: +A select query is a string which with the following clauses: * a SELECT clause, which determines the type of the objects or values to be selected. @@ -106,24 +105,50 @@ filtering over aggregated groups. * an optional ORDER BY clause, which may be used to order the results that are returned by the query. -In BNF syntax, a select statement is defined -as: +In BNF syntax, a select query is defined by: ---- -select_statement :: = select_clause from_clause [where_clause] [groupby_clause] [having_clause] [orderby_clause] +select_query ::= select_clause from_clause [where_clause] [groupby_clause] [having_clause] [orderby_clause] ---- A select statement must always have a SELECT and a FROM clause. The square brackets [] indicate that the other clauses are optional. +===== Set Operators in Select Statements + +A select statement may be a single select query, or it may combine +multiple select queries using the binary left-associative operators +`UNION`, `UNION ALL`, `INTERSECT`, `INTERSECT ALL`, `EXCEPT`, and +`EXCEPT ALL`. The semantics of these operators are identical to SQL. +footnote:[As in SQL, the `INTERSECT` and `INTERSECT ALL` operations have +higher precedence than `UNION`, `UNION ALL`, `EXCEPT`, and `EXCEPT ALL`.] + +The full syntax for a select statement is defined by: + +---- +select_statement := union +union := intersection | union {UNION [ALL] | EXCEPT [ALL]} intersection +intersection := query_expression | intersection INTERSECT [ALL] query_expression +query_expression := select_query | (union) +---- + +A provider is only required to support select statements where every +constituent select query has the same number of items in the select +clause, and where corresponding items in the select clauses of the +constituent select queries either: + +- have exactly the same type, as defined by <>, or +- are entity types which inherit a common entity type, as defined + by <>. + + ==== Update and Delete Statements Update and delete statements provide bulk operations over sets of entities. -In BNF syntax, these operations are defined -as: +In BNF syntax, these operations are defined by: ---- update_statement :: = update_clause [where_clause] @@ -2246,7 +2271,7 @@ ORDER BY itemCount ---- -==== Result Type of the SELECT Clause +==== Result Type of the SELECT Clause [[a5439]] The type of the query result specified by the SELECT clause of a query is an entity @@ -2949,7 +2974,8 @@ The following is the BNF for the Jakarta Persistence query language. ---- QL_statement ::= select_statement | update_statement | delete_statement -select_statement ::= select_clause from_clause [where_clause] [groupby_clause] +select_statement ::= select_query {{UNION | INTERSECT | EXCEPT} [ALL] select_query}* +select_query ::= select_clause from_clause [where_clause] [groupby_clause] [having_clause] [orderby_clause] update_statement ::= update_clause [where_clause] delete_statement ::= delete_clause [where_clause]