Project

General

Profile

Download (10.5 KB) Statistics
| Branch: | Tag: | Revision:
1
/**
2
* Copyright (C) 2009 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
package eu.etaxonomy.cdm.database.update;
10

    
11
import java.util.List;
12

    
13
import org.apache.logging.log4j.LogManager;import org.apache.logging.log4j.Logger;
14

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

    
19
/**
20
 * @author a.mueller
21
 * @since 16.09.2010
22
 */
23
public class ColumnAdder extends AuditedSchemaUpdaterStepBase {
24
	private static final Logger logger = LogManager.getLogger(ColumnAdder.class);
25

    
26
	private final String newColumnName;
27
	private final Datatype columnType;
28
	private final Integer size;
29
	private final Integer scale;
30
	private final Object defaultValue;
31
	private boolean isNotNull;
32
	private final String referencedTable;
33

    
34
	/**
35
	 * Add ForeignKey.
36
	 * @param referencedTable
37
	 * @return
38
	 */
39
	public static final ColumnAdder NewIntegerInstance(List<? extends ISchemaUpdaterStep> stepList, String stepName, String tableName, String newColumnName, boolean includeAudTable, boolean notNull, String referencedTable){
40
		return new ColumnAdder(stepList, stepName, tableName, newColumnName, Datatype.INTEGER, null, null, includeAudTable, null, notNull, referencedTable);
41
	}
42

    
43
	public static final ColumnAdder NewIntegerInstance(List<? extends ISchemaUpdaterStep> stepList, String stepName, String tableName, String newColumnName, boolean includeAudTable, Integer defaultValue, boolean notNull){
44
		return new ColumnAdder(stepList, stepName, tableName, newColumnName, Datatype.INTEGER, null, null, includeAudTable, defaultValue, notNull, null);
45
	}
46

    
47
	public static final ColumnAdder NewTinyIntegerInstance(List<? extends ISchemaUpdaterStep> stepList, String stepName, String tableName, String newColumnName, boolean includeAudTable, boolean notNull){
48
		return new ColumnAdder(stepList, stepName, tableName, newColumnName, Datatype.TINYINTEGER, null, null, includeAudTable, null, notNull, null);
49
	}
50

    
51
	public static final ColumnAdder NewDoubleInstance(List<? extends ISchemaUpdaterStep> stepList, String stepName, String tableName, String newColumnName, boolean includeAudTable, boolean notNull){
52
		return new ColumnAdder(stepList, stepName, tableName, newColumnName, Datatype.DOUBLE, null, null, includeAudTable, null, notNull, null);
53
	}
54

    
55
    public static final ColumnAdder NewDecimalInstance(List<? extends ISchemaUpdaterStep> stepList, String stepName, String tableName, String newColumnName, int precision,  int scale, boolean includeAudTable, Integer defaultValue, boolean notNull){
56
        return new ColumnAdder(stepList, stepName, tableName, newColumnName, Datatype.BIGDECIMAL, precision, scale, includeAudTable, defaultValue, notNull, null);
57
    }
58

    
59
	public static final ColumnAdder NewBooleanInstance(List<? extends ISchemaUpdaterStep> stepList, String stepName, String tableName, String newColumnName, boolean includeAudTable, Boolean defaultValue){
60
		return new ColumnAdder(stepList, stepName, tableName, newColumnName, Datatype.BIT, null, null, includeAudTable, defaultValue, false, null);
61
	}
62

    
63
	/**
64
	 * Adds a string column with length 255 and default value <code>null</code>
65
	 */
66
	public static final ColumnAdder NewStringInstance(List<? extends ISchemaUpdaterStep> stepList, String stepName, String tableName, String newColumnName, boolean includeAudTable){
67
		return new ColumnAdder(stepList, stepName, tableName, newColumnName, Datatype.VARCHAR, 255, null, includeAudTable, null, false, null);
68
	}
69

    
70
    public static final ColumnAdder NewDTYPEInstance(List<? extends ISchemaUpdaterStep> stepList, String stepName, String tableName, String defaultValue, boolean includeAudTable){
71
        return new ColumnAdder(stepList, stepName, tableName, "DTYPE", Datatype.VARCHAR, 31, null, includeAudTable, defaultValue, true, null);
72
    }
73

    
74
    /**
75
     * Adds a string column with the given length and default value <code>null</code>
76
     */
77
	public static final ColumnAdder NewStringInstance(List<? extends ISchemaUpdaterStep> stepList, String stepName, String tableName, String newColumnName, int length, boolean includeAudTable){
78
		return new ColumnAdder(stepList, stepName, tableName, newColumnName, Datatype.VARCHAR, length, null, includeAudTable, null, false, null);
79
	}
80

    
81
    /**
82
     * Adds a string column with the given length and the given default value
83
     */
84
    public static final ColumnAdder NewStringInstance(List<? extends ISchemaUpdaterStep> stepList, String stepName, String tableName, String newColumnName, int length, String defaultValue, boolean includeAudTable){
85
        return new ColumnAdder(stepList, stepName, tableName, newColumnName, Datatype.VARCHAR, length, null, includeAudTable, defaultValue, false, null);
86
    }
87

    
88
	public static final ColumnAdder NewClobInstance(List<? extends ISchemaUpdaterStep> stepList, String stepName, String tableName, String newColumnName, boolean includeAudTable){
89
		return new ColumnAdder(stepList, stepName, tableName, newColumnName, Datatype.CLOB, null, null, includeAudTable, null, false, null);
90
	}
91

    
92
	public static final ColumnAdder NewDateTimeInstance(List<? extends ISchemaUpdaterStep> stepList, String stepName, String tableName, String newColumnName, boolean includeAudTable, boolean notNull){
93
		return new ColumnAdder(stepList, stepName, tableName, newColumnName, Datatype.DATETIME, null, null, includeAudTable, null, notNull, null);
94
	}
95

    
96
	protected ColumnAdder(List<? extends ISchemaUpdaterStep> stepList, String stepName, String tableName, String newColumnName,
97
	        Datatype columnType, Integer size, Integer scale, boolean includeAudTable, Object defaultValue, boolean notNull, String referencedTable) {
98
		super(stepList, stepName, tableName, includeAudTable);
99
		this.newColumnName = newColumnName;
100
		this.columnType = columnType;
101
		this.size = size;
102
		this.defaultValue = defaultValue;
103
		this.isNotNull = notNull;
104
		this.referencedTable = referencedTable;
105
		this.scale = scale;
106
	}
107

    
108
	public ColumnAdder setNotNull(boolean isNotNull) {
109
		this.isNotNull = isNotNull;
110
		return this;
111
	}
112

    
113
    @Override
114
    protected void invokeOnTable(String tableName, ICdmDataSource datasource,
115
            IProgressMonitor monitor, CaseType caseType, SchemaUpdateResult result) {
116

    
117
        try {
118
			String updateQuery = getUpdateQueryString(tableName, datasource, monitor);
119
			datasource.executeUpdate(updateQuery);
120

    
121
			if (defaultValue instanceof Boolean){
122
				String defaultValueQuery = "UPDATE @tableName SET @columnName = " + (defaultValue == null ? "NULL" : getBoolean((Boolean) defaultValue, datasource));
123
				defaultValueQuery = defaultValueQuery.replace("@tableName", tableName);
124
				defaultValueQuery = defaultValueQuery.replace("@columnName", newColumnName);
125
				datasource.executeUpdate(defaultValueQuery);
126
			}else if (defaultValue instanceof Integer){
127
				String defaultValueQuery = "UPDATE @tableName SET @columnName = " + (defaultValue == null ? "NULL" : defaultValue);
128
				defaultValueQuery = defaultValueQuery.replace("@tableName", tableName);
129
				defaultValueQuery = defaultValueQuery.replace("@columnName", newColumnName);
130
				datasource.executeUpdate(defaultValueQuery);
131
            }else if (defaultValue instanceof String){
132
                String defaultValueQuery = "UPDATE @tableName SET @columnName = " + (defaultValue == null ? "NULL" : "'" + defaultValue + "'");
133
                defaultValueQuery = defaultValueQuery.replace("@tableName", tableName);
134
                defaultValueQuery = defaultValueQuery.replace("@columnName", newColumnName);
135
                datasource.executeUpdate(defaultValueQuery);
136
			}else if (defaultValue != null){
137
				logger.warn("Default Value not implemented for type " + defaultValue.getClass().getName());
138
			}
139
			if (referencedTable != null){
140
				TableCreator.makeForeignKey(tableName, datasource, monitor, newColumnName, referencedTable, caseType, result);
141
			}
142
			return;
143
		} catch ( Exception e) {
144
		    String message = "Unhandled exception when trying to add column " +
145
		            newColumnName + " for table " +  tableName;
146
			monitor.warning(message, e);
147
			logger.error(e);
148
			result.addException(e, message, getStepName());
149
			return;
150
		}
151
	}
152

    
153
	/**
154
	 * Returns the update query string. tableName must already be cased correctly. See {@link CaseType}.
155
	 * @param tableName correctly cased table name
156
	 * @param datasource data source
157
	 * @param monitor monitor
158
	 * @return the query string
159
	 * @throws DatabaseTypeNotSupportedException
160
	 */
161
	public String getUpdateQueryString(String tableName, ICdmDataSource datasource, IProgressMonitor monitor) throws DatabaseTypeNotSupportedException {
162
		String updateQuery;
163
		DatabaseTypeEnum type = datasource.getDatabaseType();
164
		String databaseColumnType = this.columnType.format(datasource, size, scale);
165

    
166
		if (type.equals(DatabaseTypeEnum.SqlServer2005)){
167
			//MySQL allows both syntaxes
168
			updateQuery = "ALTER TABLE @tableName ADD @columnName @columnType";
169
		}else if (type.equals(DatabaseTypeEnum.H2) || type.equals(DatabaseTypeEnum.PostgreSQL) || type.equals(DatabaseTypeEnum.MySQL)){
170
			updateQuery = "ALTER TABLE @tableName @addSeparator @columnName @columnType";
171
		}else{
172
			updateQuery = null;
173
			String warning = "Update step '" + this.getStepName() + "' is not supported by " + type.getName();
174
			monitor.warning(warning);
175
			throw new DatabaseTypeNotSupportedException(warning);
176
		}
177
		if (isNotNull && !isAuditing){
178
			updateQuery += " NOT NULL";
179
		}
180
		updateQuery = updateQuery.replace("@tableName", tableName);
181
		updateQuery = updateQuery.replace("@columnName", newColumnName);
182
		updateQuery = updateQuery.replace("@columnType", databaseColumnType);
183
		updateQuery = updateQuery.replace("@addSeparator", getAddColumnSeperator(datasource));
184

    
185
		return updateQuery;
186
	}
187

    
188

    
189
	/**
190
	 * Returns the sql keywords for adding a column. This is usually 'ADD' or 'ADD COLUMN'
191
	 * @param datasource
192
	 * @return
193
	 * @throws DatabaseTypeNotSupportedException
194
	 */
195
	public static String getAddColumnSeperator(ICdmDataSource datasource) throws DatabaseTypeNotSupportedException {
196
		DatabaseTypeEnum type = datasource.getDatabaseType();
197
		if (type.equals(DatabaseTypeEnum.SqlServer2005)){
198
			return "ADD ";
199
		}else if (type.equals(DatabaseTypeEnum.H2) || type.equals(DatabaseTypeEnum.PostgreSQL) || type.equals(DatabaseTypeEnum.MySQL)){
200
			return "ADD COLUMN ";
201
		}else{
202
			throw new DatabaseTypeNotSupportedException(datasource.getName());
203
		}
204
	}
205

    
206
	public String getReferencedTable() {
207
		return referencedTable;
208
	}
209

    
210
	public String getNewColumnName() {
211
		return newColumnName;
212
	}
213
}
(7-7/41)