Project

General

Profile

Download (6 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.sql.SQLException;
12
import java.util.List;
13

    
14
import org.apache.commons.lang.StringUtils;
15
import org.apache.logging.log4j.LogManager;import org.apache.logging.log4j.Logger;
16

    
17
import eu.etaxonomy.cdm.common.monitor.IProgressMonitor;
18
import eu.etaxonomy.cdm.database.DatabaseTypeEnum;
19
import eu.etaxonomy.cdm.database.ICdmDataSource;
20
import eu.etaxonomy.cdm.database.update.v30_40.UsernameConstraintUpdater;
21

    
22
/**
23
 * Adds an Index on a string column.
24
 *
25
 * @see {@link UsernameConstraintUpdater}
26
 * @author a.mueller
27
 * @since 2016-10-18
28
 */
29
public class IndexAdder extends SchemaUpdaterStepBase {
30
	private static final Logger logger = LogManager.getLogger(IndexAdder.class);
31

    
32
	private String tableName;
33

    
34
	private String columnName;
35

    
36
	private Integer length;
37

    
38
// ********************** FACTORY ****************************************/
39

    
40
	public static final IndexAdder NewStringInstance(List<ISchemaUpdaterStep> stepList, String stepName, String tableName, String columnName, Integer length){
41
		return new IndexAdder(stepList, stepName, tableName, columnName, length == null ? 255 : length);
42
	}
43

    
44
    public static final IndexAdder NewIntegerInstance(List<ISchemaUpdaterStep> stepList, String stepName, String tableName, String columnName){
45
        return new IndexAdder(stepList, stepName, tableName, columnName, null);
46
    }
47

    
48
// **************************** CONSTRUCTOR *********************************/
49

    
50
	protected IndexAdder(List<ISchemaUpdaterStep> stepList, String stepName, String tableName, String columnName, Integer length) {
51
		super(stepList, stepName);
52
		this.tableName = tableName;
53
		this.columnName = columnName;
54
		this.length = length;
55
	}
56

    
57
    @Override
58
    public void invoke(ICdmDataSource datasource, IProgressMonitor monitor,
59
            CaseType caseType, SchemaUpdateResult result) throws SQLException {
60
        //remove 2-fold constraint
61
//		result &= removeExistingConstraint(datasource, caseType);
62
		createColumnConstraint(datasource, caseType, result);
63
		return;
64
	}
65

    
66
	private void createColumnConstraint(ICdmDataSource datasource,
67
	        CaseType caseType, SchemaUpdateResult result) {
68
		try {
69
		    String constraintName = StringUtils.uncapitalize(tableName) + columnName + "Index";
70
			if(constraintName.length()>64){
71
			    //MySQL has problems with index names > 64,  https://stackoverflow.com/questions/28615903/error-1059-identifier-name-too-long-on-foreign-key-constraints-from-existing-ta
72
			    constraintName = constraintName.replace("Base", "");
73
			    if(constraintName.length()>64){
74
	                constraintName = constraintName.replace("OrObservation", "");
75
	            }
76
			}
77
		    String updateQuery = getCreateQuery(datasource, caseType, tableName, constraintName, columnName);
78
			datasource.executeUpdate(updateQuery);
79
			return;
80
		} catch (Exception e) {
81
		    String message = "Unique index for " + columnName + " could not be created";
82
			logger.warn(message);
83
			result.addException(e, message, "IndexAdder.createColumnConstraint");
84
			return;
85
		}
86
	}
87

    
88
	private String getCreateQuery(ICdmDataSource datasource, CaseType caseType, String tableName, String constraintName, String columnName) {
89
		DatabaseTypeEnum type = datasource.getDatabaseType();
90
//		String indexName = "_UniqueKey";
91
		String updateQuery;
92
		if (type.equals(DatabaseTypeEnum.MySQL)){
93
			//Maybe MySQL also works with the below syntax. Did not check yet.
94
			updateQuery = "ALTER TABLE @@"+ tableName + "@@ ADD INDEX " + constraintName + " ("+columnName+ makeLength()+");";
95
		}else if (type.equals(DatabaseTypeEnum.H2) || type.equals(DatabaseTypeEnum.PostgreSQL) || type.equals(DatabaseTypeEnum.SqlServer2005)){
96
			updateQuery = "CREATE INDEX " + constraintName + " ON "+tableName+"(" + columnName + ")";
97
		}else{
98
			throw new IllegalArgumentException("Datasource type not supported yet: " + type.getName());
99
		}
100
//		updateQuery = updateQuery.replace("@indexName", indexName);
101
		updateQuery = caseType.replaceTableNames(updateQuery);
102
		return updateQuery;
103
	}
104

    
105
	/**
106
     * @param length2
107
     * @return
108
     */
109
    private String makeLength() {
110
        if (length != null){
111
            return "(" + length + ")";
112
        }else{
113
            return "";
114
        }
115
    }
116

    
117
    private boolean removeExistingConstraint(ICdmDataSource datasource, CaseType caseType) {
118
		try {
119
			DatabaseTypeEnum type = datasource.getDatabaseType();
120
			String indexName = "_UniqueKey";
121
			String updateQuery = makeRemoveConstraintUpdateQuery(caseType, type, indexName);
122
			try {
123
				datasource.executeUpdate(updateQuery);
124
			} catch (Exception e) {
125
				indexName = "uuid";
126
				updateQuery = makeRemoveConstraintUpdateQuery(caseType, type, indexName);
127
				datasource.executeUpdate(updateQuery);
128
			}
129
			return true;
130
		} catch (Exception e) {
131
			logger.warn("Old index could not be removed");
132
			return false;
133
		}
134
	}
135

    
136

    
137
	/**
138
	 * @param caseType
139
	 * @param type
140
	 * @param indexName
141
	 * @param updateQuery
142
	 * @return
143
	 */
144
	private String makeRemoveConstraintUpdateQuery(CaseType caseType,
145
			DatabaseTypeEnum type, String indexName) {
146
		String updateQuery;
147
		if (type.equals(DatabaseTypeEnum.MySQL)){
148
			updateQuery = "ALTER TABLE @@" + tableName + "@@ DROP INDEX @indexName";
149
		}else if (type.equals(DatabaseTypeEnum.H2)){
150
			updateQuery = "ALTER TABLE @@" + tableName + "@@ DROP CONSTRAINT IF EXISTS @indexName";
151
		}else if (type.equals(DatabaseTypeEnum.PostgreSQL)){
152
			updateQuery = "ALTER TABLE @@" + tableName + "@@ DROP CONSTRAINT @indexName";
153
		}else if (type.equals(DatabaseTypeEnum.SqlServer2005)){
154
			//TODO
155
			throw new RuntimeException("Remove index not yet supported for SQLServer");
156
		}else{
157
			throw new IllegalArgumentException("Datasource type not supported: " + type.getName());
158
		}
159
		updateQuery = updateQuery.replace("@indexName", indexName);
160
		updateQuery = caseType.replaceTableNames(updateQuery);
161
		return updateQuery;
162
	}
163
}
(18-18/41)