Project

General

Profile

Download (8.05 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.logging.log4j.LogManager;import org.apache.logging.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
 * Dropps a UNIQUE index on a column in a table. If no unique index exists on the column no operation is executed.
22
 *
23
 * Tested: MySQL, H2, PostGreSQL
24
 * Not tested for: SQL Server (throws exception)
25
 *
26
 * @author a.mueller
27
 * @since 16.09.2010
28
 *
29
 */
30
public class UniqueIndexDropper extends AuditedSchemaUpdaterStepBase {
31

    
32
    private static final Logger logger = LogManager.getLogger(UniqueIndexDropper.class);
33

    
34
	private final String indexColumn;
35

    
36
	public static final UniqueIndexDropper NewInstance(List<ISchemaUpdaterStep> stepList, String tableName, String indexColumn, boolean includeAudTable){
37
		String stepName = "Drop index " + tableName + "-" + indexColumn;
38
		return new UniqueIndexDropper(stepList, stepName, tableName, indexColumn, includeAudTable);
39
	}
40

    
41

    
42
	protected UniqueIndexDropper(List<ISchemaUpdaterStep> stepList, String stepName, String tableName, String indexColumn, boolean includeAudTable) {
43
		super(stepList, stepName, tableName, includeAudTable);
44
		this.indexColumn = indexColumn;
45
	}
46

    
47
    @Override
48
    protected void invokeOnTable(String tableName, ICdmDataSource datasource,
49
            IProgressMonitor monitor, CaseType caseType, SchemaUpdateResult result) {
50
        try {
51
			if (checkExists(datasource, caseType)){
52
				String updateQuery = getUpdateQueryString(tableName, datasource, caseType, monitor);
53
				datasource.executeUpdate(updateQuery);
54
			}
55
			return;
56
		} catch ( Exception e) {
57
		    String message = e.getMessage();
58
            monitor.warning(message, e);
59
            logger.warn(message);
60
            result.addException(e, message, this, "invoke");
61
            return;
62
		}
63
	}
64

    
65
	private boolean checkExists(ICdmDataSource datasource, CaseType caseType) throws SQLException, DatabaseTypeNotSupportedException {
66
		DatabaseTypeEnum type = datasource.getDatabaseType();
67
		if (type.equals(DatabaseTypeEnum.MySQL)){
68
			String sql = " SELECT count(*)" +
69
			             " FROM information_schema.KEY_COLUMN_USAGE kcu " +
70
                            " INNER JOIN information_schema.TABLE_CONSTRAINTS tc ON kcu.CONSTRAINT_NAME = tc.CONSTRAINT_NAME " +
71
                            " AND tc.TABLE_NAME = kcu.TABLE_NAME AND tc.TABLE_SCHEMA = kcu.TABLE_SCHEMA " +
72
                         " WHERE kcu.table_name ='@tableName' AND kcu.CONSTRAINT_SCHEMA = '@dbName' " +
73
                            " AND kcu.COLUMN_NAME = '@columnName' AND CONSTRAINT_TYPE = 'UNIQUE' ";
74
			sql = sql.replace("@tableName", tableName);
75
			sql = sql.replace("@columnName", indexColumn);
76
			sql = sql.replace("@dbName", datasource.getDatabase());
77
			long count = (Long)datasource.getSingleValue(sql);
78
			return count > 0;
79
		}else if (type.equals(DatabaseTypeEnum.PostgreSQL)){
80
            String indexName = getIndexName(datasource, caseType);
81
            return indexName != null;
82
		}else if (type.equals(DatabaseTypeEnum.H2)){
83
			String indexName = getIndexName(datasource, caseType);
84
			return indexName != null;
85
		}else{
86
			// not needed
87
			return true;
88
		}
89
	}
90

    
91

    
92
	public String getUpdateQueryString(String tableName, ICdmDataSource datasource, CaseType caseType, IProgressMonitor monitor) throws DatabaseTypeNotSupportedException, SQLException {
93
		//NOTE: no caseType required here
94
		String updateQuery;
95
		DatabaseTypeEnum type = datasource.getDatabaseType();
96
		String indexName = getIndexName(datasource, caseType);
97

    
98
//		if (type.equals(DatabaseTypeEnum.SqlServer2005)){
99
			//MySQL allows both syntaxes
100
//			updateQuery = "ALTER TABLE @tableName ADD @columnName @columnType";
101
//		}else
102
		if (type.equals(DatabaseTypeEnum.H2)){
103
			updateQuery = "ALTER TABLE @tableName DROP CONSTRAINT IF EXISTS @indexName";
104
		}else if (type.equals(DatabaseTypeEnum.PostgreSQL)){
105
//			updateQuery = "DROP INDEX IF EXISTS @indexName";  // does not work because index is used in the constraint
106
//			updateQuery = "ALTER TABLE @tableName DROP CONSTRAINT IF EXISTS @indexName"; //"if exists" does not work (version 8.4)
107
			updateQuery = "ALTER TABLE @tableName DROP CONSTRAINT @indexName";
108
		}else if (type.equals(DatabaseTypeEnum.MySQL)){
109
			updateQuery = "ALTER TABLE @tableName DROP INDEX @indexName";
110
		}else{
111
			updateQuery = null;
112
			String warning = "Update step '" + this.getStepName() + "' is not supported by " + type.getName();
113
			monitor.warning(warning);
114
			throw new DatabaseTypeNotSupportedException(warning);
115
		}
116
		updateQuery = updateQuery.replace("@tableName", tableName);
117
		updateQuery = updateQuery.replace("@indexName", indexName);
118

    
119
		return updateQuery;
120
	}
121

    
122

    
123
	private String getIndexName(ICdmDataSource datasource, CaseType caseType) throws DatabaseTypeNotSupportedException, SQLException {
124
		String result = this.indexColumn;
125
		DatabaseTypeEnum type = datasource.getDatabaseType();
126
		if (type.equals(DatabaseTypeEnum.SqlServer2005)){
127
			throw new DatabaseTypeNotSupportedException(type.toString());
128
		}else if (type.equals(DatabaseTypeEnum.MySQL)){
129
		    String sql = "SELECT kcu.CONSTRAINT_NAME FROM information_schema.KEY_COLUMN_USAGE kcu " +
130
		                    " INNER JOIN information_schema.TABLE_CONSTRAINTS tc ON kcu.CONSTRAINT_NAME = tc.CONSTRAINT_NAME " +
131
		                    " AND tc.TABLE_NAME = kcu.TABLE_NAME AND tc.TABLE_SCHEMA = kcu.TABLE_SCHEMA " +
132
		                    " WHERE kcu.TABLE_NAME = '@tableName' AND kcu.TABLE_SCHEMA = '@dbName' AND kcu.COLUMN_NAME = '@columnName' "+
133
		                        " AND tc.TABLE_NAME = '@tableName' AND tc.TABLE_SCHEMA = '@dbName' AND CONSTRAINT_TYPE = 'UNIQUE' ";
134
		    sql = sql.replace("@tableName", caseType.replaceTableNames(tableName));
135
            sql = sql.replace("@columnName", indexColumn);
136
            sql = sql.replace("@dbName", datasource.getDatabase());
137
            String constraintName = (String)datasource.getSingleValue(sql);
138
            result = constraintName;
139
		}else if (type.equals(DatabaseTypeEnum.H2) ){
140
//			String sql = "SELECT INDEX_NAME FROM INFORMATION_SCHEMA.INDEXES WHERE TABLE_NAME = @tableName AND INDEX_TYPE_NAME = 'UNIQUE INDEX'";
141
			String sql = "SELECT CONSTRAINT_NAME " +
142
					" FROM INFORMATION_SCHEMA.CONSTRAINTS "+
143
					" WHERE CONSTRAINT_CATALOG = '@dbName' AND "+
144
					" TABLE_NAME = '@tableName' AND CONSTRAINT_TYPE = 'UNIQUE' AND "+
145
					" COLUMN_LIST = '@columnName'";
146
			sql = sql.replace("@tableName", tableName.toUpperCase());
147
			sql = sql.replace("@columnName", indexColumn.toUpperCase());
148
			sql = sql.replace("@dbName", datasource.getDatabase().toUpperCase());
149
			String constraintName = (String)datasource.getSingleValue(sql);
150
			result = constraintName;
151
		}else if (type.equals(DatabaseTypeEnum.PostgreSQL)){
152
		    String sql = " SELECT tc.constraint_name " +
153
		            " FROM information_schema.table_constraints tc " +
154
		                " LEFT JOIN information_schema.key_column_usage kcu " +
155
    		                " ON tc.constraint_catalog = kcu.constraint_catalog " +
156
    		                " AND tc.constraint_schema = kcu.constraint_schema " +
157
    		                " AND tc.constraint_name = kcu.constraint_name " +
158
		             " WHERE tc.constraint_type = 'UNIQUE' AND tc.table_name = '@tableName' " +
159
    		                " AND kcu.column_name = '@columnName' AND tc.table_catalog = '@dbName'";
160
            sql = sql.replace("@tableName", tableName.toLowerCase());  //postgres is folding to lower_case not upper case (the later is SQL standard)
161
            sql = sql.replace("@columnName", indexColumn);
162
            sql = sql.replace("@dbName", datasource.getDatabase());
163
            String constraintName = (String)datasource.getSingleValue(sql);
164
            result = constraintName;
165
		}else{
166
			throw new DatabaseTypeNotSupportedException(type.toString());
167
		}
168
		return result;
169

    
170
	}
171

    
172

    
173
}
(39-39/41)