Project

General

Profile

Download (7.92 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
 * @date 16.09.2010
27
 *
28
 */
29
public class UniqueIndexDropper extends AuditedSchemaUpdaterStepBase<UniqueIndexDropper> {
30
	@SuppressWarnings("unused")
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 boolean invokeOnTable(String tableName, ICdmDataSource datasource, IProgressMonitor monitor, CaseType caseType) {
48
		try {
49
			if (checkExists(datasource, caseType)){
50
				String updateQuery = getUpdateQueryString(tableName, datasource, caseType, monitor);
51
				datasource.executeUpdate(updateQuery);
52
			}
53
			return true;
54
		} catch ( Exception e) {
55
			monitor.warning(e.getMessage(), e);
56
			return false;
57
		}
58
	}
59

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

    
86

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

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

    
114
		return updateQuery;
115
	}
116

    
117

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

    
165
	}
166

    
167

    
168
}
(34-34/36)