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 &lt;table name&gt; DROP CONSTRAINT
      * &lt;fk name&gt;</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