Changeset 7035


Ignore:
Timestamp:
Dec 4, 2015, 9:52:50 AM (6 years ago)
Author:
Nicklas Nordborg
Message:

References #1966: The user that delete an item should see the item in the trashcan

The database schema update need to happen in a different order. The installation will for example create new item subtypes and plug-ins for Kits. This will fail if the 'removed' column exists in the tables since it is defined as 'not null' and the new mapping doesn't include this column. The update that transfers the owner/root to the 'removed_by' column and then drops the 'removed' column must be done in the adjustExistingItems() method so that the database is good to go for inserting new items after that.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/core/net/sf/basedb/core/Update.java

    r7015 r7035  
    300300      Existing items that has been flagged for removal are updated by setting the <code>removedBy</code>
    301301      property to either the owner of the item or, if the item doesn't have an owner, to the root
    302       user (update 129). In a second step (update 130) the <code>removed</code> columns are dropped
    303       from all tables.
     302      user. In a second step the <code>removed</code> columns are dropped from all tables.
     303      Note that this must be done in {@link #adjustExistingItems(ProgressReporter, int, String, String)}
     304      since otherwise the installation will try to create new items in table that still has the
     305      'removed' column but it will not accept 'null' values and the installation will fail.
    304306    </td>
    305307  </tr>
     
    481483      }
    482484     
    483       if (schemaVersion < 128)
    484       {
    485         if (progress != null) progress.display((int)(progress_current), "--Updating schema version: " + schemaVersion + " -> 128...");
    486         // Schemaversion 127-128 only updates the version number
    487         schemaVersion = setSchemaVersionInTransaction(session, 128);
    488         progress_current += 2 * progress_step;
    489       }
    490      
    491485      if (schemaVersion < 130)
    492486      {
    493487        if (progress != null) progress.display((int)(progress_current), "--Updating schema version: " + schemaVersion + " -> 130...");
    494         schemaVersion = updateToSchemaVersion130(session, schemaVersion);
    495         progress_current += 2 * progress_step;       
    496       }
    497    
     488        // Schemaversion 127-130 only updates the version number
     489        schemaVersion = setSchemaVersionInTransaction(session, 130);
     490        progress_current += 4 * progress_step;
     491      }
     492     
    498493      sc.logout();
    499494      if (progress != null) progress.display(100, "Database updated successfully.");
     
    693688      Application.start(false, false, false);
    694689
     690      if (progress != null) progress.display(50, "Checking existing items...");
    695691      // Test root user account
    696692      SessionControl sc = Application.newSessionControl(null, null, null);
     
    704700      session = HibernateUtil.newSession();
    705701      tx = HibernateUtil.newTransaction(session);
     702     
     703      // List of schema changes that need to be executed
     704      // after the main transaction has ended.
     705      List<SchemaChange> schemaChanges = new ArrayList<SchemaChange>();
    706706     
    707707      if (schemaVersion < 115)
     
    747747      }
    748748     
     749      if (schemaVersion < 130)
     750      {
     751        // Load tables names and set a flag if it has an 'owner' column or not
     752        Map<String, Boolean> tables = new LinkedHashMap<String, Boolean>();
     753        for (Item item : Metadata.getRemovableItems())
     754        {
     755          String tableName = HibernateUtil.getClassMapping(item.getDataClass().getName()).getRootTable().getName();
     756          // Multiple items may be mapped to the same table (eg. BioMaterials) -- Only add each table once
     757          if (!tables.containsKey(tableName))
     758          {
     759            // Check if 'removed' column exists
     760            // It is not present in new tables (eg. Kits)
     761            TableInfo tblInfo = getTableInfo(session, tableName);
     762            if (tblInfo.findColumn("removed") != null)
     763            {
     764              tables.put(tableName, tblInfo.findColumn("owner") != null);
     765            }
     766          }
     767        }
     768       
     769        // UPDATE all tables and set 'removed_by' to 'owner' or 'root'
     770        int rootId = SystemItems.getId(User.ROOT);
     771        for (Map.Entry<String, Boolean> entry : tables.entrySet())
     772        {
     773          String tableName = entry.getKey();
     774          org.hibernate.Query query;
     775          if (entry.getValue())
     776          {
     777            String sql = "UPDATE [" + tableName + "] SET [removed_by]=[owner], [removed]=false WHERE [removed]=true";
     778            query = HibernateUtil.createSqlQuery(session, sql);
     779          }
     780          else
     781          {
     782            String sql = "UPDATE [" + tableName + "] SET [removed_by]=:root, [removed]=false WHERE [removed]=true";
     783            query = HibernateUtil.createSqlQuery(session, sql);
     784            query.setInteger("root", rootId);
     785          }
     786          int updated = query.executeUpdate();
     787          // Schedule removal of the 'removed' column
     788          schemaChanges.add(new DropColumnChange(tableName, "removed"));
     789        }
     790      }
     791     
    749792      //  Commit the changes
    750793      HibernateUtil.commit(tx);
    751       log.info("adjustExistingItems: OK");         
    752     }
    753     catch (BaseException ex)
     794     
     795      for (SchemaChange change : schemaChanges)
     796      {
     797        change.performChange(session);
     798      }
     799      log.info("adjustExistingItems: OK"); 
     800     
     801    }
     802    catch (BaseException | SQLException ex)
    754803    {
    755804      if (tx != null) HibernateUtil.rollback(tx);
    756805      if (progress != null) progress.display(100, "The adjustment of the existing items failed: " + ex.getMessage()+"\n");
    757806      log.info("adjustExistingItems: FAILED");
    758       throw ex;
     807      throw ex instanceof SQLException ? new BaseException((SQLException)ex) : (BaseException)ex;
    759808    }
    760809    finally
     
    15491598  }
    15501599
    1551  
    1552   /**
    1553     Set the 'removed_by' column to owner of item if 'removed=true'
    1554     @return The new schema version (=130)
    1555   */
    1556   private static int updateToSchemaVersion130(org.hibernate.Session session, int currentSchemaVersion)
    1557     throws BaseException
    1558   {
    1559     final int schemaVersion = 130;
    1560     try
    1561     {
    1562       // Load tables names and set a flag if it has an 'owner' column or not
    1563       Map<String, Boolean> tables = new LinkedHashMap<String, Boolean>();
    1564       for (Item item : Metadata.getRemovableItems())
    1565       {
    1566         String tableName = HibernateUtil.getClassMapping(item.getDataClass().getName()).getRootTable().getName();
    1567         // Multiple items may be mapped to the same table (eg. BioMaterials) -- Only add each table once
    1568         if (!tables.containsKey(tableName))
    1569         {
    1570           // Check if 'removed' column exists
    1571           // It is not present in new tables (eg. Kits)
    1572           TableInfo tblInfo = getTableInfo(session, tableName);
    1573           if (tblInfo.findColumn("removed") != null)
    1574           {
    1575             tables.put(tableName, tblInfo.findColumn("owner") != null);
    1576           }
    1577         }
    1578       }
    1579      
    1580       if (currentSchemaVersion < 129)
    1581       {
    1582         // First step is to copy existing information to the new columns
    1583         org.hibernate.Transaction tx = null;
    1584         try
    1585         {
    1586           tx = HibernateUtil.newTransaction(session);
    1587          
    1588           int rootId = SystemItems.getId(User.ROOT);
    1589           for (Map.Entry<String, Boolean> entry : tables.entrySet())
    1590           {
    1591             String tableName = entry.getKey();
    1592            
    1593             org.hibernate.Query query;
    1594             if (entry.getValue())
    1595             {
    1596               String sql = "UPDATE [" + tableName + "] SET [removed_by]=[owner] WHERE [removed]=true";
    1597               query = HibernateUtil.createSqlQuery(session, sql);
    1598             }
    1599             else
    1600             {
    1601               String sql = "UPDATE [" + tableName + "] SET [removed_by]=:root WHERE [removed]=true";
    1602               query = HibernateUtil.createSqlQuery(session, sql);
    1603               query.setInteger("root", rootId);
    1604             }
    1605             int updated = query.executeUpdate();
    1606           }
    1607          
    1608           setSchemaVersion(session, 129);
    1609  
    1610           // Commit the changes
    1611           HibernateUtil.commit(tx);
    1612         }
    1613         finally
    1614         {
    1615           if (tx != null && !tx.wasCommitted()) HibernateUtil.rollback(tx);
    1616         }
    1617       }
    1618      
    1619       // Second step is to drop the old columns that are no longer used in BASE 3.7
    1620       for (String tableName : tables.keySet())
    1621       {
    1622         dropColumn(session, tableName, "removed", null);
    1623       }
    1624        
    1625       // Update the schema version number
    1626       setSchemaVersionInTransaction(session, schemaVersion);
    1627  
    1628       log.info("updateToSchemaVersion130: OK");
    1629     }
    1630     catch (SQLException ex)
    1631     {
    1632       log.error("updateToSchemaVersion130: FAILED", ex);
    1633       throw new BaseException(ex);
    1634     }
    1635     catch (RuntimeException ex)
    1636     {
    1637       log.error("updateToSchemaVersion130: FAILED", ex);
    1638       throw ex;
    1639     }   
    1640    
    1641     return schemaVersion;
    1642   }
    1643 
    1644  
    16451600  /**
    16461601    Vefify and update the remaining quantity of all biomaterials.
     
    20582013  }
    20592014
    2060  
    2061 
     2015  /**
     2016    Action that need to make some change to the database schem after the
     2017    main transaction in {@link Update#adjustExistingItems(ProgressReporter, int, String, String)}
     2018    has finished.
     2019    @since 3.7
     2020  */
     2021  static abstract class SchemaChange
     2022  {
     2023    abstract void performChange(org.hibernate.Session session)
     2024      throws SQLException;
     2025  }
     2026
     2027 
     2028  /**
     2029    Action that drops a column in a table.
     2030    @since 3.7
     2031  */
     2032  static class DropColumnChange
     2033    extends SchemaChange
     2034  {
     2035
     2036    private final String tableName;
     2037    private final String columnName;
     2038   
     2039    public DropColumnChange(String tableName, String columnName)
     2040    {
     2041      this.tableName = tableName;
     2042      this.columnName = columnName;
     2043    }
     2044   
     2045    @Override
     2046    void performChange(org.hibernate.Session session)
     2047      throws SQLException
     2048    {
     2049      dropColumn(session, tableName, "removed", null);     
     2050    }
     2051   
     2052  }
     2053 
    20622054}
Note: See TracChangeset for help on using the changeset viewer.