From fb7ab1908bfb6afe560f094ab70b9de860280ed0 Mon Sep 17 00:00:00 2001 From: Catalina Wei Date: Wed, 24 Dec 2008 00:18:32 +0000 Subject: [PATCH] OPENJPA-557 Primary key sequences broken with postgres schemas Commit patch provided by Milosz Tylenda git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@729180 13f79535-47bb-0310-9956-ffa450edef68 --- .../openjpa/jdbc/sql/PostgresDictionary.java | 3 +- .../persistence/generationtype/Dog1.java | 3 - .../persistence/generationtype/Dog2.java | 3 - .../persistence/generationtype/Dog3.java | 51 ++++++++ .../persistence/generationtype/Dog4.java | 51 ++++++++ .../persistence/generationtype/DogTable.java | 3 - .../persistence/generationtype/DogTable2.java | 3 - .../persistence/generationtype/DogTable3.java | 3 - .../persistence/generationtype/DogTable4.java | 3 - .../TestMultipleSchemaNames.java | 117 +++++++++++++++++- 10 files changed, 217 insertions(+), 23 deletions(-) create mode 100644 openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/generationtype/Dog3.java create mode 100644 openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/generationtype/Dog4.java diff --git a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/PostgresDictionary.java b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/PostgresDictionary.java index 2aaf95d3b..eb161cafb 100644 --- a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/PostgresDictionary.java +++ b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/PostgresDictionary.java @@ -113,9 +113,8 @@ public class PostgresDictionary requiresAliasForSubselect = true; allowsAliasInBulkClause = false; - // {2} is the result of getGeneratedKeySequenceName; the // single-quote escape will result in SELECT CURVAL('mysequence') - lastGeneratedKeyQuery = "SELECT CURRVAL(''{2}'')"; + lastGeneratedKeyQuery = "SELECT CURRVAL(''{1}_{0}_seq'')"; supportsAutoAssign = true; autoAssignTypeName = "BIGSERIAL"; nextSequenceQuery = "SELECT NEXTVAL(''{0}'')"; diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/generationtype/Dog1.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/generationtype/Dog1.java index a101690ab..6bf3a734c 100644 --- a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/generationtype/Dog1.java +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/generationtype/Dog1.java @@ -21,9 +21,6 @@ package org.apache.openjpa.persistence.generationtype; import javax.persistence.*; import java.io.*; -/** - * Extension of Animal class illustrating inheritance. - */ @Entity(name = "Dog1") @Table(name = "DOGAUTO", schema = "SCHEMA1") public class Dog1 implements Serializable diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/generationtype/Dog2.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/generationtype/Dog2.java index 5a62ed6ee..2fd255507 100644 --- a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/generationtype/Dog2.java +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/generationtype/Dog2.java @@ -21,9 +21,6 @@ package org.apache.openjpa.persistence.generationtype; import javax.persistence.*; import java.io.*; -/** - * Extension of Animal class illustrating inheritance. - */ @Entity(name = "Dog2") @Table(name = "DOGAUTO", schema = "SCHEMA2") public class Dog2 implements Serializable diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/generationtype/Dog3.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/generationtype/Dog3.java new file mode 100644 index 000000000..9ff1dfcb2 --- /dev/null +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/generationtype/Dog3.java @@ -0,0 +1,51 @@ +/* + * 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.generationtype; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; + +@Entity(name = "Dog3") +@Table(name = "DOGIDENT", schema = "SCHEMA1") +public class Dog3 { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private int id; + + private String name; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/generationtype/Dog4.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/generationtype/Dog4.java new file mode 100644 index 000000000..7919be60b --- /dev/null +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/generationtype/Dog4.java @@ -0,0 +1,51 @@ +/* + * 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.generationtype; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; + +@Entity(name = "Dog4") +@Table(name = "DOGIDENT4") +public class Dog4 { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private int id; + + private String name; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/generationtype/DogTable.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/generationtype/DogTable.java index 695da4845..32a5f739f 100644 --- a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/generationtype/DogTable.java +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/generationtype/DogTable.java @@ -22,9 +22,6 @@ package org.apache.openjpa.persistence.generationtype; import javax.persistence.*; import java.io.*; -/** - * Extension of Animal class illustrating inheritance. - */ @Entity(name = "DogTable") @Table(name = "DOGTABLES", schema = "SCHEMA1") public class DogTable implements Serializable diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/generationtype/DogTable2.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/generationtype/DogTable2.java index de0640428..772dd8333 100644 --- a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/generationtype/DogTable2.java +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/generationtype/DogTable2.java @@ -21,9 +21,6 @@ package org.apache.openjpa.persistence.generationtype; import java.io.*; import javax.persistence.*; -/** - * Extension of Animal class illustrating inheritance. - */ @Entity(name = "DogTable2") @Table(name = "DOGTABLES", schema = "SCHEMA2") public class DogTable2 implements Serializable diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/generationtype/DogTable3.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/generationtype/DogTable3.java index 83c2ad83a..80ac5eb34 100644 --- a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/generationtype/DogTable3.java +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/generationtype/DogTable3.java @@ -21,9 +21,6 @@ package org.apache.openjpa.persistence.generationtype; import java.io.*; import javax.persistence.*; -/** - * Extension of Animal class illustrating inheritance. - */ @Entity(name = "DogTable3") @Table(name = "DOGTABLES", schema = "SCHEMA3") public class DogTable3 implements Serializable diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/generationtype/DogTable4.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/generationtype/DogTable4.java index 8d08cd388..c37d29f23 100644 --- a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/generationtype/DogTable4.java +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/generationtype/DogTable4.java @@ -21,9 +21,6 @@ package org.apache.openjpa.persistence.generationtype; import java.io.*; import javax.persistence.*; -/** - * Extension of Animal class illustrating inheritance. - */ @Entity(name = "DogTable4") @Table(name = "DOGTABLES4") public class DogTable4 implements Serializable diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/generationtype/TestMultipleSchemaNames.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/generationtype/TestMultipleSchemaNames.java index ba841886b..b617cb3ee 100644 --- a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/generationtype/TestMultipleSchemaNames.java +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/generationtype/TestMultipleSchemaNames.java @@ -19,15 +19,31 @@ package org.apache.openjpa.persistence.generationtype; import java.util.List; + import javax.persistence.EntityManager; +import javax.persistence.PersistenceException; import javax.persistence.Query; -import org.apache.openjpa.persistence.*; + +import org.apache.openjpa.jdbc.conf.JDBCConfiguration; +import org.apache.openjpa.jdbc.sql.DBDictionary; +import org.apache.openjpa.jdbc.sql.PostgresDictionary; +import org.apache.openjpa.persistence.OpenJPAEntityManager; +import org.apache.openjpa.persistence.OpenJPAEntityManagerFactorySPI; +import org.apache.openjpa.persistence.OpenJPAEntityManagerSPI; +import org.apache.openjpa.persistence.OpenJPAPersistence; import org.apache.openjpa.persistence.test.SingleEMFTestCase; public class TestMultipleSchemaNames extends SingleEMFTestCase { + public void setUp() { - setUp(Dog1.class, Dog2.class, DogTable.class, DogTable2.class, - DogTable3.class, DogTable4.class); + // Create schemas when database requires this and we are about + // to execute the first test. + if ("testGeneratedAUTO".equals(getName())) { + createSchemas(); + } + + setUp(Dog1.class, Dog2.class, Dog3.class, Dog4.class, + DogTable.class, DogTable2.class, DogTable3.class, DogTable4.class); EntityManager em = emf.createEntityManager(); em.getTransaction().begin(); @@ -77,6 +93,22 @@ public class TestMultipleSchemaNames extends SingleEMFTestCase { em.remove(Obj); } + Query qry7 = em.createQuery("select d from Dog3 d"); + List result7 = qry7.getResultList(); + + for (int index = 0; index < result7.size(); index++) { + Dog3 Obj = (Dog3) result7.get(index); + em.remove(Obj); + } + + Query qry8 = em.createQuery("select d from Dog4 d"); + List result8 = qry8.getResultList(); + + for (int index = 0; index < result8.size(); index++) { + Dog4 Obj = (Dog4) result8.get(index); + em.remove(Obj); + } + Query delschema1 = em .createNativeQuery("delete from schema1.openjpa_sequence_table"); delschema1.executeUpdate(); @@ -321,4 +353,83 @@ public class TestMultipleSchemaNames extends SingleEMFTestCase { em.getTransaction().commit(); em.close(); } + + public void testGeneratedIDENTITY() { + EntityManager em = emf.createEntityManager(); + OpenJPAEntityManager kem = OpenJPAPersistence.cast(em); + + // Dog3 is a schema dog. + em.getTransaction().begin(); + Dog3 dog30 = new Dog3(); + dog30.setName("Dog30"); + em.persist(dog30); + + Dog3 dog31 = new Dog3(); + dog31.setName("Dog31"); + em.persist(dog31); + em.getTransaction().commit(); + + // We can't assume generated values start with 1 as + // the table might have already existed and had some rows. + Dog3 dog30x = em.find(Dog3.class, kem.getObjectId(dog30)); + Dog3 dog31x = em.find(Dog3.class, kem.getObjectId(dog31)); + assertTrue((dog30x.getId() + 1 == dog31x.getId()) || + (dog30x.getId() == dog31x.getId() + 1)); + assertEquals(dog30x.getName(), "Dog30"); + + // Dog4 is a non-schema dog. + em.getTransaction().begin(); + Dog4 dog40 = new Dog4(); + dog40.setName("Dog40"); + em.persist(dog40); + + Dog4 dog41 = new Dog4(); + dog41.setName("Dog41"); + em.persist(dog41); + em.getTransaction().commit(); + + Dog4 dog40x = em.find(Dog4.class, kem.getObjectId(dog40)); + Dog4 dog41x = em.find(Dog4.class, kem.getObjectId(dog41)); + assertTrue((dog40x.getId() + 1 == dog41x.getId()) || + (dog40x.getId() == dog41x.getId() + 1)); + assertEquals(dog40x.getName(), "Dog40"); + + em.close(); + } + + /** + * Create necessary schemas if running on PostgreSQL as it does + * not create them automatically. + * Oracle and MySQL also don't create schemas automatically but + * we give up as they treat schemas in special ways. + */ + private void createSchemas() { + OpenJPAEntityManagerFactorySPI emf = createEMF(); + OpenJPAEntityManagerSPI em = emf.createEntityManager(); + DBDictionary dict = ((JDBCConfiguration) em.getConfiguration()) + .getDBDictionaryInstance(); + + if (!(dict instanceof PostgresDictionary)) { + closeEMF(emf); + return; + } + + String[] schemas = + { "SCHEMA1", "SCHEMA2", "SCHEMA3", "SCHEMA3G", "SCHEMA4G" }; + for (String schema : schemas) { + try { + em.getTransaction().begin(); + Query q = em.createNativeQuery("create schema " + schema); + q.executeUpdate(); + em.getTransaction().commit(); + } catch (PersistenceException e) { + System.err.println("Exception caught while creating schema " + + schema + ". Schema already exists? Message: " + + e.getMessage()); + em.getTransaction().rollback(); + } + } + closeEMF(emf); + } + } // end of TestMultipleSchemaNames