From 2d5ab5c862737cf13c6a77bee4924dd959e8b941 Mon Sep 17 00:00:00 2001 From: Heath Thomann Date: Fri, 30 Nov 2012 15:39:17 +0000 Subject: [PATCH] OPENJPA-2289: Applied Albert's patch to trunk git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@1415702 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/openjpa/jdbc/sql/DBDictionary.java | 4 + .../openjpa/jdbc/sql/OracleDictionary.java | 4 + .../apache/openjpa/jdbc/sql/SelectImpl.java | 6 +- .../jdbc/query/sub/MaxQueryEntity.java | 69 ++++++++++++++ .../jdbc/query/sub/MaxQueryMapEntity.java | 83 +++++++++++++++++ .../jdbc/query/sub/TestSubQuery.java | 92 +++++++++++++++++++ 6 files changed, 257 insertions(+), 1 deletion(-) create mode 100644 openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/query/sub/MaxQueryEntity.java create mode 100644 openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/query/sub/MaxQueryMapEntity.java create mode 100644 openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/query/sub/TestSubQuery.java diff --git a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java index 7f0503711..2221060da 100644 --- a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java +++ b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java @@ -1877,6 +1877,10 @@ public class DBDictionary else if (!StringUtils.isEmpty(syntax)) throw new IllegalArgumentException(syntax); } + + public boolean isImplicitJoin() { + return false; + } /** * Return a SQL string to act as a placeholder for the given column. diff --git a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/OracleDictionary.java b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/OracleDictionary.java index 57c5f13a8..598395b8b 100644 --- a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/OracleDictionary.java +++ b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/OracleDictionary.java @@ -1366,6 +1366,10 @@ public class OracleDictionary } } + public boolean isImplicitJoin() { + return joinSyntax == SYNTAX_DATABASE; + } + /** * Oracle requires special handling of XML column. * Unless the value length is less or equal to 4000 bytes, diff --git a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SelectImpl.java b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SelectImpl.java index f30e09765..166ba107e 100644 --- a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SelectImpl.java +++ b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SelectImpl.java @@ -2847,7 +2847,11 @@ public class SelectImpl || _sel._from != null) { // don't make any joins, but update the path if a variable // has been set - this.append(this.var); + if (this.var != null) { + this.append(this.var); + } else if (this.path == null && this.correlatedVar != null && _sel._dict.isImplicitJoin()) { + this.append(this.correlatedVar); + } this.var = null; _outer = false; return this; diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/query/sub/MaxQueryEntity.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/query/sub/MaxQueryEntity.java new file mode 100644 index 000000000..58bb8b96e --- /dev/null +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/query/sub/MaxQueryEntity.java @@ -0,0 +1,69 @@ +/* + * 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.sub; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +@Entity +@Table(name = "OPENJPA_MAXQUERY_ENTITY") +public class MaxQueryEntity { + + public MaxQueryEntity() { + } + + public MaxQueryEntity(int id, int domainId, int revision) { + this.id = id; + this.domainId = domainId; + this.revision = revision; + } + + @Id + private int id; + + private int domainId; + + private int revision; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public int getRevision() { + return revision; + } + + public void setRevision(int revision) { + this.revision = revision; + } + + public int getDomainId() { + return domainId; + } + + public void setDomainId(int domainId) { + this.domainId = domainId; + } + +} diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/query/sub/MaxQueryMapEntity.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/query/sub/MaxQueryMapEntity.java new file mode 100644 index 000000000..c6764a366 --- /dev/null +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/query/sub/MaxQueryMapEntity.java @@ -0,0 +1,83 @@ +/* + * 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.sub; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.Table; + +@Entity +@Table(name = "OPENJPA_MAXQUERY_MAPENTITY") +public class MaxQueryMapEntity { + + public MaxQueryMapEntity(int id, int revision, String selectCriteria) { + this.id = id; + this.revision = revision; + this.selectCriteria = selectCriteria; + } + + public MaxQueryMapEntity() { + } + + @Id + private int id; + + private int revision; + + @ManyToOne + @JoinColumn(name = "refEntity") + private MaxQueryEntity refEntity; + + private String selectCriteria; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public int getRevision() { + return revision; + } + + public void setRevision(int revision) { + this.revision = revision; + } + + public MaxQueryEntity getRefEntity() { + return refEntity; + } + + public void setRefEntity(MaxQueryEntity refEntity) { + this.refEntity = refEntity; + } + + public String getSelectCriteria() { + return selectCriteria; + } + + public void setSelectCriteria(String selectCriteria) { + this.selectCriteria = selectCriteria; + } + +} diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/query/sub/TestSubQuery.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/query/sub/TestSubQuery.java new file mode 100644 index 000000000..b42b0ae7d --- /dev/null +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/query/sub/TestSubQuery.java @@ -0,0 +1,92 @@ +/* + * 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.sub; + +import javax.persistence.EntityManager; +import javax.persistence.EntityTransaction; +import javax.persistence.Query; + +import org.apache.openjpa.persistence.test.SingleEMFTestCase; + +public class TestSubQuery extends SingleEMFTestCase { + public void setUp() throws Exception { + super.setUp(CLEAR_TABLES, MaxQueryEntity.class, MaxQueryMapEntity.class); + populate(); + } + + public void populate() { + EntityManager em = emf.createEntityManager(); + EntityTransaction tran = em.getTransaction(); + tran.begin(); + + MaxQueryEntity mqe = new MaxQueryEntity(1, 1, 1); + MaxQueryMapEntity mqme = new MaxQueryMapEntity(1, 1, "A1"); + MaxQueryMapEntity mqme2 = new MaxQueryMapEntity(2, 2, "A2"); + mqme.setRefEntity(mqe); + mqme2.setRefEntity(mqe); + em.persist(mqe); + em.persist(mqme); + em.persist(mqme2); + + mqe = new MaxQueryEntity(2, 2, 1); + mqme = new MaxQueryMapEntity(3, 1, "B1"); + mqme.setRefEntity(mqe); + em.persist(mqe); + em.persist(mqme); + mqme = new MaxQueryMapEntity(4, 2, "B2"); + mqme.setRefEntity(mqe); + em.persist(mqme); + mqme = new MaxQueryMapEntity(5, 3, "B3"); + mqme.setRefEntity(mqe); + em.persist(mqme); + + mqe = new MaxQueryEntity(3, 3, 1); + mqme = new MaxQueryMapEntity(6, 4, "C1"); + mqme.setRefEntity(mqe); + em.persist(mqe); + em.persist(mqme); + + tran.commit(); + em.close(); + } + + public void test() { + EntityManager em = emf.createEntityManager(); + + Query query = + em + .createQuery("SELECT e FROM MaxQueryEntity e, MaxQueryMapEntity map " + + "WHERE " +// + " map.selectCriteria = 'B3' " +// + " AND map.refEntity = e " +// + " AND e.revision = ( SELECT MAX(e_.revision)" +// + " FROM MaxQueryEntity e_" +// + " WHERE e_.domainId = e.domainId )" +// + " AND " + + " map.revision = ( SELECT MAX(map_.revision)" + + " FROM MaxQueryMapEntity map_" + + " WHERE map_.refEntity = map.refEntity )" + ); + +// assertEquals(1, query.getResultList().size()); + assertEquals(9, query.getResultList().size()); + + em.close(); + } +}