Project

General

Profile

Download (8.06 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

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

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

    
33
	private final String indexColumn;
34

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

    
40

    
41
	protected UniqueIndexDropper(String stepName, String tableName, String indexColumn, boolean includeAudTable) {
42
		super(stepName, tableName, includeAudTable);
43
		this.indexColumn = indexColumn;
44
	}
45

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

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

    
90

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

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

    
118
		return updateQuery;
119
	}
120

    
121

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

    
169
	}
170

    
171

    
172
}
(33-33/35)