From 7c9ef84fb9a297025e1817557a9e54faa1d92e9d Mon Sep 17 00:00:00 2001 From: Catalina Wei Date: Tue, 17 Mar 2009 03:13:10 +0000 Subject: [PATCH] OPENJPA-967 JPA2 JPQL allow KEY(e) of basic types appear in conditional expression git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@755102 13f79535-47bb-0310-9956-ffa450edef68 --- .../openjpa/jdbc/kernel/exps/PCPath.java | 5 ++++- .../kernel/jpql/JPQLExpressionBuilder.java | 20 +++++++++++++++++++ .../org/apache/openjpa/kernel/jpql/JPQL.jjt | 6 +++++- .../openjpa/kernel/jpql/localizer.properties | 3 ++- .../maps/m2mmapex8/TestMany2ManyMapEx8.java | 7 +++++++ .../spec_10_1_26_ex1/TestSpec10_1_26_Ex1.java | 7 +++++++ 6 files changed, 45 insertions(+), 3 deletions(-) diff --git a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/PCPath.java b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/PCPath.java index d53107e60..941b42782 100644 --- a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/PCPath.java +++ b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/PCPath.java @@ -83,6 +83,7 @@ public class PCPath private Class _cast = null; private boolean _cid = false; private FieldMetaData _xmlfield = null; + private FieldMetaData _mapfield = null; /** * Return a path starting with the 'this' ptr. @@ -361,6 +362,7 @@ public class PCPath if (_cid) return; + _mapfield = last(); // change the last action to a get key Action action = (Action) _actions.getLast(); action.op = Action.GET_KEY; @@ -402,7 +404,8 @@ public class PCPath if (act != null && act.op == Action.GET_XPATH) return ((XMLMetaData) act.data).getType(); - FieldMetaData fld = (act == null || act.op == Action.GET_KEY) ? null : + FieldMetaData fld = act == null ? null : + act.op == Action.GET_KEY ? _mapfield : (FieldMetaData) act.data; boolean key = act != null && act.op == Action.GET_KEY; if (fld != null) { diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/jpql/JPQLExpressionBuilder.java b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/jpql/JPQLExpressionBuilder.java index 0e6ae5828..971ce6ec7 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/jpql/JPQLExpressionBuilder.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/jpql/JPQLExpressionBuilder.java @@ -970,6 +970,8 @@ public class JPQLExpressionBuilder case JJTGENERALIDENTIFIER: // KEY(e), VALUE(e) + if (node.parent.parent.id == JJTWHERE) + return getGeneralIdentifier(onlyChild(node), true); return getQualifiedIdentifier(onlyChild(node)); case JJTNOT: @@ -1458,6 +1460,24 @@ public class JPQLExpressionBuilder return path; } + private Value getGeneralIdentifier(JPQLNode node, boolean inWhereClause) { + JPQLNode id = onlyChild(node); + if (inWhereClause && node.id == JJTVALUE) + throw parseException(EX_USER, "bad-general-identifier", + new Object[]{ id.text, "VALUE" }, null); + + Path path = (Path) validateMapPath(node, id); + FieldMetaData fld = path.last(); + path = (Path) factory.getKey(path); + ClassMetaData meta = fld.getKey().getTypeMetaData(); + if (inWhereClause && meta != null) + // check basic type + throw parseException(EX_USER, "bad-general-identifier", + new Object[]{ id.text, "KEY" }, null); + + return path; + } + private Value getQualifiedIdentifier(JPQLNode node) { JPQLNode id = onlyChild(node); Path path = (Path) validateMapPath(node, id); diff --git a/openjpa-kernel/src/main/jjtree/org/apache/openjpa/kernel/jpql/JPQL.jjt b/openjpa-kernel/src/main/jjtree/org/apache/openjpa/kernel/jpql/JPQL.jjt index 21e1e836a..3df4c405a 100644 --- a/openjpa-kernel/src/main/jjtree/org/apache/openjpa/kernel/jpql/JPQL.jjt +++ b/openjpa-kernel/src/main/jjtree/org/apache/openjpa/kernel/jpql/JPQL.jjt @@ -944,6 +944,7 @@ void arithmetic_factor() : { } input_parameter() | LOOKAHEAD(path()) path() | LOOKAHEAD(qualified_path()) qualified_path() | + LOOKAHEAD(general_identification_variable()) general_identification_variable() | LOOKAHEAD(2) "(" arithmetic_expression() ")" | functions_returning_numerics() | aggregate_select_expression() | @@ -1078,7 +1079,9 @@ void string_expression() : { } void string_primary() : { } { - string_literal() | path() | LOOKAHEAD(2) "(" string_expression() ")" | + string_literal() | path() | + LOOKAHEAD(general_identification_variable()) general_identification_variable() | + LOOKAHEAD(2) "(" string_expression() ")" | functions_returning_strings() | LOOKAHEAD(2) "(" subquery() ")" | case_expression() } @@ -1093,6 +1096,7 @@ void datetime_expression() : { } void datetime_primary() : { } { path() | functions_returning_datetime() | input_parameter() | aggregate_select_expression() + | LOOKAHEAD(general_identification_variable()) general_identification_variable() | case_expression() } diff --git a/openjpa-kernel/src/main/resources/org/apache/openjpa/kernel/jpql/localizer.properties b/openjpa-kernel/src/main/resources/org/apache/openjpa/kernel/jpql/localizer.properties index 37ee6af3d..e93788983 100644 --- a/openjpa-kernel/src/main/resources/org/apache/openjpa/kernel/jpql/localizer.properties +++ b/openjpa-kernel/src/main/resources/org/apache/openjpa/kernel/jpql/localizer.properties @@ -76,4 +76,5 @@ not-type-literal: The specified node ("{0}") is not a valid entity type literal. bad-qualified-identifier: The identifier "{0}" in "{1}" operator is not \ referring to an association field of type java.util.Map. bad-qualified-path: Attemp to navigate a basic type of Key("{0}"). - \ No newline at end of file +bad-general-identifier: The identitier "{0}" in "{1}" operator is not valid \ + in conditional expression. \ No newline at end of file diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex8/TestMany2ManyMapEx8.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex8/TestMany2ManyMapEx8.java index 51ad9aa58..35c8b70b9 100644 --- a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex8/TestMany2ManyMapEx8.java +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex8/TestMany2ManyMapEx8.java @@ -88,6 +88,13 @@ public class TestMany2ManyMapEx8 extends SingleEMFTestCase { assertTrue(d.equals(me.getKey())); + // test KEY(e) of basic type in conditional expression + sql.clear(); + query = "select KEY(e) from PhoneNumber p, " + + " in (p.emps) e where KEY(e) like '%1'"; + rs = em.createQuery(query).getResultList(); + assertTrue(sql.get(0).toUpperCase().indexOf("LIKE") > 0); + em.close(); } diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/spec_10_1_26_ex1/TestSpec10_1_26_Ex1.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/spec_10_1_26_ex1/TestSpec10_1_26_Ex1.java index 5206e4bc0..bf542a471 100644 --- a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/spec_10_1_26_ex1/TestSpec10_1_26_Ex1.java +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/spec_10_1_26_ex1/TestSpec10_1_26_Ex1.java @@ -73,6 +73,13 @@ public class TestSpec10_1_26_Ex1 extends SingleEMFTestCase { assertTrue(d.equals(me.getKey())); + // test KEY(e) of basic type in conditional expression + sql.clear(); + query = "select KEY(e) from Department d, " + + " in (d.empMap) e where KEY(e) > 1"; + rs = em.createQuery(query).getResultList(); + assertTrue(sql.get(0).toUpperCase().indexOf(">") > 0); + em.close(); }