3 * Copyright (C) 2009 EDIT
4 * European Distributed Institute of Taxonomy
5 * http://www.e-taxonomy.eu
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.
10 package eu
.etaxonomy
.cdm
.database
.update
;
12 import org
.apache
.log4j
.Logger
;
14 import eu
.etaxonomy
.cdm
.common
.monitor
.IProgressMonitor
;
15 import eu
.etaxonomy
.cdm
.database
.DatabaseTypeEnum
;
16 import eu
.etaxonomy
.cdm
.database
.ICdmDataSource
;
23 public class ColumnAdder
extends AuditedSchemaUpdaterStepBase
<ColumnAdder
> implements ISchemaUpdaterStep
{
24 private static final Logger logger
= Logger
.getLogger(ColumnAdder
.class);
26 private String newColumnName
;
27 private String columnType
;
28 private Object defaultValue
;
29 private boolean isNotNull
;
31 private String referencedTable
;
33 public static final ColumnAdder
NewIntegerInstance(String stepName
, String tableName
, String newColumnName
, boolean includeAudTable
, boolean notNull
, String referencedTable
){
34 return new ColumnAdder(stepName
, tableName
, newColumnName
, "int", includeAudTable
, null, notNull
, referencedTable
);
37 public static final ColumnAdder
NewIntegerInstance(String stepName
, String tableName
, String newColumnName
, boolean includeAudTable
, Integer defaultValue
, boolean notNull
){
38 return new ColumnAdder(stepName
, tableName
, newColumnName
, "int", includeAudTable
, defaultValue
, notNull
, null);
41 public static final ColumnAdder
NewTinyIntegerInstance(String stepName
, String tableName
, String newColumnName
, boolean includeAudTable
, boolean notNull
){
42 return new ColumnAdder(stepName
, tableName
, newColumnName
, "tinyint", includeAudTable
, null, notNull
, null);
45 public static final ColumnAdder
NewDoubleInstance(String stepName
, String tableName
, String newColumnName
, boolean includeAudTable
, boolean notNull
){
46 return new ColumnAdder(stepName
, tableName
, newColumnName
, "double", includeAudTable
, null, notNull
, null);
49 public static final ColumnAdder
NewBooleanInstance(String stepName
, String tableName
, String newColumnName
, boolean includeAudTable
, Boolean defaultValue
){
50 return new ColumnAdder(stepName
, tableName
, newColumnName
, "bit", includeAudTable
, defaultValue
, false, null);
53 public static final ColumnAdder
NewStringInstance(String stepName
, String tableName
, String newColumnName
, boolean includeAudTable
){
54 return new ColumnAdder(stepName
, tableName
, newColumnName
, "nvarchar(255)", includeAudTable
, null, false, null);
57 public static final ColumnAdder
NewStringInstance(String stepName
, String tableName
, String newColumnName
, int length
, boolean includeAudTable
){
58 return new ColumnAdder(stepName
, tableName
, newColumnName
, "nvarchar("+length
+")", includeAudTable
, null, false, null);
61 public static final ColumnAdder
NewClobInstance(String stepName
, String tableName
, String newColumnName
, boolean includeAudTable
){
62 return new ColumnAdder(stepName
, tableName
, newColumnName
, "clob", includeAudTable
, null, false, null);
65 public static final ColumnAdder
NewDateTimeInstance(String stepName
, String tableName
, String newColumnName
, boolean includeAudTable
){
66 return new ColumnAdder(stepName
, tableName
, newColumnName
, "datetime", includeAudTable
, null, false, null);
69 protected ColumnAdder(String stepName
, String tableName
, String newColumnName
, String columnType
, boolean includeAudTable
, Object defaultValue
, boolean notNull
, String referencedTable
) {
71 this.tableName
= tableName
;
72 this.newColumnName
= newColumnName
;
73 this.columnType
= columnType
;
74 this.includeAudTable
= includeAudTable
;
75 this.defaultValue
= defaultValue
;
76 this.isNotNull
= notNull
;
77 this.referencedTable
= referencedTable
;
80 public ColumnAdder
setNotNull(boolean isNotNull
) {
81 this.isNotNull
= isNotNull
;
86 protected boolean invokeOnTable(String tableName
, ICdmDataSource datasource
, IProgressMonitor monitor
) {
87 boolean result
= true;
89 String updateQuery
= getUpdateQueryString(tableName
, datasource
, monitor
);
90 datasource
.executeUpdate(updateQuery
);
92 if (defaultValue
instanceof Boolean
){
93 updateQuery
= "UPDATE @tableName SET @columnName = " + (defaultValue
== null ?
"null" : getBoolean((Boolean
) defaultValue
, datasource
));
94 updateQuery
= updateQuery
.replace("@tableName", tableName
);
95 updateQuery
= updateQuery
.replace("@columnName", newColumnName
);
96 datasource
.executeUpdate(updateQuery
);
98 if (referencedTable
!= null){
99 result
&= TableCreator
.makeForeignKey(tableName
, datasource
, monitor
, newColumnName
, referencedTable
);
103 } catch ( Exception e
) {
104 monitor
.warning(e
.getMessage(), e
);
110 public String
getUpdateQueryString(String tableName
, ICdmDataSource datasource
, IProgressMonitor monitor
) throws DatabaseTypeNotSupportedException
{
112 DatabaseTypeEnum type
= datasource
.getDatabaseType();
113 String databaseColumnType
= getDatabaseColumnType(datasource
, this.columnType
);
115 if (type
.equals(DatabaseTypeEnum
.SqlServer2005
)){
116 //MySQL allows both syntaxes
117 updateQuery
= "ALTER TABLE @tableName ADD @columnName @columnType";
118 }else if (type
.equals(DatabaseTypeEnum
.H2
) || type
.equals(DatabaseTypeEnum
.PostgreSQL
) || type
.equals(DatabaseTypeEnum
.MySQL
)){
119 updateQuery
= "ALTER TABLE @tableName @addSeparator @columnName @columnType";
122 String warning
= "Update step '" + this.getStepName() + "' is not supported by " + type
.getName();
123 monitor
.warning(warning
);
124 throw new DatabaseTypeNotSupportedException(warning
);
127 updateQuery
+= " NOT NULL";
129 updateQuery
= updateQuery
.replace("@tableName", tableName
);
130 updateQuery
= updateQuery
.replace("@columnName", newColumnName
);
131 updateQuery
= updateQuery
.replace("@columnType", databaseColumnType
);
132 updateQuery
= updateQuery
.replace("@addSeparator", getAddColumnSeperator(datasource
));
137 protected static String
getDatabaseColumnType(ICdmDataSource datasource
, String columnType
) {
138 String result
= columnType
;
139 DatabaseTypeEnum dbType
= datasource
.getDatabaseType();
141 if (dbType
.equals(DatabaseTypeEnum
.PostgreSQL
)){
142 result
= result
.replace("nvarchar", "varchar");
145 if (columnType
.equalsIgnoreCase("clob")){
146 //TODO use hibernate dialects
147 if (dbType
.equals(DatabaseTypeEnum
.MySQL
)){
149 }else if (dbType
.equals(DatabaseTypeEnum
.H2
)){
150 result
= "CLOB"; //or NVARCHAR
151 }else if (dbType
.equals(DatabaseTypeEnum
.PostgreSQL
)){
153 }else if (dbType
.equals(DatabaseTypeEnum
.SqlServer2005
)){
154 result
= "NVARCHAR(MAX)";
162 * Returns the sql keywords for adding a column. This is usually 'ADD' or 'ADD COLUMN'
165 * @throws DatabaseTypeNotSupportedException
167 public static String
getAddColumnSeperator(ICdmDataSource datasource
) throws DatabaseTypeNotSupportedException
{
168 DatabaseTypeEnum type
= datasource
.getDatabaseType();
169 if (type
.equals(DatabaseTypeEnum
.SqlServer2005
)){
171 }else if (type
.equals(DatabaseTypeEnum
.H2
) || type
.equals(DatabaseTypeEnum
.PostgreSQL
) || type
.equals(DatabaseTypeEnum
.MySQL
)){
172 return "ADD COLUMN ";
174 throw new DatabaseTypeNotSupportedException(datasource
.getName());
178 public String
getReferencedTable() {
179 return referencedTable
;
183 public String
getNewColumnName() {
184 return newColumnName
;