3 * Copyright (C) 2009 EDIT
4 * European Distributed Institute of Taxonomy
5 * http://www.e-taxonomy.eu
7 * The contents of this file are subject to the Mozilla Public License Version 1.1
8 * See LICENSE.TXT at the top of this package for the full license terms.
10 package eu
.etaxonomy
.cdm
.database
.update
;
12 import java
.sql
.ResultSet
;
14 import org
.apache
.log4j
.Logger
;
16 import eu
.etaxonomy
.cdm
.common
.monitor
.DefaultProgressMonitor
;
17 import eu
.etaxonomy
.cdm
.common
.monitor
.IProgressMonitor
;
18 import eu
.etaxonomy
.cdm
.database
.CdmDataSource
;
19 import eu
.etaxonomy
.cdm
.database
.ICdmDataSource
;
20 import eu
.etaxonomy
.cdm
.database
.update
.v31_33
.SchemaUpdater_31_33
;
21 import eu
.etaxonomy
.cdm
.database
.update
.v31_33
.SchemaUpdater_33_331
;
22 import eu
.etaxonomy
.cdm
.database
.update
.v31_33
.TermUpdater_31_33
;
29 public class CdmUpdater
{
30 private static final Logger logger
= Logger
.getLogger(CdmUpdater
.class);
32 public static CdmUpdater
NewInstance(){
33 return new CdmUpdater();
38 * @param monitor may be <code>null</code>
41 public boolean updateToCurrentVersion(ICdmDataSource datasource
, IProgressMonitor monitor
){
42 boolean result
= true;
44 monitor
= DefaultProgressMonitor
.NewInstance();
46 CaseType caseType
= CaseType
.caseTypeOfDatasource(datasource
);
48 ISchemaUpdater currentSchemaUpdater
= getCurrentSchemaUpdater();
49 // TODO do we really always update the terms??
50 ITermUpdater currentTermUpdater
= getCurrentTermUpdater();
52 int steps
= currentSchemaUpdater
.countSteps(datasource
, monitor
, caseType
);
53 steps
+= currentTermUpdater
.countSteps(datasource
, monitor
, caseType
);
54 steps
++; //for hibernate_sequences update
56 String taskName
= "Update to schema version " + currentSchemaUpdater
.getTargetVersion() + " and to term version " + currentTermUpdater
.getTargetVersion(); //+ currentSchemaUpdater.getVersion();
57 monitor
.beginTask(taskName
, steps
);
60 datasource
.startTransaction();
61 result
&= currentSchemaUpdater
.invoke(datasource
, monitor
, caseType
);
63 result
&= currentTermUpdater
.invoke(datasource
, monitor
, caseType
);
64 updateHibernateSequence(datasource
, monitor
, caseType
);
67 datasource
.rollback();
69 datasource
.commitTransaction();
72 } catch (Exception e
) {
74 monitor
.warning("Stopped schema updater");
76 String message
= "Update finished " + (result ?
"successfully" : "with ERRORS");
77 monitor
.subTask(message
);
79 monitor
.warning(message
);
80 monitor
.setCanceled(true);
93 * Updating terms often inserts new terms, vocabularies and representations.
94 * Therefore the counter in hibernate_sequences must be increased.
95 * We do this once at the end of term updating.
97 * @return true if update was successful, false otherwise
99 private boolean updateHibernateSequence(ICdmDataSource datasource
, IProgressMonitor monitor
, CaseType caseType
) {
100 boolean result
= true;
101 monitor
.subTask("Update hibernate sequences");
103 String sql
= "SELECT * FROM hibernate_sequences ";
104 ResultSet rs
= datasource
.executeQuery(sql
);
106 String table
= rs
.getString("sequence_name");
107 Integer val
= rs
.getInt("next_val");
108 result
&= updateSingleValue(datasource
,monitor
, table
, val
, caseType
);
110 } catch (Exception e
) {
111 String message
= "Exception occurred when trying to update hibernate_sequences table: " + e
.getMessage();
112 monitor
.warning(message
, e
);
113 logger
.error(message
);
130 private boolean updateSingleValue(ICdmDataSource datasource
, IProgressMonitor monitor
, String table
, Integer oldVal
, CaseType caseType
){
131 if (table
.equals("default")){ //found in flora central africa test database
137 String sql
= " SELECT max(id) FROM %s ";
138 newVal
= (Integer
)datasource
.getSingleValue(String
.format(sql
, caseType
.transformTo(table
)));
139 } catch (Exception e
) {
140 String message
= "Could not retrieve max value for table '%s'. Will not update hibernate_sequence for this table. " +
141 "Usually this will not cause problems, however, if new data has been added to " +
142 "this table by the update script one may encounter 'unique identifier' " +
143 "exceptions when trying to add further data.";
144 monitor
.warning(String
.format(message
,table
), e
);
150 //This is how {@link PooledOptimizer#generate(org.hibernate.id.enhanced.AccessCallback)} works
151 //it substracts the increment size from the value in hibernate_sequences to get the initial value.
152 //Haven't checked why.
153 //For the correct increment size see eu.etaxonomy.cdm.model.common.package-info.java
154 int incrementSize
= 10;
155 newVal
= newVal
+ incrementSize
;
156 if (newVal
!= null && newVal
>= oldVal
){
157 String sql
= " UPDATE hibernate_sequences " +
158 " SET next_val = %d " +
159 " WHERE sequence_name = '%s' ";
160 datasource
.executeUpdate(String
.format(sql
, newVal
+ 1 , table
) );
164 } catch (Exception e
) {
165 String message
= "Exception occurred when trying to read or update hibernate_sequences table for value " + table
+ ": " + e
.getMessage();
166 monitor
.warning(message
, e
);
167 logger
.error(message
);
174 private ITermUpdater
getCurrentTermUpdater() {
175 return TermUpdater_31_33
.NewInstance();
179 * Returns the current CDM updater
182 private ISchemaUpdater
getCurrentSchemaUpdater() {
183 return SchemaUpdater_33_331
.NewInstance();
189 public static void main(String
[] args
) {
190 // logger.warn("main method not yet fully implemented (only works with mysql!!!)");
191 // if(args.length < 2){
192 // logger.error("Arguments missing: server database [username [password]]");
194 //TODO better implementation
195 CdmUpdater myUpdater
= new CdmUpdater();
196 String server
= args
[0];
197 String database
= args
[1];
198 String username
= args
.length
> 2 ? args
[2] : null;
199 String password
= args
.length
> 3 ? args
[3] : null;
201 if( args
.length
> 4){
203 port
= Integer
.parseInt(args
[4]);
204 } catch (Exception e
) {
209 ICdmDataSource dataSource
= CdmDataSource
.NewMySqlInstance(server
, database
, 3306, username
, password
, null);
210 boolean success
= myUpdater
.updateToCurrentVersion(dataSource
, null);
211 System
.out
.println("DONE " + (success ?
"successfully" : "with ERRORS"));