Project

General

Profile

Download (5.6 KB) Statistics
| Branch: | Tag: | Revision:
1
/**
2
* Copyright (C) 2007 EDIT
3
* European Distributed Institute of Taxonomy
4
* http://www.e-taxonomy.eu
5
*
6
* The contents of this file are subject to the Mozilla Public License Version 1.1
7
* See LICENSE.TXT at the top of this package for the full license terms.
8
*/
9

    
10
package eu.etaxonomy.cdm.database.update.v24_30;
11

    
12
import java.sql.DatabaseMetaData;
13
import java.sql.ResultSet;
14
import java.sql.SQLException;
15
import java.util.List;
16

    
17
import org.apache.logging.log4j.LogManager;import org.apache.logging.log4j.Logger;
18

    
19
import eu.etaxonomy.cdm.common.monitor.IProgressMonitor;
20
import eu.etaxonomy.cdm.database.DatabaseTypeEnum;
21
import eu.etaxonomy.cdm.database.ICdmDataSource;
22
import eu.etaxonomy.cdm.database.update.CaseType;
23
import eu.etaxonomy.cdm.database.update.ISchemaUpdaterStep;
24
import eu.etaxonomy.cdm.database.update.SchemaUpdateResult;
25
import eu.etaxonomy.cdm.database.update.SchemaUpdaterStepBase;
26

    
27
/**
28
 * Creates the table needed by the {@link org.hibernate.id.enhanced.TableGenerator}
29
 * We expect the generator to be configured with <code>prefer_entity_table_as_segment_value</code>
30
 * set to <code>true</code> (the generator does not make lots of sense without this option)
31
 *
32
 * We also create sequences for all tables that are not empty. Otherwise we would run into
33
 * id conflicts, because the generator expects the database to be empty and creates sequences,
34
 * if they do not exist, as needed.
35
 *
36
 * @author n.hoffmann
37
 * @since Oct 27, 2010
38
 */
39
public class SequenceTableCreator extends SchemaUpdaterStepBase {
40

    
41
	@SuppressWarnings("unused")
42
	private static final Logger logger = LogManager.getLogger(SequenceTableCreator.class);
43

    
44
	// TODO These values are configurable in the enhanced.TableGenerator
45
	// can we retrieve these values from the identity generator directly?
46
	private static final String TABLE_NAME = "hibernate_sequences";
47
	private static final String SEGMENT_COLUMN_NAME = "sequence_name";
48
	private static final String VALUE_COLUMN_NAME = "next_val";
49
	private static final int INCREMENT_SIZE = 10;
50

    
51
	/**
52
	 * @param stepName
53
	 */
54
	protected SequenceTableCreator(List<ISchemaUpdaterStep> stepList, String stepName) {
55
		super(stepList, stepName);
56
	}
57

    
58
	public static SequenceTableCreator NewInstance(List<ISchemaUpdaterStep> stepList, String stepName){
59
		return new SequenceTableCreator(stepList, stepName);
60
	}
61

    
62
    @Override
63
    public void invoke(ICdmDataSource datasource, IProgressMonitor monitor,
64
            CaseType caseType, SchemaUpdateResult result) throws SQLException {
65

    
66
        try {
67
			createSequenceTable(datasource, monitor, caseType, result);
68
			makeEntriesForEntityTables(datasource, monitor, caseType, result);
69
			return;
70
		} catch (Exception e) {
71
		    String message =e.getMessage();
72
			monitor.warning(e.getMessage(), e);
73
            result.addException(e, message, getStepName() + ", SequenceTableCreator.invoke");
74
			return;
75
		}
76

    
77
	}
78

    
79
	/**
80
	 * @param monitor
81
	 * @param datasource
82
	 * @param caseType
83
	 * @param result2
84
	 * @return
85
	 * @throws SQLException
86
	 */
87
	private void createSequenceTable(ICdmDataSource datasource, IProgressMonitor monitor,
88
	        CaseType caseType, SchemaUpdateResult result2) throws SQLException {
89
		String createTableQuery = null;
90
		// TODO add create table statements for other supported databases
91
		if(datasource.getDatabaseType().equals(DatabaseTypeEnum.MySQL)){
92
			createTableQuery = "CREATE TABLE `" + TABLE_NAME + "` (" +
93
				"  `" + SEGMENT_COLUMN_NAME + "` varchar(255) NOT NULL," +
94
				"  `" + VALUE_COLUMN_NAME + "` bigint(20) default NULL," +
95
				"  PRIMARY KEY  (`" + SEGMENT_COLUMN_NAME + "`)" +
96
				");";
97
		}else{
98
			throw new RuntimeException("Database type " + datasource.getDatabaseType() + " is currently not supported by the updater");
99
		}
100

    
101
		datasource.executeUpdate(createTableQuery);
102

    
103
		return;
104
	}
105

    
106
	/**
107
	 * @param monitor
108
	 * @param datasource
109
	 * @param caseType
110
	 * @param result
111
	 * @return
112
	 * @throws SQLException
113
	 */
114
	private void makeEntriesForEntityTables(ICdmDataSource datasource, IProgressMonitor monitor,
115
	        CaseType caseType, SchemaUpdateResult result) throws SQLException {
116

    
117
		DatabaseMetaData metaData = datasource.getMetaData();
118
		ResultSet resultSet = metaData.getTables(datasource.getDatabase(), null, null, null);
119

    
120
		String maxIdQuery = "SELECT MAX(ID) FROM @tableName";
121
		String insertQuery = "INSERT INTO " + TABLE_NAME + " ( " + SEGMENT_COLUMN_NAME + ", " + VALUE_COLUMN_NAME + ")" +
122
				" VALUES ('@tableName', (@maxId + " + INCREMENT_SIZE + "))";
123

    
124
		Object maxId = null;
125

    
126
		while(resultSet.next()){
127
			// through debugging we found out that the table name is in column 3.
128
			// TODO improve this if you know that this will not always be the case for all database types
129
			// and/or if you know of a good way to do it in more generic way
130
			String tableName = resultSet.getString(3);
131
			// this way we simply filter out all relation tables, could have done this with a tableNamePattern passed to getTables(...)
132
			// but this was faster.
133
			if(tableName.contains("_")){
134
				continue;
135
			}
136

    
137
			try{
138
				String query = maxIdQuery.replace("@tableName", tableName);
139
				maxId = datasource.getSingleValue(query);
140
			}catch(SQLException e){
141
				// table does not have a column id, so it is not an entity table
142
				maxId = null;
143
			}
144

    
145
			// empty tables will not set the maxId.
146
			// Empty tables will also not need to be updated, because the identity generator creates sequences for tables it did not have before
147
			if(maxId != null){
148
				monitor.subTask("Inserting sequence for table: " + tableName + " with maxId: " + maxId);
149

    
150
				String query = insertQuery.replace("@tableName", tableName);
151
				query = query.replace("@maxId", maxId.toString());
152

    
153
				datasource.executeUpdate(query);
154
			}
155

    
156
		}
157
		return;
158
	}
159

    
160
}
(5-5/5)