include more auditing in schema update and refactor to better allow transaction suppo...
[cdmlib.git] / cdmlib-persistence / src / main / java / eu / etaxonomy / cdm / database / update / ColumnTypeChanger.java
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 org.apache.log4j.Logger;
13
14 import eu.etaxonomy.cdm.common.monitor.IProgressMonitor;
15 import eu.etaxonomy.cdm.database.DatabaseTypeEnum;
16 import eu.etaxonomy.cdm.database.ICdmDataSource;
17
18 /**
19 * @author a.mueller
20 * @date 16.09.2010
21 *
22 */
23 public class ColumnTypeChanger extends AuditedSchemaUpdaterStepBase<ColumnTypeChanger> implements ISchemaUpdaterStep {
24 private static final Logger logger = Logger.getLogger(ColumnTypeChanger.class);
25
26 private String columnName;
27 private String newColumnType;
28 private Object defaultValue;
29 private boolean isNotNull;
30 private String referencedTable;
31
32
33 public static final ColumnTypeChanger NewStringSizeInstance(String stepName, String tableName, String columnName, int newSize, boolean includeAudTable){
34 return new ColumnTypeChanger(stepName, tableName, columnName, "nvarchar("+newSize+")", includeAudTable, null, false, null);
35 }
36
37 public static final ColumnTypeChanger NewClobInstance(String stepName, String tableName, String columnName, boolean includeAudTable){
38 return new ColumnTypeChanger(stepName, tableName, columnName, "clob", includeAudTable, null, false, null);
39 }
40
41 public static final ColumnTypeChanger NewInt2DoubleInstance(String stepName, String tableName, String columnName, boolean includeAudTable){
42 return new ColumnTypeChanger(stepName, tableName, columnName, "double", includeAudTable, null, false, null);
43 }
44
45 public static final ColumnTypeChanger NewInt2StringInstance(String stepName, String tableName, String columnName, int size, boolean includeAudTable, Integer defaultValue, boolean notNull){
46 return new ColumnTypeChanger(stepName, tableName, columnName, "nvarchar("+size+")", includeAudTable, defaultValue, notNull, null);
47 }
48
49
50 protected ColumnTypeChanger(String stepName, String tableName, String columnName, String newColumnType, boolean includeAudTable, Object defaultValue, boolean notNull, String referencedTable) {
51 super(stepName);
52 this.tableName = tableName;
53 this.columnName = columnName;
54 this.newColumnType = newColumnType;
55 this.includeAudTable = includeAudTable;
56 this.defaultValue = defaultValue;
57 this.isNotNull = notNull;
58 this.referencedTable = referencedTable;
59 }
60
61 @Override
62 protected boolean invokeOnTable(String tableName, ICdmDataSource datasource, IProgressMonitor monitor) {
63 boolean result = true;
64 try {
65
66 String updateQuery;
67 if (this.isNotNull){
68 updateQuery = getNotNullUpdateQuery(tableName, datasource, monitor);
69 datasource.executeUpdate(updateQuery);
70 }
71
72 updateQuery = getUpdateQueryString(tableName, datasource, monitor);
73 datasource.executeUpdate(updateQuery);
74
75 if (defaultValue instanceof Boolean){
76 updateQuery = "UPDATE @tableName SET @columnName = " + (defaultValue == null ? "null" : getBoolean((Boolean) defaultValue, datasource));
77 updateQuery = updateQuery.replace("@tableName", tableName);
78 updateQuery = updateQuery.replace("@columnName", columnName);
79 datasource.executeUpdate(updateQuery);
80 }
81 if (referencedTable != null){
82 result &= TableCreator.makeForeignKey(tableName, datasource, columnName, referencedTable);
83 }
84
85 return result;
86 } catch ( Exception e) {
87 monitor.warning(e.getMessage(), e);
88 logger.error(e);
89 return false;
90 }
91 }
92
93 private String getNotNullUpdateQuery(String tableName, ICdmDataSource datasource, IProgressMonitor monitor) {
94 String query = " UPDATE %s SET %s = %S WHERE %s IS NULL ";
95 String defaultValueStr = String.valueOf(this.defaultValue);
96 if (this.defaultValue instanceof Integer){
97 //OK
98 }else{
99 defaultValueStr = "'" + defaultValueStr + "'";
100 }
101 query = String.format(query, tableName, this.columnName, defaultValueStr, this.columnName);
102 return query;
103 }
104
105 public String getUpdateQueryString(String tableName, ICdmDataSource datasource, IProgressMonitor monitor) throws DatabaseTypeNotSupportedException {
106 String updateQuery;
107 DatabaseTypeEnum type = datasource.getDatabaseType();
108 String databaseColumnType = getDatabaseColumnType(datasource, this.newColumnType);
109
110 if (type.equals(DatabaseTypeEnum.SqlServer2005)){
111 //MySQL allows both syntaxes
112 updateQuery = "ALTER TABLE @tableName ALTER COLUMN @columnName @columnType";
113 }else if (type.equals(DatabaseTypeEnum.H2)){
114 updateQuery = "ALTER TABLE @tableName ALTER COLUMN @columnName @columnType";
115 }else if (type.equals(DatabaseTypeEnum.PostgreSQL)){
116 updateQuery = "ALTER TABLE @tableName ALTER COLUMN @columnName TYPE @columnType";
117 }else if (type.equals(DatabaseTypeEnum.MySQL)){
118 updateQuery = "ALTER TABLE @tableName MODIFY COLUMN @columnName @columnType";
119 }else{
120 updateQuery = null;
121 String warning = "Update step '" + this.getStepName() + "' is not supported by " + type.getName();
122 monitor.warning(warning);
123 throw new DatabaseTypeNotSupportedException(warning);
124 }
125 if (isNotNull){
126 updateQuery += " NOT NULL";
127 }
128 updateQuery = updateQuery.replace("@tableName", tableName);
129 updateQuery = updateQuery.replace("@columnName", columnName);
130 updateQuery = updateQuery.replace("@columnType", databaseColumnType);
131 // updateQuery = updateQuery.replace("@addSeparator", getAddColumnSeperator(datasource));
132
133 return updateQuery;
134 }
135
136 private String getDatabaseColumnType(ICdmDataSource datasource, String columnType) {
137 return ColumnAdder.getDatabaseColumnType(datasource, columnType);
138 }
139
140 public String getReferencedTable() {
141 return referencedTable;
142 }
143 //
144 // public String getNewColumnName() {
145 // return columnName;
146 // }
147
148 }