You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by pp...@apache.org on 2008/08/02 15:58:57 UTC
svn commit: r681977 - in /openjpa/trunk:
openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/query/
openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/query/cache/
openjpa-persistence-jdbc/src/test/java/or...
Author: ppoddar
Date: Sat Aug 2 06:58:56 2008
New Revision: 681977
URL: http://svn.apache.org/viewvc?rev=681977&view=rev
Log:
OPENJPA-497: TemporalType conversion at facade level Query.
Also includes extensive changes in parameter validation logic and data structure.
Added:
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/query/TestQueryParameterBinding.java
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/query/TestTemporalTypeQueryParameterBinding.java
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/query/domain/Binder.java
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/query/domain/TimeKeeper.java
Modified:
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/query/cache/TestNonPrimaryKeyQueryParameters.java
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/query/TestDupNamedQuery.java
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/QueryImpl.java
openjpa/trunk/openjpa-persistence/src/main/resources/org/apache/openjpa/persistence/localizer.properties
Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/query/TestQueryParameterBinding.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/query/TestQueryParameterBinding.java?rev=681977&view=auto
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/query/TestQueryParameterBinding.java (added)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/query/TestQueryParameterBinding.java Sat Aug 2 06:58:56 2008
@@ -0,0 +1,247 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.openjpa.persistence.jdbc.query;
+
+import javax.persistence.EntityManager;
+import javax.persistence.Query;
+
+import org.apache.openjpa.persistence.ArgumentException;
+import org.apache.openjpa.persistence.jdbc.query.domain.Binder;
+import org.apache.openjpa.persistence.test.SingleEMFTestCase;
+
+/**
+ * Tests validation of positional and named parameter binding for JPQL queries.
+ *
+ *
+ * @author Pinaki Poddar
+ *
+ */
+public class TestQueryParameterBinding extends SingleEMFTestCase {
+ private static String JPQL = "SELECT p FROM Binder p ";
+
+ private static int INT_VALUE = 1;
+ private static String STR_VALUE = "2";
+ private static double DBL_VALUE = 3.0;
+
+ private EntityManager em;
+ @Override
+ public void setUp() throws Exception {
+ super.setUp(CLEAR_TABLES, Binder.class);
+
+ em = emf.createEntityManager();
+ em.getTransaction().begin();
+ em.persist(new Binder(INT_VALUE, STR_VALUE, DBL_VALUE));
+ em.getTransaction().commit();
+ }
+
+ public void testPositionalParameterWithPositionalBindingSucceeds() {
+ String JPQL_POSITIONAL = JPQL + "WHERE p.p1=?1 AND p.p2=?2 AND p.p3=?3";
+ Query q = em.createQuery(JPQL_POSITIONAL);
+ q.setParameter(1, INT_VALUE);
+ q.setParameter(2, STR_VALUE);
+ q.setParameter(3, DBL_VALUE);
+
+ assertEquals(1, q.getResultList().size());
+ }
+
+ public void testPositionalParameterWithNamedBindingFails() {
+ String JPQL_POSITIONAL = JPQL + "WHERE p.p1=?1 AND p.p2=?2 AND p.p3=?3";
+ Query q = em.createQuery(JPQL_POSITIONAL);
+ q.setParameter("p1", INT_VALUE);
+ q.setParameter("p2", STR_VALUE);
+ q.setParameter("p3", DBL_VALUE);
+
+ fail(q);
+ }
+
+ public void testPositionalParameterWithInsufficientValuesFails() {
+ String JPQL_POSITIONAL = JPQL + "WHERE p.p1=?1 AND p.p2=?2 AND p.p3=?3";
+ Query q = em.createQuery(JPQL_POSITIONAL);
+ q.setParameter(1, INT_VALUE);
+ q.setParameter(2, STR_VALUE);
+
+ fail(q);
+ }
+
+ public void testPositionalParameterWithExtraValuesFails() {
+ String JPQL_POSITIONAL = JPQL + "WHERE p.p1=?1 AND p.p2=?2 AND p.p3=?3";
+ Query q = em.createQuery(JPQL_POSITIONAL);
+ q.setParameter(1, INT_VALUE);
+ q.setParameter(2, STR_VALUE);
+ q.setParameter(3, DBL_VALUE);
+ q.setParameter(4, 4);
+
+ fail(q);
+ }
+
+ public void testPositionalParameterWithRepeatedValuesSucceeds() {
+ String jPQL_POSITIONAL_REPEATED_PARAM =
+ JPQL + "WHERE p.p1=?1 OR p.p1=?1 AND p.p3=?2";
+ Query q = em.createQuery(jPQL_POSITIONAL_REPEATED_PARAM);
+ q.setParameter(1, INT_VALUE);
+ q.setParameter(2, DBL_VALUE);
+
+ assertEquals(1,q.getResultList().size());
+ }
+
+ public void testPositionalParameterWithGapSucceeds() {
+ String JPQL_POSITIONAL_GAP_IN_PARAM =
+ JPQL + "WHERE p.p1=?1 AND p.p2=?3";
+ Query q = em.createQuery(JPQL_POSITIONAL_GAP_IN_PARAM);
+ q.setParameter(1, INT_VALUE);
+ q.setParameter(3, STR_VALUE);
+
+ assertEquals(1,q.getResultList().size());
+ }
+
+ public void testPositionalParameterWithGapFails() {
+ String JPQL_POSITIONAL_GAP_IN_PARAM =
+ JPQL + "WHERE p.p1=?1 AND p.p3=?3";
+ Query q = em.createQuery(JPQL_POSITIONAL_GAP_IN_PARAM);
+ q.setParameter(1, INT_VALUE);
+ q.setParameter(2, STR_VALUE);
+ q.setParameter(3, DBL_VALUE);
+
+ fail(q);
+ }
+
+ public void testNamedParameterWithNamedBindingSucceeds() {
+ String JPQL_NAMED = JPQL + "WHERE p.p1=:p1 AND p.p2=:p2 AND p.p3=:p3";
+ Query q = em.createQuery(JPQL_NAMED);
+ q.setParameter("p1", INT_VALUE);
+ q.setParameter("p2", STR_VALUE);
+ q.setParameter("p3", DBL_VALUE);
+
+ assertEquals(1, q.getResultList().size());
+ }
+
+ public void testNamedParameterWithPositionalBindingFails() {
+ String JPQL_NAMED = JPQL + "WHERE p.p1=:p1 AND p.p2=:p2 AND p.p3=:p3";
+ Query q = em.createQuery(JPQL_NAMED);
+ q.setParameter(1, INT_VALUE);
+ q.setParameter(2, STR_VALUE);
+ q.setParameter(3, DBL_VALUE);
+
+ fail(q);
+ }
+
+ public void testNamedParameterWithInsufficientValuesFails() {
+ String JPQL_NAMED = JPQL + "WHERE p.p1=:p1 AND p.p2=:p2 AND p.p3=:p3";
+ Query q = em.createQuery(JPQL_NAMED);
+ q.setParameter("p1", INT_VALUE);
+ q.setParameter("p2", STR_VALUE);
+
+ fail(q);
+ }
+
+ public void testNamedParameterWithExtraValuesFails() {
+ String JPQL_NAMED = JPQL + "WHERE p.p1=:p1 AND p.p2=:p2 AND p.p3=:p3";
+ Query q = em.createQuery(JPQL_NAMED);
+ q.setParameter("p1", INT_VALUE);
+ q.setParameter("p2", STR_VALUE);
+ q.setParameter("p3", DBL_VALUE);
+ q.setParameter("p4", 4);
+
+ fail(q);
+ }
+
+ public void testNamedParameterWithRepeatedValuesSucceeds() {
+ String jPQL_NAMED_REPEATED_PARAM =
+ JPQL + "WHERE p.p1=:p1 OR p.p1=:p1 AND p.p3=:p2";
+ Query q = em.createQuery(jPQL_NAMED_REPEATED_PARAM);
+ q.setParameter("p1", INT_VALUE);
+ q.setParameter("p2", DBL_VALUE);
+
+ assertEquals(1,q.getResultList().size());
+ }
+
+ public void testNamedParameterWithGapSucceeds() {
+ String JPQL_NAMED_GAP_IN_PARAM =
+ JPQL + "WHERE p.p1=:p1 AND p.p2=:p3";
+ Query q = em.createQuery(JPQL_NAMED_GAP_IN_PARAM);
+ q.setParameter("p1", INT_VALUE);
+ q.setParameter("p3", STR_VALUE);
+
+ assertEquals(1,q.getResultList().size());
+ }
+
+ public void testNamedParameterWithGapFails() {
+ String JPQL_NAMED_GAP_IN_PARAM =
+ JPQL + "WHERE p.p1=:p1 AND p.p3=:p3";
+ Query q = em.createQuery(JPQL_NAMED_GAP_IN_PARAM);
+ q.setParameter("p1", INT_VALUE);
+ q.setParameter("p2", STR_VALUE);
+ q.setParameter("p3", DBL_VALUE);
+
+ fail(q);
+ }
+
+ public void testNamedParameterWithWrongType() {
+ String JPQL_NAMED = JPQL + "WHERE p.p1=:p1 AND p.p2=:p2 AND p.p3=:p3";
+ Query q = em.createQuery(JPQL_NAMED);
+ q.setParameter("p1", INT_VALUE);
+ q.setParameter("p2", DBL_VALUE);
+ q.setParameter("p3", STR_VALUE);
+
+ fail(q);
+ }
+
+ public void testPositionalParameterWithWrongType() {
+ String JPQL_NAMED = JPQL + "WHERE p.p1=?1 AND p.p2=?2 AND p.p3=?3";
+ Query q = em.createQuery(JPQL_NAMED);
+ q.setParameter(1, INT_VALUE);
+ q.setParameter(2, DBL_VALUE);
+ q.setParameter(3, STR_VALUE);
+
+ fail(q);
+ }
+
+ public void testNamedParameterWithNullValue() {
+ String JPQL_NAMED = JPQL + "WHERE p.p1=:p1 AND p.p2=:p2 AND p.p3=:p3";
+ Query q = em.createQuery(JPQL_NAMED);
+ q.setParameter("p1", INT_VALUE);
+ q.setParameter("p2", null);
+ q.setParameter("p3", null);
+
+ fail(q);
+ }
+
+ public void testPositionalParameterWithNullValue() {
+ String JPQL_NAMED = JPQL + "WHERE p.p1=?1 AND p.p2=?2 AND p.p3=?3";
+ Query q = em.createQuery(JPQL_NAMED);
+ q.setParameter(1, INT_VALUE);
+ q.setParameter(2, null);
+ q.setParameter(3, null);
+
+ fail(q);
+ }
+
+
+ void fail(Query q) {
+ try {
+ q.getResultList();
+ fail("Expeceted " + ArgumentException.class.getName());
+ } catch (IllegalArgumentException ex) {
+ // good
+ System.err.println("*** ERROR " + getName());
+ System.err.println("*** ERROR " + ex.getMessage());
+ }
+ }
+
+}
Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/query/TestTemporalTypeQueryParameterBinding.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/query/TestTemporalTypeQueryParameterBinding.java?rev=681977&view=auto
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/query/TestTemporalTypeQueryParameterBinding.java (added)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/query/TestTemporalTypeQueryParameterBinding.java Sat Aug 2 06:58:56 2008
@@ -0,0 +1,198 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.openjpa.persistence.jdbc.query;
+
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.util.Calendar;
+import java.util.Date;
+
+import javax.persistence.EntityManager;
+import javax.persistence.Query;
+import javax.persistence.TemporalType;
+
+import org.apache.openjpa.persistence.ArgumentException;
+import org.apache.openjpa.persistence.jdbc.query.domain.TimeKeeper;
+import org.apache.openjpa.persistence.test.SingleEMFTestCase;
+
+/**
+ * Tests that queries can convert to temporal types.
+ * Also tests that parameter validation for mismatch between named parameter
+ * and positional binding or vice versa.
+ *
+ * Originally reported in
+ * <A HRE="http://issues.apache.org/jira/browse/OPENJPA-112>OPENJPA-497</A>
+ *
+ * @author Pinaki Poddar
+ *
+ */
+public class TestTemporalTypeQueryParameterBinding extends SingleEMFTestCase {
+ private static Calendar PARAM_CALENDAR = Calendar.getInstance();
+ private static long T1 = PARAM_CALENDAR.getTimeInMillis();
+ private static long T2 = T1 + 2000;
+ private static long T3 = T1 + 3000;
+
+ private static Date VALUE_DATE = new Date(T1);
+ private static Time VALUE_TIME = new Time(T2);
+ private static Timestamp VALUE_TSTAMP = new Timestamp(T3);
+
+
+ private static String JPQL_NAMED =
+ "SELECT p FROM TimeKeeper p WHERE p.date=:d AND p.time=:t AND p.tstamp=:ts";
+ private static String JPQL_POSITIONAL =
+ "SELECT p FROM TimeKeeper p WHERE p.date=?1 AND p.time=?2 AND p.tstamp=?3";
+
+ private EntityManager em;
+ @Override
+ public void setUp() throws Exception {
+ super.setUp(CLEAR_TABLES, TimeKeeper.class);
+ em = emf.createEntityManager();
+
+ TimeKeeper pc = new TimeKeeper();
+ pc.setDate(VALUE_DATE);
+ pc.setTime(VALUE_TIME);
+ pc.setTstamp(VALUE_TSTAMP);
+
+ em.getTransaction().begin();
+ em.persist(pc);
+ em.getTransaction().commit();
+ }
+
+ public void testNamedParameterConvertedFromCalendarValue() {
+ Calendar c1 = Calendar.getInstance();
+ Calendar c2 = Calendar.getInstance();
+ Calendar c3 = Calendar.getInstance();
+ c1.setTimeInMillis(T1);
+ c2.setTimeInMillis(T2);
+ c3.setTimeInMillis(T3);
+
+ Query q = em.createQuery(JPQL_NAMED);
+ q.setParameter("d", c1, TemporalType.DATE);
+ q.setParameter("t", c2, TemporalType.TIME);
+ q.setParameter("ts", c3, TemporalType.TIMESTAMP);
+
+ assertEquals(1, q.getResultList().size());
+ }
+
+ public void testPositionalParameterConvertedFromCalendarValue() {
+ Calendar c1 = Calendar.getInstance();
+ Calendar c2 = Calendar.getInstance();
+ Calendar c3 = Calendar.getInstance();
+ c1.setTimeInMillis(T1);
+ c2.setTimeInMillis(T2);
+ c3.setTimeInMillis(T3);
+
+ Query q = em.createQuery(JPQL_POSITIONAL);
+ q.setParameter(1, c1, TemporalType.DATE);
+ q.setParameter(2, c2, TemporalType.TIME);
+ q.setParameter(3, c3, TemporalType.TIMESTAMP);
+
+ assertEquals(1, q.getResultList().size());
+ }
+ public void testNamedParameterConvertedFromDateValue() {
+ Date d1 = new Date(T1);
+ Date d2 = new Date(T2);
+ Date d3 = new Date(T3);
+
+ Query q = em.createQuery(JPQL_NAMED);
+ q.setParameter("d", d1, TemporalType.DATE);
+ q.setParameter("t", d2, TemporalType.TIME);
+ q.setParameter("ts", d3, TemporalType.TIMESTAMP);
+
+ assertEquals(1, q.getResultList().size());
+ }
+
+ public void testPositionalParameterConvertedFromDateValue() {
+ Date d1 = new Date(T1);
+ Date d2 = new Date(T2);
+ Date d3 = new Date(T3);
+
+ Query q = em.createQuery(JPQL_POSITIONAL);
+ q.setParameter(1, d1, TemporalType.DATE);
+ q.setParameter(2, d2, TemporalType.TIME);
+ q.setParameter(3, d3, TemporalType.TIMESTAMP);
+
+ assertEquals(1, q.getResultList().size());
+ }
+
+
+ public void testNamedParameterWithMismatchedValue() {
+ Date d1 = new Date(T1);
+ Date d2 = new Date(T2);
+ Date d3 = new Date(T3);
+
+ Query q = em.createQuery(JPQL_NAMED);
+ q.setParameter("d", d1, TemporalType.TIME);
+ q.setParameter("ts", d2, TemporalType.TIMESTAMP);
+ q.setParameter("t", d3, TemporalType.DATE);
+
+ try {
+ q.getResultList();
+ fail("Expeceted " + ArgumentException.class.getName());
+ } catch (ArgumentException ex) {
+ // good
+ System.err.println(ex.getMessage());
+ }
+ }
+
+ public void testPositionalParameterWithMismatchedValue() {
+ Date d1 = new Date(T1);
+ Date d2 = new Date(T2);
+ Date d3 = new Date(T3);
+
+ Query q = em.createQuery(JPQL_POSITIONAL);
+ q.setParameter(1, d1, TemporalType.TIME);
+ q.setParameter(2, d2, TemporalType.TIMESTAMP);
+ q.setParameter(3, d3, TemporalType.DATE);
+
+ try {
+ q.getResultList();
+ fail("Expeceted " + ArgumentException.class.getName());
+ } catch (ArgumentException ex) {
+ // good
+ System.err.println(ex.getMessage());
+ }
+ }
+
+ void verifyParams(String jpql, Class error, Object...params) {
+ EntityManager em = emf.createEntityManager();
+ em.getTransaction().begin();
+ Query query = em.createNativeQuery(jpql);
+ for (int i=0; params != null && i<params.length; i=+2) {
+ try {
+ if (params[i] instanceof Number) {
+ query.setParameter(((Number)params[i]).intValue(), params[i+1]);
+ } else {
+ query.setParameter(params[i].toString(), params[i+1]);
+ }
+ if (error != null)
+ fail("Expected " + error.getName());
+ } catch (Exception e) {
+ if (error.isAssignableFrom(e.getClass())) {
+ System.err.println(e.getMessage());
+ } else {
+ e.printStackTrace();
+ fail();
+ }
+ }
+
+ }
+ em.getTransaction().commit();
+ }
+}
Modified: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/query/cache/TestNonPrimaryKeyQueryParameters.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/query/cache/TestNonPrimaryKeyQueryParameters.java?rev=681977&r1=681976&r2=681977&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/query/cache/TestNonPrimaryKeyQueryParameters.java (original)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/query/cache/TestNonPrimaryKeyQueryParameters.java Sat Aug 2 06:58:56 2008
@@ -80,7 +80,6 @@
EntityManager em = emf.createEntityManager();
Query query = em.createQuery("SELECT d from Department d");
- query.setParameter(1, DEPT_NAME);
Department dept = (Department) query.getSingleResult();
assertEquals(FULLTIME_EMPLOYEE_COUNT, dept.getFullTimeEmployees()
Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/query/domain/Binder.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/query/domain/Binder.java?rev=681977&view=auto
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/query/domain/Binder.java (added)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/query/domain/Binder.java Sat Aug 2 06:58:56 2008
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.openjpa.persistence.jdbc.query.domain;
+
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.util.Date;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+
+@Entity
+public class Binder {
+ @Id
+ @GeneratedValue
+ private long id;
+
+ private int p1;
+ private String p2;
+ private double p3;
+
+ protected Binder() {
+ this(-1, "-1" , -1.0);
+ }
+
+ public Binder(int i1, String i2, double i3) {
+ p1 = i1;
+ p2 = i2;
+ p3 = i3;
+ }
+
+}
Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/query/domain/TimeKeeper.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/query/domain/TimeKeeper.java?rev=681977&view=auto
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/query/domain/TimeKeeper.java (added)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/query/domain/TimeKeeper.java Sat Aug 2 06:58:56 2008
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.openjpa.persistence.jdbc.query.domain;
+
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.util.Date;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+
+@Entity
+public class TimeKeeper {
+ @Id
+ @GeneratedValue
+ private long id;
+
+ @Column(name="D")
+ private Date date;
+ @Column(name="T")
+ private Time time;
+ @Column(name="TS")
+ private Timestamp tstamp;
+
+ public Date getDate() {
+ return date;
+ }
+ public void setDate(Date date) {
+ this.date = date;
+ }
+ public Time getTime() {
+ return time;
+ }
+ public void setTime(Time time) {
+ this.time = time;
+ }
+ public Timestamp getTstamp() {
+ return tstamp;
+ }
+ public void setTstamp(Timestamp tstamp) {
+ this.tstamp = tstamp;
+ }
+ public long getId() {
+ return id;
+ }
+
+}
Modified: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/query/TestDupNamedQuery.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/query/TestDupNamedQuery.java?rev=681977&r1=681976&r2=681977&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/query/TestDupNamedQuery.java (original)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/query/TestDupNamedQuery.java Sat Aug 2 06:58:56 2008
@@ -55,7 +55,7 @@
String ValueTwo) {
EntityManager em = emf.createEntityManager();
- List list = em.createNamedQuery(findOneQName).setParameter(1, nameOne)
+ List list = em.createNamedQuery(findOneQName).setParameter("fname", nameOne)
.getResultList();
assertNotNull(list);
assertEquals(list.size(), 1);
Modified: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/QueryImpl.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/QueryImpl.java?rev=681977&r1=681976&r2=681977&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/QueryImpl.java (original)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/QueryImpl.java Sat Aug 2 06:58:56 2008
@@ -20,7 +20,10 @@
import java.io.Serializable;
import java.lang.reflect.Method;
+import java.sql.Time;
+import java.sql.Timestamp;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
@@ -30,9 +33,12 @@
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.TreeMap;
+
import javax.persistence.FlushModeType;
import javax.persistence.Query;
import javax.persistence.TemporalType;
+import javax.swing.text.Position;
import org.apache.commons.collections.map.LinkedMap;
import org.apache.openjpa.enhance.Reflection;
@@ -50,543 +56,681 @@
/**
* Implementation of {@link Query} interface.
- *
+ *
* @author Marc Prud'hommeaux
* @author Abe White
* @nojavadoc
*/
-public class QueryImpl
- implements OpenJPAQuerySPI, Serializable {
+public class QueryImpl implements OpenJPAQuerySPI, Serializable {
+
+ private static final Object[] EMPTY_ARRAY = new Object[0];
- private static final Object[] EMPTY_ARRAY = new Object[0];
+ private static final Localizer _loc = Localizer.forPackage(QueryImpl.class);
- private static final Localizer _loc = Localizer.forPackage
- (QueryImpl.class);
+ private final DelegatingQuery _query;
+ private transient EntityManagerImpl _em;
+ private transient FetchPlan _fetch;
+
+ private Map<String, Object> _named;
+ private Map<Integer, Object> _positional;
+
+ private static Object GAP_FILLER = new Object();
+
+ /**
+ * Constructor; supply factory exception translator and delegate.
+ *
+ * @param em
+ * The EntityManager which created this query
+ * @param ret
+ * Exception translater for this query
+ * @param query
+ * The underlying "kernel" query.
+ */
+ public QueryImpl(EntityManagerImpl em, RuntimeExceptionTranslator ret,
+ org.apache.openjpa.kernel.Query query) {
+ _em = em;
+ _query = new DelegatingQuery(query, ret);
+ }
- private final DelegatingQuery _query;
- private transient EntityManagerImpl _em;
- private transient FetchPlan _fetch;
-
- private Map _named;
- private List _positional;
-
- /**
- * Constructor; supply factory exception translator and delegate.
- *
- * @param em
- * The EntityManager which created this query
- * @param ret
- * Exception translater for this query
- * @param query
- * The underlying "kernel" query.
- */
- public QueryImpl(EntityManagerImpl em, RuntimeExceptionTranslator ret,
- org.apache.openjpa.kernel.Query query) {
- _em = em;
- _query = new DelegatingQuery(query, ret);
- }
-
- /**
- * Constructor; supply factory and delegate.
- * @deprecated
- */
- public QueryImpl(EntityManagerImpl em, org.apache.openjpa.kernel.Query query) {
- this(em, null, query);
- }
+ /**
+ * Constructor; supply factory and delegate.
+ *
+ * @deprecated
+ */
+ public QueryImpl(EntityManagerImpl em, org.apache.openjpa.kernel.Query query) {
+ this(em, null, query);
+ }
- /**
+ /**
* Delegate.
*/
- public org.apache.openjpa.kernel.Query getDelegate() {
- return _query.getDelegate();
- }
-
- public OpenJPAEntityManager getEntityManager() {
- return _em;
- }
-
- public String getLanguage() {
- return _query.getLanguage();
- }
-
- public QueryOperationType getOperation() {
- return QueryOperationType.fromKernelConstant(_query.getOperation());
- }
-
- public FetchPlan getFetchPlan() {
- _em.assertNotCloseInvoked();
- _query.assertNotSerialized();
- _query.lock();
- try {
- if (_fetch == null)
- _fetch = ((EntityManagerFactoryImpl) _em.
- getEntityManagerFactory()).toFetchPlan(_query.getBroker(),
- _query.getFetchConfiguration());
- return _fetch;
- } finally {
- _query.unlock();
- }
- }
-
- public String getQueryString() {
- return _query.getQueryString();
- }
-
- public boolean getIgnoreChanges() {
- return _query.getIgnoreChanges();
- }
-
- public OpenJPAQuery setIgnoreChanges(boolean ignore) {
- _em.assertNotCloseInvoked();
- _query.setIgnoreChanges(ignore);
- return this;
- }
-
- public OpenJPAQuery addFilterListener(FilterListener listener) {
- _em.assertNotCloseInvoked();
- _query.addFilterListener(listener);
- return this;
- }
-
- public OpenJPAQuery removeFilterListener(FilterListener listener) {
- _em.assertNotCloseInvoked();
- _query.removeFilterListener(listener);
- return this;
- }
-
- public OpenJPAQuery addAggregateListener(AggregateListener listener) {
- _em.assertNotCloseInvoked();
- _query.addAggregateListener(listener);
- return this;
- }
-
- public OpenJPAQuery removeAggregateListener(AggregateListener listener) {
- _em.assertNotCloseInvoked();
- _query.removeAggregateListener(listener);
- return this;
- }
-
- public Collection getCandidateCollection() {
- return _query.getCandidateCollection();
- }
-
- public OpenJPAQuery setCandidateCollection(Collection coll) {
- _em.assertNotCloseInvoked();
- _query.setCandidateCollection(coll);
- return this;
- }
-
- public Class getResultClass() {
- Class res = _query.getResultType();
- if (res != null)
- return res;
- return _query.getCandidateType();
- }
-
- public OpenJPAQuery setResultClass(Class cls) {
- _em.assertNotCloseInvoked();
- if (ImplHelper.isManagedType(_em.getConfiguration(), cls))
- _query.setCandidateType(cls, true);
- else
- _query.setResultType(cls);
- return this;
- }
-
- public boolean hasSubclasses() {
- return _query.hasSubclasses();
- }
-
- public OpenJPAQuery setSubclasses(boolean subs) {
- _em.assertNotCloseInvoked();
- Class cls = _query.getCandidateType();
- _query.setCandidateExtent(_query.getBroker().newExtent(cls, subs));
- return this;
- }
-
- public int getFirstResult() {
- return asInt(_query.getStartRange());
- }
-
- public OpenJPAQuery setFirstResult(int startPosition) {
- _em.assertNotCloseInvoked();
- long end;
- if (_query.getEndRange() == Long.MAX_VALUE)
- end = Long.MAX_VALUE;
- else
- end = startPosition +
- (_query.getEndRange() - _query.getStartRange());
- _query.setRange(startPosition, end);
- return this;
- }
-
- public int getMaxResults() {
- return asInt(_query.getEndRange() - _query.getStartRange());
- }
-
- public OpenJPAQuery setMaxResults(int max) {
- _em.assertNotCloseInvoked();
- long start = _query.getStartRange();
- if (max == Integer.MAX_VALUE)
- _query.setRange(start, Long.MAX_VALUE);
- else
- _query.setRange(start, start + max);
- return this;
- }
-
- public OpenJPAQuery compile() {
- _em.assertNotCloseInvoked();
- _query.compile();
- return this;
- }
-
- private Object execute() {
- if (_query.getOperation() != QueryOperations.OP_SELECT)
- throw new InvalidStateException(_loc.get("not-select-query",
- _query.getQueryString()), null, null, false);
-
- validateParameters();
-
- // handle which types of parameters we are using, if any
- if (_positional != null)
- return _query.execute(_positional.toArray());
- if (_named != null)
- return _query.execute(_named);
- return _query.execute();
- }
-
- /**
- * Validate that the types of the parameters are correct.
- */
- private void validateParameters() {
- if (_positional != null) {
- LinkedMap types = _query.getParameterTypes();
- for (int i = 0,
- size = Math.min(_positional.size(), types.size());
- i < size; i++)
- validateParameter(String.valueOf(i),
- (Class) types.getValue(i), _positional.get(i));
- } else if (_named != null) {
- Map types = _query.getParameterTypes();
- for (Iterator i = _named.entrySet().iterator(); i.hasNext();) {
- Map.Entry entry = (Map.Entry) i.next();
- String name = (String) entry.getKey();
- validateParameter(name, (Class) types.get(name),
- entry.getValue());
- }
- }
- }
-
- private void validateParameter(String paramDesc, Class type, Object param) {
- // null parameters are allowed, so are not validated
- if (param == null || type == null)
- return;
-
- // check the parameter against the wrapped type
- if (!Filters.wrap(type).isInstance(param))
- throw new ArgumentException(_loc.get("bad-param-type",
- paramDesc, param.getClass().getName(), type.getName()),
- null, null, false);
- }
-
- public List getResultList() {
- _em.assertNotCloseInvoked();
- Object ob = execute();
- if (ob instanceof List) {
- List ret = (List) ob;
- if (ret instanceof ResultList)
- return new DelegatingResultList((ResultList) ret,
- PersistenceExceptions.getRollbackTranslator(_em));
- else
- return ret;
- }
-
- return Collections.singletonList(ob);
- }
-
- /**
- * Execute a query that returns a single result.
- */
- public Object getSingleResult() {
- _em.assertNotCloseInvoked();
- // temporarily set query to unique so that a single result is validated
- // and returned; unset again in case the user executes query again
- // via getResultList
- _query.setUnique(true);
- try {
- return execute();
- } finally {
- _query.setUnique(false);
- }
- }
-
- public int executeUpdate() {
- _em.assertNotCloseInvoked();
- if (_query.getOperation() == QueryOperations.OP_DELETE) {
- // handle which types of parameters we are using, if any
- if (_positional != null)
- return asInt(_query.deleteAll(_positional.toArray()));
- if (_named != null)
- return asInt(_query.deleteAll(_named));
- return asInt(_query.deleteAll());
- }
- if (_query.getOperation() == QueryOperations.OP_UPDATE) {
- // handle which types of parameters we are using, if any
- if (_positional != null)
- return asInt(_query.updateAll(_positional.toArray()));
- if (_named != null)
- return asInt(_query.updateAll(_named));
- return asInt(_query.updateAll());
- }
- throw new InvalidStateException(_loc.get("not-update-delete-query",
- _query.getQueryString()), null, null, false);
- }
-
- /**
- * Cast the specified long down to an int, first checking for overflow.
- */
- private static int asInt(long l) {
- if (l > Integer.MAX_VALUE)
- return Integer.MAX_VALUE;
- if (l < Integer.MIN_VALUE) // unlikely, but we might as well check
- return Integer.MIN_VALUE;
- return (int) l;
- }
-
- public FlushModeType getFlushMode() {
- return EntityManagerImpl.fromFlushBeforeQueries(_query.
- getFetchConfiguration().getFlushBeforeQueries());
- }
-
- public OpenJPAQuery setFlushMode(FlushModeType flushMode) {
- _em.assertNotCloseInvoked();
- _query.getFetchConfiguration().setFlushBeforeQueries
- (EntityManagerImpl.toFlushBeforeQueries(flushMode));
- return this;
- }
-
- public OpenJPAQuery setHint(String key, Object value) {
- _em.assertNotCloseInvoked();
- if (key == null || !key.startsWith("openjpa."))
- return this;
- String k = key.substring("openjpa.".length());
-
- try {
- if ("Subclasses".equals(k)) {
- if (value instanceof String)
- value = Boolean.valueOf((String) value);
- setSubclasses(((Boolean) value).booleanValue());
- } else if ("FilterListener".equals(k))
- addFilterListener(Filters.hintToFilterListener(value,
- _query.getBroker().getClassLoader()));
- else if ("FilterListeners".equals(k)) {
- FilterListener[] arr = Filters.hintToFilterListeners(value,
- _query.getBroker().getClassLoader());
- for (int i = 0; i < arr.length; i++)
- addFilterListener(arr[i]);
- } else if ("AggregateListener".equals(k))
- addAggregateListener(Filters.hintToAggregateListener(value,
- _query.getBroker().getClassLoader()));
- else if ("FilterListeners".equals(k)) {
- AggregateListener[] arr = Filters.hintToAggregateListeners
- (value, _query.getBroker().getClassLoader());
- for (int i = 0; i < arr.length; i++)
- addAggregateListener(arr[i]);
- } else if (k.startsWith("FetchPlan.")) {
- k = k.substring("FetchPlan.".length());
- hintToSetter(getFetchPlan(), k, value);
- } else if (k.startsWith("hint.")) {
- if ("hint.OptimizeResultCount".equals(k)) {
- if (value instanceof String) {
- try {
- value = new Integer((String) value);
- } catch (NumberFormatException nfe) {
- }
- }
- if (!(value instanceof Number)
- || ((Number) value).intValue() < 0)
- throw new ArgumentException(_loc.get
- ("bad-query-hint-value", key, value), null, null,
- false);
- }
- _query.getFetchConfiguration().setHint(key, value);
- }
- else
- throw new ArgumentException(_loc.get("bad-query-hint", key),
- null, null, false);
- return this;
- } catch (Exception e) {
- throw PersistenceExceptions.toPersistenceException(e);
- }
- }
-
- private void hintToSetter(FetchPlan fetchPlan, String k, Object value) {
- if (fetchPlan == null || k == null)
- return;
-
- Method setter = Reflection.findSetter(fetchPlan.getClass(), k, true);
- Class paramType = setter.getParameterTypes()[0];
- if (Enum.class.isAssignableFrom(paramType) && value instanceof String)
- value = Enum.valueOf(paramType, (String) value);
-
- Filters.hintToSetter(fetchPlan, k, value);
- }
-
- public OpenJPAQuery setParameter(int position, Calendar value,
- TemporalType t) {
- return setParameter(position, value);
- }
-
- public OpenJPAQuery setParameter(int position, Date value,
- TemporalType type) {
- return setParameter(position, value);
- }
-
- public OpenJPAQuery setParameter(int position, Object value) {
- _query.assertOpen();
- _em.assertNotCloseInvoked();
- _query.lock();
- try {
- if (isNative() && position < 1) {
- throw new IllegalArgumentException(_loc.get("bad-pos-params",
- position, _query.getQueryString()).toString());
- }
- // not allowed to mix positional and named parameters (EDR2 3.6.4)
- if (_named != null)
- throw new InvalidStateException(_loc.get
- ("no-pos-named-params-mix", _query.getQueryString()),
- null, null, false);
-
- if (position < 1)
- throw new InvalidStateException(_loc.get
- ("illegal-index", position), null, null, false);
-
- if (_positional == null)
- _positional = new ArrayList();
-
- // make sure it is at least the requested size
- while (_positional.size() < position)
- _positional.add(null);
-
- // note that we add it to position - 1, since setPosition
- // starts at 1, while List starts at 0
- _positional.set(position - 1, value);
- return this;
- } finally {
- _query.unlock();
- }
- }
-
- public OpenJPAQuery setParameter(String name, Calendar value,
- TemporalType t) {
- return setParameter(name, value);
- }
-
- public OpenJPAQuery setParameter(String name, Date value,
- TemporalType type) {
- return setParameter(name, value);
- }
-
- public OpenJPAQuery setParameter(String name, Object value) {
- _query.assertOpen();
- _em.assertNotCloseInvoked();
- _query.lock();
- try {
- if (isNative()) {
- throw new IllegalArgumentException(_loc.get("no-named-params",
- name, _query.getQueryString()).toString());
- }
- // not allowed to mix positional and named parameters (EDR2 3.6.4)
- if (_positional != null)
- throw new InvalidStateException(_loc.get
- ("no-pos-named-params-mix", _query.getQueryString()),
- null, null, false);
-
- if (_named == null)
- _named = new HashMap();
- _named.put(name, value);
- return this;
- } finally {
- _query.unlock();
- }
- }
-
- public boolean isNative() {
- return QueryLanguages.LANG_SQL.equals(getLanguage());
- }
-
- public boolean hasPositionalParameters() {
- return _positional != null;
- }
-
- public Object[] getPositionalParameters() {
- _query.lock();
- try {
- return (_positional == null) ? EMPTY_ARRAY : _positional.toArray();
- } finally {
- _query.unlock();
- }
- }
-
- public OpenJPAQuery setParameters(Object... params) {
- _query.assertOpen();
- _em.assertNotCloseInvoked();
- _query.lock();
- try {
- _positional = null;
- _named = null;
- if (params != null)
- for (int i = 0; i < params.length; i++)
- setParameter(i + 1, params[i]);
- return this;
- } finally {
- _query.unlock();
- }
- }
-
- public Map getNamedParameters() {
- _query.lock();
- try {
- return (_named == null) ? Collections.EMPTY_MAP
- : Collections.unmodifiableMap(_named);
- } finally {
- _query.unlock();
- }
- }
-
- public OpenJPAQuery setParameters(Map params) {
- _query.assertOpen();
- _em.assertNotCloseInvoked();
- _query.lock();
- try {
- _positional = null;
- _named = null;
- if (params != null)
- for (Map.Entry e : (Set<Map.Entry>) params.entrySet())
- setParameter((String) e.getKey(), e.getValue());
- return this;
- } finally {
- _query.unlock();
- }
- }
-
- public OpenJPAQuery closeAll() {
- _query.closeAll();
- return this;
- }
-
- public String[] getDataStoreActions(Map params) {
- return _query.getDataStoreActions(params);
- }
-
- public int hashCode() {
- return _query.hashCode();
- }
-
- public boolean equals(Object other) {
- if (other == this)
- return true;
- if (!(other instanceof QueryImpl))
- return false;
- return _query.equals(((QueryImpl) other)._query);
+ public org.apache.openjpa.kernel.Query getDelegate() {
+ return _query.getDelegate();
+ }
+
+ public OpenJPAEntityManager getEntityManager() {
+ return _em;
+ }
+
+ public String getLanguage() {
+ return _query.getLanguage();
+ }
+
+ public QueryOperationType getOperation() {
+ return QueryOperationType.fromKernelConstant(_query.getOperation());
+ }
+
+ public FetchPlan getFetchPlan() {
+ _em.assertNotCloseInvoked();
+ _query.assertNotSerialized();
+ _query.lock();
+ try {
+ if (_fetch == null)
+ _fetch = ((EntityManagerFactoryImpl) _em
+ .getEntityManagerFactory()).toFetchPlan(_query
+ .getBroker(), _query.getFetchConfiguration());
+ return _fetch;
+ } finally {
+ _query.unlock();
+ }
+ }
+
+ public String getQueryString() {
+ return _query.getQueryString();
+ }
+
+ public boolean getIgnoreChanges() {
+ return _query.getIgnoreChanges();
+ }
+
+ public OpenJPAQuery setIgnoreChanges(boolean ignore) {
+ _em.assertNotCloseInvoked();
+ _query.setIgnoreChanges(ignore);
+ return this;
+ }
+
+ public OpenJPAQuery addFilterListener(FilterListener listener) {
+ _em.assertNotCloseInvoked();
+ _query.addFilterListener(listener);
+ return this;
+ }
+
+ public OpenJPAQuery removeFilterListener(FilterListener listener) {
+ _em.assertNotCloseInvoked();
+ _query.removeFilterListener(listener);
+ return this;
+ }
+
+ public OpenJPAQuery addAggregateListener(AggregateListener listener) {
+ _em.assertNotCloseInvoked();
+ _query.addAggregateListener(listener);
+ return this;
+ }
+
+ public OpenJPAQuery removeAggregateListener(AggregateListener listener) {
+ _em.assertNotCloseInvoked();
+ _query.removeAggregateListener(listener);
+ return this;
+ }
+
+ public Collection getCandidateCollection() {
+ return _query.getCandidateCollection();
+ }
+
+ public OpenJPAQuery setCandidateCollection(Collection coll) {
+ _em.assertNotCloseInvoked();
+ _query.setCandidateCollection(coll);
+ return this;
+ }
+
+ public Class getResultClass() {
+ Class res = _query.getResultType();
+ if (res != null)
+ return res;
+ return _query.getCandidateType();
+ }
+
+ public OpenJPAQuery setResultClass(Class cls) {
+ _em.assertNotCloseInvoked();
+ if (ImplHelper.isManagedType(_em.getConfiguration(), cls))
+ _query.setCandidateType(cls, true);
+ else
+ _query.setResultType(cls);
+ return this;
+ }
+
+ public boolean hasSubclasses() {
+ return _query.hasSubclasses();
+ }
+
+ public OpenJPAQuery setSubclasses(boolean subs) {
+ _em.assertNotCloseInvoked();
+ Class cls = _query.getCandidateType();
+ _query.setCandidateExtent(_query.getBroker().newExtent(cls, subs));
+ return this;
+ }
+
+ public int getFirstResult() {
+ return asInt(_query.getStartRange());
+ }
+
+ public OpenJPAQuery setFirstResult(int startPosition) {
+ _em.assertNotCloseInvoked();
+ long end;
+ if (_query.getEndRange() == Long.MAX_VALUE)
+ end = Long.MAX_VALUE;
+ else
+ end = startPosition
+ + (_query.getEndRange() - _query.getStartRange());
+ _query.setRange(startPosition, end);
+ return this;
+ }
+
+ public int getMaxResults() {
+ return asInt(_query.getEndRange() - _query.getStartRange());
+ }
+
+ public OpenJPAQuery setMaxResults(int max) {
+ _em.assertNotCloseInvoked();
+ long start = _query.getStartRange();
+ if (max == Integer.MAX_VALUE)
+ _query.setRange(start, Long.MAX_VALUE);
+ else
+ _query.setRange(start, start + max);
+ return this;
+ }
+
+ public OpenJPAQuery compile() {
+ _em.assertNotCloseInvoked();
+ _query.compile();
+ return this;
+ }
+
+ private Object execute() {
+ if (_query.getOperation() != QueryOperations.OP_SELECT)
+ throw new InvalidStateException(_loc.get("not-select-query", _query
+ .getQueryString()), null, null, false);
+
+ validateParameters();
+
+ // handle which types of parameters we are using, if any
+ if (_positional != null)
+ return _query.execute(_positional);
+ if (_named != null)
+ return _query.execute(_named);
+ return _query.execute();
+ }
+
+ /**
+ * Validate that the types of the parameters are correct.
+ * The idea is to catch as many validation error as possible at the facade
+ * layer itself.
+ *
+ * The expected parameters are parsed from the query and in a LinkedMap
+ * key : name of the parameter as declared in query
+ * value : expected Class of allowed value
+ *
+ * The bound parameters depends on positional or named parameter style
+ *
+ * TreeMap<Integer, Object> for positional parameters:
+ * key : 1-based Integer index
+ * value : bound value. GAP_FILLER if the position is not set. This
+ * simplifies validation at the kernel layer
+ *
+ * Map<String, Object> for named parameters:
+ * key : parameter name
+ * value : the bound value
+ *
+ * Validation accounts for
+ * a) gaps in positional parameters
+ * SELECT p FROM PObject p WHERE p.a1=?1 AND p.a3=?3
+ *
+ * b) repeated parameters
+ * SELECT p FROM PObject p WHERE p.a1=?1 AND p.a2=?1 AND p.a3=?2
+ *
+ * c) parameter is bound but not declared
+ *
+ * d) parameter is declared but not bound
+ *
+ * e) parameter does not match the value type
+ *
+ * f) parameter is primitive type but bound to null value
+ */
+ private void validateParameters() {
+ String query = getQueryString();
+ if (_positional != null) {
+ LinkedMap expected = _query.getParameterTypes();
+ Map<Integer, Object> actual = _positional;
+ for (Object o : expected.keySet()) {
+ String position = (String) o;
+ Class expectedParamType = (Class) expected.get(position);
+ try {
+ Integer.parseInt(position);
+ } catch (NumberFormatException ex) {
+ newValidationException("param-style-mismatch", query,
+ expected.asList(),
+ Arrays.toString(actual.keySet().toArray()));
+ }
+ Object actualValue = actual.get(Integer.parseInt(position));
+ boolean valueUnspecified = (actualValue == GAP_FILLER)
+ || (actualValue == null && (actual.size() < expected
+ .size()));
+ if (valueUnspecified)
+ newValidationException("param-missing", position, query,
+ Arrays.toString(actual.keySet().toArray()));
+
+ if (expectedParamType.isPrimitive() && actualValue == null)
+ newValidationException("param-type-null",
+ position, query, expectedParamType.getName());
+ if (actualValue == null)
+ continue;
+ if (!Filters.wrap(expectedParamType).isInstance(actualValue))
+ newValidationException("param-type-mismatch",
+ position, query, actualValue,
+ actualValue.getClass().getName(),
+ expectedParamType.getName());
+
+ }
+ for (Integer position : actual.keySet()) {
+ Object actualValue = actual.get(position);
+ Class expectedParamType = (Class) expected.get("" + position);
+ boolean paramExpected = expected.containsKey("" + position);
+ if (actualValue == GAP_FILLER) {
+ if (paramExpected) {
+ newValidationException("param-missing", position, query,
+ Arrays.toString(actual.keySet().toArray()));
+ }
+ } else {
+ if (!paramExpected)
+ newValidationException("param-extra", position, query,
+ expected.asList());
+ if (expectedParamType.isPrimitive() && actualValue == null)
+ newValidationException("param-type-null",
+ position, query, expectedParamType.getName());
+ if (!Filters.wrap(expectedParamType)
+ .isInstance(actualValue))
+ newValidationException("param-type-mismatch",
+ position, query, actualValue,
+ actualValue.getClass().getName(),
+ expectedParamType.getName());
+
+ }
+ }
+
+ } else if (_named != null) {
+ LinkedMap expected = _query.getParameterTypes();
+ // key : name of the parameter used while binding
+ // value : user supplied parameter value. null may mean either
+ // user has supplied a value or not specified at all
+ Map<String, Object> actual = _named;
+ for (Object o : expected.keySet()) {
+ String expectedName = (String) o;
+ Class expectedParamType = (Class) expected.get(expectedName);
+ Object actualValue = actual.get(expectedName);
+ boolean valueUnspecified = !actual.containsKey(expectedName);
+ if (valueUnspecified) {
+ newValidationException("param-missing", expectedName, query,
+ Arrays.toString(actual.keySet().toArray()));
+ }
+ if (expectedParamType.isPrimitive() && actualValue == null)
+ newValidationException("param-type-null",
+ expectedName, query, expectedParamType.getName());
+ if (actualValue == null)
+ continue;
+ if (!Filters.wrap(expectedParamType).isInstance(actualValue)) {
+ newValidationException("param-type-mismatch",
+ expectedName, query, actualValue,
+ actualValue.getClass().getName(),
+ expectedParamType.getName());
+ }
+ }
+ for (String actualName : actual.keySet()) {
+ Object actualValue = actual.get(actualName);
+ Class expectedParamType = (Class) expected.get(actualName);
+ boolean paramExpected = expected.containsKey(actualName);
+ if (!paramExpected) {
+ newValidationException("param-extra", actualName, query,
+ expected.asList());
+ }
+ if (expectedParamType.isPrimitive() && actualValue == null)
+ newValidationException("param-type-null",
+ actualName, query, expectedParamType.getName());
+ if (!Filters.wrap(expectedParamType).isInstance(actualValue)) {
+ newValidationException("param-type-mismatch",
+ actualName, query, actualValue,
+ actualValue.getClass().getName(),
+ expectedParamType.getName());
+ }
+ }
+ }
+ }
+
+ void newValidationException(String msgKey, Object...args) {
+ throw new ArgumentException(_loc.get(msgKey, args), null, null, false);
+ }
+
+ public List getResultList() {
+ _em.assertNotCloseInvoked();
+ Object ob = execute();
+ if (ob instanceof List) {
+ List ret = (List) ob;
+ if (ret instanceof ResultList)
+ return new DelegatingResultList((ResultList) ret,
+ PersistenceExceptions.getRollbackTranslator(_em));
+ else
+ return ret;
+ }
+
+ return Collections.singletonList(ob);
+ }
+
+ /**
+ * Execute a query that returns a single result.
+ */
+ public Object getSingleResult() {
+ _em.assertNotCloseInvoked();
+ // temporarily set query to unique so that a single result is validated
+ // and returned; unset again in case the user executes query again
+ // via getResultList
+ _query.setUnique(true);
+ try {
+ return execute();
+ } finally {
+ _query.setUnique(false);
+ }
+ }
+
+ public int executeUpdate() {
+ _em.assertNotCloseInvoked();
+ if (_query.getOperation() == QueryOperations.OP_DELETE) {
+ // handle which types of parameters we are using, if any
+ if (_positional != null)
+ return asInt(_query.deleteAll(_positional));
+ if (_named != null)
+ return asInt(_query.deleteAll(_named));
+ return asInt(_query.deleteAll());
+ }
+ if (_query.getOperation() == QueryOperations.OP_UPDATE) {
+ // handle which types of parameters we are using, if any
+ if (_positional != null)
+ return asInt(_query.updateAll(_positional));
+ if (_named != null)
+ return asInt(_query.updateAll(_named));
+ return asInt(_query.updateAll());
+ }
+ throw new InvalidStateException(_loc.get("not-update-delete-query",
+ _query.getQueryString()), null, null, false);
+ }
+
+ /**
+ * Cast the specified long down to an int, first checking for overflow.
+ */
+ private static int asInt(long l) {
+ if (l > Integer.MAX_VALUE)
+ return Integer.MAX_VALUE;
+ if (l < Integer.MIN_VALUE) // unlikely, but we might as well check
+ return Integer.MIN_VALUE;
+ return (int) l;
+ }
+
+ public FlushModeType getFlushMode() {
+ return EntityManagerImpl.fromFlushBeforeQueries(_query
+ .getFetchConfiguration().getFlushBeforeQueries());
+ }
+
+ public OpenJPAQuery setFlushMode(FlushModeType flushMode) {
+ _em.assertNotCloseInvoked();
+ _query.getFetchConfiguration().setFlushBeforeQueries(
+ EntityManagerImpl.toFlushBeforeQueries(flushMode));
+ return this;
+ }
+
+ public OpenJPAQuery setHint(String key, Object value) {
+ _em.assertNotCloseInvoked();
+ if (key == null || !key.startsWith("openjpa."))
+ return this;
+ String k = key.substring("openjpa.".length());
+
+ try {
+ if ("Subclasses".equals(k)) {
+ if (value instanceof String)
+ value = Boolean.valueOf((String) value);
+ setSubclasses(((Boolean) value).booleanValue());
+ } else if ("FilterListener".equals(k))
+ addFilterListener(Filters.hintToFilterListener(value, _query
+ .getBroker().getClassLoader()));
+ else if ("FilterListeners".equals(k)) {
+ FilterListener[] arr = Filters.hintToFilterListeners(value,
+ _query.getBroker().getClassLoader());
+ for (int i = 0; i < arr.length; i++)
+ addFilterListener(arr[i]);
+ } else if ("AggregateListener".equals(k))
+ addAggregateListener(Filters.hintToAggregateListener(value,
+ _query.getBroker().getClassLoader()));
+ else if ("FilterListeners".equals(k)) {
+ AggregateListener[] arr = Filters.hintToAggregateListeners(
+ value, _query.getBroker().getClassLoader());
+ for (int i = 0; i < arr.length; i++)
+ addAggregateListener(arr[i]);
+ } else if (k.startsWith("FetchPlan.")) {
+ k = k.substring("FetchPlan.".length());
+ hintToSetter(getFetchPlan(), k, value);
+ } else if (k.startsWith("hint.")) {
+ if ("hint.OptimizeResultCount".equals(k)) {
+ if (value instanceof String) {
+ try {
+ value = new Integer((String) value);
+ } catch (NumberFormatException nfe) {
+ }
+ }
+ if (!(value instanceof Number)
+ || ((Number) value).intValue() < 0)
+ throw new ArgumentException(_loc.get(
+ "bad-query-hint-value", key, value), null,
+ null, false);
+ }
+ _query.getFetchConfiguration().setHint(key, value);
+ } else
+ throw new ArgumentException(_loc.get("bad-query-hint", key),
+ null, null, false);
+ return this;
+ } catch (Exception e) {
+ throw PersistenceExceptions.toPersistenceException(e);
+ }
+ }
+
+ private void hintToSetter(FetchPlan fetchPlan, String k, Object value) {
+ if (fetchPlan == null || k == null)
+ return;
+
+ Method setter = Reflection.findSetter(fetchPlan.getClass(), k, true);
+ Class paramType = setter.getParameterTypes()[0];
+ if (Enum.class.isAssignableFrom(paramType) && value instanceof String)
+ value = Enum.valueOf(paramType, (String) value);
+
+ Filters.hintToSetter(fetchPlan, k, value);
+ }
+
+ public OpenJPAQuery setParameter(int position, Calendar value,
+ TemporalType t) {
+ return setParameter(position, convertTemporalType(value, t));
+ }
+
+ public OpenJPAQuery setParameter(int position, Date value, TemporalType type) {
+ return setParameter(position, convertTemporalType(value, type));
+ }
+
+ /**
+ * Converts the given Date to a value corresponding to given temporal type.
+ */
+
+ Object convertTemporalType(Date value, TemporalType type) {
+ switch (type) {
+ case DATE:
+ return value;
+ case TIME:
+ return new Time(value.getTime());
+ case TIMESTAMP:
+ return new Timestamp(value.getTime());
+ default:
+ return null;
+ }
+ }
+
+ Object convertTemporalType(Calendar value, TemporalType type) {
+ return convertTemporalType(value.getTime(), type);
+ }
+
+ public OpenJPAQuery setParameter(int position, Object value) {
+ _query.assertOpen();
+ _em.assertNotCloseInvoked();
+ _query.lock();
+ try {
+ if (isNative() && position < 1) {
+ throw new IllegalArgumentException(_loc.get("bad-pos-params",
+ position, _query.getQueryString()).toString());
+ }
+ // not allowed to mix positional and named parameters (EDR2 3.6.4)
+ if (_named != null)
+ throw new InvalidStateException(_loc.get(
+ "no-pos-named-params-mix", _query.getQueryString()),
+ null, null, false);
+
+ if (position < 1)
+ throw new InvalidStateException(_loc.get("illegal-index",
+ position), null, null, false);
+
+ if (_positional == null)
+ _positional = new TreeMap<Integer, Object>();
+
+ _positional.put(position, value);
+ for (int i = 1; i < position; i++)
+ if (!_positional.containsKey(i))
+ _positional.put(i, GAP_FILLER);
+
+ return this;
+ } finally {
+ _query.unlock();
+ }
+ }
+
+ public OpenJPAQuery setParameter(String name, Calendar value,
+ TemporalType type) {
+ return setParameter(name, convertTemporalType(value, type));
+ }
+
+ public OpenJPAQuery setParameter(String name, Date value, TemporalType type) {
+ return setParameter(name, convertTemporalType(value, type));
+ }
+
+ public OpenJPAQuery setParameter(String name, Object value) {
+ _query.assertOpen();
+ _em.assertNotCloseInvoked();
+ _query.lock();
+ try {
+ if (isNative()) {
+ throw new IllegalArgumentException(_loc.get("no-named-params",
+ name, _query.getQueryString()).toString());
+ }
+ // not allowed to mix positional and named parameters (EDR2 3.6.4)
+ if (_positional != null)
+ throw new InvalidStateException(_loc.get(
+ "no-pos-named-params-mix", _query.getQueryString()),
+ null, null, false);
+
+ if (_named == null)
+ _named = new HashMap();
+ _named.put(name, value);
+ return this;
+ } finally {
+ _query.unlock();
+ }
+ }
+
+ public boolean isNative() {
+ return QueryLanguages.LANG_SQL.equals(getLanguage());
+ }
+
+ public boolean hasPositionalParameters() {
+ return _positional != null;
+ }
+
+ /**
+ * Gets the array of positional parameter values. A value of
+ * <code>GAP_FILLER</code> indicates that user has not set the
+ * corresponding positional parameter. A value of null implies that user has
+ * set the value as null.
+ */
+ public Object[] getPositionalParameters() {
+ _query.lock();
+ try {
+ return (_positional == null) ? EMPTY_ARRAY : _positional.values()
+ .toArray();
+ } finally {
+ _query.unlock();
+ }
+ }
+
+ public OpenJPAQuery setParameters(Object... params) {
+ _query.assertOpen();
+ _em.assertNotCloseInvoked();
+ _query.lock();
+ try {
+ _positional = null;
+ _named = null;
+ if (params != null)
+ for (int i = 0; i < params.length; i++)
+ setParameter(i + 1, params[i]);
+ return this;
+ } finally {
+ _query.unlock();
+ }
+ }
+
+ public Map getNamedParameters() {
+ _query.lock();
+ try {
+ return (_named == null) ? Collections.EMPTY_MAP : Collections
+ .unmodifiableMap(_named);
+ } finally {
+ _query.unlock();
+ }
+ }
+
+ public OpenJPAQuery setParameters(Map params) {
+ _query.assertOpen();
+ _em.assertNotCloseInvoked();
+ _query.lock();
+ try {
+ _positional = null;
+ _named = null;
+ if (params != null)
+ for (Map.Entry e : (Set<Map.Entry>) params.entrySet())
+ setParameter((String) e.getKey(), e.getValue());
+ return this;
+ } finally {
+ _query.unlock();
+ }
+ }
+
+ public OpenJPAQuery closeAll() {
+ _query.closeAll();
+ return this;
+ }
+
+ public String[] getDataStoreActions(Map params) {
+ return _query.getDataStoreActions(params);
+ }
+
+ public int hashCode() {
+ return _query.hashCode();
+ }
+
+ public boolean equals(Object other) {
+ if (other == this)
+ return true;
+ if (!(other instanceof QueryImpl))
+ return false;
+ return _query.equals(((QueryImpl) other)._query);
}
}
Modified: openjpa/trunk/openjpa-persistence/src/main/resources/org/apache/openjpa/persistence/localizer.properties
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/resources/org/apache/openjpa/persistence/localizer.properties?rev=681977&r1=681976&r2=681977&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/resources/org/apache/openjpa/persistence/localizer.properties (original)
+++ openjpa/trunk/openjpa-persistence/src/main/resources/org/apache/openjpa/persistence/localizer.properties Sat Aug 2 06:58:56 2008
@@ -102,8 +102,10 @@
Use only 1-based positional parameter in native queries.
bad-pos-params: Positional parameter "{0}" is invalid for native query "{1}". \
Use only 1-based positional parameter in native queries.
-bad-param-type: The parameter "{0}" is of type "{1}", but the \
- declaration in the query is for type "{2}".
+bad-param-type: The parameter "{1}" in query "{0}" is set to a value of type \
+ "{2}", but the parameter binds to a field of type "{3}".
+missing-param-name: The parameter "{1}" in query "{0}" is not found in the \
+ available list of parameters "{2}".
bad-em-prop: Invalid EntityManager property passed to createEntityManager. \
Key: "{0}", Value: "{1}".
bad-em-props: Invalid EntityManager properties passed to createEntityManager. \
@@ -148,4 +150,14 @@
EntityManagerFactory-displayorder: 50
EntityManagerFactory-expert: true
EntityManagerFactory-interface: org.apache.openjpa.persistence.EntityManagerFactoryImpl
-
+param-style-mismatch: Query "{0}" is declared with named parameters "{1}" but \
+ actual parameters "{2}" are bound by position.
+param-missing: Parameter "{0}" declared in "{1}" but is missing from the bound \
+ parameters "{2}".
+param-extra: Parameter "{0}" is bound to "{1}" but is missing from the \
+ declared parameters "{2}".
+param-type-mismatch: Parameter "{0}" declared in "{1}" is set to value of \
+ "{2}" of type "{3}", but this parameter is bound to a field of type "{4}".
+param-type-mismatch: Parameter "{0}" declared in "{1}" is set to null, \
+ but this parameter is bound to a field of primitive type "{2}".
+
\ No newline at end of file