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 d83cdb7d3..157d5d054 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 @@ -2469,19 +2469,36 @@ public class JPQLExpressionBuilder } - // throws an exception if there are numeric parameters which do not start with 1. + // throws an exception if there are numeric parameters which do not start with 1. private void validateParameters() { - if(parameterTypes == null || parameterTypes.isEmpty()) { + if (parameterTypes == null || parameterTypes.isEmpty()) { return; } - - Object firstKey = parameterTypes.keySet().iterator().next(); - if (firstKey != null) { // paranoia - if (firstKey instanceof Number) { - if (!parameterTypes.keySet().contains(1)) { - throw new UserException(_loc.get("missing-positional-parameter", resolver.getQueryContext() + + boolean numericParms = false; + boolean namedParms = false; + + for (Object key : parameterTypes.keySet()) { + + if (key instanceof Number) { + if (namedParms) { + throw new UserException(_loc.get("mixed-parameter-types", resolver.getQueryContext() .getQueryString(), parameterTypes.keySet().toString())); } + numericParms = true; + } else { + if (numericParms) { + throw new UserException(_loc.get("mixed-parameter-types", resolver.getQueryContext() + .getQueryString(), parameterTypes.keySet().toString())); + } + namedParms = true; + } + } + + if (numericParms) { + if (!parameterTypes.keySet().contains(1)) { + throw new UserException(_loc.get("missing-positional-parameter", resolver.getQueryContext() + .getQueryString(), parameterTypes.keySet().toString())); } } } 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 b7814874e..434cf1a33 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 @@ -89,3 +89,5 @@ cant-groupby-key-value-embeddable: Grouping by embeddables: "{0}({1})" is not al no-constructor: NEW constructor operation could not resolve class named "{0}". missing-positional-parameter: Query "{0}" did not contain positional parameter 1. \ JPQL positional parameters must start at 1. Detected parameters "{1}". +mixed-parameter-types: Query "{0}" Contains both named and positional parameters \ + this is not allowed by the JPA specification. Detected parameters "{1}". diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jpql/functions/TestSetParameter.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jpql/functions/TestSetParameter.java index 734154444..c1711a7b5 100644 --- a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jpql/functions/TestSetParameter.java +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jpql/functions/TestSetParameter.java @@ -145,6 +145,18 @@ public class TestSetParameter extends SingleEMFTestCase { // expected } em.close(); + } + + public void testMixedParameterTypesParameter() { + EntityManager em = emf.createEntityManager(); + String query = "UPDATE CompUser e set e.name= :name, e.age = ?1 " + "WHERE e.userid = ?3"; + try { + em.createQuery(query); + fail("Did not get UserException with invalid JPQL query"); + } catch (ArgumentException ae) { + // expected + } + em.close(); } public CompUser createUser(String name, String cName, int age,