Project

General

Profile

Download (5.35 KB) Statistics
| Branch: | Tag: | Revision:
1
// $Id$
2
/**
3
* Copyright (C) 2009 EDIT
4
* European Distributed Institute of Taxonomy 
5
* http://www.e-taxonomy.eu
6
* 
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.
9
*/
10
package eu.etaxonomy.cdm.database.update;
11

    
12
import org.apache.log4j.Logger;
13

    
14
import eu.etaxonomy.cdm.common.monitor.IProgressMonitor;
15
import eu.etaxonomy.cdm.database.DatabaseTypeEnum;
16
import eu.etaxonomy.cdm.database.ICdmDataSource;
17
import eu.etaxonomy.cdm.model.common.ITreeNode;
18

    
19
/**
20
 * @author a.mueller
21
 * @date 09.08.2013
22
 *
23
 */
24
public class TreeIndexUpdater extends AuditedSchemaUpdaterStepBase<TreeIndexUpdater> implements ISchemaUpdaterStep {
25
	private static final Logger logger = Logger.getLogger(TreeIndexUpdater.class);
26
	
27
	private String indexColumnName = "treeIndex";
28
	private String treeIdColumnName;
29
	private String parentIdColumnName = "parent_id";
30
	
31
	public static final TreeIndexUpdater NewInstance(String stepName, String tableName, String treeIdColumnName, boolean includeAudTable){
32
		return new TreeIndexUpdater(stepName, tableName, treeIdColumnName, null, includeAudTable);
33
	}
34

    
35
	public static final TreeIndexUpdater NewInstance(String stepName, String tableName, String treeIdColumnName, String indexColumnName, boolean includeAudTable){
36
		return new TreeIndexUpdater(stepName, tableName, treeIdColumnName, indexColumnName, includeAudTable);
37
	}
38
	
39
	
40
	protected TreeIndexUpdater(String stepName, String tableName, String treeIdColumnName, String indexColumnName, boolean includeAudTable) {
41
		super(stepName);
42
		this.tableName = tableName;
43
		this.treeIdColumnName = treeIdColumnName;
44
		this.indexColumnName = indexColumnName == null ? this.indexColumnName : indexColumnName;
45
		this.includeAudTable = includeAudTable;
46
	}
47

    
48
	@Override
49
	protected boolean invokeOnTable(String tableName, ICdmDataSource datasource, IProgressMonitor monitor, CaseType caseType) {
50
		try{
51
			boolean result = true;			
52
			
53
	//		String charType = "CHAR";  //TODO may depend on database type
54
			
55
			//clean up nodes without classification  //this should not happen with correct "delete" implementation
56
			String sql = String.format(" DELETE FROM %s WHERE %s IS NULL ", tableName, treeIdColumnName);
57
			datasource.executeUpdate(sql);
58
			
59
			//... set all index entries to NULL
60
			sql = String.format(" UPDATE %s SET %s = NULL", tableName, indexColumnName);
61
			datasource.executeUpdate(sql);
62
			
63
			//start
64
			String separator = ITreeNode.separator;
65
			String treePrefix = ITreeNode.treePrefix;
66
			sql = String.format(" UPDATE %s " +
67
					" SET %s = CONCAT('%s%s', %s, '%s', id, '%s') " +
68
					" WHERE %s IS NULL AND %s IS NOT NULL ", 
69
						tableName, 
70
						indexColumnName, separator, treePrefix, treeIdColumnName, separator, separator, 
71
						parentIdColumnName, treeIdColumnName);
72
			datasource.executeUpdate(sql);
73
			
74
			//width search index creation
75
			String sqlCount = String.format(" SELECT count(*) as n " +
76
					" FROM %s child INNER JOIN %s parent ON child.%s = parent.id " +
77
					" WHERE parent.%s IS NOT NULL AND child.%s IS NULL ",
78
					tableName, tableName, parentIdColumnName, indexColumnName, indexColumnName);
79
			
80
			Long n;
81
			do {
82
			
83
				//MySQL
84
				if (datasource.getDatabaseType().equals(DatabaseTypeEnum.MySQL)){
85
					sql = String.format(" UPDATE %s child " +
86
							" INNER JOIN %s parent ON child.%s = parent.id " +
87
							" SET child.%s = CONCAT( parent.%s, child.id, '%s') " +
88
							" WHERE parent.%s IS NOT NULL AND child.%s IS NULL ", 
89
								tableName, 
90
								tableName, parentIdColumnName, 
91
								indexColumnName, indexColumnName, separator,
92
								indexColumnName, indexColumnName);
93
				}else{
94
					//ANSI
95
					//http://stackoverflow.com/questions/1293330/how-can-i-do-an-update-statement-with-join-in-sql
96
					//does not work with MySQL as MySQL does not allow to use the same table in Subselect and Update (error 1093: http://dev.mysql.com/doc/refman/5.1/de/subquery-errors.html) 
97
					sql = String.format(" UPDATE %s " +
98
							" SET %s = ( " +
99
								" ( SELECT CONCAT ( parent.%s, %s.id, '%s') " + 
100
									" FROM %s parent " +
101
									" WHERE parent.id = %s.%s ) " +
102
								" ) " +
103
							" WHERE EXISTS ( " +
104
									" SELECT * " +
105
									" FROM %s parent " +
106
									" WHERE parent.id = %s.%s AND parent.%s IS NOT NULL AND %s.%s IS NULL " +
107
								") " +
108
								" ",
109
							tableName,
110
							indexColumnName,
111
								indexColumnName, tableName, separator,
112
								tableName,
113
								tableName, parentIdColumnName,
114
								
115
								tableName,
116
								tableName, parentIdColumnName, indexColumnName, tableName, indexColumnName
117
							);
118
				}
119
				
120
				datasource.executeUpdate(sql);
121
				
122
				n = (Long)datasource.getSingleValue(sqlCount);
123
			}	while (n > 0) ;
124
			
125
			sqlCount = String.format(" SELECT count(*) as n " +
126
					" FROM %s " +
127
					" WHERE %s IS NULL ", tableName, indexColumnName);
128
			n = (Long)datasource.getSingleValue(sqlCount);
129
			if (n > 0){
130
				String message = "There are tree nodes with no tree index in %s. This indicates that there is a problem in the tree structure of 1 or more classifications.";
131
				logger.error(String.format(message, tableName));
132
			}
133
			
134
			return result;
135
		}catch(Exception e){
136
			monitor.warning(e.getMessage(), e);
137
			logger.error(e.getMessage());
138
			return false;
139
		}
140
	}
141

    
142
}
(29-29/32)