[ 
https://issues.apache.org/jira/browse/OPENJPA-2572?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14371713#comment-14371713
 ] 

Heath Thomann commented on OPENJPA-2572:
----------------------------------------

HI!  I had my colleague, Jody Grassel, review my findings and upon further 
review he noted that things are working as expect and that the JPA Spec's Query 
Language BNF makes the parentheses illegal on the left hand side of the IN 
clause.  Let me post Jody's comments exactly as he sent them to me (i.e. let me 
give credit where credit is due):

>>>>>>>>>>>>>>>>>>>> START >>>>>>>>>>>>>>>>>>>>>>
I've been looking at your JIRA's query: em.createQuery("select m from MyEntity2 
m WHERE (m.id) IN (1,2,5)");

and I got the bug to go look at the JPA spec's Query language BNF:

QL_statement ::= select_statement | update_statement | delete_statement
select_statement ::= select_clause from_clause [where_clause] [groupby_clause] 
[having_clause] [orderby_clause]

where_clause ::= WHERE conditional_expression
conditional_expression ::= conditional_term | conditional_expression OR 
conditional_term
conditional_term ::= conditional_factor | conditional_term AND 
conditional_factor
conditional_factor ::= [ NOT ] conditional_primary
conditional_primary ::= simple_cond_expression | (conditional_expression)
simple_cond_expression ::=
        comparison_expression |
        between_expression |
        in_expression |
        like_expression |
        null_comparison_expression |
        empty_collection_comparison_expression |
        collection_member_expression |
        exists_expression
in_expression ::=
        {state_field_path_expression | type_discriminator} [NOT] IN
        { ( in_item {, in_item}* ) | (subquery) | 
collection_valued_input_parameter }

<probably this bnf branch, as the sample doesn't use TYPE()>
state_field_path_expression ::=
        
general_identification_variable.{single_valued_object_field.}*state_field
general_identification_variable ::=
        identification_variable |
        KEY(identification_variable) |
        VALUE(identification_variable)

<not this one, since the expression isnt' a TYPE(xx) IN (yy).>
type_discriminator ::=
        TYPE(identification_variable |
        single_valued_object_path_expression |
        input_parameter)

JPA 2.0 Spec section 4.4.2 "Identification Variables" addresses what 
constitutes as what's valid for that pattern.  

The section "Abstract Schema Types and Query Domains" defines state field as:
For every persistent field or get accessor method (for a persistent property) 
of the class, there
is a field (“state field”) whose abstract schema type corresponds to that of 
the field or the
result type of the accessor method.

So I would assume "state field" is defined as a pattern that makes for a legal 
persistent property name.

So in your example, "m.id" matches state_field_path_expression, where m is the 
identification_variable and id is the state_field.  The BNF grammar doesn't 
declare () as elements that can appear in the in_expression at all.

This may suggest that "WHERE (m.id) IN (1,2,5)" usage is illegal here after 
all, as you can see the BNF after IN has ()s in its grammer: [NOT] IN { ( 
in_item {, in_item}* ) | (subquery) | collection_valued_input_parameter }
>>>>>>>>>>>>>>>>>>>> END >>>>>>>>>>>>>>>>>>>>>>


In addition to Jody's comment I would like to add that *some* databases may 
actually allow for parenthesis on the left had side of an IN expression.  In 
other words, if you take OpenJPA out of the picture, and directly execute in 
your favorite SQL editor the SQL with parenthesis on the left hand side, the 
SQL may work fine.  However, this is moot given the JPA Spec's Query Language 
BNF doesn't allow it.  I apologize for not catching this sooner!

Thanks,

Heath

> Parentheses before an IN operator causes a parser exception.
> ------------------------------------------------------------
>
>                 Key: OPENJPA-2572
>                 URL: https://issues.apache.org/jira/browse/OPENJPA-2572
>             Project: OpenJPA
>          Issue Type: Bug
>          Components: sql
>    Affects Versions: 2.2.3, 2.4.0
>            Reporter: Heath Thomann
>            Priority: Critical
>
> I have recreated a simple version of a more complex query which is not 
> working.  Take these two queries which work fine and as expected:
> em.createQuery("select m from MyEntity2 m WHERE (m.id = 1)");
> em.createQuery("select m from MyEntity2 m WHERE m.id IN (1,2,5)");
> Now take this query and note the parentheses around m.id:
> em.createQuery("select m from MyEntity2 m WHERE (m.id) IN (1,2,5)");
> This yields the following exception:
> Caused by: <openjpa-2.2.3-SNAPSHOT-r422266:1655221M nonfatal user error> 
> org.apache.openjpa.persistence.ArgumentException: Encountered "m . id ) IN" 
> at character 34, but expected: ["(", ")", "*", "+", "-", ".", "/", ":", "<", 
> "<=", "<>", "=", ">", ">=", "?", "ABS", "ALL", "AND", "ANY", "AS", "ASC", 
> "AVG", "BETWEEN", "BOTH", "BY", "CONCAT", "COUNT", "CURRENT_DATE", 
> "CURRENT_TIME", "CURRENT_TIMESTAMP", "DELETE", "DESC", "DISTINCT", "EMPTY", 
> "ESCAPE", "EXISTS", "FETCH", "FROM", "GROUP", "HAVING", "IN", "INNER", "IS", 
> "JOIN", "LEADING", "LEFT", "LENGTH", "LIKE", "LOCATE", "LOWER", "MAX", 
> "MEMBER", "MIN", "MOD", "NEW", "NOT", "NULL", "OBJECT", "OF", "OR", "ORDER", 
> "OUTER", "SELECT", "SET", "SIZE", "SOME", "SQRT", "SUBSTRING", "SUM", 
> "TRAILING", "TRIM", "TYPE", "UPDATE", "UPPER", "WHERE", <DATE_LITERAL>, 
> <DECIMAL_LITERAL>, <IDENTIFIER>, <INTEGER_LITERAL>, <STRING_LITERAL2>, 
> <STRING_LITERAL>, <TIMESTAMP_LITERAL>, <TIME_LITERAL>].
>       at 
> org.apache.openjpa.kernel.jpql.JPQL.generateParseException(JPQL.java:13180)
>       at org.apache.openjpa.kernel.jpql.JPQL.jj_consume_token(JPQL.java:13054)
>       at 
> org.apache.openjpa.kernel.jpql.JPQL.conditional_primary(JPQL.java:1980)
> ........
> Looks like something in our parser doesn't expect this.
> Oh, BTW, the answer is not to simply remove the parentheses......ultimately 
> what we want to do is something more like the following (this works when I 
> execute from my Oracle SQL editor):
> SELECT * FROM MyEntity2 t0 WHERE (t0.id, t0.num) IN (SELECT t1.id, t1.num 
> FROM MyEntity2 t1 GROUP BY t1.id, t1.num);
> I.e. we need the parentheses.
> Thanks,
> Heath Thomann



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)

Reply via email to