Changeset 6941


Ignore:
Timestamp:
Aug 31, 2015, 11:32:24 AM (6 years ago)
Author:
Nicklas Nordborg
Message:

Fixes #1952: Converting to/from Fahrenheit yield incorrect result

Location:
trunk
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/data/units.xml

    r4669 r6941  
    220220      <alias>F</alias>
    221221      <factor>0.55555555555555555555555555555556</factor>
    222       <offset>241.15</offset>
     222      <offset>255.3722</offset>
    223223      <description>
    224224        In the Fahrenheit scale the water freezes as 32 degrees
  • trunk/src/core/net/sf/basedb/core/Install.java

    r6917 r6941  
    118118    method.
    119119  */
    120   public static final int NEW_SCHEMA_VERSION = Integer.valueOf(125).intValue();
     120  public static final int NEW_SCHEMA_VERSION = Integer.valueOf(126).intValue();
    121121 
    122122  public static synchronized int createTables(SchemaGenerator.Mode mode, ProgressReporter progress,
  • trunk/src/core/net/sf/basedb/core/Unit.java

    r6922 r6941  
    494494    if (isInDatabase())
    495495    {
    496       boolean sameFactor = Double.compare(data.getReferenceFactor(), factor) == 0;
    497       boolean sameOffset = Double.compare(data.getReferenceOffset(), offset) == 0;
    498       if (!sameFactor || !sameOffset)
     496      changeReferenceFactorAndOffset(getDbControl().getSessionControl(), getDbControl().getHibernateSession(),
     497        data, factor, offset);
     498    }
     499    else
     500    {
     501      data.setReferenceFactor(factor);
     502      data.setReferenceOffset(offset);
     503    }
     504  }
     505
     506 
     507  static void changeReferenceFactorAndOffset(SessionControl sc, org.hibernate.Session session, UnitData unit, double factor, double offset)
     508  {
     509    boolean sameFactor = Double.compare(unit.getReferenceFactor(), factor) == 0;
     510    boolean sameOffset = Double.compare(unit.getReferenceOffset(), offset) == 0;
     511    if (!sameFactor || !sameOffset)
     512    {
     513      /*
     514        Need to recalculate annotation values for existing annotations
     515        using this unit. There are two cases. Both are re-calculated
     516        with newValue = aFactor * oldValue + anOffset:
     517        1. Annotations with this unit with an annotation type of a different
     518           default unit.
     519           aFactor = newFactor / oldFactor
     520           anOffset = newOffset - oldOffset * aFactor
     521        2. Annotation with a different unit that has an annotation type with
     522           this unit as default unit.
     523           aFactor = oldFactor / newFactor
     524           anOffset = (oldOffset - newOffset) / newFactor
     525        We need to execute all SQL:s on all numerical value
     526        tables.
     527      */
     528      double case1Factor = factor / unit.getReferenceFactor();
     529      double case2Factor = unit.getReferenceFactor() / factor;
     530      double case1Offset = offset - unit.getReferenceOffset() * case1Factor;
     531      double case2Offset = (unit.getReferenceOffset() - offset) / factor;
     532     
     533      for (Type valueType : Type.values())
    499534      {
    500         /*
    501           Need to recalculate annotation values for existing annotations
    502           using this unit. There are two cases. Both are re-calculated
    503           with newValue = aFactor * oldValue + anOffset:
    504           1. Annotations with this unit with an annotation type of a different
    505              default unit.
    506              aFactor = newFactor / oldFactor
    507              anOffset = newOffset - oldOffset * aFactor
    508           2. Annotation with a different unit that has an annotation type with
    509              this unit as default unit.
    510              aFactor = oldFactor / newFactor
    511              anOffset = (oldOffset - newOffset) / newFactor
    512           We need to execute all SQL:s on all numerical value
    513           tables.
    514         */
    515         double case1Factor = factor / getReferenceFactor();
    516         double case2Factor = getReferenceFactor() / factor;
    517         double case1Offset = offset - getReferenceOffset() * case1Factor;
    518         double case2Offset = (getReferenceOffset() - offset) / factor;
    519        
    520         for (Type valueType : Type.values())
     535        if (!valueType.isNumerical())
    521536        {
    522           if (!valueType.isNumerical())
    523           {
    524             /* #### CONTINUE-STATEMENT #### */
    525             continue;
    526           }
    527          
    528           String tableName = valueType.getTableName();
    529           org.hibernate.Query query = HibernateUtil.getPredefinedSQLQuery(
    530             getDbControl().getHibernateSession(),
    531             "RECALCULATE_ANNOTATIONS_FOR_UNIT", tableName);
    532           /*
    533             UPDATE [{1}] SET [value] = [value] * :factor + :offset
    534             WHERE [id] IN
    535             (
    536               SELECT [a].[value_id]
    537               FROM [Annotations] [a]
    538               JOIN [AnnotationTypes] [at] ON [at].[id] = [a].[annotationtype_id]
    539               WHERE [at].[value_type] = :valueType
    540               AND
    541               (
    542                 (:case = 1 AND [a].[unit_id] = :unit AND [at].[default_unit_id] <> :unit)
    543                 OR
    544                 (:case = 2 AND [a].[unit_id] <> :unit AND [at].[default_unit_id] = :unit)
    545               )
    546             )
    547           */
    548           query.setInteger("unit", getId());
    549           query.setInteger("valueType", valueType.getValue());
    550          
    551           // Case 1
    552           query.setInteger("case", 1);
    553           query.setDouble("factor", case1Factor);
    554           query.setDouble("offset", case1Offset);
    555           HibernateUtil.executeUpdate(query);
    556          
    557           // Case 2
    558           query.setInteger("case", 2);
    559           query.setDouble("factor", case2Factor);
    560           query.setDouble("offset", case2Offset);
    561           HibernateUtil.executeUpdate(query);
     537          /* #### CONTINUE-STATEMENT #### */
     538          continue;
    562539        }
    563540       
    564         // We also need to invalidate the annotations in the snapshot cache
    565         org.hibernate.Query query = HibernateUtil.createQuery(getDbControl().getHibernateSession(),
    566           "SELECT a.annotationSet " +
    567           "FROM AnnotationData a " +
    568           "INNER JOIN a.annotationType at " +
    569           "WHERE (a.unit = :unit OR at.defaultUnit = :unit) AND a.unit <> at.defaultUnit");
    570         query.setEntity("unit", getData());
    571         List<AnnotationSetData> tmp = HibernateUtil.loadList(AnnotationSetData.class, query, getSessionControl());
    572         for (AnnotationSetData as : tmp)
    573         {
    574           SnapshotManager.removeSnapshot(as.getId());
    575         }
     541        String tableName = valueType.getTableName();
     542        org.hibernate.Query query = HibernateUtil.getPredefinedSQLQuery(session,
     543          "RECALCULATE_ANNOTATIONS_FOR_UNIT", tableName);
     544        /*
     545          UPDATE [{1}] SET [value] = [value] * :factor + :offset
     546          WHERE [id] IN
     547          (
     548            SELECT [a].[value_id]
     549            FROM [Annotations] [a]
     550            JOIN [AnnotationTypes] [at] ON [at].[id] = [a].[annotationtype_id]
     551            WHERE [at].[value_type] = :valueType
     552            AND
     553            (
     554              (:case = 1 AND [a].[unit_id] = :unit AND [at].[default_unit_id] <> :unit)
     555              OR
     556              (:case = 2 AND [a].[unit_id] <> :unit AND [at].[default_unit_id] = :unit)
     557            )
     558          )
     559        */
     560        query.setInteger("unit", unit.getId());
     561        query.setInteger("valueType", valueType.getValue());
     562       
     563        // Case 1
     564        query.setInteger("case", 1);
     565        query.setDouble("factor", case1Factor);
     566        query.setDouble("offset", case1Offset);
     567        HibernateUtil.executeUpdate(query);
     568       
     569        // Case 2
     570        query.setInteger("case", 2);
     571        query.setDouble("factor", case2Factor);
     572        query.setDouble("offset", case2Offset);
     573        HibernateUtil.executeUpdate(query);
    576574      }
    577     }
    578     data.setReferenceFactor(factor);
    579     data.setReferenceOffset(offset);
    580   }
    581 
     575     
     576      // We also need to invalidate the annotations in the snapshot cache
     577      org.hibernate.Query query = HibernateUtil.createQuery(session,
     578        "SELECT a.annotationSet " +
     579        "FROM AnnotationData a " +
     580        "INNER JOIN a.annotationType at " +
     581        "WHERE (a.unit = :unit OR at.defaultUnit = :unit) AND a.unit <> at.defaultUnit");
     582      query.setEntity("unit", unit);
     583      List<AnnotationSetData> tmp = HibernateUtil.loadList(AnnotationSetData.class, query, sc);
     584      for (AnnotationSetData as : tmp)
     585      {
     586        SnapshotManager.removeSnapshot(as.getId());
     587      }
     588    }
     589   
     590    unit.setReferenceFactor(factor);
     591    unit.setReferenceOffset(offset);
     592  }
     593 
    582594  /**
    583595    Convert a value from this unit to the reference unit.
  • trunk/src/core/net/sf/basedb/core/Update.java

    r6917 r6941  
    5555import net.sf.basedb.core.data.MeasuredBioMaterialData;
    5656import net.sf.basedb.core.data.PropertyFilterData;
     57import net.sf.basedb.core.data.QuantityData;
    5758import net.sf.basedb.core.data.RawBioAssayData;
    5859import net.sf.basedb.core.data.ReporterCloneTemplateData;
     
    6162import net.sf.basedb.core.data.SchemaVersionData;
    6263import net.sf.basedb.core.data.ShareableData;
     64import net.sf.basedb.core.data.UnitData;
    6365import net.sf.basedb.core.dbengine.DbEngine;
    6466import net.sf.basedb.core.dbengine.TableInfo;
     
    266268      inherited by the {@link RootRawBioAssayData} items. This means that existing
    267269      experiments will continue to have access to the experimental factors as before.
     270    </td>
     271  </tr>
     272  <tr>
     273    <td>126</td>
     274    <td>
     275      Fixes the conversion formula for Fahrenheit. Existing annotation values
     276      that are re-calculated to the corrent result.
    268277    </td>
    269278  </tr>
     
    435444        if (progress != null) progress.display((int)(progress_current), "--Updating schema version: " + schemaVersion + " -> 125...");
    436445        schemaVersion = updateToSchemaVersion125(session);
     446        progress_current += progress_step;
     447      }
     448     
     449      if (schemaVersion < 126)
     450      {
     451        if (progress != null) progress.display((int)(progress_current), "--Updating schema version: " + schemaVersion + " -> 126...");
     452        schemaVersion = updateToSchemaVersion126(session);
    437453        progress_current += progress_step;
    438454      }
     
    14531469
    14541470  /**
     1471    Fix the conversion formula for Fahrenheit.
     1472    @return The new schema version (=126)
     1473  */
     1474  private static int updateToSchemaVersion126(org.hibernate.Session session)
     1475    throws BaseException
     1476  {
     1477    final int schemaVersion = 126;
     1478    org.hibernate.Transaction tx = null;
     1479    try
     1480    {
     1481      tx = HibernateUtil.newTransaction(session);
     1482     
     1483      QuantityData temperature = HibernateUtil.loadData(session, QuantityData.class, SystemItems.getId(Quantity.TEMPERATURE));
     1484     
     1485      org.hibernate.Query query = HibernateUtil.getPredefinedQuery(session,
     1486          "GET_UNIT_WITH_NAME_FOR_QUANTITY");
     1487      query.setString("name", "Fahrenheit");
     1488      query.setEntity("quantity", temperature);
     1489      UnitData fahrenheit = HibernateUtil.loadData(UnitData.class, query);
     1490     
     1491      Unit.changeReferenceFactorAndOffset(null, session, fahrenheit, fahrenheit.getReferenceFactor(), 255.3722);
     1492     
     1493      // Update the schema version number
     1494      setSchemaVersion(session, schemaVersion);
     1495     
     1496      // Commit the changes
     1497      HibernateUtil.commit(tx);
     1498      log.info("updateToSchemaVersion126: OK");
     1499    }
     1500    catch (RuntimeException ex)
     1501    {
     1502      if (tx != null) HibernateUtil.rollback(tx);
     1503      log.error("updateToSchemaVersion126: FAILED", ex);
     1504      throw ex;
     1505    }
     1506    return schemaVersion;
     1507  }
     1508
     1509 
     1510  /**
    14551511    Vefify and update the remaining quantity of all biomaterials.
    14561512    @return The number of biomaterial fixed
Note: See TracChangeset for help on using the changeset viewer.