Skip to content

Commit

Permalink
make identification variables (and the SELECT) clause optional in JPQL
Browse files Browse the repository at this point in the history
this is a minimal change to support the subset in Jakarta Data
i.e. it is only allowed when there is just one thing in the
FROM clause

see jakartaee#452
  • Loading branch information
gavinking committed Mar 11, 2024
1 parent 864c56d commit 165d97f
Showing 1 changed file with 130 additions and 46 deletions.
176 changes: 130 additions & 46 deletions spec/src/main/asciidoc/ch04-query-language.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -108,12 +108,11 @@ used to order the results that are returned by the query.
In BNF syntax, a select query is defined by:

----
select_query ::= 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.
Every select statement has a FROM clause. The square brackets `[]` in the
BNF indicate that the other clauses are optional.

===== Set Operators in Select Statements

Expand Down Expand Up @@ -202,7 +201,7 @@ entity's or embeddable's abstract schema type determine navigability.
Using the association fields and their values, a query can select
related entities and use their abstract schema types in the query.

==== Naming
==== Naming [[naming]]

Entities are designated in query strings by
their entity names. The entity name is defined by the `name` element of
Expand Down Expand Up @@ -283,20 +282,32 @@ navigation is provided by the association fields `lineItems` and

=== The FROM Clause and Navigational Declarations

The FROM clause of a query defines the domain
of the query by declaring identification
variables. An identification variable is an identifier declared in the
FROM clause of a query. The domain of the
query may be constrained by path expressions. (See <<a4792>>.)
The FROM clause of a query defines the _domain_ of the query:

Identification variables designate instances
of a particular abstract schema type. The FROM clause can contain
multiple identification variable declarations separated by a comma (`,`).
- one or more named entity abstract schema types, as specified below
in <<a4766>>, together with
- zero or more joined associations and collections, as specified
below in <<joins>>.

An _identification variable_ is an identifier declared in the FROM
clause of a query. Each identification variable is assigned an
abstract schema type. Each element of the domain may declare an
identification variable.

- If domain has exactly one named entity abstract schema type, and
no joins, then the named entity does not require an identification
variable.
- Otherwise, every element of the FROM clause&mdash;that is, every
named entity abstract schema types and every join&mdash;must
declare an identification variable.

----
from_clause ::=
FROM identification_variable_declaration
{, {identification_variable_declaration | collection_member_declaration}}*
FROM entity_name | identification_variable_declarations
identification_variable_declarations ::=
identification_variable_declaration
{, {identification_variable_declaration | collection_member_declaration}}*
identification_variable_declaration ::= range_variable_declaration {join | fetch_join}*
Expand All @@ -319,9 +330,9 @@ join_association_path_expression ::=
TREAT(join_collection_valued_path_expression AS subtype) |
TREAT(join_single_valued_path_expression AS subtype)
join_collection_valued_path_expression ::= identification_variable.{single_valued_embeddable_object_field.}*collection_valued_field
join_collection_valued_path_expression ::= [identification_variable.]{single_valued_embeddable_object_field.}*collection_valued_field
join_single_valued_path_expression ::= identification_variable.{single_valued_embeddable_object_field.}*single_valued_object_field
join_single_valued_path_expression ::= [identification_variable.]{single_valued_embeddable_object_field.}*single_valued_object_field
join_condition ::= ON conditional_expression
Expand Down Expand Up @@ -363,7 +374,7 @@ result variables (see <<a5438>>).

[NOTE]
====
It is recommended that SQL key words other
It is recommended that SQL keywords other
than those listed above not be used as identification variables in
queries because they may be used as reserved identifiers in future
releases of this specification.
Expand Down Expand Up @@ -439,16 +450,22 @@ variable of the same name.

==== Range Variable Declarations [[a4766]]

The syntax for declaring an
identification variable as a range variable is similar to that of SQL;
optionally, it uses the AS keyword. A range variable designates an
entity abstract schema type.footnote:[A range variable must
not designate an embeddable class abstract schema type.]
A range variable declaration introduces a query domain element ranging
over a given named entity abstract schema type, with an associated
identification variable.

The syntax for declaring an identification variable as a range variable
is similar to that of SQL; optionally, it may use the AS keyword. A
range variable declaration designates an entity abstract schema type by
its entity name, as defined above in <<naming>>.footnote:[A range variable
never designates an embeddable class abstract schema type.]

----
range_variable_declaration ::= entity_name [AS] identification_variable
----

The entity name in a range variable declaration is case-sensitive.

Range variable declarations allow the
developer to designate a “root” for objects which may not be reachable
by navigation.
Expand All @@ -474,23 +491,63 @@ WHERE o1.quantity > o2.quantity AND
o2.customer.firstname= 'John'
----

The entity name in a range variable declaration is case-sensitive.
If the query domain is a single entity type, the range variable
declaration is optional. These queries are equivalent:

[source,sql]
----
SELECT ord.quantity
FROM Order AS ord
WHERE ord.customer.lastname = 'Smith'
AND ord.customer.firstname= 'John'
----
[source,sql]
----
SELECT quantity
FROM Order
WHERE customer.lastname = 'Smith'
AND customer.firstname= 'John'
----

Otherwise, if the query domain has more than one element,
each entity type listed in the FROM clause must specify
be a range variable declaration.


[[a4792]]
==== Path Expressions

An identification variable followed by the
navigation operator (`.`) and a state field or association field is a
path expression. The type of the path expression is the type computed as
A path expression is a sequence of identifiers uniquely identifying
a state field or association field of an element of the query domain.

A path expression may begin with a reference to an identification
variable, followed by the navigation operator (`.`).

- If the query domain has a single element, then the identification
variable is optional, and every path expression which does not begin
with an identification variable is interpreted exactly as if it began
with an identification variable referring to the single element of
the domain.
- Otherwise, every path expression must begin with an identification
variable.

The remaining elements of the path expression are interpreted as
references to state fields or association fields in the context of the
abstract schema type assigned to the identification variable, or in the
context of the single abstract schema type of the query domain, in the
case where the path expression does not begin with an identification
variable.

A reference to a state field or association field in a path expression
is case-sensitive.

The type of the path expression is the type computed as
the result of navigation; that is, the type of the state field or
association field to which the expression navigates. The type of a path
expression that navigates to an association field may be specified as a
subtype of the declared type of the association field by means of the
TREAT operator. See <<a4965>>.

A reference to a state field or association field in a path expression is
case-sensitive.

An identification variable qualified
by the KEY, VALUE, or ENTRY operator is a path expression. The KEY,
VALUE, and ENTRY operators may only be applied to identification
Expand Down Expand Up @@ -646,7 +703,7 @@ single_valued_path_expression ::=
state_field_path_expression |
single_valued_object_path_expression
state_field_path_expression ::= general_subpath.state_field
state_field_path_expression ::= [general_subpath.]state_field
state_valued_path_expression ::= state_field_path_expression | general_identification_variable
Expand Down Expand Up @@ -699,7 +756,7 @@ A `collection_valued_path_expression` may only occur in:

See <<a5139>>, <<a5150>>, and <<a5284>>.

==== Joins
==== Joins [[joins]]

JPQL defines the following varieties of join:

Expand Down Expand Up @@ -757,10 +814,10 @@ join_association_path_expression ::=
TREAT(join_single_valued_path_expression AS subtype)
join_collection_valued_path_expression ::=
identification_variable.{single_valued_embeddable_object_field.}*collection_valued_field
[identification_variable.]{single_valued_embeddable_object_field.}*collection_valued_field
join_single_valued_path_expression ::=
identification_variable.{single_valued_embeddable_object_field.}*single_valued_object_field
[identification_variable.]{single_valued_embeddable_object_field.}*single_valued_object_field
join_condition ::= ON conditional_expression
----
Expand Down Expand Up @@ -2343,13 +2400,16 @@ HAVING COUNT(o) >= 5

=== SELECT Clause [[a5438]]

The SELECT clause denotes the query result.
More than one value may be returned from the SELECT clause of a query.
The SELECT clause specifies the query result, as a list of items to
be returned by the query.

The SELECT clause can contain one or more of the following elements:

The SELECT clause can contain one or more of
the following elements: an identification variable that ranges over an
abstract schema type, a single-valued path expression, a scalar
expression, an aggregate expression, a constructor expression.
- an identification variable that ranges over an abstract schema type,
- a single-valued path expression,
- a scalar expression,
- an aggregate expression,
- a constructor expression.

The SELECT clause has the following syntax:

Expand Down Expand Up @@ -2438,6 +2498,28 @@ GROUP BY c
ORDER BY itemCount
----

If the query domain is a single entity type, the SELECT clause
declaration is optional. A query with a missing SELECT clause
is interpreted as if it had a SELECT clause with a single item
containing an identification variable referencing the single
element of the domain. These queries are equivalent:

[source,sql]
----
SELECT ord
FROM Order AS ord
WHERE ord.customer.lastname = 'Smith'
AND ord.customer.firstname= 'John'
----
[source,sql]
----
FROM Order
WHERE customer.lastname = 'Smith'
AND customer.firstname= 'John'
----

Otherwise, if the query domain has more than one element,
the SELECT clause is required.

==== Result Type of the SELECT Clause [[a5439]]

Expand Down Expand Up @@ -3088,13 +3170,15 @@ select_statement ::= union
union ::= intersection | union {UNION [ALL] | EXCEPT [ALL]} intersection
intersection ::= query_expression | intersection INTERSECT [ALL] query_expression
query_expression ::= select_query | (union)
select_query ::= select_clause from_clause [where_clause] [groupby_clause]
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]
from_clause ::=
FROM identification_variable_declaration
{, {identification_variable_declaration | collection_member_declaration}}*
FROM entity_name | identification_variable_declarations
identification_variable_declarations ::=
identification_variable_declaration
{, {identification_variable_declaration | collection_member_declaration}}*
identification_variable_declaration ::= range_variable_declaration {join | fetch_join}*
range_variable_declaration ::= entity_name [AS] identification_variable
join ::= range_join | path_join
Expand All @@ -3110,9 +3194,9 @@ join_association_path_expression ::=
TREAT(join_collection_valued_path_expression AS subtype) |
TREAT(join_single_valued_path_expression AS subtype)
join_collection_valued_path_expression ::=
identification_variable.{single_valued_embeddable_object_field.}* collection_valued_field
[identification_variable.]{single_valued_embeddable_object_field.}* collection_valued_field
join_single_valued_path_expression ::=
identification_variable.{single_valued_embeddable_object_field.}* single_valued_object_field
[identification_variable.]{single_valued_embeddable_object_field.}* single_valued_object_field
collection_member_declaration ::=
IN (collection_valued_path_expression) [AS] identification_variable
qualified_identification_variable ::=
Expand All @@ -3134,7 +3218,7 @@ simple_subpath ::=
general_identification_variable |
general_identification_variable{.single_valued_object_field}*
treated_subpath ::= TREAT(general_subpath AS subtype)
state_field_path_expression ::= general_subpath.state_field
state_field_path_expression ::= [general_subpath.]state_field
state_valued_path_expression ::=
state_field_path_expression | general_identification_variable
single_valued_object_path_expression ::=
Expand Down

0 comments on commit 165d97f

Please sign in to comment.