Project

General

Profile

Download (8.39 KB) Statistics
| Branch: | Tag: | Revision:
1
// $Id$
2
/**
3
* Copyright (C) 2009 EDIT
4
* European Distributed Institute of Taxonomy 
5
* http://www.e-taxonomy.eu
6
* 
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.
9
*/
10
package eu.etaxonomy.cdm.database.update;
11

    
12
import java.sql.Types;
13

    
14
import org.apache.log4j.Logger;
15

    
16
import eu.etaxonomy.cdm.common.monitor.IProgressMonitor;
17
import eu.etaxonomy.cdm.database.DatabaseTypeEnum;
18
import eu.etaxonomy.cdm.database.ICdmDataSource;
19

    
20
/**
21
 * @author a.mueller
22
 * @date 16.09.2010
23
 *
24
 */
25
public class ColumnAdder extends AuditedSchemaUpdaterStepBase<ColumnAdder> implements ISchemaUpdaterStep {
26
	private static final Logger logger = Logger.getLogger(ColumnAdder.class);
27
	
28
	private String newColumnName;
29
	private String columnType;
30
	private Object defaultValue;
31
	private boolean isNotNull;
32

    
33
	private String referencedTable;
34

    
35
	public static final ColumnAdder NewIntegerInstance(String stepName, String tableName, String newColumnName, boolean includeAudTable, boolean notNull, String referencedTable){
36
		return new ColumnAdder(stepName, tableName, newColumnName, "int", includeAudTable, null, notNull, referencedTable);
37
	}
38
	
39
	public static final ColumnAdder NewIntegerInstance(String stepName, String tableName, String newColumnName, boolean includeAudTable, Integer defaultValue, boolean notNull){
40
		return new ColumnAdder(stepName, tableName, newColumnName, "int", includeAudTable, defaultValue, notNull, null);
41
	}
42
	
43
	public static final ColumnAdder NewTinyIntegerInstance(String stepName, String tableName, String newColumnName, boolean includeAudTable, boolean notNull){
44
		return new ColumnAdder(stepName, tableName, newColumnName, "tinyint", includeAudTable, null, notNull, null);
45
	}
46
	
47
	public static final ColumnAdder NewDoubleInstance(String stepName, String tableName, String newColumnName, boolean includeAudTable, boolean notNull){
48
		return new ColumnAdder(stepName, tableName, newColumnName, "double", includeAudTable, null, notNull, null);
49
	}
50

    
51
	public static final ColumnAdder NewBooleanInstance(String stepName, String tableName, String newColumnName, boolean includeAudTable, Boolean defaultValue){
52
		return new ColumnAdder(stepName, tableName, newColumnName, "bit", includeAudTable, defaultValue, false, null);
53
	}
54
	
55
	public static final ColumnAdder NewStringInstance(String stepName, String tableName, String newColumnName, boolean includeAudTable){
56
		return new ColumnAdder(stepName, tableName, newColumnName, "nvarchar(255)", includeAudTable, null, false, null);
57
	}
58

    
59
	public static final ColumnAdder NewStringInstance(String stepName, String tableName, String newColumnName, int length, boolean includeAudTable){
60
		return new ColumnAdder(stepName, tableName, newColumnName, "nvarchar("+length+")", includeAudTable, null, false, null);
61
	}
62

    
63
	public static final ColumnAdder NewClobInstance(String stepName, String tableName, String newColumnName, boolean includeAudTable){
64
		return new ColumnAdder(stepName, tableName, newColumnName, "clob", includeAudTable, null, false, null);
65
	}
66
	
67
	public static final ColumnAdder NewDateTimeInstance(String stepName, String tableName, String newColumnName, boolean includeAudTable){
68
		return new ColumnAdder(stepName, tableName, newColumnName, "datetime", includeAudTable, null, false, null);
69
	}
70
	
71
	protected ColumnAdder(String stepName, String tableName, String newColumnName, String columnType, boolean includeAudTable, Object defaultValue, boolean notNull, String referencedTable) {
72
		super(stepName);
73
		this.tableName = tableName;
74
		this.newColumnName = newColumnName;
75
		this.columnType = columnType;
76
		this.includeAudTable = includeAudTable;
77
		this.defaultValue = defaultValue;
78
		this.isNotNull = notNull;
79
		this.referencedTable = referencedTable;
80
	}
81

    
82
	public ColumnAdder setNotNull(boolean isNotNull) {
83
		this.isNotNull = isNotNull;
84
		return this;
85
	}
86

    
87
	@Override
88
	protected boolean invokeOnTable(String tableName, ICdmDataSource datasource, IProgressMonitor monitor, CaseType caseType) {
89
		boolean result = true;
90
		try {
91
			String updateQuery = getUpdateQueryString(tableName, datasource, monitor);
92
			datasource.executeUpdate(updateQuery);
93
			
94
			if (defaultValue instanceof Boolean){
95
				updateQuery = "UPDATE @tableName SET @columnName = " + (defaultValue == null ? "null" : getBoolean((Boolean) defaultValue, datasource));
96
				updateQuery = updateQuery.replace("@tableName", tableName);
97
				updateQuery = updateQuery.replace("@columnName", newColumnName);
98
				datasource.executeUpdate(updateQuery);
99
			}
100
			if (referencedTable != null){
101
				result &= TableCreator.makeForeignKey(tableName, datasource, monitor, newColumnName, referencedTable, caseType);
102
			}
103
			
104
			return result;
105
		} catch ( Exception e) {
106
			monitor.warning(e.getMessage(), e);
107
			logger.error(e);
108
			return false;
109
		}
110
	}
111

    
112
	/**
113
	 * Returns the update query string. tableName must already be cased correctly. See {@link CaseType}. 
114
	 * @param tableName correctly cased table name
115
	 * @param datasource data source
116
	 * @param monitor monitor
117
	 * @return the query string 
118
	 * @throws DatabaseTypeNotSupportedException
119
	 */
120
	public String getUpdateQueryString(String tableName, ICdmDataSource datasource, IProgressMonitor monitor) throws DatabaseTypeNotSupportedException {
121
		String updateQuery;
122
		DatabaseTypeEnum type = datasource.getDatabaseType();
123
		String databaseColumnType = getDatabaseColumnType(datasource, this.columnType);
124

    
125
		if (type.equals(DatabaseTypeEnum.SqlServer2005)){
126
			//MySQL allows both syntaxes
127
			updateQuery = "ALTER TABLE @tableName ADD @columnName @columnType";
128
		}else if (type.equals(DatabaseTypeEnum.H2) || type.equals(DatabaseTypeEnum.PostgreSQL) || type.equals(DatabaseTypeEnum.MySQL)){
129
			updateQuery = "ALTER TABLE @tableName @addSeparator @columnName @columnType";
130
		}else{
131
			updateQuery = null;
132
			String warning = "Update step '" + this.getStepName() + "' is not supported by " + type.getName();
133
			monitor.warning(warning);
134
			throw new DatabaseTypeNotSupportedException(warning);
135
		}
136
		if (isNotNull){
137
			updateQuery += " NOT NULL";
138
		}
139
		updateQuery = updateQuery.replace("@tableName", tableName);
140
		updateQuery = updateQuery.replace("@columnName", newColumnName);
141
		updateQuery = updateQuery.replace("@columnType", databaseColumnType);
142
		updateQuery = updateQuery.replace("@addSeparator", getAddColumnSeperator(datasource));
143
		
144
		return updateQuery;
145
	}
146

    
147
	protected static String getDatabaseColumnType(ICdmDataSource datasource, String columnType) {
148
		String result = columnType;
149
		DatabaseTypeEnum dbType = datasource.getDatabaseType();
150
		//nvarchar
151
		if (dbType.equals(DatabaseTypeEnum.PostgreSQL)){  //TODO use PostgeSQL82 Dialect infos
152
			result = result.replace("nvarchar", "varchar");
153
			result = result.replace("double", "float8");
154
			result = result.replace("bit", DatabaseTypeEnum.PostgreSQL.getHibernateDialect().getTypeName(Types.BIT));
155
			result = result.replace("datetime", DatabaseTypeEnum.PostgreSQL.getHibernateDialect().getTypeName(Types.TIMESTAMP));
156
			result = result.replace("tinyint", DatabaseTypeEnum.PostgreSQL.getHibernateDialect().getTypeName(Types.TINYINT));
157
		}
158
		//CLOB
159
		if (columnType.equalsIgnoreCase("clob")){
160
			//TODO use hibernate dialects
161
			if (dbType.equals(DatabaseTypeEnum.MySQL)){
162
				result = "longtext";
163
			}else if (dbType.equals(DatabaseTypeEnum.H2)){
164
				result = "CLOB";  //or NVARCHAR
165
			}else if (dbType.equals(DatabaseTypeEnum.PostgreSQL)){
166
				result = "text";
167
			}else if (dbType.equals(DatabaseTypeEnum.SqlServer2005)){
168
				result = "NVARCHAR(MAX)";
169
			}
170
		}
171
		return result;
172
	}
173
	
174

    
175
	/**
176
	 * Returns the sql keywords for adding a column. This is usually 'ADD' or 'ADD COLUMN'
177
	 * @param datasource
178
	 * @return
179
	 * @throws DatabaseTypeNotSupportedException
180
	 */
181
	public static String getAddColumnSeperator(ICdmDataSource datasource) throws DatabaseTypeNotSupportedException {
182
		DatabaseTypeEnum type = datasource.getDatabaseType();
183
		if (type.equals(DatabaseTypeEnum.SqlServer2005)){
184
			return "ADD ";
185
		}else if (type.equals(DatabaseTypeEnum.H2) || type.equals(DatabaseTypeEnum.PostgreSQL) || type.equals(DatabaseTypeEnum.MySQL)){
186
			return "ADD COLUMN ";
187
		}else{
188
			throw new DatabaseTypeNotSupportedException(datasource.getName());
189
		}
190
	}
191

    
192
	public String getReferencedTable() {
193
		return referencedTable;
194
	}
195
	
196

    
197
	public String getNewColumnName() {
198
		return newColumnName;
199
	}
200

    
201
}
(5-5/32)