Project

General

Profile

Download (5.38 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.v25_30;
11

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

    
16
import org.apache.log4j.Logger;
17

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

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

    
39
	@SuppressWarnings("unused")
40
	private static final Logger logger = Logger.getLogger(SequenceTableCreator.class);
41

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

    
49
	/**
50
	 * @param stepName
51
	 */
52
	protected SequenceTableCreator(String stepName) {
53
		super(stepName);
54
	}
55

    
56
	public static SequenceTableCreator NewInstance(String stepName){
57
		return new SequenceTableCreator(stepName);
58
	}
59

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

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

    
75
	}
76

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

    
99
		datasource.executeUpdate(createTableQuery);
100

    
101
		return;
102
	}
103

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

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

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

    
122
		Object maxId = null;
123

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

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

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

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

    
151
				datasource.executeUpdate(query);
152
			}
153

    
154
		}
155
		return;
156
	}
157

    
158
}
(4-4/4)