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
.TermUpdater_31_33
;
28 public class CdmUpdater
{
29 private static final Logger logger
= Logger
.getLogger(CdmUpdater
.class);
31 public static CdmUpdater
NewInstance(){
32 return new CdmUpdater();
37 * @param monitor may be <code>null</code>
40 public boolean updateToCurrentVersion(ICdmDataSource datasource
, IProgressMonitor monitor
){
41 boolean result
= true;
43 monitor
= DefaultProgressMonitor
.NewInstance();
46 ISchemaUpdater currentSchemaUpdater
= getCurrentSchemaUpdater();
47 // TODO do we really always update the terms??
48 ITermUpdater currentTermUpdater
= getCurrentTermUpdater();
50 int steps
= currentSchemaUpdater
.countSteps(datasource
, monitor
);
51 steps
+= currentTermUpdater
.countSteps(datasource
, monitor
);
52 steps
++; //for hibernate_sequences update
54 String taskName
= "Update to schema version " + currentSchemaUpdater
.getTargetVersion() + " and to term version " + currentTermUpdater
.getTargetVersion(); //+ currentSchemaUpdater.getVersion();
55 monitor
.beginTask(taskName
, steps
);
58 datasource
.startTransaction();
59 result
&= currentSchemaUpdater
.invoke(datasource
, monitor
);
61 result
&= currentTermUpdater
.invoke(datasource
, monitor
);
62 updateHibernateSequence(datasource
, monitor
);
65 datasource
.rollback();
67 datasource
.commitTransaction();
70 } catch (Exception e
) {
72 monitor
.warning("Stopped schema updater");
74 String message
= "Update finished " + (result ?
"successfully" : "with ERRORS");
75 monitor
.subTask(message
);
77 monitor
.warning(message
);
78 monitor
.setCanceled(true);
90 * Updating terms often inserts new terms, vocabularies and representations.
91 * Therefore the counter in hibernate_sequences must be increased.
92 * We do this once at the end of term updating.
93 * @return true if update was successful, false otherwise
95 private boolean updateHibernateSequence(ICdmDataSource datasource
, IProgressMonitor monitor
) {
96 boolean result
= true;
97 monitor
.subTask("Update hibernate sequences");
99 String sql
= "SELECT * FROM hibernate_sequences ";
100 ResultSet rs
= datasource
.executeQuery(sql
);
102 String table
= rs
.getString("sequence_name");
103 Integer val
= rs
.getInt("next_val");
104 result
&= updateSingleValue(datasource
,monitor
, table
, val
);
106 } catch (Exception e
) {
107 String message
= "Exception occurred when trying to update hibernate_sequences table: " + e
.getMessage();
108 monitor
.warning(message
, e
);
109 logger
.error(message
);
125 private boolean updateSingleValue(ICdmDataSource datasource
, IProgressMonitor monitor
, String table
, Integer oldVal
){
126 if (table
.equals("default")){ //found in flora central africa test database
132 String sql
= " SELECT max(id) FROM %s ";
133 newVal
= (Integer
)datasource
.getSingleValue(String
.format(sql
, table
));
134 } catch (Exception e
) {
135 String message
= "Could not retrieve max value for table '%s'. Will not update hibernate_sequence for this table. " +
136 "Usually this will not cause problems, however, if new data has been added to " +
137 "this table by the update script one may encounter 'unique identifier' " +
138 "exceptions when trying to add further data.";
139 monitor
.warning(String
.format(message
,table
), e
);
145 //This is how {@link PooledOptimizer#generate(org.hibernate.id.enhanced.AccessCallback)} works
146 //it substracts the increment size from the value in hibernate_sequences to get the initial value.
147 //Haven't checked why.
148 //For the correct increment size see eu.etaxonomy.cdm.model.common.package-info.java
149 int incrementSize
= 10;
150 newVal
= newVal
+ incrementSize
;
151 if (newVal
!= null && newVal
>= oldVal
){
152 String sql
= " UPDATE hibernate_sequences " +
153 " SET next_val = %d " +
154 " WHERE sequence_name = '%s' ";
155 datasource
.executeUpdate(String
.format(sql
, newVal
+ 1 , table
) );
159 } catch (Exception e
) {
160 String message
= "Exception occurred when trying to read or update hibernate_sequences table for value " + table
+ ": " + e
.getMessage();
161 monitor
.warning(message
, e
);
162 logger
.error(message
);
169 private ITermUpdater
getCurrentTermUpdater() {
170 return TermUpdater_31_33
.NewInstance();
174 * Returns the current CDM updater
177 private ISchemaUpdater
getCurrentSchemaUpdater() {
178 return SchemaUpdater_31_33
.NewInstance();
184 public static void main(String
[] args
) {
185 logger
.warn("main method not yet fully implemented (only works with mysql!!!)");
187 logger
.error("Arguments missing: server database [username [password]]");
189 //TODO better implementation
190 CdmUpdater myUpdater
= new CdmUpdater();
191 String server
= args
[0];
192 String database
= args
[1];
193 String username
= args
.length
> 2 ? args
[2] : null;
194 String password
= args
.length
> 3 ? args
[3] : null;
196 ICdmDataSource dataSource
= CdmDataSource
.NewMySqlInstance(server
, database
, username
, password
);
197 boolean success
= myUpdater
.updateToCurrentVersion(dataSource
, null);
198 System
.out
.println("DONE " + (success ?
"successfully" : "with ERRORS"));