You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by mi...@apache.org on 2009/06/04 19:47:56 UTC
svn commit: r781809 - in /openjpa/branches/1.3.x:
openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/
openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/
openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/kernel/
Author: mikedd
Date: Thu Jun 4 17:47:56 2009
New Revision: 781809
URL: http://svn.apache.org/viewvc?rev=781809&view=rev
Log:
OPENJPA-1083 committing patch provided by Ravi Palacherla
Added:
openjpa/branches/1.3.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/kernel/TestForeignKeyCountViolation.java (with props)
Modified:
openjpa/branches/1.3.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/ForeignKey.java
openjpa/branches/1.3.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/SchemaTool.java
openjpa/branches/1.3.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java
openjpa/branches/1.3.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/MySQLDictionary.java
Modified: openjpa/branches/1.3.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/ForeignKey.java
URL: http://svn.apache.org/viewvc/openjpa/branches/1.3.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/ForeignKey.java?rev=781809&r1=781808&r2=781809&view=diff
==============================================================================
--- openjpa/branches/1.3.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/ForeignKey.java (original)
+++ openjpa/branches/1.3.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/ForeignKey.java Thu Jun 4 17:47:56 2009
@@ -19,6 +19,7 @@
package org.apache.openjpa.jdbc.schema;
import java.sql.DatabaseMetaData;
+import java.sql.Connection;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -28,6 +29,7 @@
import org.apache.openjpa.lib.util.Localizer;
import org.apache.openjpa.lib.util.StringDistance;
import org.apache.openjpa.util.InvalidStateException;
+import org.apache.openjpa.jdbc.sql.DBDictionary;
/**
* Represents a database foreign key; may be a logical key with no
@@ -738,4 +740,51 @@
return false;
return true;
}
+
+ /**
+ * Return the name of the foreignkey constraint as defined in the database.
+ */
+ public String loadNameFromDB(DBDictionary dbdict, Connection conn) {
+ if( isLogical() || getTable() == null)
+ return null;
+ String retVal = null;
+ try{
+ Schema schema = getTable().getSchema();
+ ForeignKey[] fks = dbdict.getImportedKeys(conn.getMetaData(),
+ conn.getCatalog(), schema.getName(),
+ getTable().getName(), conn);
+ for ( int i=0; i< fks.length; i++) {
+ Table localtable = schema.getTable(fks[i].getTableName());
+ Table pkTable = schema.getTable(
+ fks[i].getPrimaryKeyTableName());
+ boolean addFK = false;
+ ForeignKey fkTemp = localtable.getForeignKey(
+ fks[i].getName());
+ if( fkTemp == null) {
+ addFK=true;
+ fkTemp = localtable.addForeignKey(
+ fks[i].getName());
+ fkTemp.setDeferred(fks[i].isDeferred());
+ fkTemp.setDeleteAction(fks[i].getDeleteAction());
+ }
+ if( ! fkTemp.containsColumn(
+ localtable.getColumn(fks[i].getColumnName())))
+ fkTemp.join(localtable.getColumn(fks[i].getColumnName()),
+ pkTable.getColumn(fks[i].getPrimaryKeyColumnName()));
+ if( equalsForeignKey(fkTemp))
+ {
+ if(addFK)
+ localtable.removeForeignKey(fkTemp);
+ retVal = fks[i].getName();
+ break;
+ }
+ if(addFK)
+ localtable.removeForeignKey(fkTemp);
+ }
+ } catch(Exception ex){
+ // TO DO -- It would be nice to log a warning here.
+ }
+ return retVal;
+ }
+
}
Modified: openjpa/branches/1.3.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/SchemaTool.java
URL: http://svn.apache.org/viewvc/openjpa/branches/1.3.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/SchemaTool.java?rev=781809&r1=781808&r2=781809&view=diff
==============================================================================
--- openjpa/branches/1.3.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/SchemaTool.java (original)
+++ openjpa/branches/1.3.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/SchemaTool.java Thu Jun 4 17:47:56 2009
@@ -423,7 +423,7 @@
}
Table[] tableArray = (Table[]) tables.toArray(new Table[tables.size()]);
String[] sql = _conf.getDBDictionaryInstance()
- .getDeleteTableContentsSQL(tableArray);
+ .getDeleteTableContentsSQL(tableArray,_ds.getConnection());
if (!executeSQL(sql))
_log.warn(_loc.get("delete-table-contents"));
}
@@ -1073,7 +1073,7 @@
*/
public boolean dropForeignKey(ForeignKey fk)
throws SQLException {
- return executeSQL(_dict.getDropForeignKeySQL(fk));
+ return executeSQL(_dict.getDropForeignKeySQL(fk,_ds.getConnection()));
}
/**
Modified: openjpa/branches/1.3.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java
URL: http://svn.apache.org/viewvc/openjpa/branches/1.3.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java?rev=781809&r1=781808&r2=781809&view=diff
==============================================================================
--- openjpa/branches/1.3.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java (original)
+++ openjpa/branches/1.3.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java Thu Jun 4 17:47:56 2009
@@ -2146,33 +2146,36 @@
* Databases with more optimal ways of deleting the contents of several
* tables should override this method.
*/
- public String[] getDeleteTableContentsSQL(Table[] tables) {
- Collection sql = new ArrayList();
+ public String[] getDeleteTableContentsSQL(Table[] tables,Connection conn) {
+ Collection<String> sql = new ArrayList<String>();
// collect and drop non-deferred physical restrict constraints, and
// collect the DELETE FROM statements
- Collection deleteSQL = new ArrayList(tables.length);
- Collection restrictConstraints = new LinkedHashSet();
+ Collection<String> deleteSQL = new ArrayList<String>(tables.length);
+ Collection<ForeignKey> restrictConstraints =
+ new LinkedHashSet<ForeignKey>();
for (int i = 0; i < tables.length; i++) {
ForeignKey[] fks = tables[i].getForeignKeys();
for (int j = 0; j < fks.length; j++) {
if (!fks[j].isLogical() && !fks[j].isDeferred()
&& fks[j].getDeleteAction() == ForeignKey.ACTION_RESTRICT)
restrictConstraints.add(fks[j]);
- String[] constraintSQL = getDropForeignKeySQL(fks[j]);
- sql.addAll(Arrays.asList(constraintSQL));
}
deleteSQL.add("DELETE FROM " + tables[i].getFullName());
}
+ for(ForeignKey fk : restrictConstraints) {
+ String[] constraintSQL = getDropForeignKeySQL(fk,conn);
+ sql.addAll(Arrays.asList(constraintSQL));
+ }
+
// add the delete statements after all the constraint mutations
sql.addAll(deleteSQL);
// add the deleted constraints back to the schema
- for (Iterator iter = restrictConstraints.iterator(); iter.hasNext(); ) {
- String[] constraintSQL =
- getAddForeignKeySQL((ForeignKey) iter.next());
+ for (ForeignKey fk : restrictConstraints) {
+ String[] constraintSQL = getAddForeignKeySQL(fk);
sql.addAll(Arrays.asList(constraintSQL));
}
@@ -3331,9 +3334,16 @@
* Returns <code>ALTER TABLE <table name> DROP CONSTRAINT
* <fk name></code> by default.
*/
- public String[] getDropForeignKeySQL(ForeignKey fk) {
- if (fk.getName() == null)
- return new String[0];
+ public String[] getDropForeignKeySQL(ForeignKey fk, Connection conn) {
+ if (fk.getName() == null) {
+ String[] retVal;
+ String fkName = fk.loadNameFromDB(this,conn);
+ retVal = (fkName == null) ? new String[0] :
+ new String[]{ "ALTER TABLE "
+ + getFullName(fk.getTable(), false)
+ + " DROP CONSTRAINT " + fkName };
+ return retVal;
+ }
return new String[]{ "ALTER TABLE "
+ getFullName(fk.getTable(), false)
+ " DROP CONSTRAINT " + fk.getName() };
Modified: openjpa/branches/1.3.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/MySQLDictionary.java
URL: http://svn.apache.org/viewvc/openjpa/branches/1.3.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/MySQLDictionary.java?rev=781809&r1=781808&r2=781809&view=diff
==============================================================================
--- openjpa/branches/1.3.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/MySQLDictionary.java (original)
+++ openjpa/branches/1.3.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/MySQLDictionary.java Thu Jun 4 17:47:56 2009
@@ -221,10 +221,10 @@
return super.getForeignKeyConstraintSQL(fk);
}
- public String[] getDeleteTableContentsSQL(Table[] tables) {
+ public String[] getDeleteTableContentsSQL(Table[] tables,Connection conn) {
// mysql >= 4 supports more-optimal delete syntax
if (!optimizeMultiTableDeletes)
- return super.getDeleteTableContentsSQL(tables);
+ return super.getDeleteTableContentsSQL(tables,conn);
else {
StringBuffer buf = new StringBuffer(tables.length * 8);
buf.append("DELETE FROM ");
Added: openjpa/branches/1.3.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/kernel/TestForeignKeyCountViolation.java
URL: http://svn.apache.org/viewvc/openjpa/branches/1.3.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/kernel/TestForeignKeyCountViolation.java?rev=781809&view=auto
==============================================================================
--- openjpa/branches/1.3.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/kernel/TestForeignKeyCountViolation.java (added)
+++ openjpa/branches/1.3.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/kernel/TestForeignKeyCountViolation.java Thu Jun 4 17:47:56 2009
@@ -0,0 +1,183 @@
+/*
+ * 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.jdbc.kernel;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.persistence.EntityManager;
+import javax.sql.DataSource;
+
+import org.apache.openjpa.jdbc.conf.JDBCConfiguration;
+import org.apache.openjpa.jdbc.schema.ForeignKey;
+import org.apache.openjpa.jdbc.schema.Table;
+import org.apache.openjpa.persistence.test.SingleEMFTestCase;
+
+/**
+ * Test that makes sure the number of foreign keys are same on a table after
+ * calling loadNameFromDB method of ForeignKey class.
+ *
+ */
+public class TestForeignKeyCountViolation extends SingleEMFTestCase {
+
+ private JDBCConfiguration _conf;
+
+ public void setUp() {
+ super.setUp(EntityF.class, EntityG.class);
+ Map props = new HashMap(System.getProperties());
+ _conf = (JDBCConfiguration) emf.getConfiguration();
+ }
+
+ public void testFKCount() throws SQLException {
+ EntityManager em = emf.createEntityManager();
+ Table tableG = getMapping(EntityG.class).getTable();
+ tableG.addForeignKey();
+ int b4Count = tableG.getForeignKeys().length;
+
+ EntityF f = new EntityF();
+ f.setId(1);
+
+ List<EntityG> listG = new ArrayList<EntityG>();
+ EntityG g1 = new EntityG();
+ g1.setId(1);
+ listG.add(g1);
+ g1.setEntityF(f);
+
+ EntityG g2 = new EntityG();
+ g2.setId(2);
+ listG.add(g2);
+ g2.setEntityF(f);
+
+ EntityG g3 = new EntityG();
+ g3.setId(3);
+ listG.add(g3);
+ g3.setEntityF(f);
+
+ EntityG g4 = new EntityG();
+ g4.setId(4);
+ listG.add(g4);
+ g4.setEntityF(f);
+
+ f.setListG(listG);
+ em.getTransaction().begin();
+ em.persist(f);
+ em.persist(g1);
+ em.persist(g2);
+ em.persist(g3);
+ em.persist(g4);
+ em.getTransaction().commit();
+
+ ForeignKey fks[] = tableG.getForeignKeys();
+
+ DataSource ds = (DataSource) _conf.getConnectionFactory();
+ Connection c = ds.getConnection(_conf.getConnectionUserName(),
+ _conf.getConnectionPassword());
+
+ for (int i=0; i< fks.length; i++) {
+ fks[i].loadNameFromDB(
+ _conf.getDBDictionaryInstance(), c);
+ }
+
+ assertEquals(b4Count, tableG.getForeignKeys().length);
+ em.close();
+ }
+
+ public void testFKNamefromDB()throws SQLException {
+
+ EntityManager em = emf.createEntityManager();
+ Table tableG = getMapping(EntityG.class).getTable();
+ tableG.addForeignKey();
+
+ EntityF f = new EntityF();
+ f.setId(1);
+
+ List<EntityG> listG = new ArrayList<EntityG>();
+ EntityG g1 = new EntityG();
+ g1.setId(1);
+ listG.add(g1);
+ g1.setEntityF(f);
+
+ EntityG g2 = new EntityG();
+ g2.setId(2);
+ listG.add(g2);
+ g2.setEntityF(f);
+
+ EntityG g3 = new EntityG();
+ g3.setId(3);
+ listG.add(g3);
+ g3.setEntityF(f);
+
+ EntityG g4 = new EntityG();
+ g4.setId(4);
+ listG.add(g4);
+ g4.setEntityF(f);
+
+ f.setListG(listG);
+ em.getTransaction().begin();
+ em.persist(f);
+ em.persist(g1);
+ em.persist(g2);
+ em.persist(g3);
+ em.persist(g4);
+ em.getTransaction().commit();
+
+ DataSource ds = (DataSource) _conf.getConnectionFactory();
+ Connection c = ds.getConnection(_conf.getConnectionUserName(),
+ _conf.getConnectionPassword());
+
+ ForeignKey fkfromDB[] = _conf.getDBDictionaryInstance().getImportedKeys(
+ c.getMetaData(), c.getCatalog() , tableG.getSchemaName()
+ , tableG.getName(), c);
+
+
+ ArrayList<String> fkListfromDB = new ArrayList<String>();
+ ArrayList<String> fkListfromTable = new ArrayList<String>();
+
+ for (int i=0; i< fkfromDB.length; i++) {
+ fkListfromDB.add(fkfromDB[i].getName());
+ }
+
+ ForeignKey fks[] = tableG.getForeignKeys();
+ for (int i=0; i< fks.length; i++) {
+ String fkNamefromDB =fks[i].loadNameFromDB(
+ _conf.getDBDictionaryInstance(), c);
+ if( fkNamefromDB != null)
+ fkListfromTable.add(fkNamefromDB);
+ }
+
+ assertEquals(fkListfromDB.toArray().length,
+ fkListfromTable.toArray().length);
+
+ Collections.sort(fkListfromTable);
+ Collections.sort(fkListfromDB);
+
+ for(int i=0; i< fkListfromDB.size(); i++)
+ {
+ assertEquals(fkListfromDB.get(i),fkListfromTable.get(i));
+ }
+
+ em.close();
+ }
+
+}
Propchange: openjpa/branches/1.3.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jdbc/kernel/TestForeignKeyCountViolation.java
------------------------------------------------------------------------------
svn:eol-style = native