From 31c4790c328fa208ed8b9e3c4ed4bb8b168b9c50 Mon Sep 17 00:00:00 2001 From: Catalina Wei Date: Sat, 3 Oct 2009 01:35:09 +0000 Subject: [PATCH] OPENJPA-1327 Doc update for JPA2 JPQL Query git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@821214 13f79535-47bb-0310-9956-ffa450edef68 --- .../src/doc/manual/jpa_overview_query.xml | 546 +++++++++++++----- 1 file changed, 407 insertions(+), 139 deletions(-) diff --git a/openjpa-project/src/doc/manual/jpa_overview_query.xml b/openjpa-project/src/doc/manual/jpa_overview_query.xml index 11cce3e5b..84de55101 100644 --- a/openjpa-project/src/doc/manual/jpa_overview_query.xml +++ b/openjpa-project/src/doc/manual/jpa_overview_query.xml @@ -665,7 +665,12 @@ Digest are Magazine subclasses. SELECT x FROM Magazine x WHERE x.price < 5 Non-polymorphic queries or queries whose polymorphism is restricted can be specified using entity -type expressions in the WHERE clause to restrict the domain of the query. +type expressions (see ) + in the WHERE clause to restrict the domain of the query. +For example, the following query returns instances of Digest: + +SELECT x FROM Magazine WHERE TYPE(x) = Digest +
@@ -723,7 +728,7 @@ This code substitutes JDJ for the :titleParam All input parameters must be single-valued, except in IN expressions -(see section ), which support the use of collection-valued +(see ), which support the use of collection-valued input parameters.
@@ -1147,7 +1152,7 @@ QL_statement ::= select_statement | update_statement | delete_statement -The complete BNF for JPQL is defined in . +The complete BNF for JPQL is defined in . Any JPQL statement may be constructed dynamically or may be statically defined in a metadata annotation or XML descriptor element. All statement types may have parameters, as discussed in . @@ -1436,6 +1441,17 @@ join_single_valued_association_path_expression +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_spec ::= [ LEFT [OUTER] | INNER ] JOIN @@ -2195,7 +2211,7 @@ in the FROM clause of a query except in an empty_collection_comparison_expression, in a collection_member_expression, or as an argument to the SIZE operator. -See Sections , , +See , , and . @@ -2212,7 +2228,7 @@ the FROM clause and a join condition in the WHERE The main use case for this generalized style of join is when a join condition does not involve a foreign key relationship that is mapped to an entity relationship. For Example, -SELECT c FROM Customer c, Employee e WHERE c.hatsize = e.shoesize +SELECT c FROM Customer c, Employee e WHERE c.hatsize = e.shoesize In general, use of this style of inner join (also referred to as theta-join) is less typical than explicitly defined joins over relationships. @@ -2256,16 +2272,19 @@ join_spec ::= [ LEFT [OUTER] | INNER ] JOIN -The following inner and outer join operation types are supported. +The inner and outer join operation types described in + and are supported.
JPQL Inner Joins (Relationship Joins) -The syntax for the inner join operation is +The syntax for the inner join operation is + [ INNER ] JOIN join_association_path_expression [AS] identification_variable - For example, the query below joins over the relationship + + For example, the query below joins over the relationship between publishers and magazines. This type of join typically equates to a join over a foreign key relationship in the database. @@ -2304,8 +2323,10 @@ WHERE c.address.zipcode = '95054' LEFT JOIN and LEFT OUTER JOIN are synonymous. They enable the retrieval of a set of entities where matching values in the join condition may be absent. The syntax for a left outer join is: -LEFT [OUTER] JOIN join_association_path_expression [AS] identification_variable - + +LEFT [OUTER] JOIN join_association_path_expression [AS] identification_variable + + For example: SELECT pub FROM Publisher pub LEFT JOIN pub.magazines mag WHERE pub.revenue > 1000000 @@ -2423,7 +2444,7 @@ query can depend on whether there are any values of the declared type. For example, the FROM clause below defines a query over all orders that have line items and existing -products. If there are no Product instances in the database, +products. If there are no Product instances in the database, the domain of the query is empty and no order is selected. @@ -2445,8 +2466,8 @@ the query criteria. Non-polymorphic queries or queries whose polymorphism is restricted can be specified using entity -type expressions in the WHERE clause to restrict the domain of the query. -See section . +type expressions in the WHERE clause to restrict the domain of the query. +See .
@@ -2607,8 +2628,8 @@ arithmetic operations involving the input parameter will return an unknown value. See .
-All input parameters must be single-valued, except in IN expressions (see section -), which support the use of collection-valued +All input parameters must be single-valued, except in IN expressions (see + ), which support the use of collection-valued input parameters.
@@ -2671,8 +2692,8 @@ comparison operations, logical operations, path expressions that evaluate to boolean values, boolean literals, and boolean input parameters. -The scalar expressions described in section - can be used in conditional expressions. +The scalar expressions described in + can be used in conditional expressions. Standard bracketing () @@ -2840,7 +2861,7 @@ FROM CreditCard c JOIN c.transactionHistory t WHERE c.holder.name = ‘John Doe’ AND INDEX(t) BETWEEN 0 AND 9
-
+
JPQL In Expressions @@ -2861,7 +2882,8 @@ in_item ::= literal | single_valued_input_parameter -The state_field_path_expression must have a string, numeric, or enum value. +The state_field_path_expression must have a string, numeric, +date, time, timestamp, or enum value. The literal and/or input_parameter values must be like @@ -3133,56 +3155,60 @@ magazine: SELECT auth FROM Author auth Subqueries may be used in the WHERE or HAVING - clause. The syntax for subqueries is as follows: -subquery ::= simple_select_clause subquery_from_clause -[where_clause] [groupby_clause] [having_clause] - - - + clause. The syntax for subqueries is as follows: - -Subqueries are restricted to the WHERE and HAVING - clauses in this release. Support for subqueries in the FROM - clause will be considered in a later release of the specification. -simple_select_clause ::= SELECT [DISTINCT] + + + +subquery ::= simple_select_clause subquery_from_clause +[where_clause] [groupby_clause] [having_clause] + + + + +simple_select_clause ::= SELECT [DISTINCT] simple_select_expression - - - - + + + + subquery_from_clause ::= FROM subselect_identification_variable_declaration {, subselect_identification_variable_declaration | collection_member_declaration }* - - - - + + + + subselect_identification_variable_declaration ::= identification_variable_declaration | derived_path_expression [AS] identification_variable {join}* | derived_collection_member_declaration - - - - + + + + simple_select_expression ::= single_valued_path_expression | scalar_expression | aggregate_expression | identification_variable - - - - + + + + derived_path_expression ::= superquery_identification_variable.{single_valued_object_field.}*collection_valued_field | superquery_identification_variable.{single_valued_object_field.}*single_valued_object_field - - - - + + + + derived_collection_member_declaration ::= IN superquery_identification_variable.{single_valued_object_field.}*collection_valued_field - - - + + + + +Subqueries are restricted to the WHERE and HAVING + clauses in this release. Support for subqueries in the FROM + clause will be considered in a later release of the specification. Examples: SELECT DISTINCT auth FROM Author auth @@ -3240,7 +3266,7 @@ The arithmetic operators are: Arithmetic operations use numeric promotion. -Arithmetic functions are described in section . +Arithmetic functions are described in .
@@ -3397,7 +3423,7 @@ the database server. The following forms of case expressions are supported: general case expressions, simple case expressions, -coalesce expressions, and nullif expressions.[ +coalesce expressions, and nullif expressions. case_expression::= @@ -3707,7 +3733,7 @@ the OBJECT operator. The SELECT clause must not use the OBJECT operator to qualify path expressions. -A result_variable may be used to name a select_item in the query result. +A result_variable may be used to name a select_item in the query result. For example, SELECT c, COUNT(l) AS itemCount @@ -3796,7 +3822,7 @@ and map value respectively. The result type of a scalar_expression is the type of the scalar value to which the expression -evaluates. The result type of a numeric scalar_expression is defined in section +evaluates. The result type of a numeric scalar_expression is defined in @@ -3809,7 +3835,7 @@ resulting abstract schema type corresponds. -The result type of aggregate_expression is defined in section +The result type of aggregate_expression is defined in . @@ -4013,13 +4039,13 @@ The type of a numeric expression in the query result is determined as follows: An operand that corresponds to a persistent state-field is of the same type as that persistent state-field. -An operand that corresponds to one of arithmetic functions described in section - is of the type defined by section +An operand that corresponds to one of arithmetic functions described in + is of the type defined by . -An operand that corresponds to one of an aggregate functions described in section - is of the type defined by section +An operand that corresponds to one of an aggregate functions described in + is of the type defined by . @@ -4086,20 +4112,106 @@ orderby_item ::= { state_field_path_expression | result_variable } [ASC | DESC] -When the ORDER BY clause is used in a query, each element of -the SELECT clause of the query must be one of the following: -an identification variable x, optionally denoted as OBJECT(x) -, a single_valued_association_path_expression, or a state_field_path_expression. -For example: +An orderby_item must be one of the following: + + + + + A state_field_path_expression that evaluates to an orderable state field of an entity or +embeddable class abstract schema type designated in the SELECT clause by one of the following: + + + + a general_identification_variable + + + a single_valued_object_path_expression + + + + + +A state_field_path_expression that evaluates to the same state field of the same entity or +embeddable abstract schema type as a state_field_path_expression +in the SELECT clause. + + + + +A result_variable that refers to an orderable item in the +SELECT clause for which the same +result_variable has been specified. +This may be the result of an aggregate_expression, a +scalar_expression, +or a state_field_path_expression in the SELECT clause. + + + + +For example, the five queries below are legal. + + SELECT pub FROM Publisher pub ORDER BY pub.revenue, pub.name - If more than one orderby_item is specified, the left-to-right -sequence of the orderby_item elements determines the precedence, whereby the -leftmost orderby_item has highest precedence. The keyword ASC + + +SELECT o +FROM Customer c JOIN c.orders o JOIN c.address a +WHERE a.state = ‘CA’ +ORDER BY o.quantity DESC, o.totalcost + + +SELECT o.quantity, a.zipcode +FROM Customer c JOIN c.orders o JOIN c.address a +WHERE a.state = ‘CA’ +ORDER BY o.quantity, a.zipcode + + +SELECT o.quantity, o.cost*1.08 AS taxedCost, a.zipcode +FROM Customer c JOIN c.orders o JOIN c.address a +WHERE a.state = ‘CA’ AND a.county = ‘Santa Clara’ +ORDER BY o.quantity, taxedCost, a.zipcode + + +SELECT AVG(o.quantity) as q, a.zipcode +FROM Customer c JOIN c.orders o JOIN c.address a +WHERE a.state = ‘CA’ +GROUP BY a.zipcode +ORDER BY q DESC + + +The following two queries are not legal because the orderby_item +is not reflected in the SELECT +clause of the query. + + +SELECT p.product_name +FROM Order o JOIN o.lineItems l JOIN l.product p JOIN o.customer c +WHERE c.lastname = ‘Smith’ AND c.firstname = ‘John’ +ORDER BY p.price + + +SELECT p.product_name +FROM Order o, IN(o.lineItems) l JOIN o.customer c +WHERE c.lastname = ‘Smith’ AND c.firstname = ‘John’ +ORDER BY o.quantity + + +If more than one orderby_item is specified, the left-to-right +sequence of the orderby_item elements determines the precedence, whereby the +leftmost orderby_item has highest precedence. + + +The keyword ASC specifies that ascending ordering be used; the keyword DESC specifies that descending ordering be used. Ascending ordering is the default. + + SQL rules for the ordering of null values apply: that is, all null values must appear before all non-null values in the ordering or all null values must appear -after all non-null values in the ordering, but it is not specified which. The +after all non-null values in the ordering, but it is not specified which. + + +The ordering of the query result is preserved in the result of the query method if the ORDER BY clause is used. @@ -4120,20 +4232,20 @@ schema type may be specified in the FROM or UPDATE -update_clause ::= UPDATE abstract_schema_name [[AS] identification_variable] SET +update_clause ::= UPDATE entity_name [[AS] identification_variable] SET update_item {, update_item}* update_item ::= [identification_variable.]{state_field | -single_valued_association_field} = new_value +single_valued_object_field} = new_value -new_value ::= simple_arithmetic_expression | string_primary | datetime_primary | -boolean_primary | enum_primary simple_entity_expression | NULL +new_value ::= scalar_expression | +simple_entity_expression | NULL @@ -4143,7 +4255,7 @@ delete_statement ::= delete_clause [where_clause] -delete_clause ::= DELETE FROM abstract_schema_name [[AS] +delete_clause ::= DELETE FROM entity_name [[AS] identification_variable] @@ -4151,18 +4263,32 @@ identification_variable] The syntax of the WHERE clause is described in -. A delete operation only applies to +. + + +A delete operation only applies to entities of the specified class and its subclasses. It does not cascade to -related entities. The new_value specified for an update operation must be -compatible in type with the state-field to which it is assigned. Bulk update +related entities. + + +The new_value specified for an update operation must be +compatible in type with the state-field to which it is assigned. + + +Bulk update maps directly to a database update operation, bypassing optimistic locking checks. Portable applications must manually update the value of the version column, if desired, and/or manually validate the value of the version column. + + The persistence context is not synchronized with the result of the bulk update -or delete. Caution should be used when executing bulk update or delete +or delete. + + +Caution should be used when executing bulk update or delete operations because they may result in inconsistencies between the database and the entities in the active persistence context. In general, bulk update and -delete operations should only be performed within a separate transaction or at +delete operations should only be performed within a transaction in a new persistence context or at the beginning of a transaction (before entities have been accessed whose state might be affected by such operations). @@ -4225,18 +4351,29 @@ semantics of query comparisons involving the empty string and NULL JPQL Equality and Comparison Semantics -Only the values of like types are permitted to be compared. A type is like +Only the values of like types are permitted to be compared. A type is like another type if they correspond to the same Java language type, or if one is a primitive Java language type and the other is the wrappered Java class type -equivalent (e.g., int and Integer are like types in this sense). There is one +equivalent (e.g., int and Integer are like types in this sense). There is one exception to this rule: it is valid to compare numeric values for which the rules of numeric promotion apply. Conditional expressions attempting to compare -non-like type values are disallowed except for this numeric case. Note that the +non-like type values are disallowed except for this numeric case. + + +Note that the arithmetic operators and comparison operators are permitted to be applied to state-fields and input parameters of the wrappered Java class equivalents to the -primitive numeric Java types. Two entities of the same abstract schema type are -equal if and only if they have the same primary key value. Only -equality/inequality comparisons over enums are required to be supported. +primitive numeric Java types. + + +Two entities of the same abstract schema type are +equal if and only if they have the same primary key value. + + +Equality/inequality comparisons over enums are supported. + + +Comparisons over instances of embeddable class or map entry types are not supported.
@@ -4245,7 +4382,7 @@ equality/inequality comparisons over enums are required to be supported. The following is the BNF for the Java Persistence query language, from section -4.14 of the JSR 220 specification. +4.14 of the JSR 317 specification. @@ -4283,7 +4420,7 @@ fetch_join }* -range_variable_declaration ::= abstract_schema_name [ AS ] +range_variable_declaration ::= entity_name [ AS ] identification_variable @@ -4301,74 +4438,81 @@ join_association_path_expression -association_path_expression ::= collection_valued_path_expression | -single_valued_association_path_expression - - - - join_spec ::= [ LEFT [ OUTER ]| INNER ] JOIN - + join_association_path_expression ::= join_collection_valued_path_expression | -join_single_valued_association_path_expression +join_single_valued_path_expression join_collection_valued_path_expression ::= -identification_variable.collection_valued_association_field +identification_variable.{single_valued_embeddable_object_field.}*collection_valued_field -join_single_valued_association_path_expression ::= -identification_variable.single_valued_association_field +join_single_valued_path_expression ::= +identification_variable.{single_valued_embeddable_object_field.}*single_valued_object_field collection_member_declaration ::= IN -(collection_valued_path_expression) [ AS ] +(join_collection_valued_path_expression) [ AS ] identification_variable -single_valued_path_expression ::= state_field_path_expression | -single_valued_association_path_expression +qualified_identification_variable ::= +KEY(identification_variable) | +VALUE(identification_variable) | +ENTRY(identification_variable) -state_field_path_expression ::= {identification_variable | -single_valued_association_path_expression}.state_field +single_valued_path_expression ::= +qualified_identification_variable | +state_field_path_expression | +single_valued_object_path_expression -single_valued_association_path_expression ::= -identification_variable.{single_valued_association_field.}* -single_valued_association_field +general_identification_variable ::= +identification_variable | +KEY(identification_variable) | +VALUE(identification_variable) + + + + +state_field_path_expression ::= +general_identification_variable.{single_valued_object_field.}*state_field + + + + +single_valued_object_path_expression ::= +general_identification_variable.{single_valued_object_field.}* +single_valued_object_field collection_valued_path_expression ::= -identification_variable.{single_valued_association_field.}*collection_valued_association_field +general_identification_variable.{single_valued_object_field.}*collection_valued_field -state_field ::= {embedded_class_state_field.}*simple_state_field - - - - -update_clause ::= UPDATE abstract_schema_name [[ AS +update_clause ::= UPDATE entity_name [[ AS ] identification_variable] SET update_item {, update_item}* @@ -4376,31 +4520,38 @@ update_item}* update_item ::= [identification_variable.]{state_field | -single_valued_association_field}= new_value +single_valued_object_field}= new_value -new_value ::= simple_arithmetic_expression | string_primary | datetime_primary | -boolean_primary | enum_primary simple_entity_expression | NULL +new_value ::= scalar_expression | +simple_entity_expression | NULL delete_clause ::= DELETEFROM -abstract_schema_name [[ AS ] identification_variable] +entity_name [[ AS ] identification_variable] select_clause ::= SELECT [ DISTINCT ] -select_expression {, select_expression}* +select_item {, select_item}* + + +select_item ::= select_expression [[AS] result_variable] + + -select_expression ::= single_valued_path_expression | aggregate_expression | +select_expression ::= single_valued_path_expression | +scalar_expression | +aggregate_expression | identification_variable | OBJECT (identification_variable)| constructor_expression @@ -4413,7 +4564,10 @@ constructor_item {, constructor_item}*) -constructor_item ::= single_valued_path_expression | aggregate_expression +constructor_item ::= single_valued_path_expression | +scalar_expression | +aggregate_expression | +identification_variable @@ -4422,7 +4576,7 @@ aggregate_expression ::= { AVG | MAX | MIN | SUM }([ DISTINCT ] state_field_path_expression) | COUNT ([ DISTINCT ] identification_variable | state_field_path_expression | -single_valued_association_path_expression) +single_valued_object_path_expression) @@ -4454,7 +4608,7 @@ orderby_item}* -orderby_item ::= state_field_path_expression [ ASC | +orderby_item ::= state_field_path_expression | result_variable [ ASC | DESC ] @@ -4468,14 +4622,28 @@ subquery ::= simple_select_clause subquery_from_clause [where_clause] subquery_from_clause ::= FROM subselect_identification_variable_declaration {, -subselect_identification_variable_declaration}* +subselect_identification_variable_declaration | +collection_member_declaration}* subselect_identification_variable_declaration ::= -identification_variable_declaration | association_path_expression [ AS - ] identification_variable | collection_member_declaration +identification_variable_declaration | derived_path_expression [ AS + ] identification_variable | derived_collection_member_declaration + + + + +derived_path_expression ::= +superquery_identification_variable.{single_valued_object_field.}*collection_valued_field | +superquery_identification_variable.{single_valued_object_field.}*single_valued_object_field + + + + +derived_collection_member_declaration ::= +IN superquery_identification_variable.{single_valued_object_field.}*collection_valued_field @@ -4487,7 +4655,19 @@ simple_select_clause ::= SELECT [ DISTINCT simple_select_expression ::= single_valued_path_expression | -aggregate_expression | identification_variable +scalar_expression | aggregate_expression | identification_variable + + + + +scalar_expression ::= +simple_arithmetic_expression | +string_primary | +enum_primary | +datetime_primary | +boolean_primary | +case_expression | +entity_type_expression @@ -4532,13 +4712,13 @@ datetime_expression AND datetime_expression -in_expression ::= state_field_path_expression [ NOT ] -IN ( in_item {, in_item}* | subquery) +in_expression ::= {state_field_path_expression | type_discriminator} [ NOT ] +IN {( in_item {, in_item}*) | (subquery) | collection_valued_input_parameter } -in_item ::= literal | input_parameter +in_item ::= literal | single_valued_input_parameter @@ -4568,6 +4748,22 @@ collection_valued_path_expression +entity_or_value_expression ::= +single_valued_object_path_expression | +state_field_path_expression | +simple_entity_or_value_expression + + + + +simple_entity_or_value_expression ::= +identification_variable | +input_parameter | +literal + + + + exists_expression ::= [ NOT ] EXISTS (subquery) @@ -4587,7 +4783,8 @@ enum_expression {=|<>} {enum_expression | all_or_any_expression} | datetime_expression comparison_operator {datetime_expression | all_or_any_expression} | entity_expression {= |<> } {entity_expression | all_or_any_expression} | arithmetic_expression comparison_operator -{arithmetic_expression | all_or_any_expression} +{arithmetic_expression | all_or_any_expression} | +entity_type_expression { =|<>>} entity_type_expression} @@ -4621,7 +4818,8 @@ arithmetic_factor ::= [{+ |-}] arithmetic_primary arithmetic_primary ::= state_field_path_expression | numeric_literal | (simple_arithmetic_expression) | input_parameter | functions_returning_numerics -| aggregate_expression +| aggregate_expression | +case_expression @@ -4632,7 +4830,8 @@ string_expression ::= string_primary |(subquery) string_primary ::= state_field_path_expression | string_literal | -input_parameter | functions_returning_strings | aggregate_expression +input_parameter | functions_returning_strings | aggregate_expression | +case_expression @@ -4643,7 +4842,9 @@ datetime_expression ::= datetime_primary |(subquery) datetime_primary ::= state_field_path_expression | input_parameter | -functions_returning_datetime | aggregate_expression +functions_returning_datetime | aggregate_expression | +case_expression | +date_time_timestamp_literal @@ -4655,6 +4856,7 @@ boolean_expression ::= boolean_primary |(subquery) boolean_primary ::= state_field_path_expression | boolean_literal | input_parameter | +case_expression @@ -4664,12 +4866,13 @@ enum_expression ::= enum_primary |(subquery) -enum_primary ::= state_field_path_expression | enum_literal | input_parameter | +enum_primary ::= state_field_path_expression | enum_literal | input_parameter | +case_expression -entity_expression ::= single_valued_association_path_expression | +entity_expression ::= single_valued_object_path_expression | simple_entity_expression @@ -4680,13 +4883,30 @@ simple_entity_expression ::= identification_variable | input_parameter +entity_type_expression ::= +type_discriminator | +entity_type_literal | +input_parameter + + + + +type_discriminator ::= +TYPE(identification_variable | +single_valued_object_path_expression | +input_parameter) + + + + functions_returning_numerics ::= LENGTH (string_primary)| LOCATE (string_primary,string_primary [, simple_arithmetic_expression]) | ABS (simple_arithmetic_expression) | SQRT (simple_arithmetic_expression) | MOD (simple_arithmetic_expression, simple_arithmetic_expression) | SIZE - (collection_valued_path_expression) + (collection_valued_path_expression) | +INDEX(identification_variable) @@ -4699,7 +4919,7 @@ CURRENT_TIME | CURRENT_TIMESTAMP functions_returning_strings ::= CONCAT (string_primary, string_primary) | SUBSTRING (string_primary, -simple_arithmetic_expression,simple_arithmetic_expression)| TRIM +simple_arithmetic_expression[,simple_arithmetic_expression])| TRIM ([[trim_specification] [trim_character] FROM ] string_primary) | LOWER (string_primary) | UPPER (string_primary) @@ -4711,6 +4931,54 @@ trim_specification ::= LEADING | TRAILING | BOTH + + +case_expression ::= +general_case_expression | +simple_case_expression | +coalesce_expression | +nullif_expression + + + + +general_case_expression::= +CASE when_clause {when_clause}* ELSE scalar_expression END + + + + +when_clause::= WHEN conditional_expression THEN scalar_expression + + + + +simple_case_expression::= +CASE case_operand simple_when_clause {simple_when_clause}* +ELSE scalar_expression +END + + + + +case_operand::= state_field_path_expression | type_discriminator + + + + +simple_when_clause::= WHEN scalar_expression THEN scalar_expression + + + + +coalesce_expression::= COALESCE(scalar_expression {, scalar_expression}+) + + + + +nullif_expression::= NULLIF(scalar_expression, scalar_expression) + +